cgpt: Support non-standard (smaller) entries table

The standard says that entries table must be at least 16384 bytes. On
some of our devices, the NOR section is only 8 KiB and used to store
both primary and secondary tables. On this device, we can only store 24
entries.

Therefore, this CL adds support for non-standard entry table. It adjusts
the MIN_NUMBER_OF_ENTRIES to 16, and replaces GPT_ENTRIES_SECTORS with
CalculateEntriesSectors.

BUG=chromium:441812
BRANCH=none
TEST=unittest

Change-Id: I6b85b35ce5612c7abb22142f8252bd0d45b676c5
Reviewed-on: https://chromium-review.googlesource.com/234996
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Commit-Queue: Nam Nguyen <namnguyen@chromium.org>
Tested-by: Nam Nguyen <namnguyen@chromium.org>
diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c
index e81f50e..759fa50 100644
--- a/tests/cgptlib_test.c
+++ b/tests/cgptlib_test.c
@@ -247,7 +247,7 @@
 		{512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
 		{512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER},
 		{512, GPT_PMBR_SECTORS + GPT_HEADER_SECTORS * 2 +
-		 GPT_ENTRIES_SECTORS * 2, GPT_SUCCESS},
+		 TOTAL_ENTRIES_SIZE / DEFAULT_SECTOR_SIZE * 2, GPT_SUCCESS},
 		{4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
 	};
 	int i;
@@ -537,6 +537,8 @@
 	BuildTestGptData(gpt);
 	h1->number_of_entries--;
 	h2->number_of_entries /= 2;
+	/* Because we halved h2 entries, its entries_lba is going to change. */
+	h2->entries_lba = h2->my_lba - CalculateEntriesSectors(h2);
 	RefreshCrc32(gpt);
 	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
 	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
@@ -1460,6 +1462,9 @@
 
 	BuildTestGptData(gpt);
 	secondary_header->number_of_entries = 100;
+	/* Because we change number of entries, we need to also update entrie_lba. */
+	secondary_header->entries_lba = secondary_header->my_lba -
+		CalculateEntriesSectors(secondary_header);
 	RefreshCrc32(gpt);
 	EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
 		gpt->gpt_drive_sectors, 0));
diff --git a/tests/run_cgpt_tests.sh b/tests/run_cgpt_tests.sh
index 6619a6b..7170eef 100755
--- a/tests/run_cgpt_tests.sh
+++ b/tests/run_cgpt_tests.sh
@@ -291,12 +291,17 @@
 
 # Enable write access again to test boundary in off device storage
 chmod 600 ${DEV}
+# Create a small 8K file to simulate Flash NOR section
+dd if=/dev/zero of=${DEV} bs=8K count=1
 # Drive size is not multiple of 512
 assert_fail $CGPT create -D 511 ${DEV}
 assert_fail $CGPT create -D 513 ${DEV}
 MTD="-D 1024"
 # Create a GPT table for a device of 1024 bytes (2 sectors)
 $CGPT create $MTD ${DEV}
+# Make sure number of entries is reasonable for 8KiB GPT
+X=$($CGPT show -D 1024 -d ${DEV} | grep -c "Number of entries: 24")
+[ "$X" = "2" ] || error
 # This fails because header verification is off due to different drive size
 assert_fail $CGPT show ${DEV}
 # But this passes because we pass in correct drive size
@@ -306,6 +311,7 @@
 # This fails because partition size is over the size of the device
 assert_fail $CGPT add $MTD -b 0 -s 3 -t data ${DEV}
 
+
 echo "Done."
 
 happy "All tests passed."
diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c
index 6f47ae3..41ac7ad 100644
--- a/tests/vboot_kernel_tests.c
+++ b/tests/vboot_kernel_tests.c
@@ -87,14 +87,14 @@
 	/* Set LBA pointers for primary or secondary header */
 	if (is_secondary) {
 		h->my_lba = MOCK_SECTOR_COUNT - GPT_HEADER_SECTORS;
-		h->entries_lba = h->my_lba - GPT_ENTRIES_SECTORS;
+		h->entries_lba = h->my_lba - CalculateEntriesSectors(h);
 	} else {
 		h->my_lba = GPT_PMBR_SECTORS;
 		h->entries_lba = h->my_lba + 1;
 	}
 
-	h->first_usable_lba = 2 + GPT_ENTRIES_SECTORS;
-	h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - GPT_ENTRIES_SECTORS;
+	h->first_usable_lba = 2 + CalculateEntriesSectors(h);
+	h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - CalculateEntriesSectors(h);
 
 	h->header_crc32 = HeaderCrc(h);
 }