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>
diff --git a/cgpt/cgpt_create.c b/cgpt/cgpt_create.c
index 60e23c9..c34cfe3 100644
--- a/cgpt/cgpt_create.c
+++ b/cgpt/cgpt_create.c
@@ -48,7 +48,7 @@
 
     /* Calculate number of entries */
     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) {
       // We might have smaller space for the GPT table. Scale accordingly.
       //
diff --git a/firmware/include/gpt_misc.h b/firmware/include/gpt_misc.h
index 0618069..f48133a 100644
--- a/firmware/include/gpt_misc.h
+++ b/firmware/include/gpt_misc.h
@@ -35,12 +35,6 @@
 #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
  * because those are what verified boot needs.  For more precise control on GPT
  * attribute bits, please refer to gpt_internal.h.
diff --git a/firmware/lib/cgptlib/cgptlib_internal.c b/firmware/lib/cgptlib/cgptlib_internal.c
index 6a89d84..a389e69 100644
--- a/firmware/lib/cgptlib/cgptlib_internal.c
+++ b/firmware/lib/cgptlib/cgptlib_internal.c
@@ -40,11 +40,11 @@
 	/*
 	 * Sector count of a drive should be reasonable. If the given value is
 	 * too small to contain basic GPT structure (PMBR + Headers + Entries),
-	 * the value is wrong. Entries size is hard coded to TOTAL_ENTRIES_SIZE (see
-	 * cgpt_create.c). This check is only applicable when GPT is stored on device.
+	 * the value is wrong.
 	 */
-	if (!(gpt->flags & GPT_FLAG_EXTERNAL) &&
-		gpt->gpt_drive_sectors < (1 + 2 * (1 + TOTAL_ENTRIES_SIZE / SECTOR_SIZE)))
+	if (gpt->gpt_drive_sectors <
+		(1 + 2 * (1 + MIN_NUMBER_OF_ENTRIES /
+				(SECTOR_SIZE / sizeof(GptEntry)))))
 		return GPT_ERROR_INVALID_SECTOR_NUMBER;
 
 	return GPT_SUCCESS;
@@ -103,7 +103,7 @@
 	if ((h->number_of_entries < MIN_NUMBER_OF_ENTRIES) ||
 	    (h->number_of_entries > MAX_NUMBER_OF_ENTRIES) ||
 	    (!(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;
 
 	/*
diff --git a/firmware/lib/cgptlib/include/cgptlib_internal.h b/firmware/lib/cgptlib/include/cgptlib_internal.h
index b4e2f5f..0be2bc5 100644
--- a/firmware/lib/cgptlib/include/cgptlib_internal.h
+++ b/firmware/lib/cgptlib/include/cgptlib_internal.h
@@ -52,7 +52,7 @@
 #define MAX_SIZE_OF_ENTRY 512
 #define SIZE_OF_ENTRY_MULTIPLE 8
 #define MIN_NUMBER_OF_ENTRIES 16
-#define MAX_NUMBER_OF_ENTRIES 512
+#define MAX_NUMBER_OF_ENTRIES 128
 
 /* Defines GPT sizes */
 #define GPT_PMBR_SECTORS 1  /* size (in sectors) of PMBR */
diff --git a/firmware/lib/gpt_misc.c b/firmware/lib/gpt_misc.c
index c16d472..00c7f9f 100644
--- a/firmware/lib/gpt_misc.c
+++ b/firmware/lib/gpt_misc.c
@@ -23,7 +23,7 @@
  */
 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;
 
 	/* No data to be written yet */
@@ -33,8 +33,8 @@
 	gptdata->primary_header = (uint8_t *)VbExMalloc(gptdata->sector_bytes);
 	gptdata->secondary_header =
 		(uint8_t *)VbExMalloc(gptdata->sector_bytes);
-	gptdata->primary_entries = (uint8_t *)VbExMalloc(TOTAL_ENTRIES_SIZE);
-	gptdata->secondary_entries = (uint8_t *)VbExMalloc(TOTAL_ENTRIES_SIZE);
+	gptdata->primary_entries = (uint8_t *)VbExMalloc(max_entries_bytes);
+	gptdata->secondary_entries = (uint8_t *)VbExMalloc(max_entries_bytes);
 
 	if (gptdata->primary_header == NULL ||
 	    gptdata->secondary_header == NULL ||
@@ -53,6 +53,10 @@
 			gptdata->gpt_drive_sectors,
 			gptdata->flags)) {
 		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,
 				      primary_header->entries_lba,
 				      entries_sectors,
@@ -74,6 +78,10 @@
 			gptdata->gpt_drive_sectors,
 			gptdata->flags)) {
 		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,
 				      secondary_header->entries_lba,
 				      entries_sectors,
@@ -95,7 +103,10 @@
 int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
 {
 	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;
 
 	/*
diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c
index 759fa50..13244a5 100644
--- a/tests/cgptlib_test.c
+++ b/tests/cgptlib_test.c
@@ -42,6 +42,7 @@
 #define DEFAULT_SECTOR_SIZE 512
 #define MAX_SECTOR_SIZE 4096
 #define DEFAULT_DRIVE_SECTORS 467
+#define TOTAL_ENTRIES_SIZE (MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry)) /* 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}}}};
@@ -245,7 +246,7 @@
 		{512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
 		{520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
 		{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 +
 		 TOTAL_ENTRIES_SIZE / DEFAULT_SECTOR_SIZE * 2, GPT_SUCCESS},
 		{4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c
index e19ac11..03e77f9 100644
--- a/tests/vboot_kernel_tests.c
+++ b/tests/vboot_kernel_tests.c
@@ -83,7 +83,7 @@
 
 	/* 16KB: 128 entries of 128 bytes */
 	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 */
 	if (is_secondary) {
@@ -429,6 +429,8 @@
 	Memset(g.primary_header, '\0', g.sector_bytes);
 	h = (GptHeader*)g.primary_header;
 	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_CALLS("VbExDiskWrite(h, 1, 1)\n"
 		   "VbExDiskWrite(h, 2, 32)\n");
@@ -441,6 +443,8 @@
 	Memset(g.primary_header, '\0', g.sector_bytes);
 	h = (GptHeader*)g.primary_header;
 	h->entries_lba = 2;
+	h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
+	h->size_of_entry = sizeof(GptEntry);
 	h = (GptHeader*)g.secondary_header;
 	h->entries_lba = 991;
 	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");