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;
void written_fw_block();
void written_fw_checksum();
void uc_reset();
void get_fw_type(void);
void boot_new_fw();
static uint16_t fw_len;
......@@ -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},
{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},
{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}
};
......@@ -154,12 +155,22 @@ void uc_reset()
NVIC_SystemReset();
}
void get_fw_type(void)
{
fw_type = FW_BOOTLOADER;
}
void boot_new_fw()
{
uint8_t *char_user_flash = (uint8_t *)&user_flash;
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 */
for (uint16_t i = 0; i < FLASH_ROW_SIZE; ++i)
fw_write_buf[i] = char_user_flash[i];
......
......@@ -26,6 +26,9 @@ typedef void(*fp_t)(void);
#define FW_BOOTLOADER 1
#define FW_MAIN 2
/* Defines of Magic numbers */
#define BOOT_NEW_FW_MAGIC 0xAD
// QUERY command returned data format
enum QUERY_RET_VALS {
QUERY_SUP = 0x80, // no need to define this for every command
......
......@@ -48,7 +48,7 @@ Bootloader
The bootloader, after bringing up the device, will check for the
special word :code:`0xBEC0ABCD` in the flash storage (see struct
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
:project: common
......@@ -600,11 +600,12 @@ BOOT_NEW_FW
| Transaction type: **Byte write / read**
| Data length: **1**
The BOOT_NEW_FW command passes execution to the bootloader. A special
code is written to the flash memory to direct the bootloader to switch
to PMBus mode. When already in
bootloader mode, this clears the special code and boots to the main
FW, instead.
The BOOT_NEW_FW command changes the execution mode of the Firmware.
When the byte 0xAD is written to this register the running firmware is switched
between bootloader and main mode.
When the proper byte is received, a special code is written to or removed form
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.
......
......@@ -77,7 +77,7 @@ extern uint32_t seconds_up;
uint32_t TMR_ERROR_CNT;
static uint8_t dummy_byte;
static uint8_t fw_type = FW_MAIN;
static uint8_t fw_type;
static uint8_t capablity;
void get_capablity(void);
......@@ -107,6 +107,7 @@ extern uint16_t fan_cmdrpm[3] __xMR;
extern uint16_t fan_ppr[3] __xMR;
void uc_reset();
void get_fw_type(void);
void boot_new_fw();
enum {
......@@ -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},
{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},
{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},
{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},
......@@ -246,12 +247,22 @@ void uc_reset()
NVIC_SystemReset();
}
void get_fw_type(void)
{
fw_type = FW_MAIN;
}
void boot_new_fw()
{
uint32_t *char_user_flash = (uint32_t *)&user_flash;
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 */
for (uint8_t i = 0; i < FLASH_ROW_SIZE/4; ++i)
fw_write_buf[i] = char_user_flash[i];
......
......@@ -111,7 +111,7 @@ class monimod:
return self.FW_UNKNOWN
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):
pass
......
......@@ -135,7 +135,7 @@ void user_interaction()
break;
case 'R':
// 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)
check_res_print_error(res);
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