Port MTD structures to use 64-bit byte offsets instead of sectors.

As per the discussion on issue 221745 we will be using 64-bit byte offsets
for the MTD partition table and converting to/from sectors internally in cgpt.
Existing interfaces do not change, eg sizes are still reported in sectors, only
the on-disk representation is affected.

BRANCH=none
BUG=chromium:221745
TEST=unit tests pass

Change-Id: Id312d42783acfdabe6eb8aea11dcbd298e00a100
Reviewed-on: https://gerrit.chromium.org/gerrit/60919
Commit-Queue: Albert Chaulk <achaulk@chromium.org>
Reviewed-by: Albert Chaulk <achaulk@chromium.org>
Tested-by: Albert Chaulk <achaulk@chromium.org>
diff --git a/cgpt/cgpt_add.c b/cgpt/cgpt_add.c
index 8332f22..e0e24b8 100644
--- a/cgpt/cgpt_add.c
+++ b/cgpt/cgpt_add.c
@@ -103,9 +103,14 @@
 
   entry = MtdGetEntry(&drive->mtd, PRIMARY, index);
   if (params->set_begin)
-    entry->starting_lba = params->begin;
-  if (params->set_size)
-    entry->ending_lba = entry->starting_lba + params->size - 1;
+    memcpy(&entry->starting_offset, &params->begin, sizeof(params->begin));
+  if (params->set_size) {
+    uint64_t start;
+    uint64_t end;
+    MtdGetPartitionSize(entry, &start, NULL, NULL);
+    end = start + params->size - 1;
+    memcpy(&entry->ending_offset, &end, sizeof(end));
+  }
   if (params->set_type)
     MtdSetEntryType(entry, LookupMtdTypeForGuid(&params->type_guid));
 
@@ -273,14 +278,10 @@
 
   if(drive.is_mtd) {
     MtdDiskPartition *entry = MtdGetEntry(&drive.mtd, PRIMARY, index);
-    uint64_t start_lba, end_lba;
     const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
     memcpy(&params->type_guid, guid, sizeof(params->type_guid));
     memset(&params->unique_guid, 0, sizeof(params->unique_guid));
-    start_lba = entry->starting_lba;
-    end_lba = entry->ending_lba;
-    params->begin = start_lba;
-    params->size = end_lba - start_lba + 1;
+    MtdGetPartitionSizeInSectors(entry, &params->begin, NULL, &params->size);
     params->raw_value = entry->flags;
   } else {
     // GPT-specific code
diff --git a/cgpt/cgpt_create.c b/cgpt/cgpt_create.c
index 0b116b2..e7cbadf 100644
--- a/cgpt/cgpt_create.c
+++ b/cgpt/cgpt_create.c
@@ -60,8 +60,8 @@
     // Prep basic parameters
     memcpy(h->signature, MTD_DRIVE_SIGNATURE, sizeof(h->signature));
     h->size = sizeof(*h);
-    h->first_lba = 0;
-    h->last_lba = drive->mtd.drive_sectors - 1;
+    h->first_offset = 0;
+    h->last_offset = (drive->mtd.drive_sectors * drive->mtd.sector_bytes) - 1;
     h->crc32 = MtdHeaderCrc(h);
   }
 
diff --git a/cgpt/cgpt_find.c b/cgpt/cgpt_find.c
index df6c4d3..fc223a0 100644
--- a/cgpt/cgpt_find.c
+++ b/cgpt/cgpt_find.c
@@ -150,13 +150,13 @@
 
 static int mtd_match_content(CgptFindParams *params, struct drive *drive,
                              MtdDiskPartition *entry) {
-  uint64_t part_size;
+  uint64_t start, part_size;
 
   if (!params->matchlen)
     return 1;
 
   // Ensure that the region we want to match against is inside the partition.
-  part_size = LBA_SIZE * (entry->ending_lba - entry->starting_lba + 1);
+  MtdGetPartitionSize(entry, &start, NULL, &part_size);
   if (params->matchoffset + params->matchlen > part_size) {
     return 0;
   }
@@ -164,7 +164,7 @@
   // Read the partition data.
   if (!FillBuffer(params,
                   drive->fd,
-                  (LBA_SIZE * entry->starting_lba) + params->matchoffset,
+                  start + params->matchoffset,
                   params->matchlen)) {
     Error("unable to read partition data\n");
     return 0;
diff --git a/cgpt/cgpt_show.c b/cgpt/cgpt_show.c
index c3c222e..78a285c 100644
--- a/cgpt/cgpt_show.c
+++ b/cgpt/cgpt_show.c
@@ -73,8 +73,10 @@
   printf("%sSize: %d\n", indent, header->size);
   printf("%sCRC: 0x%08x %s\n", indent, header->crc32,
          (MtdHeaderCrc(header) != header->crc32) ? "(INVALID)" : "");
-  printf("%sFirst LBA: %u\n", indent, header->first_lba);
-  printf("%sLast LBA: %u\n", indent, header->last_lba);
+  printf("%sFirst LBA: %llu\n", indent,
+    (unsigned long long)header->first_offset);
+  printf("%sLast LBA: %llu\n", indent,
+    (unsigned long long)header->last_offset);
 }
 
 static void HeaderDetails(GptHeader *header, GptEntry *entries,
@@ -110,20 +112,19 @@
 void MtdEntryDetails(MtdDiskPartition *entry, uint32_t index, int raw) {
   const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
   char buf[256];                   // scratch buffer for formatting output
+  uint64_t start, size;
   if (guid) {
     ResolveType(guid, buf);
   } else {
     snprintf(buf, sizeof(buf), "MTD partition type %d", MtdGetEntryType(entry));
   }
 
+  MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
+
   if (!raw) {
-    printf(PARTITION_FMT, (int)entry->starting_lba,
-           (int)(entry->ending_lba - entry->starting_lba + 1),
-           index+1, buf);
+    printf(PARTITION_FMT, (int)start, (int)size, index+1, buf);
   } else {
-    printf(PARTITION_FMT, (int)entry->starting_lba,
-           (int)(entry->ending_lba - entry->starting_lba + 1),
-           index+1, buf);
+    printf(PARTITION_FMT, (int)start, (int)size, index+1, buf);
   }
 }
 
@@ -257,14 +258,17 @@
     MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, index);
     char buf[256];                      // scratch buffer for string conversion
     const Guid *guid;
+    uint64_t start, size;
+
+    MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
 
     if (params->single_item) {
       switch(params->single_item) {
       case 'b':
-        printf("%u\n", entry->starting_lba);
+        printf("%u\n", (int)start);
         break;
       case 's':
-        printf("%u\n", entry->ending_lba - entry->starting_lba + 1);
+        printf("%u\n", (int)size);
         break;
       case 't':
         guid = LookupGuidForMtdType(MtdGetEntryType(entry));
@@ -295,6 +299,9 @@
     for (i = 0; i < GetNumberOfEntries(drive); ++i) {
       MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, i);
       const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
+      uint64_t start, size;
+
+      MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
 
       if (IsUnused(drive, ANY_VALID, i))
         continue;
@@ -305,9 +312,7 @@
         snprintf(type, sizeof(type), "MTD partition type %d",
                  MtdGetEntryType(entry));
       }
-      printf(PARTITION_FMT, (int)entry->starting_lba,
-             (int)(entry->ending_lba - entry->starting_lba + 1),
-             i+1, type);
+      printf(PARTITION_FMT, (int)start, (int)size, i+1, type);
     }
   } else {                              // show all partitions
     if (params->debug || params->verbose) {
diff --git a/firmware/lib/cgptlib/include/mtdlib.h b/firmware/lib/cgptlib/include/mtdlib.h
index 59fb8b3..0c87822 100644
--- a/firmware/lib/cgptlib/include/mtdlib.h
+++ b/firmware/lib/cgptlib/include/mtdlib.h
@@ -63,10 +63,9 @@
 
 
 typedef struct {
-  uint32_t starting_lba;
-  uint32_t ending_lba;
+  uint64_t starting_offset;
+  uint64_t ending_offset;
   uint32_t flags;
-  uint32_t reserved;
 } __attribute__((packed)) MtdDiskPartition;
 
 typedef struct {
@@ -77,15 +76,15 @@
    */
   uint32_t crc32;
   uint32_t size;
-  uint32_t first_lba;
-  uint32_t last_lba;
+  uint64_t first_offset;
+  uint64_t last_offset;
   MtdDiskPartition partitions[MTD_MAX_PARTITIONS];
 } __attribute__((packed)) MtdDiskLayout;
 
-#define MTD_DRIVE_V1_SIZE (24 + 16*16)
+#define MTD_DRIVE_V1_SIZE (32 + 16*20)
 
-#define MTDENTRY_EXPECTED_SIZE (16)
-#define MTDLAYOUT_EXPECTED_SIZE (24 + 16 * MTDENTRY_EXPECTED_SIZE)
+#define MTDENTRY_EXPECTED_SIZE (20)
+#define MTDLAYOUT_EXPECTED_SIZE (32 + 16 * MTDENTRY_EXPECTED_SIZE)
 
 
 typedef struct {
@@ -135,6 +134,12 @@
 void MtdSetEntryTries(MtdDiskPartition *e, int tries);
 void MtdSetEntryType(MtdDiskPartition *e, int type);
 
+void MtdGetPartitionSize(const MtdDiskPartition *e,
+                         uint64_t *start, uint64_t *end, uint64_t *size);
+
+void MtdGetPartitionSizeInSectors(const MtdDiskPartition *e, uint64_t *start,
+                                  uint64_t *end, uint64_t *size);
+
 void MtdModified(MtdData *mtd);
 int MtdGptInit(MtdData *mtd);
 int MtdIsPartitionValid(const MtdDiskPartition *part);
diff --git a/firmware/lib/cgptlib/mtdlib.c b/firmware/lib/cgptlib/mtdlib.c
index db9f4b5..18aa7c5 100644
--- a/firmware/lib/cgptlib/mtdlib.c
+++ b/firmware/lib/cgptlib/mtdlib.c
@@ -11,6 +11,8 @@
 #include "utility.h"
 #include "vboot_api.h"
 
+const int kSectorShift = 9; /* 512 bytes / sector. */
+
 int MtdInit(MtdData *mtd) {
   int ret;
 
@@ -85,8 +87,8 @@
   e->flags = (e->flags & ~mask) | ((v << offset) & mask);
 }
 void MtdSetEntrySuccessful(MtdDiskPartition *e, int successful) {
-  SetBitfield(e, MTD_ATTRIBUTE_SUCCESSFUL_OFFSET, MTD_ATTRIBUTE_SUCCESSFUL_MASK,
-              successful);
+  SetBitfield(e, MTD_ATTRIBUTE_SUCCESSFUL_OFFSET,
+              MTD_ATTRIBUTE_SUCCESSFUL_MASK, successful);
 }
 void MtdSetEntryPriority(MtdDiskPartition *e, int priority) {
   SetBitfield(e, MTD_ATTRIBUTE_PRIORITY_OFFSET, MTD_ATTRIBUTE_PRIORITY_MASK,
@@ -116,31 +118,36 @@
       if (i != j) {
         MtdDiskPartition *entry = entries + i;
         MtdDiskPartition *e2 = entries + j;
+        uint64_t start, end;
+        uint64_t other_start, other_end;
 
         if (!MtdIsPartitionValid(entry) || !MtdIsPartitionValid(e2))
           continue;
 
-        if((entry->starting_lba == 0 && entry->ending_lba == 0) ||
-           (e2->starting_lba == 0 && e2->ending_lba == 0)) {
+        MtdGetPartitionSize(entry, &start, &end, NULL);
+        MtdGetPartitionSize(e2, &other_start, &other_end, NULL);
+
+        if((start == 0 && end == 0) ||
+           (other_start == 0 && other_end == 0)) {
           continue;
         }
 
-        if (entry->ending_lba > h->last_lba) {
+        if (end > h->last_offset) {
           return GPT_ERROR_OUT_OF_REGION;
         }
-        if (entry->starting_lba < h->first_lba) {
+        if (start < h->first_offset) {
           return GPT_ERROR_OUT_OF_REGION;
         }
-        if (entry->starting_lba > entry->ending_lba) {
+        if (start > end) {
           return GPT_ERROR_OUT_OF_REGION;
         }
 
-        if ((entry->starting_lba >= e2->starting_lba) &&
-            (entry->starting_lba <= e2->ending_lba)) {
+        if ((start >= other_start) &&
+            (start <= other_end)) {
           return GPT_ERROR_START_LBA_OVERLAP;
         }
-        if ((entry->ending_lba >= e2->starting_lba) &&
-            (entry->ending_lba <= e2->ending_lba)) {
+        if ((end >= other_start) &&
+            (end <= other_end)) {
           return GPT_ERROR_END_LBA_OVERLAP;
         }
       }
@@ -162,8 +169,8 @@
     return GPT_ERROR_INVALID_HEADERS;
   }
 
-  if (disk->primary.first_lba > disk->primary.last_lba ||
-      disk->primary.last_lba > disk->drive_sectors) {
+  if (disk->primary.first_offset > disk->primary.last_offset ||
+      disk->primary.last_offset > disk->drive_sectors * disk->sector_bytes) {
     return GPT_ERROR_INVALID_SECTOR_NUMBER;
   }
 
@@ -196,6 +203,31 @@
   return crc32;
 }
 
+void MtdGetPartitionSize(const MtdDiskPartition *e,
+                         uint64_t *start, uint64_t *end, uint64_t *size) {
+  uint64_t start_tmp, end_tmp;
+  if (!start)
+    start = &start_tmp;
+  if (!end)
+    end = &end_tmp;
+
+  Memcpy(start, &e->starting_offset, sizeof(e->starting_offset));
+  Memcpy(end, &e->ending_offset, sizeof(e->ending_offset));
+  if (size) {
+    *size = *end - *start + 1;
+  }
+}
+
+void MtdGetPartitionSizeInSectors(const MtdDiskPartition *e, uint64_t *start,
+                                  uint64_t *end, uint64_t *size) {
+  MtdGetPartitionSize(e, start, end, size);
+  if (start)
+    *start >>= kSectorShift;
+  if (end)
+    *end >>= kSectorShift;
+  if (size)
+    *size >>= kSectorShift;
+}
 
 
 int MtdNextKernelEntry(MtdData *mtd, uint64_t *start_sector, uint64_t *size)
@@ -218,18 +250,17 @@
       e = entries + i;
       if (!MtdIsKernelEntry(e))
         continue;
-      VBDEBUG(("GptNextKernelEntry looking at same prio "
+      VBDEBUG(("MtdNextKernelEntry looking at same prio "
          "partition %d\n", i+1));
-      VBDEBUG(("GptNextKernelEntry s%d t%d p%d\n",
+      VBDEBUG(("MtdNextKernelEntry s%d t%d p%d\n",
          MtdGetEntrySuccessful(e), MtdGetEntryTries(e),
          MtdGetEntryPriority(e)));
       if (!(MtdGetEntrySuccessful(e) || MtdGetEntryTries(e)))
         continue;
       if (MtdGetEntryPriority(e) == mtd->current_priority) {
+        MtdGetPartitionSizeInSectors(e, start_sector, NULL, size);
         mtd->current_kernel = i;
-        *start_sector = e->starting_lba;
-        *size = e->ending_lba - e->starting_lba + 1;
-        VBDEBUG(("GptNextKernelEntry likes it\n"));
+        VBDEBUG(("MtdNextKernelEntry likes it\n"));
         return GPT_SUCCESS;
       }
     }
@@ -243,9 +274,9 @@
     int current_prio = MtdGetEntryPriority(e);
     if (!MtdIsKernelEntry(e))
       continue;
-    VBDEBUG(("GptNextKernelEntry looking at new prio "
+    VBDEBUG(("MtdNextKernelEntry looking at new prio "
        "partition %d\n", i+1));
-    VBDEBUG(("GptNextKernelEntry s%d t%d p%d\n",
+    VBDEBUG(("MtdNextKernelEntry s%d t%d p%d\n",
        MtdGetEntrySuccessful(e), MtdGetEntryTries(e),
        MtdGetEntryPriority(e)));
     if (!(MtdGetEntrySuccessful(e) || MtdGetEntryTries(e)))
@@ -269,14 +300,14 @@
   mtd->current_priority = new_prio;
 
   if (CGPT_KERNEL_ENTRY_NOT_FOUND == new_kernel) {
-    VBDEBUG(("GptNextKernelEntry no more kernels\n"));
+    VBDEBUG(("MtdNextKernelEntry no more kernels\n"));
     return GPT_ERROR_NO_VALID_KERNEL;
   }
 
-  VBDEBUG(("GptNextKernelEntry likes partition %d\n", new_kernel + 1));
+  VBDEBUG(("MtdNextKernelEntry likes partition %d\n", new_kernel + 1));
   e = entries + new_kernel;
-  *start_sector = e->starting_lba;
-  *size = e->ending_lba - e->starting_lba + 1;
+  MtdGetPartitionSizeInSectors(e, start_sector, NULL, size);
+
   return GPT_SUCCESS;
 }
 
diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c
index ba9cd05..1ee551d 100644
--- a/tests/cgptlib_test.c
+++ b/tests/cgptlib_test.c
@@ -225,8 +225,8 @@
 
 	Memcpy(mtd->primary.signature, MTD_DRIVE_SIGNATURE,
 		sizeof(mtd->primary.signature));
-	mtd->primary.first_lba = 32;
-	mtd->primary.last_lba = DEFAULT_DRIVE_SECTORS - 1;
+	mtd->primary.first_offset = 32 * DEFAULT_SECTOR_SIZE;
+	mtd->primary.last_offset = DEFAULT_DRIVE_SECTORS * DEFAULT_SECTOR_SIZE - 1;
 	mtd->primary.size = MTD_DRIVE_V1_SIZE;
 
 	/* These values are not used directly by the library, but they are checked */
@@ -236,20 +236,20 @@
 	mtd->fts_block_size = 1;
 
 	partitions = &mtd->primary.partitions[0];
-	partitions[0].starting_lba = 34;
-	partitions[0].ending_lba = 133;
+	partitions[0].starting_offset = 34 * DEFAULT_SECTOR_SIZE;
+	partitions[0].ending_offset = 134 * DEFAULT_SECTOR_SIZE - 1;
 	partitions[0].flags =
 		MTD_PARTITION_TYPE_CHROMEOS_KERNEL << MTD_ATTRIBUTE_TYPE_OFFSET;
-	partitions[1].starting_lba = 134;
-	partitions[1].ending_lba = 232;
+	partitions[1].starting_offset = 134 * DEFAULT_SECTOR_SIZE;
+	partitions[1].ending_offset = 233 * DEFAULT_SECTOR_SIZE - 1;
 	partitions[1].flags =
 		MTD_PARTITION_TYPE_CHROMEOS_ROOTFS << MTD_ATTRIBUTE_TYPE_OFFSET;
-	partitions[2].starting_lba = 234;
-	partitions[2].ending_lba = 331;
+	partitions[2].starting_offset = 234 * DEFAULT_SECTOR_SIZE;
+	partitions[2].ending_offset = 332 * DEFAULT_SECTOR_SIZE - 1;
 	partitions[2].flags =
 		MTD_PARTITION_TYPE_CHROMEOS_KERNEL << MTD_ATTRIBUTE_TYPE_OFFSET;
-	partitions[3].starting_lba = 334;
-	partitions[3].ending_lba = 430;
+	partitions[3].starting_offset = 334 * DEFAULT_SECTOR_SIZE;
+	partitions[3].ending_offset = 431 * DEFAULT_SECTOR_SIZE - 1;
 	partitions[3].flags =
 		MTD_PARTITION_TYPE_CHROMEOS_ROOTFS << MTD_ATTRIBUTE_TYPE_OFFSET;
 
@@ -809,8 +809,8 @@
 	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
 
 	BuildTestMtdData(mtd);
-	if (mh->first_lba > 0) {
-		me[0].starting_lba = mh->first_lba - 1;
+	if (mh->first_offset > 0) {
+		me[0].starting_offset = mh->first_offset - 1;
 		mh->crc32 = MtdHeaderCrc(mh);
 		EXPECT(GPT_ERROR_OUT_OF_REGION == MtdCheckEntries(me, mh));
 	}
@@ -822,7 +822,7 @@
 	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
 
 	BuildTestMtdData(mtd);
-	me[0].ending_lba = mh->last_lba + 1;
+	me[0].ending_offset = mh->last_offset + 1;
 	mh->crc32 = MtdHeaderCrc(mh);
 	EXPECT(GPT_ERROR_OUT_OF_REGION == MtdCheckEntries(me, mh));
 
@@ -833,7 +833,7 @@
 	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
 
 	BuildTestMtdData(mtd);
-	me[0].starting_lba = me[0].ending_lba + 1;
+	me[0].starting_offset = me[0].ending_offset + 1;
 	mh->crc32 = MtdHeaderCrc(mh);
 	EXPECT(GPT_ERROR_OUT_OF_REGION == MtdCheckEntries(me, mh));
 
@@ -846,7 +846,7 @@
 
 	BuildTestMtdData(mtd);
 	me[0].flags = 0;
-	me[0].starting_lba = me[0].ending_lba + 1;
+	me[0].starting_offset = me[0].ending_offset + 1;
 	mh->crc32 = MtdHeaderCrc(mh);
 	EXPECT(GPT_SUCCESS == MtdCheckEntries(me, mh));
 
@@ -928,8 +928,10 @@
 			SetGuid(&e[j].unique, j);
 			e[j].starting_lba = cases[i].entries[j].starting_lba;
 			e[j].ending_lba = cases[i].entries[j].ending_lba;
-			me[j].starting_lba = cases[i].entries[j].starting_lba;
-			me[j].ending_lba = cases[i].entries[j].ending_lba;
+			me[j].starting_offset = cases[i].entries[j].starting_lba *
+			    DEFAULT_SECTOR_SIZE;
+			me[j].ending_offset = cases[i].entries[j].ending_lba *
+			    DEFAULT_SECTOR_SIZE;
 
 		}
 		RefreshCrc32(gpt);