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

Add support to bootloader self-update #212

Merged
merged 1 commit into from
Mar 12, 2024
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
97 changes: 31 additions & 66 deletions port/ucontroller/nxp/lpc17xx/lpc17_hpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ static uint8_t get_sector_number(const void* flash_addr)
return ret;
}

uint8_t hpm_prepare_comp(enum memory_area area)
uint8_t hpm_prepare_comp( void )
{
finish_upload_success = false;
ipmc_image_size = 0;
Expand All @@ -94,20 +94,9 @@ uint8_t hpm_prepare_comp(enum memory_area area)
for (uint32_t i=0; i<(sizeof(ipmc_page)/sizeof(uint32_t)); i++) {
ipmc_page[i] = 0xFFFFFFFF;
}
const uint32_t *start, *end;

if (area == BOOT_FLASH) {
start = boot_start_addr;
end = boot_end_addr;
} else if (area == FW_UPDATE_FLASH) {
start = update_start_addr;
end = update_end_addr;
} else {
return IPMI_CC_PARAM_OUT_OF_RANGE;
}

/* Checks flash update region integrity */
for (const uint32_t *ptr = start; ptr <= end; ptr++) {
for (const uint32_t *ptr = update_start_addr; ptr <= update_end_addr; ptr++){
if (*ptr != 0xFFFFFFFF) {
const uint32_t sec = get_sector_number(ptr);

Expand All @@ -132,15 +121,15 @@ uint8_t hpm_prepare_comp(enum memory_area area)

uint8_t ipmc_hpm_prepare_comp(void)
{
return hpm_prepare_comp(FW_UPDATE_FLASH);
return hpm_prepare_comp();
}

uint8_t bootloader_hpm_prepare_comp(void)
{
return hpm_prepare_comp(BOOT_FLASH);
return hpm_prepare_comp();
}

uint8_t hpm_upload_block(uint8_t *block, uint16_t size, enum memory_area area)
uint8_t hpm_upload_block(uint8_t *block, uint16_t size)
{
const uint32_t ipmc_page_available_bytes_n = sizeof(ipmc_page) - ipmc_page_byte_index;

Expand All @@ -157,7 +146,7 @@ uint8_t hpm_upload_block(uint8_t *block, uint16_t size, enum memory_area area)
ipmc_page_byte_index = 0;

/* Program the complete page in the Flash */
program_page(ipmc_page_addr, ipmc_page, sizeof(ipmc_page), area);
program_page(ipmc_page_addr, ipmc_page, sizeof(ipmc_page));

/* Advance the address counter */
ipmc_page_addr += sizeof(ipmc_page);
Expand All @@ -177,20 +166,20 @@ uint8_t hpm_upload_block(uint8_t *block, uint16_t size, enum memory_area area)

uint8_t ipmc_hpm_upload_block(uint8_t *block, uint16_t size)
{
return hpm_upload_block(block, size, FW_UPDATE_FLASH);
return hpm_upload_block(block, size);
}

uint8_t bootloader_hpm_upload_block(uint8_t *block, uint16_t size)
{
return hpm_upload_block(block, size, BOOT_FLASH);
return hpm_upload_block(block, size);
}

uint8_t hpm_finish_upload(uint32_t image_size, enum memory_area area)
uint8_t hpm_finish_upload(uint32_t image_size)
{
/* Check if the last page was already programmed */
if(ipmc_page_byte_index != 0) {
/* Program the complete page in the Flash */
program_page( ipmc_page_addr, ipmc_page, sizeof(ipmc_page), area);
program_page(ipmc_page_addr, ipmc_page, sizeof(ipmc_page));
ipmc_image_size += ipmc_page_byte_index;
ipmc_page_byte_index = 0;
ipmc_page_addr = 0;
Expand All @@ -210,12 +199,12 @@ uint8_t hpm_finish_upload(uint32_t image_size, enum memory_area area)

uint8_t ipmc_hpm_finish_upload(uint32_t image_size)
{
return hpm_finish_upload(image_size, FW_UPDATE_FLASH);
return hpm_finish_upload(image_size);
}

uint8_t bootloader_hpm_finish_upload(uint32_t image_size)
{
return hpm_finish_upload(image_size, BOOT_FLASH);
return hpm_finish_upload(image_size);
}

uint8_t ipmc_hpm_get_upgrade_status(void)
Expand All @@ -230,7 +219,7 @@ uint8_t bootloader_hpm_get_upgrade_status(void)
return IPMI_CC_OK;
}

uint8_t ipmc_hpm_activate_firmware(void)
uint8_t hpm_activate_firmware( enum fw_type type )
{
/*
* Doesn't write the magic word if the function hpm_finish_upload fails
Expand All @@ -249,12 +238,12 @@ uint8_t ipmc_hpm_activate_firmware(void)
* TODO: Write actual firmware ID
*/
fw_update_header.magic = 0xAAAAAAAA;
fw_update_header.fw_type = 1; // Update application
fw_update_header.fw_type = type; // 2 -> bootloader | 1 -> application
fw_update_header.version[0] = 1;
fw_update_header.version[1] = 4;
fw_update_header.version[2] = 1;

program_page((uint32_t)fw_header - (uint32_t)update_start_addr, (uint32_t*)&fw_update_header, sizeof(fw_update_header), FW_UPDATE_FLASH);
program_page((uint32_t)fw_header - (uint32_t)update_start_addr, (uint32_t*)&fw_update_header, sizeof(fw_update_header));

/*
* Schedule a reset to 500ms from now
Expand All @@ -264,21 +253,17 @@ uint8_t ipmc_hpm_activate_firmware(void)
return IPMI_CC_OK;
}

uint8_t bootloader_hpm_activate_firmware(void)
uint8_t ipmc_hpm_activate_firmware(void)
{
/*
* Doesn't activate the firmware if the function hpm_finish_upload fails
*/

if (!finish_upload_success) {
return IPMI_CC_UNSPECIFIED_ERROR;
}
hpm_activate_firmware( APPLICATION );
}

sys_schedule_reset(500);
return IPMI_CC_OK;
uint8_t bootloader_hpm_activate_firmware(void)
{
hpm_activate_firmware( BOOTLOADER );
}

uint8_t program_page(uint32_t address, uint32_t *data, uint32_t size, enum memory_area area)
uint8_t program_page(uint32_t address, uint32_t *data, uint32_t size)
{
uint32_t update_start_sec, update_end_sec;

Expand All @@ -289,37 +274,17 @@ uint8_t program_page(uint32_t address, uint32_t *data, uint32_t size, enum memor
return IPMI_CC_PARAM_OUT_OF_RANGE;
}

if (area == BOOT_FLASH) {
update_start_sec = get_sector_number(boot_start_addr);
update_end_sec = get_sector_number(boot_end_addr);

if (Chip_IAP_PreSectorForReadWrite(update_start_sec, update_end_sec) != IAP_CMD_SUCCESS) {
portENABLE_INTERRUPTS();
return IPMI_CC_UNSPECIFIED_ERROR;
}

if (Chip_IAP_CopyRamToFlash((uint32_t)boot_start_addr + address, data, size)) {
portENABLE_INTERRUPTS();
return IPMI_CC_UNSPECIFIED_ERROR;
}

} else if (area == FW_UPDATE_FLASH) {
update_start_sec = get_sector_number(update_start_addr);
update_end_sec = get_sector_number(update_end_addr);

if (Chip_IAP_PreSectorForReadWrite(update_start_sec, update_end_sec) != IAP_CMD_SUCCESS) {
portENABLE_INTERRUPTS();
return IPMI_CC_UNSPECIFIED_ERROR;
}

if (Chip_IAP_CopyRamToFlash((uint32_t)update_start_addr + address, data, size)) {
portENABLE_INTERRUPTS();
return IPMI_CC_UNSPECIFIED_ERROR;
}
update_start_sec = get_sector_number(update_start_addr);
update_end_sec = get_sector_number(update_end_addr);

if (Chip_IAP_PreSectorForReadWrite(update_start_sec, update_end_sec) != IAP_CMD_SUCCESS) {
portENABLE_INTERRUPTS();
return IPMI_CC_UNSPECIFIED_ERROR;
}

} else {
return IPMI_CC_PARAM_OUT_OF_RANGE;
if (Chip_IAP_CopyRamToFlash((uint32_t)update_start_addr + address, data, size)) {
portENABLE_INTERRUPTS();
return IPMI_CC_UNSPECIFIED_ERROR;
}

portENABLE_INTERRUPTS();
Expand Down
8 changes: 4 additions & 4 deletions port/ucontroller/nxp/lpc17xx/lpc17_hpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,17 @@
#define IPMC_UPDATE_SECTOR_END 0x11
#define IPMC_UPDATE_ADDRESS_OFFSET (IPMC_UPDATE_SECTOR_START << 12)

enum memory_area {
BOOT_FLASH,
FW_UPDATE_FLASH
enum fw_type {
APPLICATION = 1,
BOOTLOADER = 2
};

uint8_t ipmc_hpm_prepare_comp(void);
uint8_t ipmc_hpm_upload_block(uint8_t *block, uint16_t size);
uint8_t ipmc_hpm_finish_upload(uint32_t image_size);
uint8_t ipmc_hpm_activate_firmware(void);
uint8_t ipmc_hpm_get_upgrade_status(void);
uint8_t program_page(uint32_t address, uint32_t *data, uint32_t size, enum memory_area area);
uint8_t program_page(uint32_t address, uint32_t *data, uint32_t size);
uint8_t ipmc_erase_sector(uint32_t sector_start, uint32_t sector_end);


Expand Down
Loading