From 02c1934c03eb86901634ed63e0cc9b13eb743fa8 Mon Sep 17 00:00:00 2001 From: Carl Date: Wed, 13 Feb 2019 16:33:07 -0800 Subject: [PATCH] Added ability to lock and unlock boot rom for samd controllers --- src/target/samd.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/target/samd.c b/src/target/samd.c index bc143b4..e489d7e 100644 --- a/src/target/samd.c +++ b/src/target/samd.c @@ -44,6 +44,8 @@ static int samd_flash_write(struct target_flash *f, static bool samd_cmd_erase_all(target *t); static bool samd_cmd_lock_flash(target *t); static bool samd_cmd_unlock_flash(target *t); +static bool samd_cmd_unlock_bootprot(target *t); +static bool samd_cmd_lock_bootprot(target *t); static bool samd_cmd_read_userrow(target *t); static bool samd_cmd_serial(target *t); static bool samd_cmd_mbist(target *t); @@ -53,6 +55,8 @@ const struct command_s samd_cmd_list[] = { {"erase_mass", (cmd_handler)samd_cmd_erase_all, "Erase entire flash memory"}, {"lock_flash", (cmd_handler)samd_cmd_lock_flash, "Locks flash against spurious commands"}, {"unlock_flash", (cmd_handler)samd_cmd_unlock_flash, "Unlocks flash"}, + {"lock_bootprot", (cmd_handler)samd_cmd_lock_bootprot, "Lock the boot protections to maximum"}, + {"unlock_bootprot", (cmd_handler)samd_cmd_unlock_bootprot, "Unlock the boot protections to minimum"}, {"user_row", (cmd_handler)samd_cmd_read_userrow, "Prints user row from flash"}, {"serial", (cmd_handler)samd_cmd_serial, "Prints serial number"}, {"mbist", (cmd_handler)samd_cmd_mbist, "Runs the built-in memory test"}, @@ -599,6 +603,48 @@ static bool samd_cmd_unlock_flash(target *t) return samd_set_flashlock(t, 0xFFFF); } +static bool samd_set_bootprot(target *t, uint16_t value) +{ + uint32_t high = target_mem_read32(t, SAMD_NVM_USER_ROW_HIGH); + uint32_t low = target_mem_read32(t, SAMD_NVM_USER_ROW_LOW); + + /* Write address of a word in the row to erase it */ + /* Must be shifted right for 16-bit address, see Datasheet ยง20.8.8 Address */ + target_mem_write32(t, SAMD_NVMC_ADDRESS, SAMD_NVM_USER_ROW_LOW >> 1); + + /* Issue the erase command */ + target_mem_write32(t, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEAUXROW); + + /* Poll for NVM Ready */ + while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + if (target_check_error(t)) + return -1; + + /* Modify the low word of the user row */ + low = (low & 0xFFFFFFF8) | ((value << 0 ) & 0x00000007); + + /* Write back */ + target_mem_write32(t, SAMD_NVM_USER_ROW_LOW, low); + target_mem_write32(t, SAMD_NVM_USER_ROW_HIGH, high); + + /* Issue the page write command */ + target_mem_write32(t, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEAUXPAGE); + + return true; +} + +static bool samd_cmd_lock_bootprot(target *t) +{ + return samd_set_bootprot(t, 0); +} + +static bool samd_cmd_unlock_bootprot(target *t) +{ + return samd_set_bootprot(t, 7); +} + static bool samd_cmd_read_userrow(target *t) { tc_printf(t, "User Row: 0x%08x%08x\n",