Enable attributes to display and set properly.

Review URL: http://codereview.chromium.org/2614002
diff --git a/utility/cgpt/cgpt.c b/utility/cgpt/cgpt.c
index 7cfc4c1..5bcba17 100644
--- a/utility/cgpt/cgpt.c
+++ b/utility/cgpt/cgpt.c
@@ -142,6 +142,7 @@
       utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
     }
   }
+  utf8[s8idx++] = 0;
 }
 
 /* Convert UTF8 string to UTF16. Rewritten from gpt utility.
@@ -209,10 +210,11 @@
   char *description;
 } supported_types[] = {
  {GPT_ENT_TYPE_UNUSED, "unused", "Unused partition"},
- {GPT_ENT_TYPE_EFI, "efi", "EFI partition"},
+ {GPT_ENT_TYPE_EFI, "efi", "EFI System Partition"},
  {GPT_ENT_TYPE_CHROMEOS_KERNEL, "croskern", "ChromeOS kernel"},
  {GPT_ENT_TYPE_CHROMEOS_ROOTFS, "crosroot", "ChromeOS rootfs"},
  {GPT_ENT_TYPE_CHROMEOS_RESERVED, "crosresv", "ChromeOS reserved"},
+ {GPT_ENT_TYPE_LINUX_DATA, "data", "Linux data"},
 };
 
 /* Resolves human-readable GPT type.
@@ -444,7 +446,6 @@
   int i;
 
   progname = argv[0];
-  printf("Copyright (c) 2010 The Chromium OS Authors. All rights reserved.\n");
   cmd = argv[optind++];
   for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
     if (cmd && !strcmp(cmds[i].name, cmd))
diff --git a/utility/cgpt/cgpt.h b/utility/cgpt/cgpt.h
index a675990..1782fe1 100644
--- a/utility/cgpt/cgpt.h
+++ b/utility/cgpt/cgpt.h
@@ -120,6 +120,7 @@
 int ResolveType(const Guid *type, char *buf);
 int SupportedType(const char *name, Guid *type);
 void PrintTypes(void);
+void EntryDetails(GptEntry *entry, int index, int raw);
 
 /* Describes the drive storing the GPT. */
 struct drive {
diff --git a/utility/cgpt/cgpt_add_modify_delete.c b/utility/cgpt/cgpt_add_modify_delete.c
index c5fbe94..c4ddc46 100644
--- a/utility/cgpt/cgpt_add_modify_delete.c
+++ b/utility/cgpt/cgpt_add_modify_delete.c
@@ -242,8 +242,7 @@
   }
 
   if (command == DELETE) {
-    Guid unused = GPT_ENT_TYPE_UNUSED;
-    Memcpy(&entry->type, &unused, sizeof(Guid));
+    Memcpy(&entry->type, &guid_unused, sizeof(Guid));
   }
 
   if (dirty) {
diff --git a/utility/cgpt/cgpt_attribute.c b/utility/cgpt/cgpt_attribute.c
index 70c8993..37477dc 100644
--- a/utility/cgpt/cgpt_attribute.c
+++ b/utility/cgpt/cgpt_attribute.c
@@ -12,19 +12,18 @@
 #include "cgpt_tofix.h"
 #include "utility.h"
 
-static struct number_range
-    range_1_0 = {1, 0},
-    range_15_0 = {15, 0};
+static struct number_range range_1_0 = {1, 0};
+static struct number_range range_15_0 = {15, 0};
+static struct number_range range_16_1 = {16, 1};
 
 /* Integers to store parsed argument. */
-static int help, partition, bad, successful, tries, priority;
+static int help, partition, successful, tries, priority;
 
 /* The structure for getopt_long(). When you add/delete any line, please refine
  * attribute_comments[] and third parameter of getopt_long() too.  */
 static struct option attribute_options[] = {
   {.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'},
   {.name = "partition", .has_arg = required_argument, .flag = 0, .val = 'i'},
-  {.name = "bad", .has_arg = required_argument, .flag = 0, .val = 'b'},
   {.name = "successful", .has_arg = required_argument, .flag = 0, .val = 's'},
   {.name = "tries", .has_arg = required_argument, .flag = 0, .val = 't'},
   {.name = "priority", .has_arg = required_argument, .flag = 0, .val = 'p'},
@@ -41,15 +40,10 @@
     .parsed = &help},
   /* partition */
   { .comment = "partition number "
-              "(defualt: first ChromeOS kernel)",
+              "(default: first ChromeOS kernel)",
     .validator = InNumberRange,
-    .valid_range = &range_15_0,
+    .valid_range = &range_16_1,
     .parsed = &partition},
-  /* bad */
-  { .comment = "mark partition bad",
-    .validator = InNumberRange,
-    .valid_range = &range_1_0,
-    .parsed = &bad},
   /* successful */
   { .comment = "mark partition successful",
     .validator = InNumberRange,
@@ -72,13 +66,13 @@
   printf("\nUsage: %s attribute [OPTIONS] device_name\n\n", progname);
   ShowOptions(attribute_options, attribute_options_details,
               ARRAY_COUNT(attribute_options));
-  printf("\n* Attribute command only applies on ChromeOS kernel entry.\n\n");
 }
 
 /* Parses all options (and validates them), then opens the drive and sets
  * corresponding bits in GPT entry. */
 int CgptAttribute(int argc, char *argv[]) {
   struct drive drive;
+  GptEntry *entry;
 
   /* I know this is NOT the perfect place to put code to make options[] and
    * details[] are synced. But this is the best place we have right now since C
@@ -86,7 +80,7 @@
   assert(ARRAY_COUNT(attribute_options) ==
          ARRAY_COUNT(attribute_options_details));
 
-  help = partition = bad = successful = tries = priority = NOT_INITED;
+  help = partition = successful = tries = priority = NOT_INITED;
 
   if (CGPT_OK != HandleOptions(argc, argv,
                      "hi:b:s:t:p:",
@@ -108,31 +102,34 @@
   if (partition == NOT_INITED) {
     int i;
     for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) {
-      static Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
-      GptEntry *entry;
       entry = GetEntry(&drive.gpt, PRIMARY, i);
-      if (!Memcmp(&chromeos_kernel, &entry->type, sizeof(Guid))) {
-        partition = i;
+      if (!Memcmp(&guid_chromeos_kernel, &entry->type, sizeof(Guid))) {
+        partition = i+1;
         break;
       }
     }
     if (partition == NOT_INITED) {
-      printf("[ERROR] No ChromeOS kernel is found. "
+      printf("[ERROR] No ChromeOS kernel partition found. "
              "Please use --partition to specify.\n");
       return CGPT_FAILED;
     } else {
       debug("No --partition is specified. "
-            "Found the first ChromeOS kernel at index [%d].\n",
+            "Found the first ChromeOS kernel in partition [%d].\n",
             partition);
     }
   }
+  int index = partition - 1;
 
   if (successful != NOT_INITED)
-    SetSuccessful(&drive.gpt, PRIMARY, partition, successful);
+    SetSuccessful(&drive.gpt, PRIMARY, index, successful);
   if (tries != NOT_INITED)
-    SetTries(&drive.gpt, PRIMARY, partition, tries);
+    SetTries(&drive.gpt, PRIMARY, index, tries);
   if (priority != NOT_INITED)
-    SetPriority(&drive.gpt, PRIMARY, partition, priority);
+    SetPriority(&drive.gpt, PRIMARY, index, priority);
+
+  /* Display state */
+  entry = GetEntry(&drive.gpt, PRIMARY, index);
+  EntryDetails(entry, index, NOT_INITED);
 
   /* Claims primary is good, then secondary will be overwritten. */
   /* TODO: rspangler broke this during cgptlib refactoring; need to
diff --git a/utility/cgpt/cgpt_show.c b/utility/cgpt/cgpt_show.c
index b7348aa..2dfad40 100644
--- a/utility/cgpt/cgpt_show.c
+++ b/utility/cgpt/cgpt_show.c
@@ -88,11 +88,11 @@
 #define PARTITION_FMT  "%10d%10d%8d  %s\n"
 #define PARTITION_MORE "%10s%10s%8s  %s%s\n", "", "", ""
 
-static void HeaderDetails(GptHeader *header, const char *indent) {
+static void HeaderDetails(GptHeader *header, const char *indent, int raw) {
   int i;
 
   printf("%sSig: ", indent);
-  if (number == NOT_INITED) {
+  if (raw == NOT_INITED) {
     printf("[");
     for (i = 0; i < sizeof(header->signature); ++i)
       printf("%c", header->signature[i]);
@@ -123,52 +123,66 @@
   printf("%sEntries CRC: 0x%08x\n", indent, header->entries_crc32);
 }
 
-void EntriesDetails(GptData *gpt, const int secondary) {
+void EntryDetails(GptEntry *entry, int index, int raw) {
+  char contents[256];
+
+  if (raw == NOT_INITED) {
+    uint8_t label[sizeof(entry->name) * 3 / 2];
+    char type[GUID_STRLEN], unique[GUID_STRLEN];;
+
+    UTF16ToUTF8(entry->name, label);
+    snprintf(contents, sizeof(contents), "Label: \"%s\"", label);
+    printf(PARTITION_FMT, (int)entry->starting_lba,
+           (int)(entry->ending_lba - entry->starting_lba + 1),
+           index+1, contents);
+    if (CGPT_OK == ResolveType(&entry->type, type)) {
+      printf(PARTITION_MORE, "Type: ", type);
+    } else {
+      GuidToStr(&entry->type, type);
+      printf(PARTITION_MORE, "Type: ", type);
+    }
+    GuidToStr(&entry->unique, unique);
+    printf(PARTITION_MORE, "UUID: ", unique);
+    if (!Memcmp(&guid_chromeos_kernel, &entry->type, sizeof(Guid))) {
+      int tries = (entry->attributes & CGPT_ATTRIBUTE_TRIES_MASK) >>
+        CGPT_ATTRIBUTE_TRIES_OFFSET;
+      int successful = (entry->attributes & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
+        CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
+      int priority = (entry->attributes & CGPT_ATTRIBUTE_PRIORITY_MASK) >>
+        CGPT_ATTRIBUTE_PRIORITY_OFFSET;
+      snprintf(contents, sizeof(contents),
+               "priority=%d tries=%d successful=%d",
+               priority, tries, successful);
+      printf(PARTITION_MORE, "Attr: ", contents);
+    }
+  } else {
+    char label[BUFFER_SIZE(sizeof(entry->name))];
+    char type[GUID_STRLEN], unique[GUID_STRLEN];
+
+    RawDump((void*)entry->name, sizeof(entry->name), label, 2);
+    snprintf(contents, sizeof(contents), "Label: %s", label);
+    printf(PARTITION_FMT, (int)entry->starting_lba,
+           (int)(entry->ending_lba - entry->starting_lba + 1),
+           index+1, contents);
+    GuidToStr(&entry->type, type);
+    printf(PARTITION_MORE, "Type: ", type);
+    GuidToStr(&entry->unique, unique);
+    printf(PARTITION_MORE, "UUID: ", unique);
+    snprintf(contents, sizeof(contents), "[%016lx]", entry->attributes);
+    printf(PARTITION_MORE, "Attr: ", contents);
+  }
+}
+
+void EntriesDetails(GptData *gpt, const int secondary, int raw) {
   int i;
 
   for (i = 0; i < GetNumberOfEntries(gpt); ++i) {
-    static Guid unused = GPT_ENT_TYPE_UNUSED;
-    char contents[256];
-
     GptEntry *entry;
     entry = GetEntry(gpt, secondary, i);
 
-    if (!Memcmp(&unused, &entry->type, sizeof(unused))) continue;
+    if (!Memcmp(&guid_unused, &entry->type, sizeof(Guid))) continue;
 
-    if (number == NOT_INITED) {
-      uint8_t label[sizeof(entry->name) * 3 / 2];
-      char type[GUID_STRLEN], unique[GUID_STRLEN];;
-
-      UTF16ToUTF8(entry->name, label);
-      snprintf(contents, sizeof(contents), "Label: \"%s\"", label);
-      printf(PARTITION_FMT, (int)entry->starting_lba,
-             (int)(entry->ending_lba - entry->starting_lba + 1),
-             i, contents);
-      if (CGPT_OK == ResolveType(&entry->type, type)) {
-        printf(PARTITION_MORE, "Type: ", type);
-      } else {
-        GuidToStr(&entry->type, type);
-        printf(PARTITION_MORE, "Type: ", type);
-      }
-      GuidToStr(&entry->unique, unique);
-      printf(PARTITION_MORE, "UUID: ", unique);
-    } else {
-      char label[BUFFER_SIZE(sizeof(entry->name))];
-      char type[GUID_STRLEN], unique[GUID_STRLEN],
-           attributes[BUFFER_SIZE(sizeof(uint64_t))];
-
-      RawDump((void*)entry->name, sizeof(entry->name), label, 2);
-      snprintf(contents, sizeof(contents), "Label: %s", label);
-      printf(PARTITION_FMT, (int)entry->starting_lba,
-             (int)(entry->ending_lba - entry->starting_lba + 1),
-             i, contents);
-      GuidToStr(&entry->type, type);
-      printf(PARTITION_MORE, "Type: ", type);
-      GuidToStr(&entry->unique, unique);
-      printf(PARTITION_MORE, "UUID: ", unique);
-      RawDump((uint8_t*)&entry->attributes, 8, attributes, 4);
-      printf(PARTITION_MORE, "Attr: ", attributes);
-    }
+    EntryDetails(entry, i, raw);
   }
 }
 
@@ -216,7 +230,7 @@
   if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive))
     return CGPT_FAILED;
 
-  printf(TITLE_FMT, "start", "size", "index", "contents");
+  printf(TITLE_FMT, "start", "size", "part", "contents");
   printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", "PMBR");
 
   if (drive.gpt.valid_headers & MASK_PRIMARY) {
@@ -228,7 +242,7 @@
 
       snprintf(indent, sizeof(indent), GPT_MORE);
       header = (GptHeader*)drive.gpt.primary_header;
-      HeaderDetails(header, indent);
+      HeaderDetails(header, indent, number);
     }
   } else {
     printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
@@ -241,7 +255,7 @@
          "Pri GPT table");
 
   if (drive.gpt.valid_entries & MASK_PRIMARY)
-    EntriesDetails(&drive.gpt, PRIMARY);
+    EntriesDetails(&drive.gpt, PRIMARY, number);
 
   printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR -
                         GPT_ENTRIES_SECTORS),
@@ -256,7 +270,7 @@
       (!(drive.gpt.valid_entries & MASK_PRIMARY) ||
        Memcmp(drive.gpt.primary_entries, drive.gpt.secondary_entries,
               TOTAL_ENTRIES_SIZE))) {
-    EntriesDetails(&drive.gpt, SECONDARY);
+    EntriesDetails(&drive.gpt, SECONDARY, number);
   }
 
   if (drive.gpt.valid_headers & MASK_SECONDARY)
@@ -279,7 +293,7 @@
 
       snprintf(indent, sizeof(indent), GPT_MORE);
       header = (GptHeader*)drive.gpt.secondary_header;
-      HeaderDetails(header, indent);
+      HeaderDetails(header, indent, number);
     }
   }
 
diff --git a/vboot_firmware/lib/cgptlib/cgptlib.c b/vboot_firmware/lib/cgptlib/cgptlib.c
index 2cf6062..3c92384 100644
--- a/vboot_firmware/lib/cgptlib/cgptlib.c
+++ b/vboot_firmware/lib/cgptlib/cgptlib.c
@@ -9,6 +9,10 @@
 #include "gpt.h"
 #include "utility.h"
 
+/* global types to compare against */
+const Guid guid_unused = GPT_ENT_TYPE_UNUSED;
+const Guid guid_chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
+
 
 int GptInit(GptData *gpt) {
   int retval;
diff --git a/vboot_firmware/lib/cgptlib/include/cgptlib_internal.h b/vboot_firmware/lib/cgptlib/include/cgptlib_internal.h
index 195f4d6..0b993c3 100644
--- a/vboot_firmware/lib/cgptlib/include/cgptlib_internal.h
+++ b/vboot_firmware/lib/cgptlib/include/cgptlib_internal.h
@@ -18,14 +18,15 @@
 
 /* Bit definitions and masks for GPT attributes.
  *
- *     63  -- do not automounting
- *     62  -- hidden
+ *  63-61  -- (reserved)
  *     60  -- read-only
- *      :
+ *  59-57  -- (reserved)
  *     56  -- success
- *  55,52  -- tries
- *  51,48  -- priority
- *      0  -- system partition
+ *  55-52  -- tries
+ *  51-48  -- priority
+ *   47-2  -- UEFI: reserved for future use
+ *      1  -- UEFI: partition is not mapped
+ *      0  -- UEFI: partition is required
  */
 #define CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET 56
 #define CGPT_ATTRIBUTE_MAX_SUCCESSFUL (1ULL)
diff --git a/vboot_firmware/lib/cgptlib/include/gpt.h b/vboot_firmware/lib/cgptlib/include/gpt.h
index 57d722c..a199755 100644
--- a/vboot_firmware/lib/cgptlib/include/gpt.h
+++ b/vboot_firmware/lib/cgptlib/include/gpt.h
@@ -34,6 +34,8 @@
   {{{0x3cb8e202,0x3b7e,0x47dd,0x8a,0x3c,{0x7f,0xf2,0xa1,0x3c,0xfc,0xec}}}}
 #define GPT_ENT_TYPE_CHROMEOS_RESERVED \
   {{{0x2e0a753d,0x9e48,0x43b0,0x83,0x37,{0xb1,0x51,0x92,0xcb,0x1b,0x5e}}}}
+#define GPT_ENT_TYPE_LINUX_DATA \
+  {{{0xebd0a0a2,0xb9e5,0x4433,0x87,0xc0,{0x68,0xb6,0xb7,0x26,0x99,0xc7}}}}
 
 
 #define UUID_NODE_LEN 6
@@ -56,6 +58,10 @@
   } u;
 } __attribute__((packed)) Guid;
 
+/* Some constant values */
+extern const Guid guid_unused;
+extern const Guid guid_chromeos_kernel;
+
 /* GPT header defines how many partitions exist on a drive and sectors managed.
  * For every drive device, there are 2 headers, primary and secondary.
  * Most of fields are duplicated except my_lba and entries_lba.