nand: vboot support for small GPTs

This patch makes some small modifications to cgpt and vboot to
root out the last vestigates of a fixed 128-entry GPT:
- Get rid of the TOTAL_ENTRIES_SIZE constant and all users.
- Reduce MAX_NUMBER_OF_ENTRIES to 128 (which is what the GPT
  spec specifies) so that this can be used for things like memory
  allocations without additional overhead.
- Base the amount of GPT read/written on the number of entries
  specified in the GPT header on disk/flash.

BUG=chromium:433433
TEST=make runalltests
TEST=Modified fmap to make an 8k RW_GPT, wrote a GPT with cgpt, then
rebooted and found that the GPT was correctly read after restarting
and the appropriate mtd partitions were present.
BRANCH=none

Change-Id: I45317377da20259caf04a7a4fa077a892b03c45f
Signed-off-by: Dan Ehrenberg <dehrenberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/238245
Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
Dan Ehrenberg
2015-01-02 14:39:38 -08:00
committed by ChromeOS Commit Bot
parent 5d652cdffa
commit f3f7fca07f
7 changed files with 29 additions and 19 deletions

View File

@@ -48,7 +48,7 @@ static int GptCreate(struct drive *drive, CgptCreateParams *params) {
/* Calculate number of entries */ /* Calculate number of entries */
h->size_of_entry = sizeof(GptEntry); h->size_of_entry = sizeof(GptEntry);
h->number_of_entries = TOTAL_ENTRIES_SIZE / h->size_of_entry; h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
if (drive->gpt.flags & GPT_FLAG_EXTERNAL) { if (drive->gpt.flags & GPT_FLAG_EXTERNAL) {
// We might have smaller space for the GPT table. Scale accordingly. // We might have smaller space for the GPT table. Scale accordingly.
// //

View File

@@ -34,12 +34,6 @@ enum {
#define GPT_MODIFIED_ENTRIES1 0x04 #define GPT_MODIFIED_ENTRIES1 0x04
#define GPT_MODIFIED_ENTRIES2 0x08 #define GPT_MODIFIED_ENTRIES2 0x08
/*
* Size of GptData.primary_entries and secondary_entries: 128 bytes/entry * 128
* entries.
*/
#define TOTAL_ENTRIES_SIZE 16384
/* /*
* The 'update_type' of GptUpdateKernelEntry(). We expose TRY and BAD only * The 'update_type' of GptUpdateKernelEntry(). We expose TRY and BAD only
* because those are what verified boot needs. For more precise control on GPT * because those are what verified boot needs. For more precise control on GPT

View File

@@ -40,11 +40,11 @@ int CheckParameters(GptData *gpt)
/* /*
* Sector count of a drive should be reasonable. If the given value is * Sector count of a drive should be reasonable. If the given value is
* too small to contain basic GPT structure (PMBR + Headers + Entries), * too small to contain basic GPT structure (PMBR + Headers + Entries),
* the value is wrong. Entries size is hard coded to TOTAL_ENTRIES_SIZE (see * the value is wrong.
* cgpt_create.c). This check is only applicable when GPT is stored on device.
*/ */
if (!(gpt->flags & GPT_FLAG_EXTERNAL) && if (gpt->gpt_drive_sectors <
gpt->gpt_drive_sectors < (1 + 2 * (1 + TOTAL_ENTRIES_SIZE / SECTOR_SIZE))) (1 + 2 * (1 + MIN_NUMBER_OF_ENTRIES /
(SECTOR_SIZE / sizeof(GptEntry)))))
return GPT_ERROR_INVALID_SECTOR_NUMBER; return GPT_ERROR_INVALID_SECTOR_NUMBER;
return GPT_SUCCESS; return GPT_SUCCESS;
@@ -103,7 +103,7 @@ int CheckHeader(GptHeader *h, int is_secondary,
if ((h->number_of_entries < MIN_NUMBER_OF_ENTRIES) || if ((h->number_of_entries < MIN_NUMBER_OF_ENTRIES) ||
(h->number_of_entries > MAX_NUMBER_OF_ENTRIES) || (h->number_of_entries > MAX_NUMBER_OF_ENTRIES) ||
(!(flags & GPT_FLAG_EXTERNAL) && (!(flags & GPT_FLAG_EXTERNAL) &&
h->number_of_entries * h->size_of_entry != TOTAL_ENTRIES_SIZE)) h->number_of_entries != MAX_NUMBER_OF_ENTRIES))
return 1; return 1;
/* /*

View File

@@ -52,7 +52,7 @@
#define MAX_SIZE_OF_ENTRY 512 #define MAX_SIZE_OF_ENTRY 512
#define SIZE_OF_ENTRY_MULTIPLE 8 #define SIZE_OF_ENTRY_MULTIPLE 8
#define MIN_NUMBER_OF_ENTRIES 16 #define MIN_NUMBER_OF_ENTRIES 16
#define MAX_NUMBER_OF_ENTRIES 512 #define MAX_NUMBER_OF_ENTRIES 128
/* Defines GPT sizes */ /* Defines GPT sizes */
#define GPT_PMBR_SECTORS 1 /* size (in sectors) of PMBR */ #define GPT_PMBR_SECTORS 1 /* size (in sectors) of PMBR */

View File

@@ -23,7 +23,7 @@
*/ */
int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
{ {
uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes; uint64_t max_entries_bytes = MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry);
int primary_valid = 0, secondary_valid = 0; int primary_valid = 0, secondary_valid = 0;
/* No data to be written yet */ /* No data to be written yet */
@@ -33,8 +33,8 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
gptdata->primary_header = (uint8_t *)VbExMalloc(gptdata->sector_bytes); gptdata->primary_header = (uint8_t *)VbExMalloc(gptdata->sector_bytes);
gptdata->secondary_header = gptdata->secondary_header =
(uint8_t *)VbExMalloc(gptdata->sector_bytes); (uint8_t *)VbExMalloc(gptdata->sector_bytes);
gptdata->primary_entries = (uint8_t *)VbExMalloc(TOTAL_ENTRIES_SIZE); gptdata->primary_entries = (uint8_t *)VbExMalloc(max_entries_bytes);
gptdata->secondary_entries = (uint8_t *)VbExMalloc(TOTAL_ENTRIES_SIZE); gptdata->secondary_entries = (uint8_t *)VbExMalloc(max_entries_bytes);
if (gptdata->primary_header == NULL || if (gptdata->primary_header == NULL ||
gptdata->secondary_header == NULL || gptdata->secondary_header == NULL ||
@@ -53,6 +53,10 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
gptdata->gpt_drive_sectors, gptdata->gpt_drive_sectors,
gptdata->flags)) { gptdata->flags)) {
primary_valid = 1; primary_valid = 1;
uint64_t entries_bytes = primary_header->number_of_entries
* primary_header->size_of_entry;
uint64_t entries_sectors = entries_bytes
/ gptdata->sector_bytes;
if (0 != VbExDiskRead(disk_handle, if (0 != VbExDiskRead(disk_handle,
primary_header->entries_lba, primary_header->entries_lba,
entries_sectors, entries_sectors,
@@ -74,6 +78,10 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
gptdata->gpt_drive_sectors, gptdata->gpt_drive_sectors,
gptdata->flags)) { gptdata->flags)) {
secondary_valid = 1; secondary_valid = 1;
uint64_t entries_bytes = secondary_header->number_of_entries
* secondary_header->size_of_entry;
uint64_t entries_sectors = entries_bytes
/ gptdata->sector_bytes;
if (0 != VbExDiskRead(disk_handle, if (0 != VbExDiskRead(disk_handle,
secondary_header->entries_lba, secondary_header->entries_lba,
entries_sectors, entries_sectors,
@@ -95,7 +103,10 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
{ {
int legacy = 0; int legacy = 0;
uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes; GptHeader *header = (GptHeader *)gptdata->primary_header;
uint64_t entries_bytes = header->number_of_entries
* header->size_of_entry;
uint64_t entries_sectors = entries_bytes / gptdata->sector_bytes;
int ret = 1; int ret = 1;
/* /*

View File

@@ -42,6 +42,7 @@
#define DEFAULT_SECTOR_SIZE 512 #define DEFAULT_SECTOR_SIZE 512
#define MAX_SECTOR_SIZE 4096 #define MAX_SECTOR_SIZE 4096
#define DEFAULT_DRIVE_SECTORS 467 #define DEFAULT_DRIVE_SECTORS 467
#define TOTAL_ENTRIES_SIZE (MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry)) /* 16384 */
#define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */ #define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}}; static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
@@ -245,7 +246,7 @@ static int ParameterTests(void)
{512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS}, {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
{520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE}, {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
{512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER}, {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
{512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER}, {512, 10, GPT_ERROR_INVALID_SECTOR_NUMBER},
{512, GPT_PMBR_SECTORS + GPT_HEADER_SECTORS * 2 + {512, GPT_PMBR_SECTORS + GPT_HEADER_SECTORS * 2 +
TOTAL_ENTRIES_SIZE / DEFAULT_SECTOR_SIZE * 2, GPT_SUCCESS}, TOTAL_ENTRIES_SIZE / DEFAULT_SECTOR_SIZE * 2, GPT_SUCCESS},
{4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE}, {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},

View File

@@ -83,7 +83,7 @@ static void SetupGptHeader(GptHeader *h, int is_secondary)
/* 16KB: 128 entries of 128 bytes */ /* 16KB: 128 entries of 128 bytes */
h->size_of_entry = sizeof(GptEntry); h->size_of_entry = sizeof(GptEntry);
h->number_of_entries = TOTAL_ENTRIES_SIZE / h->size_of_entry; h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
/* Set LBA pointers for primary or secondary header */ /* Set LBA pointers for primary or secondary header */
if (is_secondary) { if (is_secondary) {
@@ -429,6 +429,8 @@ static void ReadWriteGptTest(void)
Memset(g.primary_header, '\0', g.sector_bytes); Memset(g.primary_header, '\0', g.sector_bytes);
h = (GptHeader*)g.primary_header; h = (GptHeader*)g.primary_header;
h->entries_lba = 2; h->entries_lba = 2;
h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
h->size_of_entry = sizeof(GptEntry);
TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
"VbExDiskWrite(h, 2, 32)\n"); "VbExDiskWrite(h, 2, 32)\n");
@@ -441,6 +443,8 @@ static void ReadWriteGptTest(void)
Memset(g.primary_header, '\0', g.sector_bytes); Memset(g.primary_header, '\0', g.sector_bytes);
h = (GptHeader*)g.primary_header; h = (GptHeader*)g.primary_header;
h->entries_lba = 2; h->entries_lba = 2;
h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
h->size_of_entry = sizeof(GptEntry);
h = (GptHeader*)g.secondary_header; h = (GptHeader*)g.secondary_header;
h->entries_lba = 991; h->entries_lba = 991;
TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all"); TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");