diff options
-rw-r--r-- | board/fizz/board.h | 23 | ||||
-rw-r--r-- | chip/npcx/registers.h | 1 | ||||
-rw-r--r-- | chip/npcx/system.c | 66 | ||||
-rw-r--r-- | common/firmware_image.S | 7 | ||||
-rw-r--r-- | common/firmware_image.lds.S | 13 | ||||
-rw-r--r-- | include/rwsig.h | 21 |
6 files changed, 112 insertions, 19 deletions
diff --git a/board/fizz/board.h b/board/fizz/board.h index 49644f0137..991b906b08 100644 --- a/board/fizz/board.h +++ b/board/fizz/board.h @@ -139,6 +139,29 @@ #define CONFIG_VBOOT_HASH #define CONFIG_VSTORE #define CONFIG_VSTORE_SLOT_COUNT 1 + +/* + * Flash layout. Since config_flash_layout.h is included before board.h, + * we can only overwrite (=undef/define) these parameters here. + * + * Flash stores 3 images: RO, RW_A, RW_B. We divide the flash by 4. + * A public key is stored at the end of RO. Signatures are stored at the + * end of RW_A and RW_B, respectively. + */ +#define CONFIG_RW_B +#define CONFIG_RW_B_MEM_OFF CONFIG_RO_MEM_OFF +#undef CONFIG_RO_SIZE +#define CONFIG_RO_SIZE (CONFIG_FLASH_SIZE / 4) +#undef CONFIG_RW_SIZE +#define CONFIG_RW_SIZE CONFIG_RO_SIZE +#define CONFIG_RW_A_STORAGE_OFF CONFIG_RW_STORAGE_OFF +#define CONFIG_RW_B_STORAGE_OFF (CONFIG_RW_A_STORAGE_OFF + \ + CONFIG_RW_SIZE) +#define CONFIG_RW_A_SIGN_STORAGE_OFF (CONFIG_RW_A_STORAGE_OFF + \ + CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) +#define CONFIG_RW_B_SIGN_STORAGE_OFF (CONFIG_RW_B_STORAGE_OFF + \ + CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) + #define CONFIG_RWSIG #define CONFIG_RWSIG_TYPE_RWSIG #define CONFIG_RSA diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h index edcaf5587f..c201576d68 100644 --- a/chip/npcx/registers.h +++ b/chip/npcx/registers.h @@ -252,6 +252,7 @@ /* MDC register fields */ #define NPCX_FWCTRL_RO_REGION 0 +#define NPCX_FWCTRL_FW_SLOT 1 /******************************************************************************/ /* High Frequency Clock Generator (HFCG) registers */ diff --git a/chip/npcx/system.c b/chip/npcx/system.c index d863c7b30c..d3b6474459 100644 --- a/chip/npcx/system.c +++ b/chip/npcx/system.c @@ -948,14 +948,25 @@ void system_jump_to_booter(void) * Get memory offset and size for RO/RW regions. * Both of them need 16-bytes alignment since GDMA burst mode. */ - if (IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION)) { - flash_offset = CONFIG_EC_PROTECTED_STORAGE_OFF + - CONFIG_RO_STORAGE_OFF; - flash_used = CONFIG_RO_SIZE; - } else { + switch (system_get_shrspi_image_copy()) { + case SYSTEM_IMAGE_RW: flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF; flash_used = CONFIG_RW_SIZE; + break; +#ifdef CONFIG_RW_B + case SYSTEM_IMAGE_RW_B: + flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + + CONFIG_RW_B_STORAGE_OFF; + flash_used = CONFIG_RW_SIZE; + break; +#endif + case SYSTEM_IMAGE_RO: + default: /* Jump to RO by default */ + flash_offset = CONFIG_EC_PROTECTED_STORAGE_OFF + + CONFIG_RO_STORAGE_OFF; + flash_used = CONFIG_RO_SIZE; + break; } /* Make sure the reset vector is inside the destination image */ @@ -998,21 +1009,54 @@ uint32_t system_get_lfw_address() return jump_addr; } +/* + * Set and clear image copy flags in MDC register. + * + * NPCX_FWCTRL_RO_REGION: 1 - RO, 0 - RW + * NPCX_FWCTRL_FW_SLOT: 1 - SLOT_A, 0 - SLOT_B + */ void system_set_image_copy(enum system_image_copy_t copy) { - /* Jump to RW region -- clear flag */ - if (copy == SYSTEM_IMAGE_RW) + switch (copy) { + case SYSTEM_IMAGE_RW: + CLEAR_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); + SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT); + break; +#ifdef CONFIG_RW_B + case SYSTEM_IMAGE_RW_B: CLEAR_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); - else /* Jump to RO region -- set flag */ + CLEAR_BIT(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT); + break; +#endif + default: + CPRINTS("Invalid copy (%d) is requested as a jump destination. " + "Change it to %d.", copy, SYSTEM_IMAGE_RO); + /* Fall through to SYSTEM_IMAGE_RO */ + case SYSTEM_IMAGE_RO: SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); + SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT); + break; + } } enum system_image_copy_t system_get_shrspi_image_copy(void) { - /* RO region FW */ - if (IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION)) + if (IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION)) { + /* RO image */ +#ifdef CHIP_HAS_RO_B + if (!IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT)) + return SYSTEM_IMAGE_RO_B; +#endif return SYSTEM_IMAGE_RO; - else/* RW region FW */ + } else { +#ifdef CONFIG_RW_B + /* RW image */ + if (!IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT)) + /* Slot A */ + return SYSTEM_IMAGE_RW_B; +#endif return SYSTEM_IMAGE_RW; + } } + #endif diff --git a/common/firmware_image.S b/common/firmware_image.S index 79661c2866..a19968994f 100644 --- a/common/firmware_image.S +++ b/common/firmware_image.S @@ -57,6 +57,13 @@ #endif #ifdef CONFIG_RW_B +#ifdef CONFIG_RWSIG_TYPE_RWSIG +.section .image.RW_B, "ax" +.incbin FW_IMAGE(RW,) +.section .image.RW_B.sign, "a" +.incbin FW_IMAGE_SIGN(RW,) +#else .section .image.RW_B, "ax" .incbin FW_IMAGE(RW,_B) #endif +#endif diff --git a/common/firmware_image.lds.S b/common/firmware_image.lds.S index a956683aa6..8e82dcf1de 100644 --- a/common/firmware_image.lds.S +++ b/common/firmware_image.lds.S @@ -15,6 +15,9 @@ #define IMAGE_RW_AT (CONFIG_PROGRAM_MEMORY_BASE + \ CONFIG_EC_WRITABLE_STORAGE_OFF + \ CONFIG_RW_STORAGE_OFF) +#define IMAGE_RW_B_AT (CONFIG_PROGRAM_MEMORY_BASE + \ + CONFIG_EC_WRITABLE_STORAGE_OFF + \ + CONFIG_RW_B_STORAGE_OFF) #elif (CONFIG_RO_MEM_OFF == CONFIG_RW_MEM_OFF) #define IMAGE_RO_AT (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RO_MEM_OFF) @@ -23,10 +26,13 @@ mapped to the same location but we still have to generate an ec.bin with RO and RW images at different Flash offset */ #define IMAGE_RW_AT (CONFIG_PROGRAM_MEMORY_BASE + \ CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE) +#define IMAGE_RW_B_AT (CONFIG_PROGRAM_MEMORY_BASE + \ + CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE + CONFIG_RW_SIZE) #else #define IMAGE_RO_AT (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RO_MEM_OFF) #define IMAGE_RW_AT (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_MEM_OFF) +#define IMAGE_RW_B_AT (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_B_MEM_OFF) #endif OUTPUT_FORMAT(BFD_FORMAT, BFD_FORMAT, BFD_FORMAT) @@ -69,9 +75,14 @@ SECTIONS } > FLASH =0xff #endif #ifdef CONFIG_RW_B_MEM_OFF - .image.RW_B : AT(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_B_MEM_OFF) { + .image.RW_B : AT(IMAGE_RW_B_AT) { *(.image.RW_B) } > FLASH =0xff +#ifdef CONFIG_RWSIG_TYPE_RWSIG + .image.RW_B.sign : AT(CONFIG_RW_B_SIG_ADDR) { + *(.image.RW_B.sign) + } > FLASH =0xff +#endif #endif .padding : AT(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_SIZE - 1) { BYTE(0xff); diff --git a/include/rwsig.h b/include/rwsig.h index 765ac09ec5..0cb98c83f0 100644 --- a/include/rwsig.h +++ b/include/rwsig.h @@ -105,13 +105,20 @@ void rwsig_jump_now(void); #define CONFIG_RW_SIG_SIZE RSANUMBYTES #endif #endif /* ! CONFIG_RW_SIG_SIZE */ +/* The signature resides at the end of each RW copy */ +#define RW_SIG_OFFSET (CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) +#define RW_A_ADDR (CONFIG_PROGRAM_MEMORY_BASE + \ + CONFIG_EC_WRITABLE_STORAGE_OFF + \ + CONFIG_RW_STORAGE_OFF) +/* Assume the layout is same as RW_A and it sits right after RW_A */ +#define RW_B_ADDR (CONFIG_PROGRAM_MEMORY_BASE + \ + CONFIG_EC_WRITABLE_STORAGE_OFF + \ + CONFIG_RW_B_STORAGE_OFF) #ifndef CONFIG_RW_SIG_ADDR -/* The signature resides at the end of the RW image */ -#define CONFIG_RW_SIG_ADDR (CONFIG_PROGRAM_MEMORY_BASE \ - + CONFIG_EC_WRITABLE_STORAGE_OFF \ - + CONFIG_RW_STORAGE_OFF \ - + CONFIG_RW_SIZE \ - - CONFIG_RW_SIG_SIZE) -#endif /* !CONFIG_RW_SIG_ADDR */ +#define CONFIG_RW_SIG_ADDR (RW_A_ADDR + RW_SIG_OFFSET) +#endif +#ifndef CONFIG_RW_B_SIG_ADDR +#define CONFIG_RW_B_SIG_ADDR (RW_B_ADDR + RW_SIG_OFFSET) +#endif #endif /* __CROS_EC_RWSIG_H */ |