Commit f5f3995e authored by Adam Wujek's avatar Adam Wujek

i2c: check write byte at firmware mode change

Compare the written byte against magic number. If not match refuse
to change a firmware mode.
Signed-off-by: 's avatarAdam Wujek <dev_public@wujek.eu>
parent 12db0990
...@@ -21,6 +21,7 @@ uint8_t query_r; ...@@ -21,6 +21,7 @@ uint8_t query_r;
void written_fw_block(); void written_fw_block();
void written_fw_checksum(); void written_fw_checksum();
void uc_reset(); void uc_reset();
void get_fw_type(void);
void boot_new_fw(); void boot_new_fw();
static uint16_t fw_len; static uint16_t fw_len;
...@@ -84,7 +85,7 @@ static cmd_t cmds_cmds[] = (cmd_t[]){ ...@@ -84,7 +85,7 @@ static cmd_t cmds_cmds[] = (cmd_t[]){
{0xD2, (int8_t *)&cmd_data_lengths[cmd_0xD2], (uint8_t *)fw_block, (fp_t)NULL, (fp_t)&written_fw_block, (fp_t)NULL, QUERY_WR | QUERY_RD, 1}, {0xD2, (int8_t *)&cmd_data_lengths[cmd_0xD2], (uint8_t *)fw_block, (fp_t)NULL, (fp_t)&written_fw_block, (fp_t)NULL, QUERY_WR | QUERY_RD, 1},
{0xD3, (int8_t *)&cmd_data_lengths[cmd_0xD3], (uint8_t *)&fw_checksum, (fp_t)NULL, (fp_t)&written_fw_checksum, (fp_t)NULL, QUERY_WR | QUERY_RD, 0}, {0xD3, (int8_t *)&cmd_data_lengths[cmd_0xD3], (uint8_t *)&fw_checksum, (fp_t)NULL, (fp_t)&written_fw_checksum, (fp_t)NULL, QUERY_WR | QUERY_RD, 0},
{0xD4, (int8_t *)&cmd_data_lengths[cmd_0xD4], (uint8_t *)&fw_local_checksum, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD, 0}, {0xD4, (int8_t *)&cmd_data_lengths[cmd_0xD4], (uint8_t *)&fw_local_checksum, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD, 0},
{0xD5, (int8_t *)&cmd_data_lengths[cmd_0xD5], (uint8_t *)&fw_type, (fp_t)NULL, (fp_t)&boot_new_fw, (fp_t)NULL, QUERY_WR | QUERY_RD, 0}, {0xD5, (int8_t *)&cmd_data_lengths[cmd_0xD5], (uint8_t *)&fw_type, &get_fw_type, (fp_t)&boot_new_fw, (fp_t)NULL, QUERY_WR | QUERY_RD, 0},
{0xD6, (int8_t *)&cmd_data_lengths[cmd_0xD6], (uint8_t *)&dummy_byte, (fp_t)NULL, (fp_t)&uc_reset, (fp_t)NULL, QUERY_WR, 0} {0xD6, (int8_t *)&cmd_data_lengths[cmd_0xD6], (uint8_t *)&dummy_byte, (fp_t)NULL, (fp_t)&uc_reset, (fp_t)NULL, QUERY_WR, 0}
}; };
...@@ -154,12 +155,22 @@ void uc_reset() ...@@ -154,12 +155,22 @@ void uc_reset()
NVIC_SystemReset(); NVIC_SystemReset();
} }
void get_fw_type(void)
{
fw_type = FW_BOOTLOADER;
}
void boot_new_fw() void boot_new_fw()
{ {
uint8_t *char_user_flash = (uint8_t *)&user_flash; uint8_t *char_user_flash = (uint8_t *)&user_flash;
user_flash_t *tmp_user_flash = (user_flash_t *)fw_write_buf; user_flash_t *tmp_user_flash = (user_flash_t *)fw_write_buf;
/* Check magic */
if (fw_type != BOOT_NEW_FW_MAGIC) {
/* Wrong magic, abort */
return;
}
/* backup existing user data */ /* backup existing user data */
for (uint16_t i = 0; i < FLASH_ROW_SIZE; ++i) for (uint16_t i = 0; i < FLASH_ROW_SIZE; ++i)
fw_write_buf[i] = char_user_flash[i]; fw_write_buf[i] = char_user_flash[i];
......
...@@ -26,6 +26,9 @@ typedef void(*fp_t)(void); ...@@ -26,6 +26,9 @@ typedef void(*fp_t)(void);
#define FW_BOOTLOADER 1 #define FW_BOOTLOADER 1
#define FW_MAIN 2 #define FW_MAIN 2
/* Defines of Magic numbers */
#define BOOT_NEW_FW_MAGIC 0xAD
// QUERY command returned data format // QUERY command returned data format
enum QUERY_RET_VALS { enum QUERY_RET_VALS {
QUERY_SUP = 0x80, // no need to define this for every command QUERY_SUP = 0x80, // no need to define this for every command
......
...@@ -48,7 +48,7 @@ Bootloader ...@@ -48,7 +48,7 @@ Bootloader
The bootloader, after bringing up the device, will check for the The bootloader, after bringing up the device, will check for the
special word :code:`0xBEC0ABCD` in the flash storage (see struct special word :code:`0xBEC0ABCD` in the flash storage (see struct
below) and, depending on the value, will either hand control to the below) and, depending on the value, will either hand control to the
main FW, or enter remote programming mode. main FW, or enter remote programming (bootloader) mode.
.. doxygenstruct:: user_flash_t .. doxygenstruct:: user_flash_t
:project: common :project: common
...@@ -600,11 +600,12 @@ BOOT_NEW_FW ...@@ -600,11 +600,12 @@ BOOT_NEW_FW
| Transaction type: **Byte write / read** | Transaction type: **Byte write / read**
| Data length: **1** | Data length: **1**
The BOOT_NEW_FW command passes execution to the bootloader. A special The BOOT_NEW_FW command changes the execution mode of the Firmware.
code is written to the flash memory to direct the bootloader to switch When the byte 0xAD is written to this register the running firmware is switched
to PMBus mode. When already in between bootloader and main mode.
bootloader mode, this clears the special code and boots to the main When the proper byte is received, a special code is written to or removed form
FW, instead. the flash memory to let the bootloader to stay in bootloader mode or proceed to
the main firmware. More information is available in the section Bootloader_.
The read gives the information which firmware is actually running. The read gives the information which firmware is actually running.
......
...@@ -77,7 +77,7 @@ extern uint32_t seconds_up; ...@@ -77,7 +77,7 @@ extern uint32_t seconds_up;
uint32_t TMR_ERROR_CNT; uint32_t TMR_ERROR_CNT;
static uint8_t dummy_byte; static uint8_t dummy_byte;
static uint8_t fw_type = FW_MAIN; static uint8_t fw_type;
static uint8_t capablity; static uint8_t capablity;
void get_capablity(void); void get_capablity(void);
...@@ -107,6 +107,7 @@ extern uint16_t fan_cmdrpm[3] __xMR; ...@@ -107,6 +107,7 @@ extern uint16_t fan_cmdrpm[3] __xMR;
extern uint16_t fan_ppr[3] __xMR; extern uint16_t fan_ppr[3] __xMR;
void uc_reset(); void uc_reset();
void get_fw_type(void);
void boot_new_fw(); void boot_new_fw();
enum { enum {
...@@ -219,7 +220,7 @@ static const cmd_t cmds_cmds[] = (cmd_t[]){ ...@@ -219,7 +220,7 @@ static const cmd_t cmds_cmds[] = (cmd_t[]){
{0x9D, (int8_t *)&cmd_data_lengths[cmd_0x9D], (uint8_t *)&MFR_DAT, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, {0x9D, (int8_t *)&cmd_data_lengths[cmd_0x9D], (uint8_t *)&MFR_DAT, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0},
{0x9E, (int8_t *)&cmd_data_lengths[cmd_0x9E], (uint8_t *)&MFR_SER, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, {0x9E, (int8_t *)&cmd_data_lengths[cmd_0x9E], (uint8_t *)&MFR_SER, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0},
{0xAE, (int8_t *)&cmd_data_lengths[cmd_0xAE], (uint8_t *)&IC_DEVICE_REV, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0}, {0xAE, (int8_t *)&cmd_data_lengths[cmd_0xAE], (uint8_t *)&IC_DEVICE_REV, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0},
{0xD5, (int8_t *)&cmd_data_lengths[cmd_0xD5], (uint8_t *)&fw_type, (fp_t)NULL, &boot_new_fw, (fp_t)NULL, QUERY_WR | QUERY_RD, 0}, {0xD5, (int8_t *)&cmd_data_lengths[cmd_0xD5], (uint8_t *)&fw_type, &get_fw_type, &boot_new_fw, (fp_t)NULL, QUERY_WR | QUERY_RD, 0},
{0xD6, (int8_t *)&cmd_data_lengths[cmd_0xD6], (uint8_t *)&dummy_byte, (fp_t)NULL, &uc_reset, (fp_t)NULL, QUERY_WR, 0}, {0xD6, (int8_t *)&cmd_data_lengths[cmd_0xD6], (uint8_t *)&dummy_byte, (fp_t)NULL, &uc_reset, (fp_t)NULL, QUERY_WR, 0},
{0xD7, (int8_t *)&cmd_data_lengths[cmd_0xD7], (uint8_t *)&seconds_up, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD, 0}, {0xD7, (int8_t *)&cmd_data_lengths[cmd_0xD7], (uint8_t *)&seconds_up, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD, 0},
{0xD8, (int8_t *)&cmd_data_lengths[cmd_0xD8], (uint8_t *)&TMR_ERROR_CNT, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_WR | QUERY_RD, 0}, {0xD8, (int8_t *)&cmd_data_lengths[cmd_0xD8], (uint8_t *)&TMR_ERROR_CNT, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_WR | QUERY_RD, 0},
...@@ -246,12 +247,22 @@ void uc_reset() ...@@ -246,12 +247,22 @@ void uc_reset()
NVIC_SystemReset(); NVIC_SystemReset();
} }
void get_fw_type(void)
{
fw_type = FW_MAIN;
}
void boot_new_fw() void boot_new_fw()
{ {
uint32_t *char_user_flash = (uint32_t *)&user_flash; uint32_t *char_user_flash = (uint32_t *)&user_flash;
user_flash_t *tmp_user_flash = (user_flash_t *)&fw_write_buf; user_flash_t *tmp_user_flash = (user_flash_t *)&fw_write_buf;
/* Check magic */
if (fw_type != BOOT_NEW_FW_MAGIC) {
/* Wrong magic, abort */
return;
}
/* backup existing user data */ /* backup existing user data */
for (uint8_t i = 0; i < FLASH_ROW_SIZE/4; ++i) for (uint8_t i = 0; i < FLASH_ROW_SIZE/4; ++i)
fw_write_buf[i] = char_user_flash[i]; fw_write_buf[i] = char_user_flash[i];
......
...@@ -111,7 +111,7 @@ class monimod: ...@@ -111,7 +111,7 @@ class monimod:
return self.FW_UNKNOWN return self.FW_UNKNOWN
def switch_fw_mode(self): def switch_fw_mode(self):
return self.pmbus_write_byte_cmd(self.cmd_ids["BOOT_NEW_FW"], 1) return self.pmbus_write_byte_cmd(self.cmd_ids["BOOT_NEW_FW"], 0xAD)
def set_page(self, page): def set_page(self, page):
pass pass
......
...@@ -135,7 +135,7 @@ void user_interaction() ...@@ -135,7 +135,7 @@ void user_interaction()
break; break;
case 'R': case 'R':
// write value doesn't matter, use whatever // write value doesn't matter, use whatever
res = i2c_m_sync_blk_cmd_write(&I2C_0, ADDR_BOOT_NEW_FW, &tmp_byte, 1); res = i2c_m_sync_blk_cmd_write(&I2C_0, ADDR_BOOT_NEW_FW, &tmp_byte, 0xAD);
if (!oneline) if (!oneline)
check_res_print_error(res); check_res_print_error(res);
if (!oneline) if (!oneline)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment