// // 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(); } }