Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Ameba] ota fix blocking erase flash and cleanup #27513

Merged
merged 1 commit into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
256 changes: 36 additions & 220 deletions src/platform/Ameba/AmebaOTAImageProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@
#include <app/clusters/ota-requestor/OTADownloader.h>
#include <app/clusters/ota-requestor/OTARequestorInterface.h>
#include <lib/support/logging/CHIPLogging.h>

#include <platform/Ameba/AmebaOTAImageProcessor.h>
#include <platform/Ameba/AmebaUtils.h>

#if defined(CONFIG_PLATFORM_8710C)
static flash_t flash_ota;
#endif
using namespace chip::DeviceLayer::Internal;

namespace chip {

Expand Down Expand Up @@ -127,18 +125,8 @@ void AmebaOTAImageProcessor::HandlePrepareDownload(intptr_t context)

imageProcessor->mHeaderParser.Init();

// Get OTA update partition
#if defined(CONFIG_PLATFORM_8721D)
if (ota_get_cur_index() == OTA_INDEX_1)
imageProcessor->ota_target_index = OTA_INDEX_2;
else if (ota_get_cur_index() == OTA_INDEX_2)
imageProcessor->ota_target_index = OTA_INDEX_1;
ChipLogProgress(SoftwareUpdate, "OTA%d address space will be upgraded", imageProcessor->ota_target_index + 1);
#elif defined(CONFIG_PLATFORM_8710C)
imageProcessor->flash_addr = sys_update_ota_prepare_addr();
ChipLogProgress(SoftwareUpdate, "New Flash Address: 0x%X", imageProcessor->flash_addr);
#endif

// prepare OTA update partition
matter_ota_prepare_partition();
imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR);
}

Expand All @@ -151,15 +139,11 @@ void AmebaOTAImageProcessor::HandleFinalize(intptr_t context)
return;
}

// Verify checksum
#if defined(CONFIG_PLATFORM_8721D)
if (verify_ota_checksum(imageProcessor->pOtaTgtHdr) != 1)
if (AmebaUtils::MapError(matter_ota_flush_last(), AmebaErrorType::kFlashError) != CHIP_NO_ERROR)
{
ota_update_free(imageProcessor->pOtaTgtHdr);
ChipLogError(SoftwareUpdate, "OTA checksum verification failed");
ChipLogError(SoftwareUpdate, "Failed to finalize OTA");
return;
}
#endif

imageProcessor->ReleaseBlock();

Expand All @@ -175,24 +159,8 @@ void AmebaOTAImageProcessor::HandleAbort(intptr_t context)
return;
}

// Abort OTA procedure
#if defined(CONFIG_PLATFORM_8721D)
ChipLogProgress(SoftwareUpdate, "Erasing target partition...");
erase_ota_target_flash(imageProcessor->pOtaTgtHdr->FileImgHdr[0].FlashAddr, imageProcessor->pOtaTgtHdr->FileImgHdr[0].ImgLen);
ChipLogProgress(SoftwareUpdate, "Erased partition OTA%d", imageProcessor->ota_target_index + 1);
#elif defined(CONFIG_PLATFORM_8710C)
ChipLogProgress(SoftwareUpdate, "Erasing partition");
imageProcessor->NewFWBlkSize = ((0x1AC000 - 1) / 4096) + 1; // Use a fixed image length of 0x1AC000, change in the future
ChipLogProgress(SoftwareUpdate, "Erasing %d sectors", imageProcessor->NewFWBlkSize);
device_mutex_lock(RT_DEV_LOCK_FLASH);
for (int i = 0; i < imageProcessor->NewFWBlkSize; i++)
flash_erase_sector(&flash_ota, imageProcessor->flash_addr + i * 4096);
device_mutex_unlock(RT_DEV_LOCK_FLASH);
#endif

#if defined(CONFIG_PLATFORM_8721D)
ota_update_free(imageProcessor->pOtaTgtHdr);
#endif
// to make flash erase non-blocking, create background task to cleanup flash, will self-delete upon completion
matter_ota_create_abort_task();

imageProcessor->ReleaseBlock();
}
Expand All @@ -211,185 +179,47 @@ void AmebaOTAImageProcessor::HandleProcessBlock(intptr_t context)
return;
}

ByteSpan block = imageProcessor->mBlock;
CHIP_ERROR error = imageProcessor->ProcessHeader(block);
uint8_t HeaderOffset = 32 - imageProcessor->RemainHeader;
ByteSpan block = imageProcessor->mBlock;
CHIP_ERROR error = imageProcessor->ProcessHeader(block); // process matter ota header
uint8_t remainHeader =
matter_ota_get_total_header_size() - matter_ota_get_current_header_size(); // size of ameba header received
uint16_t writeLength = block.size(); // length of actual data to write to flash, excluding header
uint8_t * writePointer = (uint8_t *) block.data(); // pointer to the actual data to write to flash, excluding header

#if defined(CONFIG_PLATFORM_8721D)
if (imageProcessor->RemainHeader != 0) // Still not yet received full ameba header
// 1. Check if 32-bytes Ameba header has already been received
if (remainHeader > 0)
{
if (block.size() >= imageProcessor->RemainHeader)
if (block.size() >= remainHeader)
{
memcpy(imageProcessor->AmebaHeader + HeaderOffset, block.data(), imageProcessor->RemainHeader);
imageProcessor->pOtaTgtHdr = (update_ota_target_hdr *) ota_update_malloc(sizeof(update_ota_target_hdr));

memcpy(imageProcessor->pOtaTgtHdr, imageProcessor->AmebaHeader, 8); // Store FwVer, HdrNum
memcpy(&(imageProcessor->pOtaTgtHdr->FileImgHdr[0].ImgId), imageProcessor->AmebaHeader + 8, 4); // Store OTA id
memcpy(&(imageProcessor->pOtaTgtHdr->FileImgHdr[0].ImgHdrLen), imageProcessor->AmebaHeader + 12,
16); // Store ImgHdrLen, Checksum, ImgLen, Offset

if (imageProcessor->ota_target_index == OTA_INDEX_1)
imageProcessor->pOtaTgtHdr->FileImgHdr[0].FlashAddr = LS_IMG2_OTA1_ADDR;
else if (imageProcessor->ota_target_index == OTA_INDEX_2)
imageProcessor->pOtaTgtHdr->FileImgHdr[0].FlashAddr = LS_IMG2_OTA2_ADDR;

imageProcessor->pOtaTgtHdr->ValidImgCnt = 1;

if (strncmp("OTA", (const char *) &(imageProcessor->pOtaTgtHdr->FileImgHdr[0].ImgId), 3) != 0)
if (AmebaUtils::MapError(matter_ota_store_header((uint8_t *) block.data(), remainHeader),
AmebaErrorType::kFlashError) != CHIP_NO_ERROR)
{
ota_update_free(imageProcessor->pOtaTgtHdr);
ChipLogError(SoftwareUpdate, "Wrong Image ID for OTA");
ChipLogError(SoftwareUpdate, "Failed to store OTA header");
return;
}

ChipLogProgress(SoftwareUpdate, "Correct OTA Image ID, get firmware header success");
ChipLogProgress(SoftwareUpdate, "FwVer: 0x%X", imageProcessor->pOtaTgtHdr->FileHdr.FwVer);
ChipLogProgress(SoftwareUpdate, "HdrNum: 0x%X", imageProcessor->pOtaTgtHdr->FileHdr.HdrNum);
ChipLogProgress(SoftwareUpdate, "ImgHdrLen: 0x%X", imageProcessor->pOtaTgtHdr->FileImgHdr[0].ImgHdrLen);
ChipLogProgress(SoftwareUpdate, "Checksum: 0x%X", imageProcessor->pOtaTgtHdr->FileImgHdr[0].Checksum);
ChipLogProgress(SoftwareUpdate, "ImgLen: 0x%X", imageProcessor->pOtaTgtHdr->FileImgHdr[0].ImgLen);
ChipLogProgress(SoftwareUpdate, "Offset: 0x%X", imageProcessor->pOtaTgtHdr->FileImgHdr[0].Offset);
ChipLogProgress(SoftwareUpdate, "FlashAddr: 0x%X", imageProcessor->pOtaTgtHdr->FileImgHdr[0].FlashAddr);

// Erase update partition
ChipLogProgress(SoftwareUpdate, "Erasing target partition...");
erase_ota_target_flash(imageProcessor->pOtaTgtHdr->FileImgHdr[0].FlashAddr,
imageProcessor->pOtaTgtHdr->FileImgHdr[0].ImgLen);
ChipLogProgress(SoftwareUpdate, "Erased partition OTA%d", imageProcessor->ota_target_index + 1);

// Set RemainBytes to image length, excluding 8bytes of signature
imageProcessor->RemainBytes = imageProcessor->pOtaTgtHdr->FileImgHdr[0].ImgLen - 8;

// Set flash address, incremented by 8bytes to account for signature
imageProcessor->flash_addr = imageProcessor->pOtaTgtHdr->FileImgHdr[0].FlashAddr - SPI_FLASH_BASE + 8;

// Set signature to point to pOtaTgtHdr->Sign
imageProcessor->signature = &(imageProcessor->pOtaTgtHdr->Sign[0][0]);

// Store the signature temporarily
uint8_t * tempbufptr = const_cast<uint8_t *>(block.data() + imageProcessor->pOtaTgtHdr->FileImgHdr[0].Offset);
memcpy(imageProcessor->signature, tempbufptr, 8);
tempbufptr += 8;

// Write remaining downloaded bytes to flash_addr
uint32_t tempsize = block.size() - imageProcessor->pOtaTgtHdr->FileImgHdr[0].Offset - 8;
device_mutex_lock(RT_DEV_LOCK_FLASH);
if (ota_writestream_user(imageProcessor->flash_addr + imageProcessor->size, tempsize, tempbufptr) < 0)
{
ChipLogError(SoftwareUpdate, "Write to flash failed");
device_mutex_unlock(RT_DEV_LOCK_FLASH);
imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
return;
}
device_mutex_unlock(RT_DEV_LOCK_FLASH);

imageProcessor->RemainHeader = 0;
imageProcessor->size += tempsize;
imageProcessor->RemainBytes -= tempsize;
writeLength -= remainHeader;
writePointer += remainHeader;
}
else // block.size < imageProcessor->RemainHeader
{
memcpy(imageProcessor->AmebaHeader + HeaderOffset, block.data(), block.size());
imageProcessor->RemainHeader -= block.size();
}
}
else // received subsequent blocks
{
device_mutex_lock(RT_DEV_LOCK_FLASH);
if (ota_writestream_user(imageProcessor->flash_addr + imageProcessor->size, block.size(), block.data()) < 0)
{
ChipLogError(SoftwareUpdate, "Write to flash failed");
device_mutex_unlock(RT_DEV_LOCK_FLASH);
imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
return;
}
device_mutex_unlock(RT_DEV_LOCK_FLASH);

imageProcessor->size += block.size();
imageProcessor->RemainBytes -= block.size();
}
#elif defined(CONFIG_PLATFORM_8710C)
if (imageProcessor->RemainHeader != 0) // Still not yet received full ameba header
{
if (block.size() >= imageProcessor->RemainHeader)
else
{
// Store signature temporarily
memcpy(imageProcessor->signature + HeaderOffset, block.data(), imageProcessor->RemainHeader);

imageProcessor->block_len = block.size() - 32; // minus 32 to account for signature

// Erase target partition
ChipLogProgress(SoftwareUpdate, "Erasing partition");
imageProcessor->NewFWBlkSize =
((0x1AC000 - 1) / 4096) + 1; // Use a fixed image length of 0x1AC000, change in the future
ChipLogProgress(SoftwareUpdate, "Erasing %d sectors", imageProcessor->NewFWBlkSize);
device_mutex_lock(RT_DEV_LOCK_FLASH);
for (int i = 0; i < imageProcessor->NewFWBlkSize; i++)
flash_erase_sector(&flash_ota, imageProcessor->flash_addr + i * 4096);
device_mutex_unlock(RT_DEV_LOCK_FLASH);

// Write first block to target flash
if (imageProcessor->block_len > 0)
{
device_mutex_lock(RT_DEV_LOCK_FLASH);
if (flash_burst_write(&flash_ota, imageProcessor->flash_addr + 32, imageProcessor->block_len, block.data() + 32) <
0)
{
device_mutex_unlock(RT_DEV_LOCK_FLASH);
ChipLogError(SoftwareUpdate, "Write to flash failed");
imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
return;
}
else
{
imageProcessor->size += imageProcessor->block_len;
device_mutex_unlock(RT_DEV_LOCK_FLASH);
}
}
else
if (AmebaUtils::MapError(matter_ota_store_header((uint8_t *) block.data(), block.size()),
AmebaErrorType::kFlashError) != CHIP_NO_ERROR)
{
ChipLogError(SoftwareUpdate, "Invalid size");
imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
ChipLogError(SoftwareUpdate, "Failed to store OTA header");
return;
}

imageProcessor->RemainHeader = 0;
}
else // block.size() < imageProcessor->RemainHeader
{
memcpy(imageProcessor->AmebaHeader + HeaderOffset, block.data(), block.size());
imageProcessor->RemainHeader -= block.size();
writeLength = 0;
}
}
else // received subsequent blocks
{
imageProcessor->block_len = block.size();

if (imageProcessor->block_len > 0)
{
device_mutex_lock(RT_DEV_LOCK_FLASH);
if (flash_burst_write(&flash_ota, imageProcessor->flash_addr + 32 + imageProcessor->size, imageProcessor->block_len,
block.data()) < 0)
{
device_mutex_unlock(RT_DEV_LOCK_FLASH);
ChipLogError(SoftwareUpdate, "Write to flash failed");
imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
return;
}
else
{
imageProcessor->size += imageProcessor->block_len;
device_mutex_unlock(RT_DEV_LOCK_FLASH);
}
}
else
{
ChipLogError(SoftwareUpdate, "Invalid size");
imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
return;
}
// 2. Write data to flash, flash erasure logic will be handled by lower layer
if (AmebaUtils::MapError(matter_ota_flash_burst_write(writePointer, writeLength), AmebaErrorType::kFlashError) != CHIP_NO_ERROR)
{
ChipLogError(SoftwareUpdate, "OTA write failed");
return;
}
#endif

// 3. Fetch next data block
imageProcessor->mParams.downloadedBytes += block.size();
imageProcessor->mDownloader->FetchNextData();
}
Expand All @@ -405,26 +235,12 @@ void AmebaOTAImageProcessor::HandleApply(intptr_t context)
}

// Update signature
#if defined(CONFIG_PLATFORM_8721D)
if (change_ota_signature(imageProcessor->pOtaTgtHdr, imageProcessor->ota_target_index) != 1)
if (AmebaUtils::MapError(matter_ota_update_signature(), AmebaErrorType::kFlashError) != CHIP_NO_ERROR)
{
ota_update_free(imageProcessor->pOtaTgtHdr);
ChipLogError(SoftwareUpdate, "OTA update signature failed");
GetRequestorInstance()->CancelImageUpdate();
return;
}
#elif defined(CONFIG_PLATFORM_8710C)
if (update_ota_signature(imageProcessor->signature, imageProcessor->flash_addr) < 0)
{
ChipLogError(SoftwareUpdate, "OTA update signature failed");
GetRequestorInstance()->CancelImageUpdate();
return;
}
#endif

#if defined(CONFIG_PLATFORM_8721D)
ota_update_free(imageProcessor->pOtaTgtHdr);
#endif

ChipLogProgress(SoftwareUpdate, "Rebooting in 10 seconds...");

Expand All @@ -434,7 +250,7 @@ void AmebaOTAImageProcessor::HandleApply(intptr_t context)

void AmebaOTAImageProcessor::HandleRestart(chip::System::Layer * systemLayer, void * appState)
{
ota_platform_reset();
matter_ota_platform_reset();
}

CHIP_ERROR AmebaOTAImageProcessor::ProcessHeader(ByteSpan & block)
Expand Down
23 changes: 0 additions & 23 deletions src/platform/Ameba/AmebaOTAImageProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@
#include <platform/CHIPDeviceLayer.h>
#include <platform/OTAImageProcessor.h>

#if defined(CONFIG_PLATFORM_8710C)
#include "ota_8710c.h"
#include "sys.h"
#include "sys_api.h"
#elif defined(CONFIG_PLATFORM_8721D)
#include "rtl8721d_ota.h"
#endif

namespace chip {

class AmebaOTAImageProcessor : public OTAImageProcessorInterface
Expand Down Expand Up @@ -69,23 +61,8 @@ class AmebaOTAImageProcessor : public OTAImageProcessorInterface
*/
CHIP_ERROR ReleaseBlock();

#if defined(CONFIG_PLATFORM_8721D)
uint32_t ota_target_index = OTA_INDEX_2;
update_ota_target_hdr * pOtaTgtHdr;
uint32_t RemainBytes;
uint8_t * signature;
#elif defined(CONFIG_PLATFORM_8710C)
uint32_t ota_target_index;
uint32_t NewFWBlkSize = 0;
uint32_t block_len = 0;
uint8_t signature[32];
#endif
MutableByteSpan mBlock;
OTADownloader * mDownloader;
uint32_t size = 0;
uint8_t RemainHeader = 32;
uint8_t AmebaHeader[32] = { 0 };
uint32_t flash_addr;
OTAImageHeaderParser mHeaderParser;
uint32_t mSoftwareVersion;
};
Expand Down