diff --git a/README.fmap b/README.fmap new file mode 100644 index 0000000000..416d27fe50 --- /dev/null +++ b/README.fmap @@ -0,0 +1,40 @@ +In the most general case, the flash layout looks something like this: + + +---------------------+ + | Reserved for EC use | + +---------------------+ + + +---------------------+ + | Vblock B | + +---------------------+ + | RW firmware B | + +---------------------+ + + +---------------------+ + | Vblock A | + +---------------------+ + | RW firmware A | + +---------------------+ + + +---------------------+ + | FMAP | + +---------------------+ + | Public root key | + +---------------------+ + | Read-only firmware | + +---------------------+ + + +BIOS firmware (and kernel) put the vblock info at the start of each image +where it's easy to find. The Blizzard EC expects the firmware vector table +to come first, so we have to put the vblock at the end. This means we have +to know where to look for it, but that's built into the FMAP and the RO +firmware anyway, so that's not an issue. + +The RO firmware doesn't need a vblock of course, but it does need some +reserved space for vboot-related things. + +Using SHA256/RSA4096, the vblock is 2468 bytes (0x9a4), while the public +root key is 1064 bytes (0x428) and the current FMAP is 644 bytes (0x284). If +we reserve 4K at the top of each FW image, that should give us plenty of +room for vboot-related stuff. diff --git a/chip/lm4/config.h b/chip/lm4/config.h index 88354a2ea2..d6c3f39639 100644 --- a/chip/lm4/config.h +++ b/chip/lm4/config.h @@ -22,14 +22,24 @@ #define CONFIG_FW_A_OFF CONFIG_FW_IMAGE_SIZE #define CONFIG_FW_B_OFF (2 * CONFIG_FW_IMAGE_SIZE) -/* FIXME(wfrichar): Replace with real GBB size & location. */ -#define CONFIG_FW_RO_GBB_SIZE CONFIG_FLASH_BANK_SIZE -#define CONFIG_FW_RO_GBB_OFF (CONFIG_FW_RO_OFF + CONFIG_FW_IMAGE_SIZE - \ - CONFIG_FW_RO_GBB_SIZE) -#define CONFIG_FW_RO_SIZE (CONFIG_FW_IMAGE_SIZE - CONFIG_FW_RO_GBB_SIZE) -#define CONFIG_FW_A_SIZE CONFIG_FW_IMAGE_SIZE -#define CONFIG_FW_B_SIZE CONFIG_FW_IMAGE_SIZE - +/* We'll put the vboot stuff at the top of each image, since the vector table + * has to go at the start. 4K should be enough for what we need. 2K isn't. */ +#define CONFIG_VBOOT_REGION_SIZE 0x1000 +#define CONFIG_VBOOT_ROOTKEY_SIZE 0x800 +#define CONFIG_VBOOT_REGION_OFF (CONFIG_FW_IMAGE_SIZE \ + - CONFIG_VBOOT_REGION_SIZE) +/* Specifics for each image */ +#define CONFIG_FW_RO_SIZE CONFIG_VBOOT_REGION_OFF +#define CONFIG_FW_A_SIZE CONFIG_VBOOT_REGION_OFF +#define CONFIG_FW_B_SIZE CONFIG_VBOOT_REGION_OFF +#define CONFIG_VBOOT_ROOTKEY_OFF (CONFIG_FW_RO_OFF \ + + CONFIG_VBOOT_REGION_OFF) +#define CONFIG_FMAP_OFF (CONFIG_VBOOT_ROOTKEY_OFF \ + + CONFIG_VBOOT_ROOTKEY_SIZE) +#define CONFIG_VBLOCK_A_OFF (CONFIG_FW_A_OFF + CONFIG_FW_A_SIZE) +#define CONFIG_VBLOCK_B_OFF (CONFIG_FW_B_OFF + CONFIG_FW_B_SIZE) +#define CONFIG_VBLOCK_A_SIZE CONFIG_VBOOT_REGION_SIZE +#define CONFIG_VBLOCK_B_SIZE CONFIG_VBOOT_REGION_SIZE /* Number of IRQ vectors on the NVIC */ #define CONFIG_IRQ_COUNT 132 diff --git a/common/fmap.c b/common/fmap.c index 5316917b6a..438a45d1c1 100644 --- a/common/fmap.c +++ b/common/fmap.c @@ -38,7 +38,6 @@ typedef struct _FmapAreaHeader { #define NUM_EC_FMAP_AREAS 14 - const struct _ec_fmap { FmapHeader header; FmapAreaHeader area[NUM_EC_FMAP_AREAS]; @@ -78,22 +77,22 @@ const struct _ec_fmap { /* Other RO stuff: FMAP, GBB, etc. */ { - /* FIXME(wfrichar): GBB != FMAP. Use the right terms */ - .area_name = "FMAP", - .area_offset = CONFIG_FW_RO_GBB_OFF, - .area_size = CONFIG_FW_RO_GBB_SIZE, + .area_name = "ROOT_KEY", + .area_offset = CONFIG_VBOOT_ROOTKEY_OFF, + .area_size = CONFIG_VBOOT_ROOTKEY_SIZE, .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, { - .area_name = "GBB", - .area_offset = CONFIG_FW_RO_GBB_OFF, - .area_size = 0, + /* FIXME(wfrichar): GBB != FMAP. Use the right terms */ + .area_name = "FMAP", + .area_offset = (uint32_t)&ec_fmap, + .area_size = sizeof(ec_fmap), .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, { /* A dummy region to identify it as EC firmware */ .area_name = "EC_IMAGE", - .area_offset = CONFIG_FW_RO_GBB_OFF, + .area_offset = CONFIG_FW_RO_OFF, .area_size = 0, /* Always zero */ .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, @@ -108,7 +107,7 @@ const struct _ec_fmap { { .area_name = "FW_MAIN_A", .area_offset = CONFIG_FW_A_OFF, - .area_size = CONFIG_FW_IMAGE_SIZE, + .area_size = CONFIG_FW_A_SIZE, .area_flags = FMAP_AREA_STATIC, }, { @@ -119,8 +118,8 @@ const struct _ec_fmap { }, { .area_name = "VBLOCK_A", - .area_offset = CONFIG_FW_A_OFF, - .area_size = 0, + .area_offset = CONFIG_VBLOCK_A_OFF, + .area_size = CONFIG_VBLOCK_A_SIZE, .area_flags = FMAP_AREA_STATIC, }, @@ -134,7 +133,7 @@ const struct _ec_fmap { { .area_name = "FW_MAIN_B", .area_offset = CONFIG_FW_B_OFF, - .area_size = CONFIG_FW_IMAGE_SIZE, + .area_size = CONFIG_FW_B_SIZE, .area_flags = FMAP_AREA_STATIC, }, { @@ -145,8 +144,8 @@ const struct _ec_fmap { }, { .area_name = "VBLOCK_B", - .area_offset = CONFIG_FW_A_OFF, - .area_size = 0, + .area_offset = CONFIG_VBLOCK_B_OFF, + .area_size = CONFIG_VBLOCK_B_SIZE, .area_flags = FMAP_AREA_STATIC, }, } diff --git a/common/vboot.c b/common/vboot.c index 0b0a9ef3dc..8f20054dcc 100644 --- a/common/vboot.c +++ b/common/vboot.c @@ -17,43 +17,46 @@ #define CPRINTF(format, args...) cprintf(CC_VBOOT, format, ## args) -/* Jumps to one of the RW images if necessary. */ -static void jump_to_other_image(void) +/* Might I want to jump to one of the RW images? */ +static int maybe_jump_to_other_image(void) { - /* Only jump to another image if we're currently in RO */ + /* Not all boards even have RW EC firmware. I think it's just Link at + * the moment. */ +#ifndef BOARD_link + /* TODO: (crosbug.com/p/8561) once daisy can warm-boot to another + * image, enable it here too. */ + CPUTS("[Vboot staying in RO because that's all there is]\n"); + return 0; +#endif + + /* We'll only jump to another image if we're currently in RO */ if (system_get_image_copy() != SYSTEM_IMAGE_RO) - return; + return 0; #ifdef CONFIG_TASK_KEYSCAN /* Don't jump if recovery requested */ if (keyboard_scan_recovery_pressed()) { - CPUTS("[Vboot staying in RO because key pressed]\n"); - return; + CPUTS("[Vboot staying in RO because recovery key pressed]\n"); + return 0; } #endif /* Don't jump if we're in RO becuase we jumped there (this keeps us * from jumping to RO only to jump right back). */ if (system_jumped_to_this_image()) - return; + return 0; #if !defined(BOARD_daisy) /* TODO: (crosbug.com/p/8572) Daisy doesn't define a GPIO * for the recovery signal from servo, so can't check it. */ if (gpio_get_level(GPIO_RECOVERYn) == 0) { CPUTS("[Vboot staying in RO due to recovery signal]\n"); - return; + return 0; } #endif - -#ifdef BOARD_link - /* TODO: (crosbug.com/p/8561) once daisy can warm-boot to another - * image, enable this there too. */ - /* TODO: real verified boot (including recovery reason); for now, just - * jump to image A. */ - system_run_image_copy(SYSTEM_IMAGE_RW_A, 0); -#endif + /* Okay, we might want to jump to a RW image. */ + return 1; } /*****************************************************************************/ @@ -68,9 +71,24 @@ int vboot_pre_init(void) int vboot_init(void) { + /* nothing to do, so do nothing */ + if (!maybe_jump_to_other_image()) + return EC_SUCCESS; + /* FIXME(wfrichar): placeholder for full verified boot implementation. * TBD exactly how, but we may want to continue in RO firmware, jump * directly to one of the RW firmwares, etc. */ - jump_to_other_image(); + CPRINTF("[ROOT_KEY is at 0x%x, size 0x%x]\n", + CONFIG_VBOOT_ROOTKEY_OFF, CONFIG_VBOOT_ROOTKEY_SIZE); + CPRINTF("[FW_MAIN_A is at 0x%x, size 0x%x]\n", + CONFIG_FW_A_OFF, CONFIG_FW_A_SIZE); + CPRINTF("[VBLOCK_A is at 0x%x, size 0x%x]\n", + CONFIG_VBLOCK_A_OFF, CONFIG_VBLOCK_A_SIZE); + CPRINTF("[FW_MAIN_B is at 0x%x, size 0x%x]\n", + CONFIG_FW_B_OFF, CONFIG_FW_B_SIZE); + CPRINTF("[VBLOCK_B is at 0x%x, size 0x%x]\n", + CONFIG_VBLOCK_B_OFF, CONFIG_VBLOCK_B_SIZE); + + system_run_image_copy(SYSTEM_IMAGE_RW_A, 0); return EC_SUCCESS; } diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S index eb72c4fc19..ba0b2733b5 100644 --- a/core/cortex-m/ec.lds.S +++ b/core/cortex-m/ec.lds.S @@ -79,7 +79,7 @@ SECTIONS __data_end = .; } > IRAM #if defined(SECTION_IS_RO) && defined(CONFIG_VBOOT) - .google CONFIG_FW_RO_GBB_OFF : AT(CONFIG_FW_RO_GBB_OFF) { + .google CONFIG_FMAP_OFF : AT(CONFIG_FMAP_OFF) { *(.google) } > FLASH #else