Provide MTD version of common functions

Provide an MTD implementation of several common functions in cgpt_common.c

BUG=chromium:221745
BRANCH=none
TEST=none

Original-Change-Id: Ib3248c283ca31e33a91b9ea0c14b2f72ea7c5850
Reviewed-on: https://gerrit.chromium.org/gerrit/47029
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Commit-Queue: Albert Chaulk <achaulk@chromium.org>
Tested-by: Albert Chaulk <achaulk@chromium.org>
(cherry picked from commit b0bd7e4cf8dd15cc3c371dac157093c7e7c7a874)

Change-Id: I243c2bf98a88d0019c332b274868459b5f1b8ea1
Reviewed-on: https://gerrit.chromium.org/gerrit/49791
Reviewed-by: Albert Chaulk <achaulk@chromium.org>
Tested-by: Albert Chaulk <achaulk@chromium.org>
Commit-Queue: Albert Chaulk <achaulk@chromium.org>
diff --git a/Makefile b/Makefile
index aa61523..1aad0ae 100644
--- a/Makefile
+++ b/Makefile
@@ -322,6 +322,7 @@
 	cgpt/cgpt_prioritize.c \
 	cgpt/cgpt_common.c \
 	cgpt/flash_ts_drv.c \
+	firmware/lib/cgptlib/mtdlib.c \
 	firmware/lib/flash_ts.c \
 	host/arch/${ARCH}/lib/crossystem_arch.c \
 	host/lib/crossystem.c \
@@ -355,6 +356,7 @@
 	cgpt/cgpt_prioritize.c \
 	cgpt/cgpt_common.c \
 	cgpt/flash_ts_drv.c \
+	firmware/lib/cgptlib/mtdlib.c \
 	firmware/lib/flash_ts.c \
 	utility/dump_kernel_config_lib.c \
 	firmware/lib/cgptlib/crc32.c \
diff --git a/cgpt/cgpt.h b/cgpt/cgpt.h
index 3c99179..3cd6e8d 100644
--- a/cgpt/cgpt.h
+++ b/cgpt/cgpt.h
@@ -143,6 +143,8 @@
 
 uint32_t GetNumberOfEntries(const struct drive *drive);
 GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index);
+MtdDiskPartition *MtdGetEntry(MtdData *mtd, int secondary, uint32_t index);
+
 void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
                  int priority);
 int GetPriority(struct drive *drive, int secondary, uint32_t entry_index);
@@ -165,6 +167,7 @@
 
 int IsUnused(struct drive *drive, int secondary, uint32_t index);
 int IsKernel(struct drive *drive, int secondary, uint32_t index);
+int LookupMtdTypeForGuid(const Guid *type);
 
 // For usage and error messages.
 extern const char* progname;
diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c
index 29a207a..3d2fe3b 100644
--- a/cgpt/cgpt_common.c
+++ b/cgpt/cgpt_common.c
@@ -697,20 +697,38 @@
 const Guid guid_efi =               GPT_ENT_TYPE_EFI;
 const Guid guid_unused =            GPT_ENT_TYPE_UNUSED;
 
-static struct {
+const static struct {
   const Guid *type;
   char *name;
   char *description;
+  int mtd_type;
 } supported_types[] = {
-  {&guid_chromeos_firmware, "firmware", "ChromeOS firmware"},
-  {&guid_chromeos_kernel, "kernel", "ChromeOS kernel"},
-  {&guid_chromeos_rootfs, "rootfs", "ChromeOS rootfs"},
-  {&guid_linux_data, "data", "Linux data"},
-  {&guid_chromeos_reserved, "reserved", "ChromeOS reserved"},
-  {&guid_efi, "efi", "EFI System Partition"},
-  {&guid_unused, "unused", "Unused (nonexistent) partition"},
+  {&guid_chromeos_firmware, "firmware", "ChromeOS firmware",
+    MTD_PARTITION_TYPE_CHROMEOS_FIRMWARE},
+  {&guid_chromeos_kernel, "kernel", "ChromeOS kernel",
+    MTD_PARTITION_TYPE_CHROMEOS_KERNEL},
+  {&guid_chromeos_rootfs, "rootfs", "ChromeOS rootfs",
+    MTD_PARTITION_TYPE_CHROMEOS_ROOTFS},
+  {&guid_linux_data, "data", "Linux data",
+    MTD_PARTITION_TYPE_LINUX_DATA},
+  {&guid_chromeos_reserved, "reserved", "ChromeOS reserved",
+    MTD_PARTITION_TYPE_CHROMEOS_RESERVED},
+  {&guid_efi, "efi", "EFI System Partition",
+    MTD_PARTITION_TYPE_EFI},
+  {&guid_unused, "unused", "Unused (nonexistent) partition",
+    MTD_PARTITION_TYPE_UNUSED},
 };
 
+int LookupMtdTypeForGuid(const Guid *type) {
+  int i;
+  for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
+    if (!memcmp(type, supported_types[i].type, sizeof(Guid))) {
+      return supported_types[i].mtd_type;
+    }
+  }
+  return MTD_PARTITION_TYPE_OTHER;
+}
+
 /* Resolves human-readable GPT type.
  * Returns CGPT_OK if found.
  * Returns CGPT_FAILED if no known type found. */
@@ -756,6 +774,9 @@
 }
 
 uint32_t GetNumberOfEntries(const struct drive *drive) {
+  if (drive->is_mtd)
+    return MTD_MAX_PARTITIONS;
+
   GptHeader *header = GetGptHeader(&drive->gpt);
   if (!header)
     return 0;
@@ -787,75 +808,130 @@
   return (GptEntry*)(&entries[stride * entry_index]);
 }
 
+MtdDiskPartition* MtdGetEntry(MtdData *mtd, int secondary, uint32_t index) {
+  if (index >= MTD_MAX_PARTITIONS)
+    return NULL;
+  return &mtd->primary.partitions[index];
+}
+
 void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
                  int priority) {
-  GptEntry *entry;
-  entry = GetEntry(&drive->gpt, secondary, entry_index);
   require(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
-  SetEntryPriority(entry, priority);
+  if (drive->is_mtd) {
+    MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index);
+    MtdSetEntryPriority(e, priority);
+  } else {
+    GptEntry *entry;
+    entry = GetEntry(&drive->gpt, secondary, entry_index);
+    SetEntryPriority(entry, priority);
+  }
 }
 
 int GetPriority(struct drive *drive, int secondary, uint32_t entry_index) {
-  GptEntry *entry;
-  entry = GetEntry(&drive->gpt, secondary, entry_index);
-  return GetEntryPriority(entry);
+  if (drive->is_mtd) {
+    MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index);
+    return MtdGetEntryPriority(e);
+  } else {
+    GptEntry *entry;
+    entry = GetEntry(&drive->gpt, secondary, entry_index);
+    return GetEntryPriority(entry);
+  }
 }
 
 void SetTries(struct drive *drive, int secondary, uint32_t entry_index,
               int tries) {
-  GptEntry *entry;
-  entry = GetEntry(&drive->gpt, secondary, entry_index);
   require(tries >= 0 && tries <= CGPT_ATTRIBUTE_MAX_TRIES);
-  SetEntryTries(entry, tries);
+  if (drive->is_mtd) {
+    MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index);
+    MtdSetEntryTries(e, tries);
+  } else {
+    GptEntry *entry;
+    entry = GetEntry(&drive->gpt, secondary, entry_index);
+    SetEntryTries(entry, tries);
+  }
 }
 
 int GetTries(struct drive *drive, int secondary, uint32_t entry_index) {
-  GptEntry *entry;
-  entry = GetEntry(&drive->gpt, secondary, entry_index);
-  return GetEntryTries(entry);
+  if (drive->is_mtd) {
+    MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index);
+    return MtdGetEntryTries(e);
+  } else {
+    GptEntry *entry;
+    entry = GetEntry(&drive->gpt, secondary, entry_index);
+    return GetEntryTries(entry);
+  }
 }
 
 void SetSuccessful(struct drive *drive, int secondary, uint32_t entry_index,
                    int success) {
-  GptEntry *entry;
-  entry = GetEntry(&drive->gpt, secondary, entry_index);
-
   require(success >= 0 && success <= CGPT_ATTRIBUTE_MAX_SUCCESSFUL);
-  SetEntrySuccessful(entry, success);
+  if (drive->is_mtd) {
+    MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index);
+    MtdSetEntrySuccessful(e, success);
+  } else {
+    GptEntry *entry;
+    entry = GetEntry(&drive->gpt, secondary, entry_index);
+    SetEntrySuccessful(entry, success);
+  }
 }
 
 int GetSuccessful(struct drive *drive, int secondary, uint32_t entry_index) {
-  GptEntry *entry;
-  entry = GetEntry(&drive->gpt, secondary, entry_index);
-  return GetEntrySuccessful(entry);
+  if (drive->is_mtd) {
+    MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index);
+    return MtdGetEntrySuccessful(e);
+  } else {
+    GptEntry *entry;
+    entry = GetEntry(&drive->gpt, secondary, entry_index);
+    return GetEntrySuccessful(entry);
+  }
 }
 
 void SetRaw(struct drive *drive, int secondary, uint32_t entry_index,
-           uint32_t raw) {
-  GptEntry *entry;
-  entry = GetEntry(&drive->gpt, secondary, entry_index);
-  entry->attrs.fields.gpt_att = (uint16_t)raw;
+            uint32_t raw) {
+  if (drive->is_mtd) {
+    MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, entry_index);
+    e->flags = raw;
+  } else {
+    GptEntry *entry;
+    entry = GetEntry(&drive->gpt, secondary, entry_index);
+    entry->attrs.fields.gpt_att = (uint16_t)raw;
+  }
 }
 
 void UpdateAllEntries(struct drive *drive) {
-  RepairEntries(&drive->gpt, MASK_PRIMARY);
-  RepairHeader(&drive->gpt, MASK_PRIMARY);
+  if (drive->is_mtd) {
+    drive->mtd.modified = 1;
+    drive->mtd.primary.crc32 = MtdHeaderCrc(&drive->mtd.primary);
+  } else {
+    RepairEntries(&drive->gpt, MASK_PRIMARY);
+    RepairHeader(&drive->gpt, MASK_PRIMARY);
 
-  drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
-                         GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
-  UpdateCrc(&drive->gpt);
+    drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
+                           GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
+    UpdateCrc(&drive->gpt);
+  }
 }
 
 int IsUnused(struct drive *drive, int secondary, uint32_t index) {
-  GptEntry *entry;
-  entry = GetEntry(&drive->gpt, secondary, index);
-  return GuidIsZero(&entry->type);
+  if (drive->is_mtd) {
+    MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, index);
+    return MtdGetEntryType(e) == MTD_PARTITION_TYPE_UNUSED;
+  } else {
+    GptEntry *entry;
+    entry = GetEntry(&drive->gpt, secondary, index);
+    return GuidIsZero(&entry->type);
+  }
 }
 
 int IsKernel(struct drive *drive, int secondary, uint32_t index) {
-  GptEntry *entry;
-  entry = GetEntry(&drive->gpt, secondary, index);
-  return GuidEqual(&entry->type, &guid_chromeos_kernel);
+  if (drive->is_mtd) {
+    MtdDiskPartition *e = MtdGetEntry(&drive->mtd, secondary, index);
+    return MtdGetEntryType(e) == MTD_PARTITION_TYPE_CHROMEOS_KERNEL;
+  } else {
+    GptEntry *entry;
+    entry = GetEntry(&drive->gpt, secondary, index);
+    return GuidEqual(&entry->type, &guid_chromeos_kernel);
+  }
 }
 
 
diff --git a/firmware/lib/cgptlib/include/mtdlib.h b/firmware/lib/cgptlib/include/mtdlib.h
index 135a530..59fb8b3 100644
--- a/firmware/lib/cgptlib/include/mtdlib.h
+++ b/firmware/lib/cgptlib/include/mtdlib.h
@@ -55,6 +55,7 @@
 #define MTD_PARTITION_TYPE_CHROMEOS_FLAGSTORE 5
 #define MTD_PARTITION_TYPE_LINUX_DATA         6
 #define MTD_PARTITION_TYPE_EFI                7
+#define MTD_PARTITION_TYPE_OTHER              8
 
 /* This is mostly arbitrary at the moment, but gives a little room to expand. */
 #define MTD_MAX_PARTITIONS 16