SMART_COMPONENTS_Egts/EgtsUpdateFirmware.c

320 lines
15 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by cfif on 12.07.2024.
//
#include "EgtsUpdateFirmware.h"
#include "InternalFlashPage.h"
#include "AtGsmSimComA7600_SSL_LOAD_CA.h"
#include "FirmwareLoader.h"
#include "aes.h"
#include "EgtsProcessing.h"
#include "SystemDelayInterface.h"
#include "egts_crc.h"
#include "GsmWithGnss_Info.h"
#define LOG_SIGN "EGTS_UPDATE"
#define LOGGER &env->slog->logger
extern tFirmwareLoader FIRMWARE_LOADER;
void receivedUpdateFirmware(tEgtsProcessing *env) {
if(env->isTimerUpdate == false){
env->isTimerUpdate = true;
env->timerUpdate = SystemGetMs()+60*5*1000;
}
LoggerFormatInfo(LOGGER, LOG_SIGN,
"Получен пакет прошивки, %d из %d (%d байт данных)",
env->egtsEnv.firmware->PartNumber,
env->egtsEnv.firmware->ExpectedPartsQuantity,
env->egtsEnv.firmware->dataLength);
eEgtsFirmwareResult isFirmwareResult = EGTS_FIRMWARE_OK;
uint8_t rst = EGTS_PC_IN_PROGRESS;
// Пришел первый пакет обновления
if (env->egtsEnv.firmware->PartNumber == 1) {
// Останов навигации
//LoggerInfoStatic(LOGGER, LOG_SIGN, "Остановка потока навигации");
//SetConfigureStaticRMCThreadStop(env->gsm);
env->firmwareOffset = 0;
LoggerInfoStatic(LOGGER, LOG_SIGN, "Подготовка ПЗУ");
env->firmwareBufCrc = env->egtsEnv.firmware->WholeObjectSignature;
if (osMutexAcquire(EXT_ENV_TELE.store.accessDumper, 5000) == osOK) {
if (FirmwareLoader_ClearUpdateFlash(&FIRMWARE_LOADER)) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "ПЗУ очищено");
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка очистки ПЗУ");
isFirmwareResult = EGTS_FIRMWARE_ERROR_WRITE_PZU;
}
osMutexRelease(EXT_ENV_TELE.store.accessDumper);
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка доступа receivedUpdateFirmware");
isFirmwareResult = EGTS_FIRMWARE_ERROR_ACCESS;
}
}
if (env->firmwareOffset + env->egtsEnv.firmware->dataLength > FIRMWARE_LOADER.fwSize) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Переполнение буфера ПЗУ");
isFirmwareResult = EGTS_FIRMWARE_ERROR_OVERFLOW_PZU;
} else {
if (osMutexAcquire(EXT_ENV_TELE.store.accessDumper, 5000) == osOK) {
if (sInternalFlashPage_Write(FIRMWARE_LOADER.update.address,
env->firmwareOffset,
env->egtsEnv.firmware->dataPointer,
env->egtsEnv.firmware->dataLength) == env->egtsEnv.firmware->dataLength) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Успешно записан в ПЗУ");
env->firmwareOffset += env->egtsEnv.firmware->dataLength;
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка записи в ПЗУ");
isFirmwareResult = EGTS_FIRMWARE_ERROR_WRITE_PZU;
}
osMutexRelease(EXT_ENV_TELE.store.accessDumper);
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка доступа receivedUpdateFirmware");
isFirmwareResult = EGTS_FIRMWARE_ERROR_ACCESS;
}
if (env->egtsEnv.firmware->PartNumber == env->egtsEnv.firmware->ExpectedPartsQuantity) {
uint16_t crcEgts16 = CRC16EGTS((uint8_t *) (FIRMWARE_LOADER.update.address), env->firmwareOffset);
if (crcEgts16 != env->firmwareBufCrc) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка контрольной суммы (ЕГТС)");
isFirmwareResult = EGTS_FIRMWARE_ERROR_EGTS_CRC;
}
uint32_t pos = env->firmwareOffset - 256;
uint32_t offsetMetaCrc = *(uint32_t *) &((uint8_t *) (FIRMWARE_LOADER.update.address))[pos];
pos += 4;
uint32_t offsetMetaSize = *(uint32_t *) &((uint8_t *) (FIRMWARE_LOADER.update.address))[pos];
pos += 4;
tString32 FW_NAME;
FW_NAME.length = *(uint8_t *) &((uint8_t *) (FIRMWARE_LOADER.update.address))[pos];
pos += 1;
if (FW_NAME.length > 32) {
FW_NAME.length = 0;
} else {
memcpy(FW_NAME.data, &((uint8_t *) (FIRMWARE_LOADER.update.address))[pos], FW_NAME.length);
}
uint8_t posDel = findDelimiter(&FW_NAME, '_') + 1;
if (memcmp(&FW_NAME.data[posDel], "TELE", 4) == 0) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Получена прошивка телематики");
} else if (memcmp(&FW_NAME.data[0], "CERT", 4) == 0) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Получена прошивка ключей");
} else if (memcmp(&FW_NAME.data[posDel], "UVEOS", 5) == 0) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Получена прошивка УВЭОС");
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Получена неизвестная прошивка");
isFirmwareResult = EGTS_FIRMWARE_ERROR_UNKNOWN;
}
if (isFirmwareResult == EGTS_FIRMWARE_OK) {
uint32_t crc32 = 0;
for (uint32_t i = 0; i < offsetMetaSize; ++i) {
crc32 += ((uint8_t *) FIRMWARE_LOADER.update.address)[i];
}
if (crc32 != offsetMetaCrc) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка контрольной суммы (ПРОШИВКИ)");
isFirmwareResult = EGTS_FIRMWARE_ERROR_MY_CRC;
} else {
if (memcmp(&FW_NAME.data[posDel], "TELE", 4) == 0) {
EXT_ENV_TELE.store.AdditionalSettings->REGION_SIZE_UPDATE = env->firmwareOffset;
EraGlonassUveosDumper_ForceDump(EXT_ENV_TELE.store.uveosDumper);
LoggerInfoStatic(LOGGER, LOG_SIGN, "Загрузка прошивки телематики завершена");
LoggerInfoStatic(LOGGER, LOG_SIGN, "Необходимо перезагрузить устройство");
rst = EGTS_PC_OK;
env->rebootFirmware = true;
} else if (memcmp(&FW_NAME.data[posDel], "UVEOS", 5) == 0) {
EXT_ENV_TELE.store.AdditionalSettings->REGION_SIZE_UPDATE = env->firmwareOffset;
EraGlonassUveosDumper_ForceDump(EXT_ENV_TELE.store.uveosDumper);
LoggerInfoStatic(LOGGER, LOG_SIGN, "Загрузка прошивки УВЭОС завершена");
LoggerInfoStatic(LOGGER, LOG_SIGN, "Необходимо перезагрузить устройство");
rst = EGTS_PC_OK;
env->rebootFirmware = true;
} else if (memcmp(&FW_NAME.data[0], "CERT", 4) == 0) {
tIsFind check;
memset(&check, 0, sizeof(check));
tEgtsCertInfo *egtsCertInfo = (tEgtsCertInfo *) ((uint8_t *) (FIRMWARE_LOADER.update.address));
uint8_t *firmwareKeyBuf = &env->wb[0];
if (offsetMetaSize > (sizeof(env->wb))) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка выделения ОЗУ при загрузке ключей")
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка загрузки ключей");
isFirmwareResult = EGTS_FIRMWARE_ERROR_KEY;
} else {
memcpy(firmwareKeyBuf, (uint8_t *) (FIRMWARE_LOADER.update.address), offsetMetaSize);
// Если ключи зашифрованы
if (egtsCertInfo->ENC) {
struct AES_ctx ctx;
uint8_t key[16];
uint8_t iv[16];
memset(iv, '3', sizeof(key));
memset(key, '0', sizeof(key));
uint8_t offsetKey = 0;
uint32_t lenEnc = offsetMetaSize - sizeof(tEgtsCertInfo);
uint8_t IMEI_len = EXT_ENV_TELE.store.device->cgsmid.length;
if (EXT_ENV_TELE.store.device->cgsmid.length >= 2) {
if ((EXT_ENV_TELE.store.device->cgsmid.data[IMEI_len - 1] == '\n') &&
(EXT_ENV_TELE.store.device->cgsmid.data[IMEI_len - 2] == '\r')) {
IMEI_len = EXT_ENV_TELE.store.device->cgsmid.length - 2;
}
}
if (IMEI_len < 16)
offsetKey = 16 - IMEI_len;
memcpy(&key[offsetKey], EXT_ENV_TELE.store.device->cgsmid.data, IMEI_len);
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_decrypt_buffer(&ctx, &firmwareKeyBuf[sizeof(tEgtsCertInfo)],
lenEnc);
}
if (osMutexAcquire(env->gsm->gsmAt->access, 15000) == osOK) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Удаление старых ключей");
check = AtGsmSimComA7600_SSL_CHECK_CA(env->gsm->gsmAt,
file_ca, strlen(file_ca),
file_crt, strlen(file_crt),
file_key, strlen(file_key), 2000);
if ((!check.isFind1) && (!check.isFind2) && (!check.isFind3))
LoggerInfoStatic(LOGGER, LOG_SIGN, "Старые ключи удалены");
AtGsmSimComA7600_SSL_LOAD_CA(env->gsm->gsmAt,
file_ca, strlen(file_ca),
&firmwareKeyBuf[sizeof(tEgtsCertInfo)],
egtsCertInfo->SIZE_ROOT_CA,
2000);
AtGsmSimComA7600_SSL_LOAD_CA(env->gsm->gsmAt,
file_key, strlen(file_key),
&firmwareKeyBuf[sizeof(tEgtsCertInfo) +
egtsCertInfo->SIZE_ROOT_CA],
egtsCertInfo->SIZE_CLIENT_KEY, 2000);
AtGsmSimComA7600_SSL_LOAD_CA(env->gsm->gsmAt,
file_crt, strlen(file_crt),
&firmwareKeyBuf[sizeof(tEgtsCertInfo) +
egtsCertInfo->SIZE_ROOT_CA +
egtsCertInfo->SIZE_CLIENT_KEY],
egtsCertInfo->SIZE_CLIENT_CRT, 2000);
check = AtGsmSimComA7600_SSL_CHECK_CA(env->gsm->gsmAt,
file_ca, strlen(file_ca),
file_crt, strlen(file_crt),
file_key, strlen(file_key), 2000);
if ((check.isFind1) && (check.isFind2) && (check.isFind3)) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Новые ключи загружены");
LoggerInfoStatic(LOGGER, LOG_SIGN, "Необходимо перезагрузить устройство");
rst = EGTS_PC_OK;
env->rebootFirmware = true;
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка загрузки ключей");
isFirmwareResult = EGTS_FIRMWARE_ERROR_KEY;
}
osMutexRelease(env->gsm->gsmAt->access);
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка доступа при загрузке ключей");
isFirmwareResult = EGTS_FIRMWARE_ERROR_ACCESS;
}
}
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Получена неизвестная прошивка");
isFirmwareResult = EGTS_FIRMWARE_ERROR_UNKNOWN;
}
}
}
}
}
if ((isFirmwareResult != EGTS_FIRMWARE_OK)) {
if (isFirmwareResult == EGTS_FIRMWARE_ERROR_OVERFLOW_PZU) {
rst = EGTS_PC_MODULE_MEM_FLT;
}
if ((isFirmwareResult == EGTS_FIRMWARE_ERROR_ACCESS) || (isFirmwareResult == EGTS_FIRMWARE_ERROR_KEY)) {
rst = EGTS_PC_MODULE_PROC_FLT;
}
if (isFirmwareResult == EGTS_FIRMWARE_ERROR_WRITE_PZU) {
rst = EGTS_PC_MODULE_IO_FLT;
}
if (isFirmwareResult == EGTS_FIRMWARE_ERROR_UNKNOWN) {
rst = EGTS_PC_MODULE_FW_FLT;
}
if ((isFirmwareResult == EGTS_FIRMWARE_ERROR_EGTS_CRC) || (isFirmwareResult == EGTS_FIRMWARE_ERROR_MY_CRC)) {
rst = EGTS_PC_DATACRC_ERROR;
}
}
EgtsProcessing_SendResponse(env, EGTS_FIRMWARE_SERVICE,
EGTS_FIRMWARE_SERVICE,
EGTS_SERVICE_FLAGS_FIRMWARE,
rst,
env->egtsEnv.recordNumber);
if (env->rebootFirmware) {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Автоматическая перезагрузка, через 5 сек");
SystemDelayMs(5000);
NVIC_SystemReset();
}
}