Update EC config and FMAP to reserve room for vboot signatures

This just reserves room. It doesn't actually perform any verification yet.

BUG=chrome-os-partner:7459
TEST=manual

  make BOARD=link
  dump_fmap build/link/ec.bin

Change-Id: I424db1d601a614be3dfe5abb200e24e8bc62e47e
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
This commit is contained in:
Bill Richardson 2012-05-04 14:00:55 -07:00
parent d5deade06f
commit 3b361af2a7
5 changed files with 108 additions and 41 deletions

40
README.fmap Normal file
View File

@ -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.

View File

@ -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

View File

@ -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,
},
}

View File

@ -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;
}

View File

@ -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