FirmwareLoader_ARTERY_AT32/Src/FirmwareLoader.c

153 lines
5.3 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 zemon on 28.05.2022.
//
#include <InternalFlashPage.h>
#include <memory.h>
#include "FirmwareLoader.h"
#include "stdint.h"
#include "BootJump.h"
void FirmwareLoader_MapMetadata(tFirmwareBlock *block) {
block->metadata.crc = (uint32_t *) (block->metadataMem + 0);
block->metadata.size = (uint32_t *) (block->metadataMem + 4);
block->metadata.nameLength = (uint8_t *) (block->metadataMem + 8);
block->metadata.name = (uint8_t *) (block->metadataMem + 9);
}
void FirmwareLoader_Init(tFirmwareLoader *env, uint32_t fwSize, uint32_t mainFwAddr, uint32_t updateFwAddr) {
env->fwSize = fwSize;
env->main.address = mainFwAddr;
env->update.address = updateFwAddr;
env->metadataOffset = fwSize - FIRMWARE_META_LENGTH;
FirmwareLoader_MapMetadata(&env->main);
FirmwareLoader_MapMetadata(&env->update);
}
void FirmwareLoader_LoadMetadata(tFirmwareLoader *env, tFirmwareBlock *block) {
sInternalFlashPage_Read(block->address + env->metadataOffset, 0, block->metadataMem, FIRMWARE_META_LENGTH);
}
void FirmwareLoader_CopyUpdateToMain(tFirmwareLoader *env) {
bInternalFlashPage_CopyRange(
env->main.address,
env->update.address,
env->fwSize
);
}
uint32_t FirmwareLoader_crc32(uint8_t *data, uint32_t size) {
uint32_t crc = 0;
uint8_t *dataEnd = data + size;
while (data < dataEnd) {
crc += *data;
++data;
}
return crc;
}
bool FirmwareLoader_CheckBlock(tFirmwareLoader *env, tFirmwareBlock *block) {
FirmwareLoader_LoadMetadata(env, block);
if ((*block->metadata.size <= env->metadataOffset) && (*block->metadata.size > 0)) {
uint32_t calcCrc = FirmwareLoader_crc32((uint8_t *) block->address, *block->metadata.size);
if (calcCrc == *block->metadata.crc) {
return true;
}
}
return false;
}
bool FirmwareLoader_IsUpdateAndMainAreDifferent(tFirmwareLoader *env) {
//meta data must be loaded first with FirmwareLoader_LoadMetadata
//метаданные должны быть подгружены заранее с использованием FirmwareLoader_LoadMetadata
bool sameNames =
(*env->main.metadata.nameLength == *env->update.metadata.nameLength) &&
memcmp(env->main.metadata.name, env->update.metadata.name, *env->update.metadata.nameLength) == 0;
bool sameSrc = *env->main.metadata.crc == *env->update.metadata.crc;
return !sameSrc || !sameNames;
}
bool FirmwareLoader_CheckUpdate(tFirmwareLoader *env) {
return FirmwareLoader_CheckBlock(env, &env->update);
}
bool FirmwareLoader_IsLoadUpdate(tFirmwareLoader *env) {
//грузим метаданные и проверяем контрольные суммы для обоих блоков прошивки
bool mainFwOk = FirmwareLoader_CheckBlock(env, &env->main);
bool updateFwOk = FirmwareLoader_CheckBlock(env, &env->update);
//если у нас есть целая(не битая) прошивка в секции обновления
if (updateFwOk) {
//то смотрим нужно ли ее накатить
//а имеено, накатываем в том случае если текущая прошивка неисправна/отсутствует
//или если в секции обновления лежит другая (считаем что более новая) прошивка
if ((!mainFwOk) || (FirmwareLoader_IsUpdateAndMainAreDifferent(env))) {
return true;
}
}
return false;
}
bool FirmwareLoader_CheckAndUpdate(tFirmwareLoader *env) {
//если обновление есть (оно валидно) и глная прошивка битая или отличаеться от обновления
if(FirmwareLoader_IsLoadUpdate(env)){
//то гурзим обновление в основню область памяти
FirmwareLoader_CopyUpdateToMain(env);
}
//и финальная проверка, а что у нас теперь лежит в секции основной прошивки ( валидная ли прошивка там )
return FirmwareLoader_CheckBlock(env, &env->main);
}
//Загружаем основную прошивку
void FirmwareLoader_RunFirmware(tFirmwareLoader *env) {
BootJumpToAddress(env->main.address);
}
bool FirmwareLoader_ClearUpdateFlash(tFirmwareLoader *env) {
return bInternalFlashPage_ClearRange(env->update.address, env->fwSize);
}
bool FirmwareLoader_WriteUpdatePortion(tFirmwareLoader *env, uint32_t offset, uint8_t *data, uint16_t dataSize) {
return sInternalFlashPage_Write(env->update.address + offset, 0, data, dataSize) == dataSize;
}
static bool FirmwareLoader_DumpUpdateMetadata(tFirmwareLoader *env) {
// return true;
return FirmwareLoader_WriteUpdatePortion(env, env->metadataOffset, env->update.metadataMem, FIRMWARE_META_LENGTH);
}
bool FirmwareLoader_PrepareNewUpdate(
tFirmwareLoader *env, uint32_t size, uint32_t crc, uint8_t *name, uint8_t nameLen
) {
if (!FirmwareLoader_ClearUpdateFlash(env)) {
return false;
}
*env->update.metadata.crc = crc;
*env->update.metadata.size = size;
*env->update.metadata.nameLength = nameLen;
memcpy(env->update.metadata.name, name, nameLen);
return FirmwareLoader_DumpUpdateMetadata(env);
}