Nearly complete rewrite of cgpt tool.

This fixes a number of bugs, adds a bunch of commands, and essentially makes
cgpt ready to use as a replacement for gpt. Still to do is to add commands
and options that will let it generated intentionally bad partitions, for use
in testing.

Review URL: http://codereview.chromium.org/2719008
diff --git a/Makefile b/Makefile
index e30d716..853bfbf 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 export CC ?= gcc
+export CXX ?= g++
 export CFLAGS = -Wall -DNDEBUG -O3 -Werror
 export TOP = $(shell pwd)
 export FWDIR=$(TOP)/vboot_firmware
@@ -14,7 +15,7 @@
 export FWLIB=$(FWDIR)/vboot_fw.a
 export HOSTLIB=$(HOSTDIR)/vboot_host.a
 
-SUBDIRS=vboot_firmware misclibs host vfirmware vkernel utility tests
+SUBDIRS=vboot_firmware misclibs host vfirmware vkernel utility cgpt tests
 
 all:
 	set -e; \
@@ -30,6 +31,7 @@
 
 install:
 	$(MAKE) -C utility install
+	$(MAKE) -C cgpt install
 
 runtests:
 	$(MAKE) -C tests runtests
diff --git a/cgpt/Makefile b/cgpt/Makefile
new file mode 100644
index 0000000..1f8dede
--- /dev/null
+++ b/cgpt/Makefile
@@ -0,0 +1,45 @@
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+CC ?= gcc
+TOP ?= ..
+CFLAGS ?= -Wall -DNDEBUG -O3 -Werror
+CFLAGS += -static
+LDFLAGS += -luuid
+FWDIR=$(TOP)/vboot_firmware
+
+INCLUDES = -I$(FWDIR)/lib/cgptlib/include
+LIBS = $(FWDIR)/vboot_fw.a
+
+DESTDIR ?= /usr/bin
+
+PROGNAME = cgpt
+
+OBJS= \
+	cgpt.o \
+	cmd_show.o \
+	cmd_repair.o \
+	cmd_create.o \
+	cmd_add.o \
+	cmd_boot.o \
+	cgpt_common.o
+
+
+all: $(PROGNAME)
+
+$(PROGNAME): $(OBJS) $(LIBS)
+	$(CC) -o $(PROGNAME) $(CFLAGS) $^ $(LDFLAGS)
+
+.c.o:
+	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
+
+clean:
+	rm -f $(PROGNAME) *.o *~
+
+install: $(PROGNAME)
+	mkdir -p $(DESTDIR)
+	cp -f $^ $(DESTDIR)
+	chmod a+rx $(patsubst %,$(DESTDIR)/%,$^)
+
+.PHONY: all clean install
diff --git a/cgpt/cgpt.c b/cgpt/cgpt.c
new file mode 100644
index 0000000..d80bffe
--- /dev/null
+++ b/cgpt/cgpt.c
@@ -0,0 +1,75 @@
+/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c
+ * files for more details.
+ */
+
+#include "cgpt.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+const char* progname;
+const char* command;
+
+struct {
+  const char *name;
+  int (*fp)(int argc, char *argv[]);
+  const char *comment;
+} cmds[] = {
+  {"create", cmd_create, "Create or reset GPT headers and tables"},
+  {"add", cmd_add, "Add, edit or remove a partition entry"},
+  {"show", cmd_show, "Show partition table and entries"},
+  {"repair", cmd_repair, "Repair damaged GPT headers and tables"},
+  {"boot", cmd_boot, "Edit the PMBR sector for legacy BIOSes"},
+};
+
+
+void Usage(void) {
+  int i;
+
+  printf("Usage: %s COMMAND [OPTIONS] DRIVE\n\n"
+         "Supported COMMANDs:\n\n",
+         progname);
+
+  for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
+    printf("    %-10s  %s\n", cmds[i].name, cmds[i].comment);
+  }
+  printf("\nFor more detailed usage, use %s COMMAND -h\n\n", progname);
+}
+
+
+
+int main(int argc, char *argv[]) {
+  int i;
+
+  progname = strrchr(argv[0], '/');
+  if (progname)
+    progname++;
+  else
+    progname = argv[0];
+
+  if (argc < 2) {
+    Usage();
+    return CGPT_FAILED;
+  }
+
+  // increment optind now, so that getopt skips argv[0] in command function
+  command = argv[optind++];
+
+  // Find the command to invoke.
+  for (i = 0; command && i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
+    if (0 == strcmp(cmds[i].name, command)) {
+      return cmds[i].fp(argc, argv);
+    }
+  }
+
+  // Couldn't find the command.
+  Usage();
+
+  return CGPT_FAILED;
+}
diff --git a/cgpt/cgpt.h b/cgpt/cgpt.h
new file mode 100644
index 0000000..504e6dd
--- /dev/null
+++ b/cgpt/cgpt.h
@@ -0,0 +1,130 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
+#define VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+#include <features.h>
+#include <stdint.h>
+#include "endian.h"
+#include "gpt.h"
+#include "cgptlib.h"
+
+
+// Just for clarity
+enum {
+  CGPT_OK = 0,
+  CGPT_FAILED,
+};
+
+
+struct legacy_partition {
+  uint8_t  status;
+  uint8_t  f_head;
+  uint8_t  f_sect;
+  uint8_t  f_cyl;
+  uint8_t  type;
+  uint8_t  l_head;
+  uint8_t  l_sect;
+  uint8_t  l_cyl;
+  uint32_t f_lba;
+  uint32_t num_sect;
+} __attribute__((packed));
+
+
+// syslinux uses this format:
+struct pmbr {
+  uint8_t                 bootcode[424];
+  Guid                    boot_guid;
+  uint32_t                disk_id;
+  uint8_t                 magic[2];     // 0x1d, 0x9a
+  struct legacy_partition part[4];
+  uint8_t                 sig[2];       // 0x55, 0xaa
+} __attribute__((packed));
+
+void PMBRToStr(struct pmbr *pmbr, char *str);
+
+// Handle to the drive storing the GPT.
+struct drive {
+  int fd;           /* file descriptor */
+  uint64_t size;    /* total size (in bytes) */
+  GptData gpt;
+  struct pmbr pmbr;
+};
+
+
+int DriveOpen(const char *drive_path, struct drive *drive);
+int DriveClose(struct drive *drive, int update_as_needed);
+int CheckValid(const struct drive *drive);
+
+/* GUID conversion functions. Accepted format:
+ *
+ *   "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
+ *
+ * At least GUID_STRLEN bytes should be reserved in 'str' (included the tailing
+ * '\0').
+ */
+#define GUID_STRLEN 37
+int StrToGuid(const char *str, Guid *guid);
+void GuidToStr(const Guid *guid, char *str);
+int IsZero(const Guid *guid);
+
+
+int ReadPMBR(struct drive *drive);
+int WritePMBR(struct drive *drive);
+
+
+/* Convert UTF16 string to UTF8. Rewritten from gpt utility.
+ * Caller must prepare enough space for UTF8. The rough estimation is:
+ *
+ *   utf8 length = bytecount(utf16) * 1.5
+ */
+void UTF16ToUTF8(const uint16_t *utf16, uint8_t *utf8);
+/* Convert UTF8 string to UTF16. Rewritten from gpt utility.
+ * Caller must prepare enough space for UTF16. The conservative estimation is:
+ *
+ *   utf16 bytecount = bytecount(utf8) / 3 * 4
+ */
+void UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16);
+
+/* Helper functions for supported GPT types. */
+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);
+
+uint32_t GetNumberOfEntries(const GptData *gpt);
+GptEntry *GetEntry(GptData *gpt, int secondary, int entry_index);
+void SetPriority(GptData *gpt, int secondary, int entry_index, int priority);
+int GetPriority(GptData *gpt, int secondary, int entry_index);
+void SetTries(GptData *gpt, int secondary, int entry_index, int tries);
+int GetTries(GptData *gpt, int secondary, int entry_index);
+void SetSuccessful(GptData *gpt, int secondary, int entry_index, int success);
+int GetSuccessful(GptData *gpt, int secondary, int entry_index);
+
+uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers);
+uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries);
+void UpdateCrc(GptData *gpt);
+int IsSynonymous(const GptHeader* a, const GptHeader* b);
+
+// For usage and error messages.
+extern const char* progname;
+extern const char* command;
+void Error(const char *format, ...);
+
+
+// Command functions.
+int cmd_show(int argc, char *argv[]);
+int cmd_repair(int argc, char *argv[]);
+int cmd_create(int argc, char *argv[]);
+int cmd_add(int argc, char *argv[]);
+int cmd_boot(int argc, char *argv[]);
+
+#define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0]))
+const char *GptError(int errnum);
+
+
+#endif  // VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c
new file mode 100644
index 0000000..f165f7a
--- /dev/null
+++ b/cgpt/cgpt_common.c
@@ -0,0 +1,726 @@
+/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c
+ * files for more details.
+ */
+
+#include "cgpt.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include "cgptlib_internal.h"
+#include "crc32.h"
+
+
+void Error(const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  fprintf(stderr, "ERROR: %s %s: ", progname, command);
+  vfprintf(stderr, format, ap);
+  va_end(ap);
+}
+
+
+int CheckValid(const struct drive *drive) {
+  if ((drive->gpt.valid_headers != MASK_BOTH) ||
+      (drive->gpt.valid_entries != MASK_BOTH)) {
+    fprintf(stderr, "\nWARNING: one of the GPT header/entries is invalid, "
+           "please run '%s repair'\n", progname);
+    return CGPT_FAILED;
+  }
+  return CGPT_OK;
+}
+
+/* Loads sectors from 'fd'.
+ * *buf is pointed to an allocated memory when returned, and should be
+ * freed by cgpt_close().
+ *
+ *   fd -- file descriptot.
+ *   buf -- pointer to buffer pointer
+ *   sector -- offset of starting sector (in sectors)
+ *   sector_bytes -- bytes per sector
+ *   sector_count -- number of sectors to load
+ *
+ * Returns CGPT_OK for successful. Aborts if any error occurs.
+ */
+static int Load(const int fd, uint8_t **buf,
+                const uint64_t sector,
+                const uint64_t sector_bytes,
+                const uint64_t sector_count) {
+  int count;  /* byte count to read */
+  int nread;
+
+  assert(buf);
+  count = sector_bytes * sector_count;
+  *buf = malloc(count);
+  assert(*buf);
+
+  if (-1 == lseek(fd, sector * sector_bytes, SEEK_SET))
+    goto error_free;
+
+  nread = read(fd, *buf, count);
+  if (nread < count)
+    goto error_free;
+
+  return CGPT_OK;
+
+error_free:
+  free(*buf);
+  *buf = 0;
+  return CGPT_FAILED;
+}
+
+
+int ReadPMBR(struct drive *drive) {
+  if (-1 == lseek(drive->fd, 0, SEEK_SET))
+    return CGPT_FAILED;
+
+  int nread = read(drive->fd, &drive->pmbr, sizeof(struct pmbr));
+  if (nread != sizeof(struct pmbr))
+    return CGPT_FAILED;
+
+  return CGPT_OK;
+}
+
+int WritePMBR(struct drive *drive) {
+  if (-1 == lseek(drive->fd, 0, SEEK_SET))
+    return CGPT_FAILED;
+
+  int nwrote = write(drive->fd, &drive->pmbr, sizeof(struct pmbr));
+  if (nwrote != sizeof(struct pmbr))
+    return CGPT_FAILED;
+
+  return CGPT_OK;
+}
+
+/* Saves sectors to 'fd'.
+ *
+ *   fd -- file descriptot.
+ *   buf -- pointer to buffer
+ *   sector -- starting sector offset
+ *   sector_bytes -- bytes per sector
+ *   sector_count -- number of sector to save
+ *
+ * Returns CGPT_OK for successful, CGPT_FAILED for failed.
+ */
+static int Save(const int fd, const uint8_t *buf,
+                const uint64_t sector,
+                const uint64_t sector_bytes,
+                const uint64_t sector_count) {
+  int count;  /* byte count to write */
+  int nwrote;
+
+  assert(buf);
+  count = sector_bytes * sector_count;
+
+  if (-1 == lseek(fd, sector * sector_bytes, SEEK_SET))
+    return CGPT_FAILED;
+
+  nwrote = write(fd, buf, count);
+  if (nwrote < count)
+    return CGPT_FAILED;
+
+  return CGPT_OK;
+}
+
+
+// Opens a block device or file, loads raw GPT data from it.
+// 
+// Returns CGPT_FAILED if any error happens.
+// Returns CGPT_OK if success and information are stored in 'drive'. */
+int DriveOpen(const char *drive_path, struct drive *drive) {
+  struct stat stat;
+
+  assert(drive_path);
+  assert(drive);
+
+  // Clear struct for proper error handling.
+  memset(drive, 0, sizeof(struct drive));
+
+  drive->fd = open(drive_path, O_RDWR | O_LARGEFILE);
+  if (drive->fd == -1) {
+    Error("Can't open %s: %s\n", drive_path, strerror(errno));
+    return CGPT_FAILED;
+  }
+
+  if (fstat(drive->fd, &stat) == -1) {
+    goto error_close;
+  }
+  if ((stat.st_mode & S_IFMT) != S_IFREG) {
+    if (ioctl(drive->fd, BLKGETSIZE64, &drive->size) < 0) {
+      Error("Can't read drive size from %s: %s\n", drive_path, strerror(errno));
+      goto error_close;
+    }
+    if (ioctl(drive->fd, BLKSSZGET, &drive->gpt.sector_bytes) < 0) {
+      Error("Can't read sector size from %s: %s\n",
+            drive_path, strerror(errno));
+      goto error_close;
+    }
+  } else {
+    drive->gpt.sector_bytes = 512;  /* bytes */
+    drive->size = stat.st_size;
+  }
+  if (drive->size % drive->gpt.sector_bytes) {
+    Error("Media size (%llu) is not a multiple of sector size(%d)\n",
+          (long long unsigned int)drive->size, drive->gpt.sector_bytes);
+    goto error_close;
+  }
+  drive->gpt.drive_sectors = drive->size / drive->gpt.sector_bytes;
+
+  // Read the data.
+  if (CGPT_OK != Load(drive->fd, &drive->gpt.primary_header,
+                      GPT_PMBR_SECTOR,
+                      drive->gpt.sector_bytes, GPT_HEADER_SECTOR)) {
+    goto error_close;
+  }
+  if (CGPT_OK != Load(drive->fd, &drive->gpt.secondary_header,
+                      drive->gpt.drive_sectors - GPT_PMBR_SECTOR,
+                      drive->gpt.sector_bytes, GPT_HEADER_SECTOR)) {
+    goto error_close;
+  }
+  if (CGPT_OK != Load(drive->fd, &drive->gpt.primary_entries,
+                      GPT_PMBR_SECTOR + GPT_HEADER_SECTOR,
+                      drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
+        goto error_close;
+  }
+  if (CGPT_OK != Load(drive->fd, &drive->gpt.secondary_entries,
+                      drive->gpt.drive_sectors - GPT_HEADER_SECTOR
+                      - GPT_ENTRIES_SECTORS,
+                      drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
+    goto error_close;
+  }
+    
+  // We just load the data. Caller must validate it.
+  return CGPT_OK;
+
+error_close:
+  (void) DriveClose(drive, 0);
+  return CGPT_FAILED;
+}
+
+
+int DriveClose(struct drive *drive, int update_as_needed) {
+  int errors = 0;
+
+  if (update_as_needed) {
+    if (drive->gpt.modified & GPT_MODIFIED_HEADER1) {
+      if (CGPT_OK != Save(drive->fd, drive->gpt.primary_header,
+                          GPT_PMBR_SECTOR,
+                          drive->gpt.sector_bytes, GPT_HEADER_SECTOR)) {
+        errors++;
+        Error("Cannot write primary header: %s\n", strerror(errno));
+      }
+    }
+      
+    if (drive->gpt.modified & GPT_MODIFIED_HEADER2) {
+      if(CGPT_OK != Save(drive->fd, drive->gpt.secondary_header,
+                         drive->gpt.drive_sectors - GPT_PMBR_SECTOR,
+                         drive->gpt.sector_bytes, GPT_HEADER_SECTOR)) {
+        errors++;
+        Error("Cannot write secondary header: %s\n", strerror(errno));
+      }
+    }
+    if (drive->gpt.modified & GPT_MODIFIED_ENTRIES1) {
+      if (CGPT_OK != Save(drive->fd, drive->gpt.primary_entries,
+                          GPT_PMBR_SECTOR + GPT_HEADER_SECTOR,
+                          drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
+        errors++;
+        Error("Cannot write primary entries: %s\n", strerror(errno));
+      }
+    }
+    if (drive->gpt.modified & GPT_MODIFIED_ENTRIES2) {
+      if (CGPT_OK != Save(drive->fd, drive->gpt.secondary_entries,
+                          drive->gpt.drive_sectors - GPT_HEADER_SECTOR
+                          - GPT_ENTRIES_SECTORS,
+                          drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
+        errors++;
+        Error("Cannot write secondary entries: %s\n", strerror(errno));
+      }
+    }
+  }
+
+  close(drive->fd);
+
+  if (drive->gpt.primary_header)
+    free(drive->gpt.primary_header);
+  drive->gpt.primary_header = 0;
+  if (drive->gpt.primary_entries)
+    free(drive->gpt.primary_entries);
+  drive->gpt.primary_entries = 0;
+  if (drive->gpt.secondary_header)
+    free(drive->gpt.secondary_header);
+  drive->gpt.secondary_header = 0;
+  if (drive->gpt.secondary_entries)
+    free(drive->gpt.secondary_entries);
+  drive->gpt.secondary_entries = 0;
+
+  return errors ? CGPT_FAILED : CGPT_OK;
+}
+
+
+
+/* GUID conversion functions. Accepted format:
+ *
+ *   "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
+ *
+ * Returns CGPT_OK if parsing is successful; otherwise CGPT_FAILED.
+ */
+int StrToGuid(const char *str, Guid *guid) {
+  uint32_t time_low;
+  uint16_t time_mid;
+  uint16_t time_high_and_version;
+  unsigned int chunk[11];
+
+  if (11 != sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+                   chunk+0,
+                   chunk+1,
+                   chunk+2,
+                   chunk+3,
+                   chunk+4,
+                   chunk+5,
+                   chunk+6,
+                   chunk+7,
+                   chunk+8,
+                   chunk+9,
+                   chunk+10)) {                   
+    printf("FAILED\n");
+    return CGPT_FAILED;
+  }
+
+  time_low = chunk[0] & 0xffffffff;
+  time_mid = chunk[1] & 0xffff;
+  time_high_and_version = chunk[2] & 0xffff;
+
+  guid->u.Uuid.time_low = htole32(time_low);
+  guid->u.Uuid.time_mid = htole16(time_mid);
+  guid->u.Uuid.time_high_and_version = htole16(time_high_and_version);
+
+  guid->u.Uuid.clock_seq_high_and_reserved = chunk[3] & 0xff;
+  guid->u.Uuid.clock_seq_low = chunk[4] & 0xff;
+  guid->u.Uuid.node[0] = chunk[5] & 0xff;
+  guid->u.Uuid.node[1] = chunk[6] & 0xff;
+  guid->u.Uuid.node[2] = chunk[7] & 0xff;
+  guid->u.Uuid.node[3] = chunk[8] & 0xff;
+  guid->u.Uuid.node[4] = chunk[9] & 0xff;
+  guid->u.Uuid.node[5] = chunk[10] & 0xff;
+
+  return CGPT_OK;
+}
+void GuidToStr(const Guid *guid, char *str) {
+  sprintf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+          le32toh(guid->u.Uuid.time_low), le16toh(guid->u.Uuid.time_mid),
+          le16toh(guid->u.Uuid.time_high_and_version),
+          guid->u.Uuid.clock_seq_high_and_reserved, guid->u.Uuid.clock_seq_low,
+          guid->u.Uuid.node[0], guid->u.Uuid.node[1], guid->u.Uuid.node[2],
+          guid->u.Uuid.node[3], guid->u.Uuid.node[4], guid->u.Uuid.node[5]);
+}
+
+/* Convert UTF16 string to UTF8. Rewritten from gpt utility.
+ * Caller must prepare enough space for UTF8. The rough estimation is:
+ *
+ *   utf8 length = bytecount(utf16) * 1.5
+ */
+#define SIZEOF_GPTENTRY_NAME 36  /* sizeof(GptEntry.name[]) */
+void UTF16ToUTF8(const uint16_t *utf16, uint8_t *utf8)
+{
+  size_t s8idx, s16idx, s16len;
+  uint32_t utfchar;
+  unsigned int next_utf16;
+
+  for (s16len = 0; s16len < SIZEOF_GPTENTRY_NAME && utf16[s16len]; ++s16len);
+
+  *utf8 = s8idx = s16idx = 0;
+  while (s16idx < s16len) {
+    utfchar = le16toh(utf16[s16idx++]);
+    if ((utfchar & 0xf800) == 0xd800) {
+      next_utf16 = le16toh(utf16[s16idx]);
+      if ((utfchar & 0x400) != 0 || (next_utf16 & 0xfc00) != 0xdc00)
+        utfchar = 0xfffd;
+      else
+        s16idx++;
+    }
+    if (utfchar < 0x80) {
+      utf8[s8idx++] = utfchar;
+    } else if (utfchar < 0x800) {
+      utf8[s8idx++] = 0xc0 | (utfchar >> 6);
+      utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
+    } else if (utfchar < 0x10000) {
+      utf8[s8idx++] = 0xe0 | (utfchar >> 12);
+      utf8[s8idx++] = 0x80 | ((utfchar >> 6) & 0x3f);
+      utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
+    } else if (utfchar < 0x200000) {
+      utf8[s8idx++] = 0xf0 | (utfchar >> 18);
+      utf8[s8idx++] = 0x80 | ((utfchar >> 12) & 0x3f);
+      utf8[s8idx++] = 0x80 | ((utfchar >> 6) & 0x3f);
+      utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
+    }
+  }
+  utf8[s8idx++] = 0;
+}
+
+/* Convert UTF8 string to UTF16. Rewritten from gpt utility.
+ * Caller must prepare enough space for UTF16. The conservative estimation is:
+ *
+ *   utf16 bytecount = bytecount(utf8) / 3 * 4
+ */
+void UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16)
+{
+  size_t s16idx, s8idx, s8len;
+  uint32_t utfchar;
+  unsigned int c, utfbytes;
+
+  for (s8len = 0; utf8[s8len]; ++s8len);
+
+  s8idx = s16idx = 0;
+  utfbytes = 0;
+  do {
+    c = utf8[s8idx++];
+    if ((c & 0xc0) != 0x80) {
+      /* Initial characters. */
+      if (utfbytes != 0) {
+        /* Incomplete encoding. */
+        utf16[s16idx++] = 0xfffd;
+      }
+      if ((c & 0xf8) == 0xf0) {
+        utfchar = c & 0x07;
+        utfbytes = 3;
+      } else if ((c & 0xf0) == 0xe0) {
+        utfchar = c & 0x0f;
+        utfbytes = 2;
+      } else if ((c & 0xe0) == 0xc0) {
+        utfchar = c & 0x1f;
+        utfbytes = 1;
+      } else {
+        utfchar = c & 0x7f;
+        utfbytes = 0;
+      }
+    } else {
+      /* Followup characters. */
+      if (utfbytes > 0) {
+        utfchar = (utfchar << 6) + (c & 0x3f);
+        utfbytes--;
+      } else if (utfbytes == 0)
+        utfbytes = -1;
+        utfchar = 0xfffd;
+    }
+    if (utfbytes == 0) {
+      if (utfchar >= 0x10000) {
+        utf16[s16idx++] = htole16(0xd800 | ((utfchar>>10)-0x40));
+        if (s16idx >= SIZEOF_GPTENTRY_NAME) break;
+        utf16[s16idx++] = htole16(0xdc00 | (utfchar & 0x3ff));
+      } else {
+        utf16[s16idx++] = htole16(utfchar);
+      }
+    }
+  } while (c != 0 && s16idx < SIZEOF_GPTENTRY_NAME);
+  if (s16idx < SIZEOF_GPTENTRY_NAME)
+    utf16[s16idx++] = 0;
+}
+
+struct {
+  Guid type;
+  char *name;
+  char *description;
+} supported_types[] = {
+  {GPT_ENT_TYPE_CHROMEOS_KERNEL, "kernel", "ChromeOS kernel"},
+  {GPT_ENT_TYPE_CHROMEOS_ROOTFS, "rootfs", "ChromeOS rootfs"},
+  {GPT_ENT_TYPE_LINUX_DATA, "data", "Linux data"},
+  {GPT_ENT_TYPE_CHROMEOS_RESERVED, "reserved", "ChromeOS reserved"},
+  {GPT_ENT_TYPE_EFI, "efi", "EFI System Partition"},
+  {GPT_ENT_TYPE_UNUSED, "unused", "Unused (nonexistent) partition"},
+};
+
+/* Resolves human-readable GPT type.
+ * Returns CGPT_OK if found.
+ * Returns CGPT_FAILED if no known type found. */
+int ResolveType(const Guid *type, char *buf) {
+  int i;
+  for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
+    if (!memcmp(type, &supported_types[i].type, sizeof(Guid))) {
+      strcpy(buf, supported_types[i].description);
+      return CGPT_OK;
+    }
+  }
+  return CGPT_FAILED;
+}
+
+int SupportedType(const char *name, Guid *type) {
+  int i;
+  for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
+    if (!strcmp(name, supported_types[i].name)) {
+      memcpy(type, &supported_types[i].type, sizeof(Guid));
+      return CGPT_OK;
+    }
+  }
+  return CGPT_FAILED;
+}
+
+void PrintTypes(void) {
+  int i;
+  printf("The partition type may also be given as one of these aliases:\n\n");
+  for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
+    printf("    %-10s  %s\n", supported_types[i].name,
+                          supported_types[i].description);
+  }
+  printf("\n");
+}
+
+uint32_t GetNumberOfEntries(const GptData *gpt) {
+  GptHeader *header = 0;
+  if (gpt->valid_headers & MASK_PRIMARY)
+    header = (GptHeader*)gpt->primary_header;
+  else if (gpt->valid_headers & MASK_SECONDARY)
+    header = (GptHeader*)gpt->secondary_header;
+  else
+    return 0;
+  return header->number_of_entries;
+}
+
+static uint32_t GetSizeOfEntries(const GptData *gpt) {
+  GptHeader *header = 0;
+  if (gpt->valid_headers & MASK_PRIMARY)
+    header = (GptHeader*)gpt->primary_header;
+  else if (gpt->valid_headers & MASK_SECONDARY)
+    header = (GptHeader*)gpt->secondary_header;
+  else
+    return 0;
+  return header->number_of_entries;
+}
+
+GptEntry *GetEntry(GptData *gpt, int secondary, int entry_index) {
+  uint8_t *entries;
+  int stride = GetSizeOfEntries(gpt);
+  if (!stride)
+    return 0;
+
+  if (secondary == PRIMARY) {
+    entries = gpt->primary_entries;
+  } else {
+    entries = gpt->secondary_entries;
+  }
+
+  return (GptEntry*)(&entries[stride * entry_index]);
+}
+
+void SetPriority(GptData *gpt, int secondary, int entry_index, int priority) {
+  GptEntry *entry;
+  entry = GetEntry(gpt, secondary, entry_index);
+
+  assert(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
+  entry->attributes &= ~CGPT_ATTRIBUTE_PRIORITY_MASK;
+  entry->attributes |= (uint64_t)priority << CGPT_ATTRIBUTE_PRIORITY_OFFSET;
+}
+
+int GetPriority(GptData *gpt, int secondary, int entry_index) {
+  GptEntry *entry;
+  entry = GetEntry(gpt, secondary, entry_index);
+  return (entry->attributes & CGPT_ATTRIBUTE_PRIORITY_MASK) >>
+         CGPT_ATTRIBUTE_PRIORITY_OFFSET;
+}
+
+void SetTries(GptData *gpt, int secondary, int entry_index, int tries) {
+  GptEntry *entry;
+  entry = GetEntry(gpt, secondary, entry_index);
+
+  assert(tries >= 0 && tries <= CGPT_ATTRIBUTE_MAX_TRIES);
+  entry->attributes &= ~CGPT_ATTRIBUTE_TRIES_MASK;
+  entry->attributes |= (uint64_t)tries << CGPT_ATTRIBUTE_TRIES_OFFSET;
+}
+
+int GetTries(GptData *gpt, int secondary, int entry_index) {
+  GptEntry *entry;
+  entry = GetEntry(gpt, secondary, entry_index);
+  return (entry->attributes & CGPT_ATTRIBUTE_TRIES_MASK) >>
+         CGPT_ATTRIBUTE_TRIES_OFFSET;
+}
+
+void SetSuccessful(GptData *gpt, int secondary, int entry_index, int success) {
+  GptEntry *entry;
+  entry = GetEntry(gpt, secondary, entry_index);
+
+  assert(success >= 0 && success <= CGPT_ATTRIBUTE_MAX_SUCCESSFUL);
+  entry->attributes &= ~CGPT_ATTRIBUTE_SUCCESSFUL_MASK;
+  entry->attributes |= (uint64_t)success << CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
+}
+
+int GetSuccessful(GptData *gpt, int secondary, int entry_index) {
+  GptEntry *entry;
+  entry = GetEntry(gpt, secondary, entry_index);
+  return (entry->attributes & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
+         CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
+}
+
+
+#define TOSTRING(A) #A
+const char *GptError(int errnum) {
+  const char *error_string[] = {
+    TOSTRING(GPT_SUCCESS),
+    TOSTRING(GPT_ERROR_NO_VALID_KERNEL),
+    TOSTRING(GPT_ERROR_INVALID_HEADERS),
+    TOSTRING(GPT_ERROR_INVALID_ENTRIES),
+    TOSTRING(GPT_ERROR_INVALID_SECTOR_SIZE),
+    TOSTRING(GPT_ERROR_INVALID_SECTOR_NUMBER),
+    TOSTRING(GPT_ERROR_INVALID_UPDATE_TYPE)
+  };
+  if (errnum < 0 || errnum >= ARRAY_COUNT(error_string))
+    return "<illegal value>";
+  return error_string[errnum];
+}
+
+/*  Update CRC value if necessary.  */
+void UpdateCrc(GptData *gpt) {
+  GptHeader *primary_header, *secondary_header;
+
+  primary_header = (GptHeader*)gpt->primary_header;
+  secondary_header = (GptHeader*)gpt->secondary_header;
+
+  if (gpt->modified & GPT_MODIFIED_ENTRIES1) {
+    primary_header->entries_crc32 =
+        Crc32(gpt->primary_entries, TOTAL_ENTRIES_SIZE);
+  }
+  if (gpt->modified & GPT_MODIFIED_ENTRIES2) {
+    secondary_header->entries_crc32 =
+        Crc32(gpt->secondary_entries, TOTAL_ENTRIES_SIZE);
+  }
+  if (gpt->modified & GPT_MODIFIED_HEADER1) {
+    primary_header->header_crc32 = 0;
+    primary_header->header_crc32 = Crc32(
+        (const uint8_t *)primary_header, primary_header->size);
+  }
+  if (gpt->modified & GPT_MODIFIED_HEADER2) {
+    secondary_header->header_crc32 = 0;
+    secondary_header->header_crc32 = Crc32(
+        (const uint8_t *)secondary_header, secondary_header->size);
+  }
+}
+/* Two headers are NOT bitwise identical. For example, my_lba pointers to header
+ * itself so that my_lba in primary and secondary is definitely different.
+ * Only the following fields should be identical.
+ *
+ *   first_usable_lba
+ *   last_usable_lba
+ *   number_of_entries
+ *   size_of_entry
+ *   disk_uuid
+ *
+ * If any of above field are not matched, overwrite secondary with primary since
+ * we always trust primary.
+ * If any one of header is invalid, copy from another. */
+int IsSynonymous(const GptHeader* a, const GptHeader* b) {
+  if ((a->first_usable_lba == b->first_usable_lba) &&
+      (a->last_usable_lba == b->last_usable_lba) &&
+      (a->number_of_entries == b->number_of_entries) &&
+      (a->size_of_entry == b->size_of_entry) &&
+      (!memcmp(&a->disk_uuid, &b->disk_uuid, sizeof(Guid))))
+    return 1;
+  return 0;
+}
+
+/* Primary entries and secondary entries should be bitwise identical.
+ * If two entries tables are valid, compare them. If not the same,
+ * overwrites secondary with primary (primary always has higher priority),
+ * and marks secondary as modified.
+ * If only one is valid, overwrites invalid one.
+ * If all are invalid, does nothing.
+ * This function returns bit masks for GptData.modified field.
+ * Note that CRC is NOT re-computed in this function.
+ */
+uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) {
+  if (valid_entries == MASK_BOTH) {
+    if (memcmp(gpt->primary_entries, gpt->secondary_entries,
+               TOTAL_ENTRIES_SIZE)) {
+      memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE);
+      return GPT_MODIFIED_ENTRIES2;
+    }
+  } else if (valid_entries == MASK_PRIMARY) {
+    memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE);
+    return GPT_MODIFIED_ENTRIES2;
+  } else if (valid_entries == MASK_SECONDARY) {
+    memcpy(gpt->primary_entries, gpt->secondary_entries, TOTAL_ENTRIES_SIZE);
+    return GPT_MODIFIED_ENTRIES1;
+  }
+
+  return 0;
+}
+
+/* The above five fields are shared between primary and secondary headers.
+ * We can recover one header from another through copying those fields. */
+void CopySynonymousParts(GptHeader* target, const GptHeader* source) {
+  target->first_usable_lba = source->first_usable_lba;
+  target->last_usable_lba = source->last_usable_lba;
+  target->number_of_entries = source->number_of_entries;
+  target->size_of_entry = source->size_of_entry;
+  memcpy(&target->disk_uuid, &source->disk_uuid, sizeof(Guid));
+}
+
+/* This function repairs primary and secondary headers if possible.
+ * If both headers are valid (CRC32 is correct) but
+ *   a) indicate inconsistent usable LBA ranges,
+ *   b) inconsistent partition entry size and number,
+ *   c) inconsistent disk_uuid,
+ * we will use the primary header to overwrite secondary header.
+ * If primary is invalid (CRC32 is wrong), then we repair it from secondary.
+ * If secondary is invalid (CRC32 is wrong), then we repair it from primary.
+ * This function returns the bitmasks for modified header.
+ * Note that CRC value is NOT re-computed in this function. UpdateCrc() will
+ * do it later.
+ */
+uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) {
+  GptHeader *primary_header, *secondary_header;
+
+  primary_header = (GptHeader*)gpt->primary_header;
+  secondary_header = (GptHeader*)gpt->secondary_header;
+
+  if (valid_headers == MASK_BOTH) {
+    if (!IsSynonymous(primary_header, secondary_header)) {
+      CopySynonymousParts(secondary_header, primary_header);
+      return GPT_MODIFIED_HEADER2;
+    }
+  } else if (valid_headers == MASK_PRIMARY) {
+    memcpy(secondary_header, primary_header, primary_header->size);
+    secondary_header->my_lba = gpt->drive_sectors - 1;  /* the last sector */
+    secondary_header->alternate_lba = primary_header->my_lba;
+    secondary_header->entries_lba = secondary_header->my_lba -
+        GPT_ENTRIES_SECTORS;
+    return GPT_MODIFIED_HEADER2;
+  } else if (valid_headers == MASK_SECONDARY) {
+    memcpy(primary_header, secondary_header, secondary_header->size);
+    primary_header->my_lba = GPT_PMBR_SECTOR;  /* the second sector on drive */
+    primary_header->alternate_lba = secondary_header->my_lba;
+    primary_header->entries_lba = primary_header->my_lba + GPT_HEADER_SECTOR;
+    return GPT_MODIFIED_HEADER1;
+  }
+
+  return 0;
+}
+
+
+int IsZero(const Guid *gp) {
+  return (0 == memcmp(gp, &guid_unused, sizeof(Guid)));
+}
+
+void PMBRToStr(struct pmbr *pmbr, char *str) {
+  char buf[256];
+  if (IsZero(&pmbr->boot_guid)) {
+    sprintf(str, "PMBR");
+  } else {
+    GuidToStr(&pmbr->boot_guid, buf);
+    sprintf(str, "PMBR (Boot GUID: %s)", buf);
+  }
+}
+
diff --git a/cgpt/cmd_add.c b/cgpt/cmd_add.c
new file mode 100644
index 0000000..18a0285
--- /dev/null
+++ b/cgpt/cmd_add.c
@@ -0,0 +1,276 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cgpt.h"
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uuid/uuid.h>
+
+#include "cgptlib_internal.h"
+
+static void Usage(void)
+{
+  printf("\nUsage: %s add [OPTIONS] DRIVE\n\n"
+         "Add, edit, or remove a partition entry.\n\n"
+         "Options:\n"
+         "  -i NUM       Specify partition (default is next available)\n"
+         "  -b NUM       Beginning sector\n"
+         "  -s NUM       Size in sectors\n"
+         "  -t GUID      Partition Type GUID\n"
+         "  -u GUID      Partition Unique ID\n"
+         "  -l LABEL     Label\n"
+         "  -S NUM       set Successful flag (0|1)\n"
+         "  -T NUM       set Tries flag (0-15)\n"
+         "  -P NUM       set Priority flag (0-15)\n"
+         "  -A NUM       set raw 64-bit attribute value\n"
+         "\n"
+         "Use the -i option to modify an existing partition.\n"
+         "The -b, -s, and -t options must be given for new partitions.\n"
+         "\n", progname);
+  PrintTypes();
+}
+
+int cmd_add(int argc, char *argv[]) {
+  struct drive drive;
+  int partition = 0;
+  uint64_t begin = 0;
+  uint64_t size = 0;
+  Guid type_guid;
+  Guid unique_guid;
+  char *label = 0;
+  int successful = 0;
+  int tries = 0;
+  int priority = 0;
+  uint64_t raw_value = 0;
+  int set_begin = 0;
+  int set_size = 0;
+  int set_type = 0;
+  int set_unique = 0;
+  int set_successful = 0;
+  int set_tries = 0;
+  int set_priority = 0;
+  int set_raw = 0;
+
+  int gpt_retval;
+  GptEntry *entry;
+  int index;
+  
+  int c;
+  int errorcnt = 0;
+  char *e = 0;
+
+  opterr = 0;                     // quiet, you
+  while ((c=getopt(argc, argv, ":hi:b:s:t:u:l:S:T:P:A:")) != -1)
+  {
+    switch (c)
+    {
+    case 'i':
+      partition = (uint32_t)strtoul(optarg, &e, 0);
+      if (!*optarg || (e && *e))
+      {
+        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
+        errorcnt++;
+      }
+      break;
+    case 'b':
+      set_begin = 1;
+      begin = strtoull(optarg, &e, 0);
+      if (!*optarg || (e && *e))
+      {
+        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
+        errorcnt++;
+      }
+      break;
+    case 's':
+      set_size = 1;
+      size = strtoull(optarg, &e, 0);
+      if (!*optarg || (e && *e))
+      {
+        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
+        errorcnt++;
+      }
+      break;
+    case 't':
+      set_type = 1;
+      if (CGPT_OK != SupportedType(optarg, &type_guid) &&
+          CGPT_OK != StrToGuid(optarg, &type_guid)) {
+        Error("invalid argument to -%c: %s\n", c, optarg);
+        errorcnt++;
+      }
+      break;
+    case 'u':
+      set_unique = 1;
+      if (CGPT_OK != StrToGuid(optarg, &unique_guid)) {
+        Error("invalid argument to -%c: %s\n", c, optarg);
+        errorcnt++;
+      }
+      break;
+    case 'l':
+      label = optarg;
+      break;
+    case 'S':
+      set_successful = 1;
+      successful = (uint32_t)strtoul(optarg, &e, 0);
+      if (!*optarg || (e && *e))
+      {
+        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
+        errorcnt++;
+      }
+      if (successful < 0 || successful > 1) {
+        Error("value for -%c must be between 0 and 1", c);
+        errorcnt++;
+      }
+      break;
+    case 'T':
+      set_tries = 1;
+      tries = (uint32_t)strtoul(optarg, &e, 0);
+      if (!*optarg || (e && *e))
+      {
+        fprintf(stderr, "%s: invalid argument to -%c: \"%s\"\n",
+                progname, c, optarg);
+        errorcnt++;
+      }
+      if (tries < 0 || tries > 15) {
+        Error("value for -%c must be between 0 and 15", c);
+        errorcnt++;
+      }
+      break;
+    case 'P':
+      set_priority = 1;
+      priority = (uint32_t)strtoul(optarg, &e, 0);
+      if (!*optarg || (e && *e))
+      {
+        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
+        errorcnt++;
+      }
+      if (priority < 0 || priority > 15) {
+        Error("value for -%c must be between 0 and 15", c);
+        errorcnt++;
+      }
+      break;
+    case 'A':
+      set_raw = 1;
+      raw_value = strtoull(optarg, &e, 0);
+      if (!*optarg || (e && *e))
+      {
+        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
+        errorcnt++;
+      }
+      break;
+
+    case 'h':
+      Usage();
+      return CGPT_OK;
+    case '?':
+      Error("unrecognized option: -%c\n", optopt);
+      errorcnt++;
+      break;
+    case ':':
+      Error("missing argument to -%c\n", optopt);
+      errorcnt++;
+      break;
+    default:
+      errorcnt++;
+      break;
+    }
+  }
+  if (errorcnt)
+  {
+    Usage();
+    return CGPT_FAILED;
+  }
+
+  if (optind >= argc) {
+    Error("missing drive argument\n");
+    return CGPT_FAILED;
+  }
+
+  if (CGPT_OK != DriveOpen(argv[optind], &drive))
+    return CGPT_FAILED;
+
+  if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
+    Error("GptSanityCheck() returned %d: %s\n",
+          gpt_retval, GptError(gpt_retval));
+    return CGPT_FAILED;
+  }
+
+  int max_part = GetNumberOfEntries(&drive.gpt);
+  if (partition) {
+    if (partition > max_part) {
+      Error("invalid partition number: %d\n", partition);
+      goto bad;
+    }
+    index = partition - 1;
+    entry = GetEntry(&drive.gpt, PRIMARY, index);
+  } else {
+    // find next empty partition
+    for (index = 0; index < max_part; index++) {
+      entry = GetEntry(&drive.gpt, PRIMARY, index);
+      if (IsZero(&entry->type)) {
+        partition = index + 1;
+        break;
+      }
+    }
+    if (index >= max_part) {
+      Error("no unused partitions available\n");
+      goto bad;
+    }
+  }
+
+  // New partitions must specify type, begin, and size.
+  if (IsZero(&entry->type)) {
+    if (!set_begin || !set_size || !set_type) {
+      Error("-t, -b, and -s options are required for new partitions\n");
+      goto bad;
+    }
+    if (IsZero(&type_guid)) {
+      Error("New partitions must have a type other than \"unused\"\n");
+      goto bad;
+    }
+    if (!set_unique)
+      uuid_generate((uint8_t *)&entry->unique);
+  }
+
+  if (set_begin)
+    entry->starting_lba = begin;
+  if (set_size)
+    entry->ending_lba = begin + size - 1;
+  if (set_type)
+    memcpy(&entry->type, &type_guid, sizeof(Guid));
+  if (set_unique)
+    memcpy(&entry->unique, &unique_guid, sizeof(Guid));
+  if (label) {
+    uint16_t buf[128];
+    UTF8ToUTF16((uint8_t *)label, buf);
+    memcpy(entry->name, buf, sizeof(entry->name));
+  }
+  if (set_raw) {
+    entry->attributes = raw_value;
+  } else {
+    if (set_successful)
+      SetSuccessful(&drive.gpt, PRIMARY, index, successful);
+    if (set_tries)
+      SetTries(&drive.gpt, PRIMARY, index, tries);
+    if (set_priority)
+      SetPriority(&drive.gpt, PRIMARY, index, priority);
+  }
+
+  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);
+
+
+  // Write it all out
+  return DriveClose(&drive, 1);
+
+bad:
+  (void) DriveClose(&drive, 0);
+  return CGPT_FAILED;
+}
diff --git a/cgpt/cmd_boot.c b/cgpt/cmd_boot.c
new file mode 100644
index 0000000..784684a
--- /dev/null
+++ b/cgpt/cmd_boot.c
@@ -0,0 +1,167 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cgpt.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <uuid/uuid.h>
+
+#include "cgptlib_internal.h"
+#include "endian.h"
+
+static void Usage(void)
+{
+  printf("\nUsage: %s boot [OPTIONS] DRIVE\n\n"
+         "Edit the PMBR sector for legacy BIOSes\n\n"
+         "Options:\n"
+         "  -i NUM       Set bootable partition\n"
+         "  -b FILE      Install bootloader code in the PMBR\n"
+         "  -p           Create legacy PMBR partition table\n"
+         "\n"
+         "With no options, it will just print the PMBR boot guid\n"
+         "\n", progname);
+}
+
+
+int cmd_boot(int argc, char *argv[]) {
+  struct drive drive;
+  int partition = 0;
+  char *bootfile = 0;
+  int create_pmbr = 0;
+  int retval = 1;
+  int gpt_retval;
+  
+  int c;
+  int errorcnt = 0;
+  char *e = 0;
+
+  opterr = 0;                     // quiet, you
+  while ((c=getopt(argc, argv, ":hi:b:p")) != -1)
+  {
+    switch (c)
+    {
+    case 'i':
+      partition = (uint32_t)strtoul(optarg, &e, 0);
+      if (!*optarg || (e && *e))
+      {
+        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
+        errorcnt++;
+      }
+      break;
+    case 'b':
+      bootfile = optarg;
+      break;
+    case 'p':
+      create_pmbr = 1;
+      break;
+      
+    case 'h':
+      Usage();
+      return CGPT_OK;
+    case '?':
+      Error("unrecognized option: -%c\n", optopt);
+      errorcnt++;
+      break;
+    case ':':
+      Error("missing argument to -%c\n", optopt);
+      errorcnt++;
+      break;
+    default:
+      errorcnt++;
+      break;
+    }
+  }
+  if (errorcnt)
+  {
+    Usage();
+    return CGPT_FAILED;
+  }
+
+  if (optind >= argc) {
+    Error("missing drive argument\n");
+    return CGPT_FAILED;
+  }
+
+  if (CGPT_OK != DriveOpen(argv[optind], &drive))
+    return CGPT_FAILED;
+
+  if (CGPT_OK != ReadPMBR(&drive)) {
+    Error("Unable to read PMBR\n");
+    goto done;
+  }
+    
+  if (create_pmbr) {
+    drive.pmbr.magic[0] = 0x1d;
+    drive.pmbr.magic[1] = 0x9a;
+    drive.pmbr.sig[0] = 0x55;
+    drive.pmbr.sig[1] = 0xaa;
+    memset(&drive.pmbr.part, 0, sizeof(drive.pmbr.part));
+    drive.pmbr.part[0].f_head = 0x00;
+    drive.pmbr.part[0].f_sect = 0x02;
+    drive.pmbr.part[0].f_cyl = 0x00;
+    drive.pmbr.part[0].type = 0xee;
+    drive.pmbr.part[0].l_head = 0xff;
+    drive.pmbr.part[0].l_sect = 0xff;
+    drive.pmbr.part[0].l_cyl = 0xff;
+    drive.pmbr.part[0].f_lba = htole32(1);
+    uint32_t max = 0xffffffff;
+    if (drive.gpt.drive_sectors < 0xffffffff)
+      max = drive.gpt.drive_sectors - 1;
+    drive.pmbr.part[0].num_sect = htole32(max);
+  }
+
+  if (partition) {
+    if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
+      Error("GptSanityCheck() returned %d: %s\n",
+            gpt_retval, GptError(gpt_retval));
+      goto done;
+    }
+
+    if (partition > GetNumberOfEntries(&drive.gpt)) {
+      Error("invalid partition number: %d\n", partition);
+      goto done;
+    }
+
+    int index = partition - 1;
+    GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index);
+    memcpy(&drive.pmbr.boot_guid, &entry->unique, sizeof(Guid));
+  }
+
+  if (bootfile) {
+    int fd = open(bootfile, O_RDONLY);
+    if (fd < 0) {
+      Error("Can't read %s: %s\n", bootfile, strerror(errno));
+      goto done;
+    }
+
+    int n = read(fd, drive.pmbr.bootcode, sizeof(drive.pmbr.bootcode));
+    if (n < 1) {
+      Error("problem reading %s: %s\n", bootfile, strerror(errno));
+      close(fd);
+      goto done;
+    }
+
+    close(fd);
+  }
+      
+  char buf[256];
+  GuidToStr(&drive.pmbr.boot_guid, buf);
+  printf("%s\n", buf);
+
+  // Write it all out
+  if (CGPT_OK == WritePMBR(&drive))
+    retval = 0;
+
+done:
+  (void) DriveClose(&drive, 1);
+  return retval;
+}
diff --git a/cgpt/cmd_create.c b/cgpt/cmd_create.c
new file mode 100644
index 0000000..4e6eb65
--- /dev/null
+++ b/cgpt/cmd_create.c
@@ -0,0 +1,106 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cgpt.h"
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uuid/uuid.h>
+
+#include "cgptlib_internal.h"
+
+static void Usage(void)
+{
+  printf("\nUsage: %s create [OPTIONS] DRIVE\n\n"
+         "Create or reset an empty GPT.\n\n"
+         "Options:\n"
+         "  -z           Zero the sectors of the GPT table and entries\n"
+         "\n", progname);
+}
+
+int cmd_create(int argc, char *argv[]) {
+  struct drive drive;
+  int zap = 0;
+  
+  int c;
+  int errorcnt = 0;
+
+  opterr = 0;                     // quiet, you
+  while ((c=getopt(argc, argv, ":hz")) != -1)
+  {
+    switch (c)
+    {
+    case 'z':
+      zap = 1;
+      break;
+
+    case 'h':
+      Usage();
+      return CGPT_OK;
+    case '?':
+      Error("unrecognized option: -%c\n", optopt);
+      errorcnt++;
+      break;
+    case ':':
+      Error("missing argument to -%c\n", optopt);
+      errorcnt++;
+      break;
+    default:
+      errorcnt++;
+      break;
+    }
+  }
+  if (errorcnt)
+  {
+    Usage();
+    return CGPT_FAILED;
+  }
+
+  if (optind >= argc) {
+    Usage();
+    return CGPT_FAILED;
+  }
+
+  if (CGPT_OK != DriveOpen(argv[optind], &drive))
+    return CGPT_FAILED;
+
+  // Erase the data
+  memset(drive.gpt.primary_header, 0,
+         drive.gpt.sector_bytes * GPT_HEADER_SECTOR);
+  memset(drive.gpt.secondary_header, 0,
+         drive.gpt.sector_bytes * GPT_HEADER_SECTOR);
+  memset(drive.gpt.primary_entries, 0,
+         drive.gpt.sector_bytes * GPT_ENTRIES_SECTORS);
+  memset(drive.gpt.secondary_entries, 0,
+         drive.gpt.sector_bytes * GPT_ENTRIES_SECTORS);
+  
+  drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
+                         GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
+
+  // Initialize a blank set
+  if (!zap)
+  {
+    GptHeader *h = (GptHeader *)drive.gpt.primary_header;
+    memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE);
+    h->revision = GPT_HEADER_REVISION;
+    h->size = sizeof(GptHeader);
+    h->my_lba = 1;
+    h->first_usable_lba = 1 + 1 + GPT_ENTRIES_SECTORS;
+    h->last_usable_lba = drive.gpt.drive_sectors - 1 - GPT_ENTRIES_SECTORS - 1;
+    uuid_generate((uint8_t *)&h->disk_uuid);
+    h->entries_lba = 2;
+    h->number_of_entries = 128;
+    h->size_of_entry = sizeof(GptEntry);
+
+    // Copy to secondary
+    RepairHeader(&drive.gpt, MASK_PRIMARY);
+
+    UpdateCrc(&drive.gpt);
+  }
+
+  // Write it all out
+  return DriveClose(&drive, 1);
+}
diff --git a/cgpt/cmd_repair.c b/cgpt/cmd_repair.c
new file mode 100644
index 0000000..aafdc93
--- /dev/null
+++ b/cgpt/cmd_repair.c
@@ -0,0 +1,85 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cgpt.h"
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cgptlib_internal.h"
+
+static void Usage(void)
+{
+  printf("\nUsage: %s repair [OPTIONS] DRIVE\n\n"
+         "Repair damaged GPT headers and tables.\n\n"
+         "Options:\n"
+         "  -v           Verbose\n"
+         "\n", progname);
+}
+
+int cmd_repair(int argc, char *argv[]) {
+  struct drive drive;
+  int verbose = 0;
+  
+  int c;
+  int errorcnt = 0;
+
+  opterr = 0;                     // quiet, you
+  while ((c=getopt(argc, argv, ":hv")) != -1)
+  {
+    switch (c)
+    {
+    case 'v':
+      verbose++;
+      break;
+
+    case 'h':
+      Usage();
+      return CGPT_OK;
+    case '?':
+      Error("unrecognized option: -%c\n", optopt);
+      errorcnt++;
+      break;
+    case ':':
+      Error("missing argument to -%c\n", optopt);
+      errorcnt++;
+      break;
+    default:
+      errorcnt++;
+      break;
+    }
+  }
+  if (errorcnt)
+  {
+    Usage();
+    return CGPT_FAILED;
+  }
+
+  if (optind >= argc) {
+    Error("missing drive argument\n");
+    return CGPT_FAILED;
+  }
+
+  if (CGPT_OK != DriveOpen(argv[optind], &drive))
+    return CGPT_FAILED;
+
+  int gpt_retval = GptSanityCheck(&drive.gpt);
+  if (verbose)
+    printf("GptSanityCheck() returned %d: %s\n",
+           gpt_retval, GptError(gpt_retval));
+
+  GptRepair(&drive.gpt);
+  if (drive.gpt.modified & GPT_MODIFIED_HEADER1)
+    printf("Primary Header is updated.\n");
+  if (drive.gpt.modified & GPT_MODIFIED_ENTRIES1)
+    printf("Primary Entries is updated.\n");
+  if (drive.gpt.modified & GPT_MODIFIED_ENTRIES2)
+    printf("Secondary Entries is updated.\n");
+  if (drive.gpt.modified & GPT_MODIFIED_HEADER2)
+    printf("Secondary Header is updated.\n");
+
+  return DriveClose(&drive, 1);
+}
diff --git a/cgpt/cmd_show.c b/cgpt/cmd_show.c
new file mode 100644
index 0000000..9f52cb1
--- /dev/null
+++ b/cgpt/cmd_show.c
@@ -0,0 +1,413 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cgpt.h"
+
+#define __STDC_FORMAT_MACROS
+#include <getopt.h>
+#include <inttypes.h> 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cgptlib_internal.h"
+
+static void Usage(void)
+{
+  printf("\nUsage: %s show [OPTIONS] DRIVE\n\n"
+         "Display the GPT table\n\n"
+         "Options:\n"
+         "  -n           Numeric output only\n"
+         "  -v           Verbose output\n"
+         "  -q           Quick output\n"
+         "  -i NUM       Show specified partition only - pick one of:\n"
+         "               -b  beginning sector\n"
+         "               -s  partition size\n"
+         "               -t  type guid\n"
+         "               -u  unique guid\n"
+         "               -l  label\n"
+         "               -S  Successful flag\n"
+         "               -T  Tries flag\n"
+         "               -P  Priority flag\n"
+         "               -A  raw 64-bit attribute value\n"
+         "\n", progname);
+}
+
+
+/* Generate output like:
+ *
+ *  [AB-CD-EF-01]   for group = 1
+ *  [ABCD-EF01]     for group = 3  (low byte first)
+ *
+ * Needs (size*3-1+3) bytes of space in 'buf' (included the tailing '\0').
+ */
+#define BUFFER_SIZE(size) (size *3 - 1 + 3)
+static short Uint8To2Chars(const uint8_t t) {
+  int h = t >> 4;
+  int l = t & 0xf;
+  h = (h >= 0xA) ? h - 0xA + 'A' : h + '0';
+  l = (l >= 0xA) ? l - 0xA + 'A' : l + '0';
+  return (h << 8) + l;
+}
+static void RawDump(const uint8_t *memory, const int size,
+                    char *buf, int group) {
+  int i, outlen = 0;
+  buf[outlen++] = '[';
+  for (i = 0; i < size; ++i) {
+    short c2 = Uint8To2Chars(memory[i]);
+    buf[outlen++] = c2 >> 8;
+    buf[outlen++] = c2 & 0xff;
+    if (i != (size - 1) && ((i + 1) % group) == 0)
+      buf[outlen++] = '-';
+  }
+  buf[outlen++] = ']';
+  buf[outlen++] = '\0';
+}
+
+/* Output formatters */
+
+
+
+#define TITLE_FMT      "%10s%10s%8s  %s\n"
+#define GPT_FMT        "%10d%10d%8s  %s\n"
+#define GPT_MORE       "%10s%10s%8s  ", "", "", ""
+#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, int raw) {
+  int i;
+
+  printf("%sSig: ", indent);
+  if (!raw) {
+    printf("["); 
+    for (i = 0; i < sizeof(header->signature); ++i)
+      printf("%c", header->signature[i]);
+    printf("]");
+  } else {
+    char buf[BUFFER_SIZE(sizeof(header->signature))];
+    RawDump((uint8_t *)header->signature, sizeof(header->signature), buf, 1);
+    printf("%s", buf);
+  }
+  printf("\n");
+
+  printf("%sRev: 0x%08x\n", indent, header->revision);
+  printf("%sSize: %d\n", indent, header->size);
+  printf("%sHeader CRC: 0x%08x\n", indent, header->header_crc32);
+  printf("%sMy LBA: %lld\n", indent, (long long)header->my_lba);
+  printf("%sFirst LBA: %lld\n", indent, (long long)header->first_usable_lba);
+  printf("%sLast LBA: %lld\n", indent, (long long)header->last_usable_lba);
+
+  {  /* For disk guid */
+    char buf[GUID_STRLEN];
+    GuidToStr(&header->disk_uuid, buf);
+    printf("%sDisk UUID: %s\n", indent, buf);
+  }
+
+  printf("%sEntries LBA: %lld\n", indent, (long long)header->entries_lba);
+  printf("%sNumber of entries: %d\n", indent, header->number_of_entries);
+  printf("%sSize of entry: %d\n", indent, header->size_of_entry);
+  printf("%sEntries CRC: 0x%08x\n", indent, header->entries_crc32);
+}
+
+void EntryDetails(GptEntry *entry, int index, int raw) {
+  char contents[256];
+  uint8_t label[sizeof(entry->name) * 3 / 2];
+
+  if (!raw) {
+    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 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);
+    GuidToStr(&entry->type, type);
+    printf(PARTITION_MORE, "Type: ", type);
+    GuidToStr(&entry->unique, unique);
+    printf(PARTITION_MORE, "UUID: ", unique);
+    snprintf(contents, sizeof(contents), "[%" PRIx64 "]", 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) {
+    GptEntry *entry;
+    entry = GetEntry(gpt, secondary, i);
+
+    if (!memcmp(&guid_unused, &entry->type, sizeof(Guid))) continue;
+
+    EntryDetails(entry, i, raw);
+  }
+}
+
+int cmd_show(int argc, char *argv[]) {
+  struct drive drive;
+  int numeric = 0;
+  int verbose = 0;
+  int quick = 0;
+  int partition = 0; 
+  int single_item = 0;
+  int gpt_retval;
+
+  int c;
+  int errorcnt = 0;
+  char *e = 0;
+
+  opterr = 0;                     // quiet, you
+  while ((c=getopt(argc, argv, ":hnvqi:bstulSTPA")) != -1)
+  {
+    switch (c)
+    {
+    case 'n':
+      numeric = 1;
+      break;
+    case 'v':
+      verbose = 1;
+      break;
+    case 'q':
+      quick = 1;
+      break;
+    case 'i':
+      partition = (uint32_t)strtoul(optarg, &e, 0);
+      if (!*optarg || (e && *e))
+      {
+        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
+        errorcnt++;
+      }
+      break;
+    case 'b':
+    case 's':
+    case 't':
+    case 'u':
+    case 'l':
+    case 'S':
+    case 'T':
+    case 'P':
+    case 'A':
+      single_item = c;
+      break;
+
+    case 'h':
+      Usage();
+      return CGPT_OK;
+    case '?':
+      Error("unrecognized option: -%c\n", optopt);
+      errorcnt++;
+      break;
+    case ':':
+      Error("missing argument to -%c\n", optopt);
+      errorcnt++;
+      break;
+    default:
+      errorcnt++;
+      break;
+    }
+  }
+  if (errorcnt)
+  {
+    Usage();
+    return CGPT_FAILED;
+  }
+
+  if (optind >= argc) {
+    Error("missing drive argument\n");
+    Usage();
+    return CGPT_FAILED;
+  }
+
+  if (CGPT_OK != DriveOpen(argv[optind], &drive))
+    return CGPT_FAILED;
+
+  if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
+    Error("GptSanityCheck() returned %d: %s\n",
+          gpt_retval, GptError(gpt_retval));
+    return CGPT_FAILED;
+  }
+
+  if (partition) {                      // show single partition
+
+    if (partition > GetNumberOfEntries(&drive.gpt)) {
+      Error("invalid partition number: %d\n", partition);
+      return CGPT_FAILED;
+    }
+
+    int index = partition - 1;
+    GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index);
+    char buf[256];
+
+    if (single_item) {
+      switch(single_item) {
+      case 'b':
+        printf("%" PRId64 "\n", entry->starting_lba);
+        break;
+      case 's':
+        printf("%" PRId64 "\n", entry->ending_lba - entry->starting_lba + 1);
+        break;
+      case 't':
+        GuidToStr(&entry->type, buf);
+        printf("%s\n", buf);
+        break;
+      case 'u':
+        GuidToStr(&entry->unique, buf);
+        printf("%s\n", buf);
+        break;
+      case 'l':
+        UTF16ToUTF8(entry->name, (uint8_t *)buf);
+        printf("%s\n", buf);
+        break;
+      case 'S':
+        printf("%d\n", GetSuccessful(&drive.gpt, PRIMARY, index));
+        break;
+      case 'T':
+        printf("%d\n", GetTries(&drive.gpt, PRIMARY, index));
+        break;
+      case 'P':
+        printf("%d\n", GetPriority(&drive.gpt, PRIMARY, index));
+        break;
+      case 'A':
+        printf("0x%" PRIx64 "\n", entry->attributes);
+        break;
+      }
+    } else {
+      printf(TITLE_FMT, "start", "size", "part", "contents");
+      EntryDetails(entry, index, numeric);
+    }
+
+  } else if (quick) {                   // show all partitions, quickly
+    int i;
+    GptEntry *entry;
+    char type[GUID_STRLEN];
+
+    for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) {
+      entry = GetEntry(&drive.gpt, PRIMARY, i);
+
+      if (IsZero(&entry->type))
+        continue;
+
+      if (!numeric && CGPT_OK == ResolveType(&entry->type, type)) {
+      } else {
+        GuidToStr(&entry->type, type);
+      }
+      printf(PARTITION_FMT, (int)entry->starting_lba,
+             (int)(entry->ending_lba - entry->starting_lba + 1),
+             i+1, type);
+    }
+
+  } else {                              // show all partitions
+
+    if (CGPT_OK != ReadPMBR(&drive)) {
+      Error("Unable to read PMBR\n");
+      return CGPT_FAILED;
+    }
+
+    printf(TITLE_FMT, "start", "size", "part", "contents");
+    char buf[256];
+    PMBRToStr(&drive.pmbr, buf);
+    printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", buf);
+
+    if (drive.gpt.valid_headers & MASK_PRIMARY) {
+      printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
+             (int)GPT_HEADER_SECTOR, "", "Pri GPT header");
+      if (verbose) {
+        GptHeader *header;
+        char indent[64];
+
+        snprintf(indent, sizeof(indent), GPT_MORE);
+        header = (GptHeader*)drive.gpt.primary_header;
+        HeaderDetails(header, indent, numeric);
+      }
+    } else {
+      printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
+             (int)GPT_HEADER_SECTOR, "INVALID", "Pri GPT header");
+    }
+
+    printf(GPT_FMT, (int)(GPT_PMBR_SECTOR + GPT_HEADER_SECTOR),
+           (int)GPT_ENTRIES_SECTORS,
+           drive.gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
+           "Pri GPT table");
+
+    if (drive.gpt.valid_entries & MASK_PRIMARY)
+      EntriesDetails(&drive.gpt, PRIMARY, numeric);
+
+    printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR -
+                          GPT_ENTRIES_SECTORS),
+           (int)GPT_ENTRIES_SECTORS,
+           drive.gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
+           "Sec GPT table");
+    /* We show secondary table details if any of following is true.
+     *   1. only secondary is valid.
+     *   2. secondary is not identical to promary.
+     */
+    if ((drive.gpt.valid_entries & MASK_SECONDARY) &&
+        (!(drive.gpt.valid_entries & MASK_PRIMARY) ||
+         memcmp(drive.gpt.primary_entries, drive.gpt.secondary_entries,
+                TOTAL_ENTRIES_SIZE))) {
+      EntriesDetails(&drive.gpt, SECONDARY, numeric);
+    }
+
+    if (drive.gpt.valid_headers & MASK_SECONDARY)
+      printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR),
+             (int)GPT_HEADER_SECTOR, "", "Sec GPT header");
+    else
+      printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
+             (int)GPT_HEADER_SECTOR, "INVALID", "Sec GPT header");
+    /* We show secondary header if any of following is true:
+     *   1. only secondary is valid.
+     *   2. secondary is not synonymous to primary.
+     */
+    if ((drive.gpt.valid_headers & MASK_SECONDARY) &&
+        (!(drive.gpt.valid_headers & MASK_PRIMARY) ||
+         !IsSynonymous((GptHeader*)drive.gpt.primary_header,
+                       (GptHeader*)drive.gpt.secondary_header))) {
+      if (verbose) {
+        GptHeader *header;
+        char indent[64];
+
+        snprintf(indent, sizeof(indent), GPT_MORE);
+        header = (GptHeader*)drive.gpt.secondary_header;
+        HeaderDetails(header, indent, numeric);
+      }
+    }
+  }
+
+  (void) CheckValid(&drive);
+  (void) DriveClose(&drive, 0);
+
+  return CGPT_OK;
+}
+
+
+
diff --git a/cgpt/endian.h b/cgpt/endian.h
new file mode 100644
index 0000000..ab62ebc
--- /dev/null
+++ b/cgpt/endian.h
@@ -0,0 +1,44 @@
+#ifndef VBOOT_REFERENCE_UTILITY_CGPT_ENDIAN_H_
+#define VBOOT_REFERENCE_UTILITY_CGPT_ENDIAN_H_
+
+// Newer distros already have this. For those that don't, we add it here.
+#include <endian.h>
+
+#ifndef le16toh
+
+# include <byteswap.h>
+
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+#  define htobe16(x) __bswap_16 (x)
+#  define htole16(x) (x)
+#  define be16toh(x) __bswap_16 (x)
+#  define le16toh(x) (x)
+
+#  define htobe32(x) __bswap_32 (x)
+#  define htole32(x) (x)
+#  define be32toh(x) __bswap_32 (x)
+#  define le32toh(x) (x)
+
+#  define htobe64(x) __bswap_64 (x)
+#  define htole64(x) (x)
+#  define be64toh(x) __bswap_64 (x)
+#  define le64toh(x) (x)
+# else
+#  define htobe16(x) (x)
+#  define htole16(x) __bswap_16 (x)
+#  define be16toh(x) (x)
+#  define le16toh(x) __bswap_16 (x)
+
+#  define htobe32(x) (x)
+#  define htole32(x) __bswap_32 (x)
+#  define be32toh(x) (x)
+#  define le32toh(x) __bswap_32 (x)
+
+#  define htobe64(x) (x)
+#  define htole64(x) __bswap_64 (x)
+#  define be64toh(x) (x)
+#  define le64toh(x) __bswap_64 (x)
+# endif
+
+#endif
+#endif  // VBOOT_REFERENCE_UTILITY_CGPT_ENDIAN_H_
diff --git a/tests/Makefile b/tests/Makefile
index d52b282..5ad4b74 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -126,6 +126,8 @@
 	./kernel_rollback_tests
 	# Helper Library Tests
 	./cgptlib_test
+	# Tool tests
+	./run_cgpt_tests.sh
 
 clean:
 	rm -f $(TEST_BINS)
diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c
index 1ab5342..f016b21 100644
--- a/tests/cgptlib_test.c
+++ b/tests/cgptlib_test.c
@@ -136,8 +136,8 @@
   Memcpy(header->signature, GPT_HEADER_SIGNATURE,
          sizeof(GPT_HEADER_SIGNATURE));
   header->revision = GPT_HEADER_REVISION;
-  header->size = sizeof(GptHeader) - sizeof(header->padding);
-  header->reserved = 0;
+  header->size = sizeof(GptHeader);
+  header->reserved_zero = 0;
   header->my_lba = 1;
   header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
   header->first_usable_lba = 34;
@@ -157,7 +157,6 @@
   Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
   entries[3].starting_lba = 334;
   entries[3].ending_lba = 430;
-  Memset(header->padding, 0, sizeof(header->padding));
 
   /* build secondary */
   header2 = (GptHeader*)gpt->secondary_header;
@@ -355,8 +354,8 @@
   GptHeader* h2 = (GptHeader*)gpt->secondary_header;
 
   BuildTestGptData(gpt);
-  h1->reserved ^= 0x12345678;  /* whatever random */
-  h2->reserved ^= 0x12345678;  /* whatever random */
+  h1->reserved_zero ^= 0x12345678;  /* whatever random */
+  h2->reserved_zero ^= 0x12345678;  /* whatever random */
   RefreshCrc32(gpt);
   EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
   EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
diff --git a/tests/common.sh b/tests/common.sh
index 421f629..6afcd77 100755
--- a/tests/common.sh
+++ b/tests/common.sh
@@ -30,10 +30,21 @@
 hash_algos=( sha1 sha256 sha512 )
 key_lengths=( 1024 2048 4096 8192 ) 
 
-function check_test_keys {
-  if [ ! -d ${TESTKEY_DIR} ]
-  then
-    echo "You must run gen_test_keys.sh to generate test keys first."
-    exit 1
-  fi
+function happy {
+  echo -e "${COL_GREEN}$*${COL_STOP}" 1>&2
 }
+
+function warning {
+  echo -e "${COL_YELLOW}WARNING: $*${COL_STOP}" 1>&2
+}
+
+function error {
+  echo -e "${COL_RED}ERROR: $*${COL_STOP}" 1>&2
+  exit 1
+}
+
+function check_test_keys {
+  [ -d ${TESTKEY_DIR} ] || \
+    error "You must run gen_test_keys.sh to generate test keys first."
+}
+
diff --git a/tests/run_cgpt_tests.sh b/tests/run_cgpt_tests.sh
new file mode 100755
index 0000000..2dcca99
--- /dev/null
+++ b/tests/run_cgpt_tests.sh
@@ -0,0 +1,114 @@
+#!/bin/bash -eu
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Run tests for RSA Signature verification.
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+GPT=${1:-../cgpt/cgpt}
+[ -x "$GPT" ] || error "Can't execute $GPT"
+warning "testing $GPT"
+
+echo "Create an empty file to use as the device..."
+NUM_SECTORS=1000
+DEV=$(mktemp)
+BOOTFILE=$(mktemp)
+dd if=/dev/zero of=${DEV} conv=notrunc bs=512 count=${NUM_SECTORS} 2>/dev/null
+trap "rm -f ${DEV}" EXIT
+
+
+echo "Create a bunch of partitions, using the real GUID types..."
+DATA_START=100
+DATA_SIZE=20
+DATA_LABEL="data stuff"
+DATA_GUID='ebd0a0a2-b9e5-4433-87c0-68b6b72699c7'
+DATA_NUM=1
+
+KERN_START=200
+KERN_SIZE=30
+KERN_LABEL="kernel stuff"
+KERN_GUID='fe3a2a5d-4f32-41a7-b725-accc3285a309'
+KERN_NUM=2
+
+ROOTFS_START=300
+ROOTFS_SIZE=40
+ROOTFS_LABEL="rootfs stuff"
+ROOTFS_GUID='3cb8e202-3b7e-47dd-8a3c-7ff2a13cfcec'
+ROOTFS_NUM=3
+
+ESP_START=400
+ESP_SIZE=50
+ESP_LABEL="ESP stuff"
+ESP_GUID='c12a7328-f81f-11d2-ba4b-00a0c93ec93b'
+ESP_NUM=4
+
+FUTURE_START=500
+FUTURE_SIZE=60
+FUTURE_LABEL="future stuff"
+FUTURE_GUID='2e0a753d-9e48-43b0-8337-b15192cb1b5e'
+FUTURE_NUM=5
+
+RANDOM_START=600
+RANDOM_SIZE=70
+RANDOM_LABEL="random stuff"
+RANDOM_GUID='2364a860-bf63-42fb-a83d-9ad3e057fcf5'
+RANDOM_NUM=6
+
+$GPT create ${DEV}
+
+$GPT add -b ${DATA_START} -s ${DATA_SIZE} -t ${DATA_GUID} \
+  -l "${DATA_LABEL}" ${DEV}
+$GPT add -b ${KERN_START} -s ${KERN_SIZE} -t ${KERN_GUID} \
+  -l "${KERN_LABEL}" ${DEV}
+$GPT add -b ${ROOTFS_START} -s ${ROOTFS_SIZE} -t ${ROOTFS_GUID} \
+  -l "${ROOTFS_LABEL}" ${DEV}
+$GPT add -b ${ESP_START} -s ${ESP_SIZE} -t ${ESP_GUID} \
+  -l "${ESP_LABEL}" ${DEV}
+$GPT add -b ${FUTURE_START} -s ${FUTURE_SIZE} -t ${FUTURE_GUID} \
+  -l "${FUTURE_LABEL}" ${DEV}
+$GPT add -b ${RANDOM_START} -s ${RANDOM_SIZE} -t ${RANDOM_GUID} \
+  -l "${RANDOM_LABEL}" ${DEV}
+
+
+echo "Extract the start and size of given partitions..."
+
+X=$($GPT show -b -i $DATA_NUM ${DEV})
+Y=$($GPT show -s -i $DATA_NUM ${DEV})
+[ "$X $Y" = "$DATA_START $DATA_SIZE" ] || error "fail at line $LINENO"
+
+X=$($GPT show -b -i $KERN_NUM ${DEV})
+Y=$($GPT show -s -i $KERN_NUM ${DEV})
+[ "$X $Y" = "$KERN_START $KERN_SIZE" ] || error "fail at line $LINENO"
+
+X=$($GPT show -b -i $ROOTFS_NUM ${DEV})
+Y=$($GPT show -s -i $ROOTFS_NUM ${DEV})
+[ "$X $Y" = "$ROOTFS_START $ROOTFS_SIZE" ] || error "fail at line $LINENO"
+
+X=$($GPT show -b -i $ESP_NUM ${DEV})
+Y=$($GPT show -s -i $ESP_NUM ${DEV})
+[ "$X $Y" = "$ESP_START $ESP_SIZE" ] || error "fail at line $LINENO"
+
+X=$($GPT show -b -i $FUTURE_NUM ${DEV})
+Y=$($GPT show -s -i $FUTURE_NUM ${DEV})
+[ "$X $Y" = "$FUTURE_START $FUTURE_SIZE" ] || error "fail at line $LINENO"
+
+X=$($GPT show -b -i $RANDOM_NUM ${DEV})
+Y=$($GPT show -s -i $RANDOM_NUM ${DEV})
+[ "$X $Y" = "$RANDOM_START $RANDOM_SIZE" ] || error "fail at line $LINENO"
+
+
+echo "Set the boot partition.."
+$GPT boot -i ${KERN_NUM} ${DEV} >/dev/null
+
+echo "Check the PMBR's idea of the boot partition..."
+X=$($GPT boot ${DEV})
+Y=$($GPT show -u -i $KERN_NUM $DEV)
+[ "$X" = "$Y" ] || error "fail at line $LINENO"
+
+echo "Done."
+
+happy "All tests passed."
diff --git a/utility/Makefile b/utility/Makefile
index 666f773..697cc9e 100644
--- a/utility/Makefile
+++ b/utility/Makefile
@@ -22,9 +22,8 @@
 	$(TOP)/vkernel/kernel_image.o \
 	$(HOSTLIB) \
 	$(FWLIB)
-SUBDIRS = cgpt
 
-DESTDIR ?= /opt/bin
+DESTDIR ?= /usr/bin
 
 TARGET_BINS = dumpRSAPublicKey \
 		firmware_utility \
@@ -36,14 +35,7 @@
 		vbutil_keyblock \
 		verify_data
 
-all: $(TARGET_BINS) subdirs
-
-.PHONY: subdirs
-subdirs:
-	set -e; \
-	for i in $(SUBDIRS); do \
-		$(MAKE) -C $$i $(MAKECMDGOALS); \
-	done
+all: $(TARGET_BINS)
 
 dumpRSAPublicKey: dumpRSAPublicKey.c
 	$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ -lcrypto
@@ -75,13 +67,9 @@
 	$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) -lcrypto
 
 clean:
-	set -e; \
-	for i in $(SUBDIRS); do \
-		$(MAKE) -C $$i clean; \
-	done
 	rm -f $(TARGET_BINS)
 
-install: $(TARGET_BINS) subdirs
+install: $(TARGET_BINS)
 	mkdir -p $(DESTDIR)
 	cp -f $(TARGET_BINS) $(DESTDIR)
 	chmod a+rx $(patsubst %,$(DESTDIR)/%,$(TARGET_BINS))
diff --git a/utility/cgpt/Makefile b/utility/cgpt/Makefile
deleted file mode 100644
index 78de27f..0000000
--- a/utility/cgpt/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-
-# Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-TOP ?= ../../
-CC ?= cc
-# Include /usr/include from inside the chroot, so that we get a version
-# of endian.h which contains endian-conversion macros - htole32(), etc.
-INCLUDES += -I$(TOP)/common/include -I$(TOP)/../../../chroot/usr/include/
-CFLAGS += -Wall -Werror -ggdb
-LIBS += $(FWLIB)
-
-DESTDIR ?= /opt/bin
-
-all: cgpt
-
-cgpt: cgpt.o cgpt_add_modify_delete.o cgpt_attribute.o cgpt_dev.o \
-      cgpt_options.o cgpt_repair.o cgpt_show.o cgpt_tofix.o $(LIBS)
-	$(CC) -o cgpt $(CFLAGS) $^
-
-.c.o: $(INCLUDES)
-	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
-clean:
-	rm -f cgpt *.o *~
-
-install: cgpt
-	mkdir -p $(DESTDIR)
-	cp -f $^ $(DESTDIR)
-	chmod a+rx $(patsubst %,$(DESTDIR)/%,$^)
diff --git a/utility/cgpt/cgpt.c b/utility/cgpt/cgpt.c
deleted file mode 100644
index 5bcba17..0000000
--- a/utility/cgpt/cgpt.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c
- * files for more details.
- */
-/* To compile on host without compatility to BSD, we include
- * endian.h under chroot. */
-#define _BSD_SOURCE
-#include "endian.h"
-
-#define __USE_LARGEFILE64
-#define __USE_FILE_OFFSET64
-#define _LARGEFILE64_SOURCE
-#include "cgpt.h"
-#include "cgpt_tofix.h"
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include "cgptlib_internal.h"
-#include "utility.h"
-
-/* For usage print */
-const char* progname;
-
-/* Lists all command here. */
-struct {
-  const char *name;
-  int (*fp)(int argc, char *argv[]);
-  const char *comment;
-} cmds[] = {
-  {"add", CgptAdm, "Add a partition to drive"},
-  {"delete", CgptAdm, "Delete a partition on drive"},
-  {"modify", CgptAdm, "Modify the partition on drive"},
-  {"attribute", CgptAttribute, "Update GPT attribute bits "
-                               "(for ChromeOS kernel entry only)"},
-  {"dev", CgptDev, "Developper mode"},
-  {"repair", CgptRepair, "Repair primary and secondary headers and tables"},
-  {"show", CgptShow, "Show partition details"},
-};
-
-/* Shows main menu. If 'message' is non-NULL, shows it as header. Then, this
- * traverses cmds[] and shows supported commands and their comments. */
-void Usage(const char *message) {
-  int i;
-
-  if (message) printf("%s\n", message);
-  printf("Usage: %s COMMAND [OPTIONS]\n\n"
-         "Supported COMMANDs:\n\n",
-         progname);
-  for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
-    printf("    %-10s  %s\n", cmds[i].name, cmds[i].comment);
-  }
-  printf("\nFor more detailed usage, use %s COMMAND --help.\n\n", progname);
-}
-
-/* GUID conversion functions. Accepted format:
- *
- *   "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
- *
- * Returns CGPT_OK if parsing is successful; otherwise CGPT_FAILED.
- */
-int StrToGuid(const char *str, Guid *guid) {
-  uint32_t time_low, time_mid, time_high_and_version;
-
-  if (11 > sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
-                  &time_low,
-                  (unsigned int *)&time_mid,
-                  (unsigned int *)&time_high_and_version,
-                  (unsigned int *)&guid->u.Uuid.clock_seq_high_and_reserved,
-                  (unsigned int *)&guid->u.Uuid.clock_seq_low,
-                  (unsigned int *)&guid->u.Uuid.node[0],
-                  (unsigned int *)&guid->u.Uuid.node[1],
-                  (unsigned int *)&guid->u.Uuid.node[2],
-                  (unsigned int *)&guid->u.Uuid.node[3],
-                  (unsigned int *)&guid->u.Uuid.node[4],
-                  (unsigned int *)&guid->u.Uuid.node[5])) return CGPT_FAILED;
-
-  guid->u.Uuid.time_low = htole32(time_low);
-  guid->u.Uuid.time_mid = htole16(time_mid);
-  guid->u.Uuid.time_high_and_version = htole16(time_high_and_version);
-
-  return CGPT_OK;
-}
-
-void GuidToStr(const Guid *guid, char *str) {
-  sprintf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
-          le32toh(guid->u.Uuid.time_low), le16toh(guid->u.Uuid.time_mid),
-          le16toh(guid->u.Uuid.time_high_and_version),
-          guid->u.Uuid.clock_seq_high_and_reserved, guid->u.Uuid.clock_seq_low,
-          guid->u.Uuid.node[0], guid->u.Uuid.node[1], guid->u.Uuid.node[2],
-          guid->u.Uuid.node[3], guid->u.Uuid.node[4], guid->u.Uuid.node[5]);
-}
-
-/* Convert UTF16 string to UTF8. Rewritten from gpt utility.
- * Caller must prepare enough space for UTF8. The rough estimation is:
- *
- *   utf8 length = bytecount(utf16) * 1.5
- */
-#define SIZEOF_GPTENTRY_NAME 36  /* sizeof(GptEntry.name[]) */
-void UTF16ToUTF8(const uint16_t *utf16, uint8_t *utf8)
-{
-  size_t s8idx, s16idx, s16len;
-  uint32_t utfchar;
-  unsigned int next_utf16;
-
-  for (s16len = 0; s16len < SIZEOF_GPTENTRY_NAME && utf16[s16len]; ++s16len);
-
-  *utf8 = s8idx = s16idx = 0;
-  while (s16idx < s16len) {
-    utfchar = le16toh(utf16[s16idx++]);
-    if ((utfchar & 0xf800) == 0xd800) {
-      next_utf16 = le16toh(utf16[s16idx]);
-      if ((utfchar & 0x400) != 0 || (next_utf16 & 0xfc00) != 0xdc00)
-        utfchar = 0xfffd;
-      else
-        s16idx++;
-    }
-    if (utfchar < 0x80) {
-      utf8[s8idx++] = utfchar;
-    } else if (utfchar < 0x800) {
-      utf8[s8idx++] = 0xc0 | (utfchar >> 6);
-      utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
-    } else if (utfchar < 0x10000) {
-      utf8[s8idx++] = 0xe0 | (utfchar >> 12);
-      utf8[s8idx++] = 0x80 | ((utfchar >> 6) & 0x3f);
-      utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
-    } else if (utfchar < 0x200000) {
-      utf8[s8idx++] = 0xf0 | (utfchar >> 18);
-      utf8[s8idx++] = 0x80 | ((utfchar >> 12) & 0x3f);
-      utf8[s8idx++] = 0x80 | ((utfchar >> 6) & 0x3f);
-      utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
-    }
-  }
-  utf8[s8idx++] = 0;
-}
-
-/* Convert UTF8 string to UTF16. Rewritten from gpt utility.
- * Caller must prepare enough space for UTF16. The conservative estimation is:
- *
- *   utf16 bytecount = bytecount(utf8) / 3 * 4
- */
-void UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16)
-{
-  size_t s16idx, s8idx, s8len;
-  uint32_t utfchar;
-  unsigned int c, utfbytes;
-
-  for (s8len = 0; utf8[s8len]; ++s8len);
-
-  s8idx = s16idx = 0;
-  utfbytes = 0;
-  do {
-    c = utf8[s8idx++];
-    if ((c & 0xc0) != 0x80) {
-      /* Initial characters. */
-      if (utfbytes != 0) {
-        /* Incomplete encoding. */
-        utf16[s16idx++] = 0xfffd;
-      }
-      if ((c & 0xf8) == 0xf0) {
-        utfchar = c & 0x07;
-        utfbytes = 3;
-      } else if ((c & 0xf0) == 0xe0) {
-        utfchar = c & 0x0f;
-        utfbytes = 2;
-      } else if ((c & 0xe0) == 0xc0) {
-        utfchar = c & 0x1f;
-        utfbytes = 1;
-      } else {
-        utfchar = c & 0x7f;
-        utfbytes = 0;
-      }
-    } else {
-      /* Followup characters. */
-      if (utfbytes > 0) {
-        utfchar = (utfchar << 6) + (c & 0x3f);
-        utfbytes--;
-      } else if (utfbytes == 0)
-        utfbytes = -1;
-        utfchar = 0xfffd;
-    }
-    if (utfbytes == 0) {
-      if (utfchar >= 0x10000) {
-        utf16[s16idx++] = htole16(0xd800 | ((utfchar>>10)-0x40));
-        if (s16idx >= SIZEOF_GPTENTRY_NAME) break;
-        utf16[s16idx++] = htole16(0xdc00 | (utfchar & 0x3ff));
-      } else {
-        utf16[s16idx++] = htole16(utfchar);
-      }
-    }
-  } while (c != 0 && s16idx < SIZEOF_GPTENTRY_NAME);
-  if (s16idx < SIZEOF_GPTENTRY_NAME)
-    utf16[s16idx++] = 0;
-}
-
-struct {
-  Guid type;
-  char *name;
-  char *description;
-} supported_types[] = {
- {GPT_ENT_TYPE_UNUSED, "unused", "Unused 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.
- * Returns CGPT_OK if found.
- * Returns CGPT_FAILED if no known type found. */
-int ResolveType(const Guid *type, char *buf) {
-  int i;
-  for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
-    if (!Memcmp(type, &supported_types[i].type, sizeof(Guid))) {
-      strcpy(buf, supported_types[i].description);
-      return CGPT_OK;
-    }
-  }
-  return CGPT_FAILED;
-}
-
-int SupportedType(const char *name, Guid *type) {
-  int i;
-  for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
-    if (!strcmp(name, supported_types[i].name)) {
-      Memcpy(type, &supported_types[i].type, sizeof(Guid));
-      return CGPT_OK;
-    }
-  }
-  return CGPT_FAILED;
-}
-
-void PrintTypes(void) {
-  int i;
-  printf("\n* For --type option, you can use the following alias, "
-         "instead of hex values:\n");
-  for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
-    printf("  %-10s %s\n", supported_types[i].name,
-                          supported_types[i].description);
-  }
-  printf("\n");
-}
-
-/* Loads sectors from 'fd'.
- * *buf is pointed to an allocated memory when returned, and should be
- * freed by cgpt_close().
- *
- *   fd -- file descriptot.
- *   buf -- pointer to buffer pointer
- *   sector -- offset of starting sector (in sectors)
- *   sector_bytes -- bytes per sector
- *   sector_count -- number of sectors to load
- *
- * Returns CGPT_OK for successful. Aborts if any error occurs.
- */
-int Load(const int fd, uint8_t **buf,
-         const uint64_t sector,
-         const uint64_t sector_bytes,
-         const uint64_t sector_count) {
-  int count;  /* byte count to read */
-  int nread;
-
-  assert(buf);
-  count = sector_bytes * sector_count;
-  *buf = Malloc(count);
-  assert(*buf);
-
-  if (-1 == lseek64(fd, sector * sector_bytes, SEEK_SET))
-    goto error_free;
-
-  nread = read(fd, *buf, count);
-  if (nread < count)
-    goto error_free;
-
-  return CGPT_OK;
-
-error_free:
-  Free(*buf);
-  *buf = 0;
-  abort();
-}
-
-/* Saves sectors to 'fd'.
- *
- *   fd -- file descriptot.
- *   buf -- pointer to buffer
- *   sector -- starting sector offset
- *   sector_bytes -- bytes per sector
- *   sector_count -- number of sector to save
- *
- * Returns CGPT_OK for successful, CGPT_FAILED for failed.
- */
-int Save(const int fd, const uint8_t *buf,
-         const uint64_t sector,
-         const uint64_t sector_bytes,
-         const uint64_t sector_count) {
-  int count;  /* byte count to write */
-  int nwrote;
-
-  assert(buf);
-  count = sector_bytes * sector_count;
-
-  if (-1 == lseek64(fd, sector * sector_bytes, SEEK_SET))
-    return CGPT_FAILED;
-
-  nwrote = write(fd, buf, count);
-  if (nwrote < count)
-    return CGPT_FAILED;
-
-  return CGPT_OK;
-}
-
-int CheckValid(const struct drive *drive) {
-  if ((drive->gpt.valid_headers != MASK_BOTH) ||
-      (drive->gpt.valid_entries != MASK_BOTH)) {
-    printf("\n[ERROR] any of GPT header/entries is invalid, "
-           "please run '%s repair' first\n", progname);
-    return CGPT_FAILED;
-  }
-  return CGPT_OK;
-}
-
-/* Opens a block device (a regular file works well too).
- *
- * Returns CGPT_FAILED if any error happens.
- * Returns CGPT_OK if success and information are stored in 'drive'. */
-int DriveOpen(const char *drive_path, struct drive *drive) {
-  struct stat stat;
-  int gpt_retval;
-
-  assert(drive_path);
-  assert(drive);
-
-  Memset(drive, 0, sizeof(struct drive));
-  drive->fd = open(drive_path, O_RDWR | O_LARGEFILE);
-  if (drive->fd == -1) {
-    printf("[ERROR] Cannot open drive file [%s]: %s\n",
-           drive_path, strerror(errno));
-    return CGPT_FAILED;
-  }
-
-  if (fstat(drive->fd, &stat) == -1) {
-    goto error_close;
-  }
-  if ((stat.st_mode & S_IFMT) != S_IFREG) {
-    if (ioctl(drive->fd, BLKGETSIZE64, &drive->size) < 0) {
-      printf("[ERROR] Cannot get sector size from drive file [%s]: %s\n",
-             drive_path, strerror(errno));
-      goto error_close;
-    }
-    if (ioctl(drive->fd, BLKSSZGET, &drive->gpt.sector_bytes) < 0) {
-      printf("[ERROR] Cannot get drive size from drive file [%s]: %s\n",
-             drive_path, strerror(errno));
-      goto error_close;
-    }
-  } else {
-    drive->gpt.sector_bytes = 512;  /* bytes */
-    drive->size = stat.st_size;
-  }
-  if (drive->size % drive->gpt.sector_bytes) {
-    printf("[ERROR] Media size (%llu) is not the multiple of sector size(%d)\n",
-           (long long unsigned int)drive->size, drive->gpt.sector_bytes);
-    goto error_close;
-  }
-  drive->gpt.drive_sectors = drive->size / drive->gpt.sector_bytes;
-
-  Load(drive->fd, &drive->gpt.primary_header, GPT_PMBR_SECTOR,
-       drive->gpt.sector_bytes, GPT_HEADER_SECTOR);
-  Load(drive->fd, &drive->gpt.secondary_header,
-       drive->gpt.drive_sectors - GPT_PMBR_SECTOR,
-       drive->gpt.sector_bytes, GPT_HEADER_SECTOR);
-  Load(drive->fd, &drive->gpt.primary_entries,
-       GPT_PMBR_SECTOR + GPT_HEADER_SECTOR,
-       drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS);
-  Load(drive->fd, &drive->gpt.secondary_entries,
-       drive->gpt.drive_sectors - GPT_HEADER_SECTOR - GPT_ENTRIES_SECTORS,
-       drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS);
-
-  if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) {
-    printf("[ERROR] GptSanityCheck(): %s\n", GptError(gpt_retval));
-    goto error_close;
-  }
-
-  drive->inited = 1;
-
-  return CGPT_OK;
-
-error_close:
-  close(drive->fd);
-  return CGPT_FAILED;
-}
-
-int DriveClose(struct drive *drive) {
-  if (drive->inited) {
-    if (drive->gpt.modified & GPT_MODIFIED_HEADER1)
-      assert(CGPT_OK ==
-          Save(drive->fd, drive->gpt.primary_header, GPT_PMBR_SECTOR,
-               drive->gpt.sector_bytes, GPT_HEADER_SECTOR));
-    if (drive->gpt.modified & GPT_MODIFIED_HEADER2)
-      assert(CGPT_OK ==
-          Save(drive->fd, drive->gpt.secondary_header,
-               drive->gpt.drive_sectors - GPT_PMBR_SECTOR,
-               drive->gpt.sector_bytes, GPT_HEADER_SECTOR));
-    if (drive->gpt.modified & GPT_MODIFIED_ENTRIES1)
-      assert(CGPT_OK ==
-          Save(drive->fd, drive->gpt.primary_entries,
-               GPT_PMBR_SECTOR + GPT_HEADER_SECTOR,
-               drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS));
-    if (drive->gpt.modified & GPT_MODIFIED_ENTRIES2)
-      assert(CGPT_OK ==
-          Save(drive->fd, drive->gpt.secondary_entries,
-               drive->gpt.drive_sectors - GPT_HEADER_SECTOR -
-                                          GPT_ENTRIES_SECTORS,
-               drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS));
-
-    close(drive->fd);
-  }
-
-  Free(drive->gpt.primary_header);
-  drive->gpt.primary_header = 0;
-  Free(drive->gpt.primary_entries);
-  drive->gpt.primary_entries = 0;
-  Free(drive->gpt.secondary_header);
-  drive->gpt.secondary_header = 0;
-  Free(drive->gpt.secondary_entries);
-  drive->gpt.secondary_entries = 0;
-
-  drive->inited = 0;
-  return CGPT_OK;
-}
-
-int main(int argc, char *argv[]) {
-  char *cmd;
-  int i;
-
-  progname = argv[0];
-  cmd = argv[optind++];
-  for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
-    if (cmd && !strcmp(cmds[i].name, cmd))
-      return cmds[i].fp(argc, argv);
-  }
-
-  Usage(0);
-  return CGPT_FAILED;
-}
diff --git a/utility/cgpt/cgpt.h b/utility/cgpt/cgpt.h
deleted file mode 100644
index 1782fe1..0000000
--- a/utility/cgpt/cgpt.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Header file for cgpt.
- */
-#ifndef VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
-#define VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
-
-#include <getopt.h>
-#include <stdint.h>
-#include "cgptlib.h"
-#include "gpt.h"
-
-enum {
-  CGPT_OK = 0,
-  CGPT_FAILED,  /* generic error */
-};
-
-#define NOT_INITED (-1)  /* to indicated a signed integer is not initialed. */
-
-#define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0]))
-
-/* 'struct option' of getopt_long() is not enough for our usage.
- * Therefore, we define the extra information to make option parsing
- * more organizable.
- * Note that please make sure every entry in struct option is mapped into an
- * individual entry in this struct. */
-struct option_details {
-  char *comment;
-
-  /* If has_arg is 'required_argument', 'validator' is called to check whether
-   * the 'argument' is valid or not. Once the argument is valid, the value is
-   * stored in 'parsed'.
-   *
-   * If has_arg is 'no_argument', 'validator' is called to load 'valid_range'
-   * into 'parsed' ('argument' is 0 in this case). Since getopt_long() only
-   * supports integer type for 'flag' and 'val', this can support for any type.
-   *
-   * If has_arg is 'optional_argument', like 'required_argument', 'validator' is
-   * called to check if 'argument' is valid or not. 'argument' indicates if
-   * argument is present or not.
-   *
-   * 'validator' returns CGPT_OK if argument is valid; otherwise CGPT_FAILED
-   * if invalid. */
-  int (*validator)(const char *argument, void *valid_range, void *parsed);
-  void *valid_range;  /* The structure passed to validator. */
-  void *parsed;  /* The structure passed to validator. */
-};
-
-/* This is a special 'validator'. It assists those options without an argument,
- * i.e. help, to indicate the option is present. */
-int AssignTrue(const char *argument, void *pointer, void *integer);
-
-/* Special validator. Copy string to 'parsed' with max 'valid_range' bytes. */
-int CopyString(const char *argument, void *max_len, void *dst);
-
-/* Validator function. Returns 1 if 'argument' is between 'max' and 'min'
- * in 'valid_range'. */
-struct number_range {
-  int max;
-  int min;
-};
-int InNumberRange(const char *argument, void *valid_range, void *parsed);
-
-void ShowOptions(const struct option *opts,
-                 const struct option_details *details,
-                 const int num);
-
-/* Handles all options from given argc and argv. This function supports both
- * short and long options.
- *
- * Assumptions:
- *   1. every short option has a corresponding long option and the short option
- *      is equal to 'val' of that long option.
- *   2. every entry in 'options' has a corresponding entry in 'details'.
- *      One by one and in order.
- *
- * Returns CGPT_OK if given options in argv are good, otherwise CGPT_FAILED.
- * Note that the global variable 'optind' points to next non-option after
- * this function returns.
- */
-int HandleOptions(const int argc,
-                  char *const *argv,
-                  const char *short_option,
-                  const int option_count,
-                  const struct option *options,
-                  const struct option_details *details);
-
-struct drive;
-int OpenDriveInLastArgument(const int argc,
-                            char *const *argv,
-                            struct drive *drive);
-
-/* GUID conversion functions. Accepted format:
- *
- *   "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
- *
- * At least GUID_STRLEN bytes should be reserved in 'str' (included the tailing
- * '\0').
- */
-#define GUID_STRLEN 37
-int StrToGuid(const char *str, Guid *guid);
-void GuidToStr(const Guid *guid, char *str);
-
-/* Convert UTF16 string to UTF8. Rewritten from gpt utility.
- * Caller must prepare enough space for UTF8. The rough estimation is:
- *
- *   utf8 length = bytecount(utf16) * 1.5
- */
-void UTF16ToUTF8(const uint16_t *utf16, uint8_t *utf8);
-/* Convert UTF8 string to UTF16. Rewritten from gpt utility.
- * Caller must prepare enough space for UTF16. The conservative estimation is:
- *
- *   utf16 bytecount = bytecount(utf8) / 3 * 4
- */
-void UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16);
-
-/* Helper functions for supported GPT types. */
-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 {
-  int inited;       /* indicated if this structure is valid */
-  int fd;           /* file descriptor */
-  uint64_t size;    /* total size (in bytes) */
-  GptData gpt;
-};
-
-extern const char* progname;
-
-/* Given a hard drive path, this function loads GPT sectors from that drive,
- * and fills 'drive' structure. All memory allocated in drive_open() will be
- * freed at drive_close().
- *
- * If 'drive_path' starts with '/', it is treated as absolute path.
- * If 'drive_path' starts with '.', it is treated as relative path.
- * Otherwise, it will be prepended with '/dev/' to comply with gpt.
- *
- * Returns CGPT_FAILED if any error happens.
- * Returns CGPT_OK if success and information are stored in 'drive'.
- */
-int DriveOpen(const char *drive_path, struct drive *drive);
-int DriveClose(struct drive *drive);
-int CheckValid(const struct drive *drive);
-
-/* Function declarations for commands.
- * The return value of these functions is passed to main()'s exit value. */
-int CgptAdm(int argc, char *argv[]);
-int CgptAttribute(int argc, char *argv[]);
-int CgptDev(int argc, char *argv[]);
-int CgptRepair(int argc, char *argv[]);
-int CgptShow(int argc, char *argv[]);
-
-#endif  /* VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_ */
diff --git a/utility/cgpt/cgpt_add_modify_delete.c b/utility/cgpt/cgpt_add_modify_delete.c
deleted file mode 100644
index c4ddc46..0000000
--- a/utility/cgpt/cgpt_add_modify_delete.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Update GPT attribute bits.
- */
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "cgpt.h"
-#include "cgptlib_internal.h"
-#include "cgpt_tofix.h"
-#include "utility.h"
-
-static struct number_range
-    range_127_0 = {127, 0};
-
-/* Integers to store parsed argument. */
-static int help, partition, begin_lba, size_lba;
-static char type[128], unique[128], name[128];
-
-/* 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 adm_options[] = {
-  {.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'},
-  {.name = "partition", .has_arg = required_argument, .flag = 0, .val = 'i'},
-#if 0//FIXME
-  {.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'},
-#endif
-  {.name = "type", .has_arg = required_argument, .flag = 0, .val = 't'},
-  {.name = "unique", .has_arg = required_argument, .flag = 0, .val = 'u'},
-  {.name = "begin", .has_arg = required_argument, .flag = 0, .val = 'b'},
-  {.name = "size", .has_arg = required_argument, .flag = 0, .val = 's'},
-  {.name = "name", .has_arg = required_argument, .flag = 0, .val = 'n'},
-  { /* last element, which should be zero. */ }
-};
-
-/* Extra information than struct option, please update this structure if you
- * add/remove any line in attribute_options[]. */
-static struct option_details adm_options_details[] = {
-  /* help */
-  { .comment = "print this help",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &help},
-  /* partition */
-  { .comment = "partition number (MUST HAVE)",
-    .validator = InNumberRange,
-    .valid_range = &range_127_0,
-    .parsed = &partition},
-#if 0//FIXME
-  /* bad */
-  { .comment = "mark partition bad",
-    .validator = InNumberRange,
-    .valid_range = &range_1_0,
-    .parsed = &bad},
-  /* successful */
-  { .comment = "mark partition successful",
-    .validator = InNumberRange,
-    .valid_range = &range_1_0,
-    .parsed = &successful},
-  /* tries */
-  { .comment = "tries",
-    .validator = InNumberRange,
-    .valid_range = &range_15_0,
-    .parsed = &tries},
-  /* priority */
-  { .comment = "priority to boot",
-    .validator = InNumberRange,
-    .valid_range = &range_15_0,
-    .parsed = &priority},
-#endif
-  /* type */
-  { .comment = "Partition Type (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)",
-    .validator = CopyString,
-    .valid_range = (void*)sizeof(type),
-    .parsed = &type},
-  /* uuid */
-  { .comment = "Partition UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)",
-    .validator = CopyString,
-    .valid_range = (void*)sizeof(unique),
-    .parsed = &unique},
-  /* start */
-  { .comment = "starting LBA",
-    .validator = InNumberRange,
-    .valid_range = 0,
-    .parsed = &begin_lba},
-  /* end */
-  { .comment = "ending LBA",
-    .validator = InNumberRange,
-    .valid_range = 0,
-    .parsed = &size_lba},
-  /* name */
-  { .comment = "Partition name",
-    .validator = CopyString,
-    .valid_range = (void*)sizeof(name),
-    .parsed = &name},
-  { /* last element, which should be zero. */ }
-};
-
-void AdmHelp() {
-  printf("\nUsage: %s {add|delete|modify} [OPTIONS] device_name\n\n", progname);
-  ShowOptions(adm_options, adm_options_details, ARRAY_COUNT(adm_options));
-  PrintTypes();
-  printf("\n");
-}
-
-enum {
-  ADD,
-  DELETE,
-  MODIFY,
-} command;
-
-/* Parses all options (and validates them), then opens the drive and sets
- * corresponding bits in GPT entry. */
-int CgptAdm(int argc, char *argv[]) {
-  struct drive drive;
-  char *cmd;
-  GptEntry *entry;
-  Guid type_guid, unique_guid;
-  int dirty = 0;
-
-  /* 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
-   * preprocessor doesn't know sizeof() for #if directive. */
-  assert(ARRAY_COUNT(adm_options) ==
-         ARRAY_COUNT(adm_options_details));
-
-  cmd = argv[optind - 1];
-  if (!strcmp("add", cmd)) command = ADD;
-  else if (!strcmp("delete", cmd)) command = DELETE;
-  else if (!strcmp("modify", cmd)) command = MODIFY;
-
-#if 0//FIXME
-  help = partition = bad = successful = tries = priority =
-#endif
-  help = partition = begin_lba = size_lba = NOT_INITED;
-  type[0] = '\0';
-  unique[0] = '\0';
-  name[0] = '\0';
-
-  if (CGPT_OK != HandleOptions(argc, argv,
-                     "hi:t:u:b:s:n:",
-                     ARRAY_COUNT(adm_options),
-                     adm_options,
-                     adm_options_details))
-    return CGPT_FAILED;
-  if (help != NOT_INITED) {
-    AdmHelp();
-    return CGPT_FAILED;
-  }
-
-  if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive))
-    return CGPT_FAILED;
-
-  if (CheckValid(&drive) != CGPT_OK) goto error_close;
-
-  if (partition == NOT_INITED) {
-    printf("[ERROR] Please provide partition number with --partition or -i.\n");
-    goto error_close;
-  }
-
-  entry = GetEntry(&drive.gpt, PRIMARY, partition);
-  /* check before really doing something. */
-  switch (command) {
-    case ADD:
-      if (NonZeroGuid(&entry->type)) {
-        printf("[ERROR] partition %d is not free, use '%s modify' instead.\n",
-               partition, progname);
-        goto error_close;
-      }
-      if (type[0] == '\0') {
-        printf("* You must give a type with '--type' or '-t'.\n");
-        PrintTypes();
-        goto error_close;
-      }
-      if (begin_lba == NOT_INITED) {
-        printf("* You didn't give the begin LBA, use '--begin' to specify.\n");
-        goto error_close;
-      }
-      if (size_lba == NOT_INITED) {
-        printf("* You didn't give size, use '--size' to specify.\n");
-        goto error_close;
-      }
-      break;
-    case DELETE:
-      if (!NonZeroGuid(&entry->type)) {
-        printf("[ERROR] partition %d is free already.\n", partition);
-        goto error_close;
-      }
-      break;
-    case MODIFY:
-      if (!NonZeroGuid(&entry->type)) {
-        printf("[ERROR] partition %d is free, use '%s add' first.\n",
-               partition, progname);
-        goto error_close;
-      }
-      break;
-  }
-
-#if 0 //FIXME
-  if (bad != NOT_INITED)
-    SetBad(&drive.gpt, PRIMARY, partition, bad);
-  if (successful != NOT_INITED)
-    SetSuccessful(&drive.gpt, PRIMARY, partition, successful);
-  if (tries != NOT_INITED)
-    SetTries(&drive.gpt, PRIMARY, partition, tries);
-  if (priority != NOT_INITED)
-    SetPriority(&drive.gpt, PRIMARY, partition, priority);
-#endif
-  if (type[0]) {
-    if (CGPT_OK != SupportedType(type, &type_guid) &&
-        CGPT_OK != StrToGuid(type, &type_guid)) {
-      printf("[ERROR] You didn't give a valid type [%s]\n", type);
-      goto error_close;
-    }
-    Memcpy(&entry->type, &type_guid, sizeof(Guid));
-    ++dirty;
-  }
-  if (unique[0]) {
-    if (CGPT_OK != StrToGuid(unique, &unique_guid)) {
-      printf("[ERROR] You didn't give a valid UUID [%s]\n", unique);
-      goto error_close;
-    }
-    Memcpy(&entry->unique, &unique_guid, sizeof(Guid));
-    ++dirty;
-  }
-  if (begin_lba != NOT_INITED) {
-    entry->starting_lba = begin_lba;
-    ++dirty;
-  }
-  if (size_lba != NOT_INITED) {
-    entry->ending_lba = entry->starting_lba + size_lba - 1;
-    ++dirty;
-  }
-  if (name[0]) {
-    UTF8ToUTF16((uint8_t*)name, entry->name);
-    ++dirty;
-  }
-
-  if (command == DELETE) {
-    Memcpy(&entry->type, &guid_unused, sizeof(Guid));
-  }
-
-  if (dirty) {
-    uint32_t valid_entries;
-
-    valid_entries = drive.gpt.valid_entries;
-    if ((valid_entries != CheckValidEntries(&drive.gpt)) ||
-        (valid_entries != CheckOverlappedPartition(&drive.gpt))) {
-      printf("\n[ERROR] Your change makes GPT invalid (or worse). "
-             "Please check your arguments.\n\n");
-      drive.gpt.modified = 0;  /* DriveClose() won't update hard drive. */
-      goto error_close;
-    }
-
-    /* Claims primary is good, then secondary will be overwritten. */
-    RepairEntries(&drive.gpt, MASK_PRIMARY);
-    RepairHeader(&drive.gpt, MASK_PRIMARY);
-
-    /* Forces headers and entries are modified so that CRC32 will be
-     * re-calculated and headers and entries will be updated to drive. */
-    drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
-                           GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
-    UpdateCrc(&drive.gpt);
-  }
-  DriveClose(&drive);
-  return CGPT_OK;
-
-error_close:
-  DriveClose(&drive);
-  return CGPT_FAILED;
-}
diff --git a/utility/cgpt/cgpt_attribute.c b/utility/cgpt/cgpt_attribute.c
deleted file mode 100644
index 37477dc..0000000
--- a/utility/cgpt/cgpt_attribute.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Update GPT attribute bits.
- */
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "cgpt.h"
-#include "cgptlib_internal.h"
-#include "cgpt_tofix.h"
-#include "utility.h"
-
-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, 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 = "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'},
-  { /* last element, which should be zero. */ }
-};
-
-/* Extra information than struct option, please update this structure if you
- * add/remove any line in attribute_options[]. */
-static struct option_details attribute_options_details[] = {
-  /* help */
-  { .comment = "print this help",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &help},
-  /* partition */
-  { .comment = "partition number "
-              "(default: first ChromeOS kernel)",
-    .validator = InNumberRange,
-    .valid_range = &range_16_1,
-    .parsed = &partition},
-  /* successful */
-  { .comment = "mark partition successful",
-    .validator = InNumberRange,
-    .valid_range = &range_1_0,
-    .parsed = &successful},
-  /* tries */
-  { .comment = "tries",
-    .validator = InNumberRange,
-    .valid_range = &range_15_0,
-    .parsed = &tries},
-  /* priority */
-  { .comment = "priority to boot",
-    .validator = InNumberRange,
-    .valid_range = &range_15_0,
-    .parsed = &priority},
-  { /* last element, which should be zero. */ }
-};
-
-void AttributeHelp() {
-  printf("\nUsage: %s attribute [OPTIONS] device_name\n\n", progname);
-  ShowOptions(attribute_options, attribute_options_details,
-              ARRAY_COUNT(attribute_options));
-}
-
-/* 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
-   * preprocessor doesn't know sizeof() for #if directive. */
-  assert(ARRAY_COUNT(attribute_options) ==
-         ARRAY_COUNT(attribute_options_details));
-
-  help = partition = successful = tries = priority = NOT_INITED;
-
-  if (CGPT_OK != HandleOptions(argc, argv,
-                     "hi:b:s:t:p:",
-                     ARRAY_COUNT(attribute_options),
-                     attribute_options,
-                     attribute_options_details))
-    return CGPT_FAILED;
-  if (help != NOT_INITED) {
-    AttributeHelp();
-    return CGPT_FAILED;
-  }
-
-  if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive))
-    return CGPT_FAILED;
-
-  if (CheckValid(&drive) != CGPT_OK) return CGPT_FAILED;
-
-  /* partition is not specified, search for the first Chromeos kernel. */
-  if (partition == NOT_INITED) {
-    int i;
-    for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) {
-      entry = GetEntry(&drive.gpt, PRIMARY, i);
-      if (!Memcmp(&guid_chromeos_kernel, &entry->type, sizeof(Guid))) {
-        partition = i+1;
-        break;
-      }
-    }
-    if (partition == NOT_INITED) {
-      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 in partition [%d].\n",
-            partition);
-    }
-  }
-  int index = partition - 1;
-
-  if (successful != NOT_INITED)
-    SetSuccessful(&drive.gpt, PRIMARY, index, successful);
-  if (tries != NOT_INITED)
-    SetTries(&drive.gpt, PRIMARY, index, tries);
-  if (priority != NOT_INITED)
-    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
-   * update this to match new internal APIs. */
-  RepairEntries(&drive.gpt, MASK_PRIMARY);
-  RepairHeader(&drive.gpt, MASK_PRIMARY);
-
-  /* Forces headers and entries are modified so that CRC32 will be re-calculated
-   * and headers and entries will be updated to drive. */
-  drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
-                         GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
-  UpdateCrc(&drive.gpt);
-  DriveClose(&drive);
-
-  return CGPT_OK;
-}
diff --git a/utility/cgpt/cgpt_dev.c b/utility/cgpt/cgpt_dev.c
deleted file mode 100644
index ca53c4c..0000000
--- a/utility/cgpt/cgpt_dev.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Developper mode.
- */
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "cgpt.h"
-#include "cgptlib_internal.h"
-#include "utility.h"
-
-/* Integers to store parsed argument. */
-static int help, primary_header, primary_entries,
-           secondary_header, secondary_entries;
-
-/* 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 dev_options[] = {
-  {.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'},
-  {.name = "primary-header", .has_arg = no_argument, .flag = 0, .val = 'a'},
-  {.name = "primary-entries", .has_arg = no_argument, .flag = 0, .val = 'b'},
-  {.name = "secondary-entries", .has_arg = no_argument, .flag = 0, .val = 'c'},
-  {.name = "secondary-header", .has_arg = no_argument, .flag = 0, .val = 'd'},
-  { /* last element, which should be zero. */ }
-};
-
-/* Extra information than struct option, please update this structure if you
- * add/remove any line in attribute_options[]. */
-static struct option_details dev_options_details[] = {
-  /* help */
-  { .comment = "print this help",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &help},
-  /* primary-header */
-  { .comment = "damage primary header",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &primary_header},
-  /* primary-entries */
-  { .comment = "damage primary entries",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &primary_entries},
-  /* secondary-entries */
-  { .comment = "damage secondary entries",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &secondary_entries},
-  /* secondary-header */
-  { .comment = "damage secondary header",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &secondary_header},
-  { /* last element, which should be zero. */ }
-};
-
-void DevHelp() {
-  printf("\nDeveloper mode.\n\n");
-  printf("\nUsage: %s dev [OPTIONS] device_name\n\n", progname);
-  ShowOptions(dev_options, dev_options_details, ARRAY_COUNT(dev_options));
-  printf("\n");
-}
-
-/* Very simple function, you may choose damage one or more of the following
- * sections:
- *
- *   Primary GPT header
- *   Primary GPT table entries
- *   Secondary GPT table entries
- *   Secondary GPT header
- */
-int CgptDev(int argc, char *argv[]) {
-  struct drive drive;
-
-  /* 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
-   * preprocessor doesn't know sizeof() for #if directive. */
-  assert(ARRAY_COUNT(dev_options) ==
-         ARRAY_COUNT(dev_options_details));
-
-  help = primary_header = primary_entries =
-         secondary_header = secondary_entries = NOT_INITED;
-
-  if (CGPT_OK != HandleOptions(argc, argv,
-                     "h",
-                     ARRAY_COUNT(dev_options),
-                     dev_options,
-                     dev_options_details))
-    return CGPT_FAILED;
-  if (help != NOT_INITED) {
-    DevHelp();
-    return CGPT_FAILED;
-  }
-
-  if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive))
-    return CGPT_FAILED;
-
-  #define ANY_PRIME 7
-  if (primary_header != NOT_INITED) {
-    printf("* damage Pri Header\n");
-    drive.gpt.primary_header[0] += ANY_PRIME;
-    drive.gpt.modified |= GPT_MODIFIED_HEADER1;
-  }
-  if (primary_entries != NOT_INITED) {
-    printf("* damage Pri Table\n");
-    drive.gpt.primary_entries[0] += ANY_PRIME;
-    drive.gpt.modified |= GPT_MODIFIED_ENTRIES1;
-  }
-  if (secondary_entries != NOT_INITED) {
-    printf("* damage Sec Table\n");
-    drive.gpt.secondary_entries[0] += ANY_PRIME;
-    drive.gpt.modified |= GPT_MODIFIED_ENTRIES2;
-  }
-  if (secondary_header != NOT_INITED) {
-    printf("* damage Sec Header\n");
-    drive.gpt.secondary_header[0] += ANY_PRIME;
-    drive.gpt.modified |= GPT_MODIFIED_HEADER2;
-  }
-
-  DriveClose(&drive);
-
-  return CGPT_OK;
-}
diff --git a/utility/cgpt/cgpt_options.c b/utility/cgpt/cgpt_options.c
deleted file mode 100644
index b434eea..0000000
--- a/utility/cgpt/cgpt_options.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Update GPT attribute bits.
- */
-#include <getopt.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "cgpt.h"
-#include "utility.h"
-
-/* Special validator. Set 'integer' as 1 to indicate the option is present. */
-int AssignTrue(const char *argument, void *pointer, void *integer) {
-  *(int*)integer = 1;
-  return CGPT_OK;
-}
-
-/* Special validator. Copy string to 'parsed' with max 'valid_range' bytes. */
-int CopyString(const char *argument, void *max_len, void *dst) {
-  Memcpy(dst, argument, (intptr_t)max_len);
-  return CGPT_OK;
-}
-
-/* Validator function. Returns 1 if 'argument' is between 'max' and 'min'
- * in 'valid_range'. */
-int InNumberRange(const char *argument, void *valid_range, void *parsed) {
-  struct number_range *range = valid_range;
-  char *endptr;
-  int number;
-
-  number = strtol(argument, &endptr, 10);
-  if (*endptr) {
-    printf("[ERROR] argument '%s' is not a number.\n", argument);
-    return CGPT_FAILED;
-  }
-
-  if (range) {
-    if (number < range->min) {
-      printf("[ERROR] argument is too small (min is %d, but you gave: %d).\n",
-             range->min, number);
-      return CGPT_FAILED;
-    } else if (number > range->max) {
-      printf("[ERROR] argument is too large (max is %d, but you gave: %d).\n",
-             range->max, number);
-      return CGPT_FAILED;
-    } else {
-      if (parsed) *(int*)parsed = number;
-      return CGPT_OK;
-    }
-  } else {
-    /* no range to check, assign integer. */
-    if (parsed) *(int*)parsed = number;
-    return CGPT_OK;
-  }
-}
-
-void ShowOptions(const struct option *opts,
-                 const struct option_details *details,
-                 const int num) {
-  int i;
-  for (i = 0; i < num; ++i) {
-    char buf[32];
-    if (!opts[i].name) break;
-    snprintf(buf, sizeof(buf), "--%s %s", opts[i].name,
-                                          opts[i].has_arg ? "ARG" : "");
-    printf("  %-20s (-%c)  %s\n", buf, opts[i].val, details[i].comment);
-  }
-}
-
-int HandleOptions(const int argc,
-                  char *const *argv,
-                  const char *short_options,
-                  const int option_count,
-                  const struct option *options,
-                  const struct option_details *details) {
-  while (1) {
-    int index;
-    int option;
-
-    /* We assume every short option has an entry in long option (for validator).
-     * So please add corresponding entry in attribute_options if you add short
-     * option. */
-    index = NOT_INITED;
-    option = getopt_long(argc, argv, short_options, options, &index);
-    if (option == -1) {
-      break;
-    } else if (option == 0) {
-      /* option 'val' has been saved in 'flag'. We do nothing here. */
-    } else if (option == ':') {
-      printf("[ERROR] Missing parameter for option.\n");
-      ShowOptions(options, details, option_count);
-      return CGPT_FAILED;
-    } else if (option == '?') {
-      printf("[ERROR] unknown option name: %s\n", argv[optind - 1]);
-      ShowOptions(options, details, option_count);
-      return CGPT_FAILED;
-    } else {
-      /* Short option doesn't update 'index'. We search whole array to find out
-       * the corresponding long option. */
-      if (index == NOT_INITED) {
-        for (index = 0; index < option_count; ++index)
-          if (option == options[index].val) break;
-        /* assumes every short option has a corresponding long option. */
-        assert(index < option_count);
-      }
-      assert(option == options[index].val);
-
-      /* Calls validator if an argument is provided. */
-      if (details[index].validator &&
-          CGPT_OK != details[index].validator(
-              optarg ? argv[optind - 1] : 0,
-              details[index].valid_range,
-              details[index].parsed)) {
-        printf("[ERROR] The argument of '%s' is invalid.\n",
-               options[index].name);
-        return CGPT_FAILED;
-      }
-    }
-  }
-  return CGPT_OK;
-}
-
-int OpenDriveInLastArgument(const int argc,
-                            char *const *argv,
-                            struct drive *drive) {
-  if (optind != (argc - 1)) {
-    printf("[ERROR] One (and only one) non-option argument is required.\n");
-    return CGPT_FAILED;
-  }
-
-  return DriveOpen(argv[optind], drive);
-}
diff --git a/utility/cgpt/cgpt_repair.c b/utility/cgpt/cgpt_repair.c
deleted file mode 100644
index f75e4a2..0000000
--- a/utility/cgpt/cgpt_repair.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Repair headers and tables.
- *
- * If primary header or table is invalid, it copies from secondary (vice versa).
- */
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "cgpt.h"
-#include "cgptlib_internal.h"
-#include "utility.h"
-
-/* Integers to store parsed argument. */
-static int help;
-
-/* 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 repair_options[] = {
-  {.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'},
-  { /* last element, which should be zero. */ }
-};
-
-/* Extra information than struct option, please update this structure if you
- * add/remove any line in attribute_options[]. */
-static struct option_details repair_options_details[] = {
-  /* help */
-  { .comment = "print this help",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &help},
-  { /* last element, which should be zero. */ }
-};
-
-void RepairHelp() {
-  printf("\nUsage: %s repair [OPTIONS] device_name\n\n", progname);
-  ShowOptions(repair_options, repair_options_details,
-              ARRAY_COUNT(repair_options));
-  printf("\n");
-}
-
-/* Parses all options (and validates them), then opens the drive and sets
- * corresponding bits in GPT entry. */
-int CgptRepair(int argc, char *argv[]) {
-  struct drive drive;
-
-  /* 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
-   * preprocessor doesn't know sizeof() for #if directive. */
-  assert(ARRAY_COUNT(repair_options) ==
-         ARRAY_COUNT(repair_options_details));
-
-  help = NOT_INITED;
-
-  if (CGPT_OK != HandleOptions(argc, argv,
-                     "hr",
-                     ARRAY_COUNT(repair_options),
-                     repair_options,
-                     repair_options_details))
-    return CGPT_FAILED;
-  if (help != NOT_INITED) {
-    RepairHelp();
-    return CGPT_FAILED;
-  }
-
-  if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive))
-    return CGPT_FAILED;
-
-  GptRepair(&drive.gpt);
-  if (drive.gpt.modified & GPT_MODIFIED_HEADER1)
-    printf("* Pri Header is updated.\n");
-  if (drive.gpt.modified & GPT_MODIFIED_ENTRIES1)
-    printf("* Pri Table Entries is updated.\n");
-  if (drive.gpt.modified & GPT_MODIFIED_ENTRIES2)
-    printf("* Sec Table Entries is updated.\n");
-  if (drive.gpt.modified & GPT_MODIFIED_HEADER2)
-    printf("* Sec Header is updated.\n");
-
-  DriveClose(&drive);
-
-  return CGPT_OK;
-}
diff --git a/utility/cgpt/cgpt_show.c b/utility/cgpt/cgpt_show.c
deleted file mode 100644
index 2dfad40..0000000
--- a/utility/cgpt/cgpt_show.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Show GPT details.
- */
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "cgpt.h"
-#include "cgptlib_internal.h"
-#include "cgpt_tofix.h"
-#include "utility.h"
-
-/* Integers to store parsed argument. */
-static int help, number, verbose;
-
-/* 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 show_options[] = {
-  {.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'},
-  {.name = "number", .has_arg = no_argument, .flag = 0, .val = 'n'},
-  {.name = "verbose", .has_arg = no_argument, .flag = 0, .val = 'v'},
-  { /* last element, which should be zero. */ }
-};
-
-/* Extra information than struct option, please update this structure if you
- * add/remove any line in attribute_options[]. */
-static struct option_details show_options_details[] = {
-  /* help */
-  { .comment = "print this help",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &help},
-  /* number */
-  { .comment = "print raw numbers (don't interpret)",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &number},
-  /* verbose */
-  { .comment = "verbose print",
-    .validator = AssignTrue,
-    .valid_range = 0,
-    .parsed = &verbose},
-  { /* last element, which should be zero. */ }
-};
-
-void ShowHelp() {
-  printf("\nUsage: %s show [OPTIONS] device_name\n\n", progname);
-  ShowOptions(show_options, show_options_details, ARRAY_COUNT(show_options));
-  printf("\n");
-}
-
-/* Generate output like:
- *
- *  [AB-CD-EF-01]   for group = 1
- *  [ABCD-EF01]     for group = 3  (low byte first)
- *
- * Needs (size*3-1+3) bytes of space in 'buf' (included the tailing '\0').
- */
-#define BUFFER_SIZE(size) (size *3 - 1 + 3)
-static short Uint8To2Chars(const uint8_t t) {
-  int h = t >> 4;
-  int l = t & 0xf;
-  h = (h >= 0xA) ? h - 0xA + 'A' : h + '0';
-  l = (l >= 0xA) ? l - 0xA + 'A' : l + '0';
-  return (h << 8) + l;
-}
-static void RawDump(const uint8_t *memory, const int size,
-                    char *buf, int group) {
-  int i, outlen = 0;
-  buf[outlen++] = '[';
-  for (i = 0; i < size; ++i) {
-    short c2 = Uint8To2Chars(memory[i]);
-    buf[outlen++] = c2 >> 8;
-    buf[outlen++] = c2 & 0xff;
-    if (i != (size - 1) && ((i + 1) % group) == 0)
-      buf[outlen++] = '-';
-  }
-  buf[outlen++] = ']';
-  buf[outlen++] = '\0';
-}
-
-/* Outpur formatters */
-#define TITLE_FMT      "%10s%10s%8s  %s\n"
-#define GPT_FMT        "%10d%10d%8s  %s\n"
-#define GPT_MORE       "%10s%10s%8s  ", "", "", ""
-#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, int raw) {
-  int i;
-
-  printf("%sSig: ", indent);
-  if (raw == NOT_INITED) {
-    printf("[");
-    for (i = 0; i < sizeof(header->signature); ++i)
-      printf("%c", header->signature[i]);
-    printf("]");
-  } else {
-    char buf[BUFFER_SIZE(sizeof(header->signature))];
-    RawDump((uint8_t *)header->signature, sizeof(header->signature), buf, 1);
-    printf("%s", buf);
-  }
-  printf("\n");
-
-  printf("%sRev: 0x%08x\n", indent, header->revision);
-  printf("%sSize: %d\n", indent, header->size);
-  printf("%sHeader CRC: 0x%08x\n", indent, header->header_crc32);
-  printf("%sMy LBA: %lld\n", indent, (long long)header->my_lba);
-  printf("%sFirst LBA: %lld\n", indent, (long long)header->first_usable_lba);
-  printf("%sLast LBA: %lld\n", indent, (long long)header->last_usable_lba);
-
-  {  /* For disk guid */
-    char buf[GUID_STRLEN];
-    GuidToStr(&header->disk_uuid, buf);
-    printf("%sDisk UUID: %s\n", indent, buf);
-  }
-
-  printf("%sEntries LBA: %lld\n", indent, (long long)header->entries_lba);
-  printf("%sNumber of entries: %d\n", indent, header->number_of_entries);
-  printf("%sSize of entry: %d\n", indent, header->size_of_entry);
-  printf("%sEntries CRC: 0x%08x\n", indent, header->entries_crc32);
-}
-
-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) {
-    GptEntry *entry;
-    entry = GetEntry(gpt, secondary, i);
-
-    if (!Memcmp(&guid_unused, &entry->type, sizeof(Guid))) continue;
-
-    EntryDetails(entry, i, raw);
-  }
-}
-
-/* Parses all options (and validates them), then opens the drive.
- * Show GPT information in following order:
- *
- *   Primary header sector
- *     details (if -v applied)
- *
- *   Primary table sectors
- *
- *   1st partition
- *     details (if -v applied)
- *   :
- *   last partition
- *     details (if -v applied)
- *
- *   Secondary table sectors
- *
- *   Secondary header sector
- *     details (if -v applied)
- */
-int CgptShow(int argc, char *argv[]) {
-  struct drive drive;
-
-  /* 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
-   * preprocessor doesn't know sizeof() for #if directive. */
-  assert(ARRAY_COUNT(show_options) ==
-         ARRAY_COUNT(show_options_details));
-
-  help = number = NOT_INITED;
-
-  if (CGPT_OK != HandleOptions(argc, argv,
-                     "hnv",
-                     ARRAY_COUNT(show_options),
-                     show_options,
-                     show_options_details))
-    return CGPT_FAILED;
-  if (help != NOT_INITED) {
-    ShowHelp();
-    return CGPT_FAILED;
-  }
-
-  if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive))
-    return CGPT_FAILED;
-
-  printf(TITLE_FMT, "start", "size", "part", "contents");
-  printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", "PMBR");
-
-  if (drive.gpt.valid_headers & MASK_PRIMARY) {
-    printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
-           (int)GPT_HEADER_SECTOR, "", "Pri GPT header");
-    if (verbose) {
-      GptHeader *header;
-      char indent[64];
-
-      snprintf(indent, sizeof(indent), GPT_MORE);
-      header = (GptHeader*)drive.gpt.primary_header;
-      HeaderDetails(header, indent, number);
-    }
-  } else {
-    printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
-           (int)GPT_HEADER_SECTOR, "INVALID", "Pri GPT header");
-  }
-
-  printf(GPT_FMT, (int)(GPT_PMBR_SECTOR + GPT_HEADER_SECTOR),
-         (int)GPT_ENTRIES_SECTORS,
-         drive.gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
-         "Pri GPT table");
-
-  if (drive.gpt.valid_entries & MASK_PRIMARY)
-    EntriesDetails(&drive.gpt, PRIMARY, number);
-
-  printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR -
-                        GPT_ENTRIES_SECTORS),
-         (int)GPT_ENTRIES_SECTORS,
-         drive.gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
-         "Sec GPT table");
-  /* We show secondary table details if any of following is true.
-   *   1. only secondary is valid.
-   *   2. secondary is not identical to promary.
-   */
-  if ((drive.gpt.valid_entries & MASK_SECONDARY) &&
-      (!(drive.gpt.valid_entries & MASK_PRIMARY) ||
-       Memcmp(drive.gpt.primary_entries, drive.gpt.secondary_entries,
-              TOTAL_ENTRIES_SIZE))) {
-    EntriesDetails(&drive.gpt, SECONDARY, number);
-  }
-
-  if (drive.gpt.valid_headers & MASK_SECONDARY)
-    printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR),
-           (int)GPT_HEADER_SECTOR, "", "Sec GPT header");
-  else
-    printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
-           (int)GPT_HEADER_SECTOR, "INVALID", "Sec GPT header");
-  /* We show secondary header if any of following is true:
-   *   1. only secondary is valid.
-   *   2. secondary is not synonymous to primary.
-   */
-  if ((drive.gpt.valid_headers & MASK_SECONDARY) &&
-      (!(drive.gpt.valid_headers & MASK_PRIMARY) ||
-       !IsSynonymous((GptHeader*)drive.gpt.primary_header,
-                     (GptHeader*)drive.gpt.secondary_header))) {
-    if (verbose) {
-      GptHeader *header;
-      char indent[64];
-
-      snprintf(indent, sizeof(indent), GPT_MORE);
-      header = (GptHeader*)drive.gpt.secondary_header;
-      HeaderDetails(header, indent, number);
-    }
-  }
-
-  CheckValid(&drive);
-  DriveClose(&drive);
-
-  return CGPT_OK;
-}
diff --git a/utility/cgpt/cgpt_tofix.c b/utility/cgpt/cgpt_tofix.c
deleted file mode 100644
index 50aed52..0000000
--- a/utility/cgpt/cgpt_tofix.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Functions to fix, after cgptlib cleanup.
- */
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "cgpt.h"
-#include "cgptlib_internal.h"
-#include "cgpt_tofix.h"
-#include "crc32.h"
-#include "utility.h"
-
-const char *GptError(int errno) {
-  const char *error_string[] = {
-    /* GPT_SUCCESS */ "Success",
-    /* GPT_ERROR_NO_VALID_KERNEL */ "No valid kernel entry",
-    /* GPT_ERROR_INVALID_HEADERS */ "Both primary and secondary headers are "
-                                    "invalid.",
-    /* GPT_ERROR_INVALID_ENTRIES */ "Both primary and secondary entries are "
-                                    "invalid.",
-    /* GPT_ERROR_INVALID_SECTOR_SIZE */ "Invalid sector size",
-    /* GPT_ERROR_INVALID_SECTOR_NUMBER */ "Invalid sector number",
-    /* GPT_ERROR_INVALID_UPDATE_TYPE */ "Invalid update type",
-  };
-  return error_string[errno];
-}
-
-
-/*  Update CRC value if necessary.  */
-void UpdateCrc(GptData *gpt) {
-  GptHeader *primary_header, *secondary_header;
-
-  primary_header = (GptHeader*)gpt->primary_header;
-  secondary_header = (GptHeader*)gpt->secondary_header;
-
-  if (gpt->modified & GPT_MODIFIED_ENTRIES1) {
-    primary_header->entries_crc32 =
-        Crc32(gpt->primary_entries, TOTAL_ENTRIES_SIZE);
-  }
-  if (gpt->modified & GPT_MODIFIED_ENTRIES2) {
-    secondary_header->entries_crc32 =
-        Crc32(gpt->secondary_entries, TOTAL_ENTRIES_SIZE);
-  }
-  if (gpt->modified & GPT_MODIFIED_HEADER1) {
-    primary_header->header_crc32 = 0;
-    primary_header->header_crc32 = Crc32(
-        (const uint8_t *)primary_header, primary_header->size);
-  }
-  if (gpt->modified & GPT_MODIFIED_HEADER2) {
-    secondary_header->header_crc32 = 0;
-    secondary_header->header_crc32 = Crc32(
-        (const uint8_t *)secondary_header, secondary_header->size);
-  }
-}
-
-/* Helper function to get a pointer to the partition entry.
- *   'secondary' is either PRIMARY or SECONDARY.
- *   'entry_index' is the partition index: [0, number_of_entries).
- */
-GptEntry *GetEntry(GptData *gpt, int secondary, int entry_index) {
-  uint8_t *entries;
-
-  if (secondary == PRIMARY) {
-    entries = gpt->primary_entries;
-  } else {
-    entries = gpt->secondary_entries;
-  }
-
-  return (GptEntry*)(&entries[GetNumberOfEntries(gpt) * entry_index]);
-}
-
-/* The following functions are helpers to access attributes bit more easily.
- *   'secondary' is either PRIMARY or SECONDARY.
- *   'entry_index' is the partition index: [0, number_of_entries).
- *
- * Get*() return the exact value (shifted and masked).
- */
-void SetPriority(GptData *gpt, int secondary, int entry_index, int priority) {
-  GptEntry *entry;
-  entry = GetEntry(gpt, secondary, entry_index);
-
-  assert(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
-  entry->attributes &= ~CGPT_ATTRIBUTE_PRIORITY_MASK;
-  entry->attributes |= (uint64_t)priority << CGPT_ATTRIBUTE_PRIORITY_OFFSET;
-}
-
-int GetPriority(GptData *gpt, int secondary, int entry_index) {
-  GptEntry *entry;
-  entry = GetEntry(gpt, secondary, entry_index);
-  return (entry->attributes & CGPT_ATTRIBUTE_PRIORITY_MASK) >>
-         CGPT_ATTRIBUTE_PRIORITY_OFFSET;
-}
-
-void SetBad(GptData *gpt, int secondary, int entry_index, int bad) {
-  GptEntry *entry;
-  entry = GetEntry(gpt, secondary, entry_index);
-
-  // There is no bad attribute
-  assert(0);
-}
-
-int GetBad(GptData *gpt, int secondary, int entry_index) {
-  GptEntry *entry;
-  entry = GetEntry(gpt, secondary, entry_index);
-
-  // There is no bad attribute
-  assert(0);
-  return 0;
-}
-
-void SetTries(GptData *gpt, int secondary, int entry_index, int tries) {
-  GptEntry *entry;
-  entry = GetEntry(gpt, secondary, entry_index);
-
-  assert(tries >= 0 && tries <= CGPT_ATTRIBUTE_MAX_TRIES);
-  entry->attributes &= ~CGPT_ATTRIBUTE_TRIES_MASK;
-  entry->attributes |= (uint64_t)tries << CGPT_ATTRIBUTE_TRIES_OFFSET;
-}
-
-int GetTries(GptData *gpt, int secondary, int entry_index) {
-  GptEntry *entry;
-  entry = GetEntry(gpt, secondary, entry_index);
-  return (entry->attributes & CGPT_ATTRIBUTE_TRIES_MASK) >>
-         CGPT_ATTRIBUTE_TRIES_OFFSET;
-}
-
-void SetSuccessful(GptData *gpt, int secondary, int entry_index, int success) {
-  GptEntry *entry;
-  entry = GetEntry(gpt, secondary, entry_index);
-
-  assert(success >= 0 && success <= CGPT_ATTRIBUTE_MAX_SUCCESSFUL);
-  entry->attributes &= ~CGPT_ATTRIBUTE_SUCCESSFUL_MASK;
-  entry->attributes |= (uint64_t)success << CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
-}
-
-int GetSuccessful(GptData *gpt, int secondary, int entry_index) {
-  GptEntry *entry;
-  entry = GetEntry(gpt, secondary, entry_index);
-  return (entry->attributes & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
-         CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
-}
-
-uint32_t GetNumberOfEntries(const GptData *gpt) {
-  GptHeader *header = 0;
-  if (gpt->valid_headers & MASK_PRIMARY)
-    header = (GptHeader*)gpt->primary_header;
-  else if (gpt->valid_headers & MASK_SECONDARY)
-    header = (GptHeader*)gpt->secondary_header;
-  else
-    assert(0);
-  return header->number_of_entries;
-}
-
-/* Two headers are NOT bitwise identical. For example, my_lba pointers to header
- * itself so that my_lba in primary and secondary is definitely different.
- * Only the following fields should be identical.
- *
- *   first_usable_lba
- *   last_usable_lba
- *   number_of_entries
- *   size_of_entry
- *   disk_uuid
- *
- * If any of above field are not matched, overwrite secondary with primary since
- * we always trust primary.
- * If any one of header is invalid, copy from another. */
-int IsSynonymous(const GptHeader* a, const GptHeader* b) {
-  if ((a->first_usable_lba == b->first_usable_lba) &&
-      (a->last_usable_lba == b->last_usable_lba) &&
-      (a->number_of_entries == b->number_of_entries) &&
-      (a->size_of_entry == b->size_of_entry) &&
-      (!Memcmp(&a->disk_uuid, &b->disk_uuid, sizeof(Guid))))
-    return 1;
-  return 0;
-}
-
-/* Primary entries and secondary entries should be bitwise identical.
- * If two entries tables are valid, compare them. If not the same,
- * overwrites secondary with primary (primary always has higher priority),
- * and marks secondary as modified.
- * If only one is valid, overwrites invalid one.
- * If all are invalid, does nothing.
- * This function returns bit masks for GptData.modified field.
- * Note that CRC is NOT re-computed in this function.
- */
-uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) {
-  if (valid_entries == MASK_BOTH) {
-    if (Memcmp(gpt->primary_entries, gpt->secondary_entries,
-               TOTAL_ENTRIES_SIZE)) {
-      Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE);
-      return GPT_MODIFIED_ENTRIES2;
-    }
-  } else if (valid_entries == MASK_PRIMARY) {
-    Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE);
-    return GPT_MODIFIED_ENTRIES2;
-  } else if (valid_entries == MASK_SECONDARY) {
-    Memcpy(gpt->primary_entries, gpt->secondary_entries, TOTAL_ENTRIES_SIZE);
-    return GPT_MODIFIED_ENTRIES1;
-  }
-
-  return 0;
-}
-
-/* The above five fields are shared between primary and secondary headers.
- * We can recover one header from another through copying those fields. */
-void CopySynonymousParts(GptHeader* target, const GptHeader* source) {
-  target->first_usable_lba = source->first_usable_lba;
-  target->last_usable_lba = source->last_usable_lba;
-  target->number_of_entries = source->number_of_entries;
-  target->size_of_entry = source->size_of_entry;
-  Memcpy(&target->disk_uuid, &source->disk_uuid, sizeof(Guid));
-}
-
-/* This function repairs primary and secondary headers if possible.
- * If both headers are valid (CRC32 is correct) but
- *   a) indicate inconsistent usable LBA ranges,
- *   b) inconsistent partition entry size and number,
- *   c) inconsistent disk_uuid,
- * we will use the primary header to overwrite secondary header.
- * If primary is invalid (CRC32 is wrong), then we repair it from secondary.
- * If secondary is invalid (CRC32 is wrong), then we repair it from primary.
- * This function returns the bitmasks for modified header.
- * Note that CRC value is NOT re-computed in this function. UpdateCrc() will
- * do it later.
- */
-uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) {
-  GptHeader *primary_header, *secondary_header;
-
-  primary_header = (GptHeader*)gpt->primary_header;
-  secondary_header = (GptHeader*)gpt->secondary_header;
-
-  if (valid_headers == MASK_BOTH) {
-    if (!IsSynonymous(primary_header, secondary_header)) {
-      CopySynonymousParts(secondary_header, primary_header);
-      return GPT_MODIFIED_HEADER2;
-    }
-  } else if (valid_headers == MASK_PRIMARY) {
-    Memcpy(secondary_header, primary_header, primary_header->size);
-    secondary_header->my_lba = gpt->drive_sectors - 1;  /* the last sector */
-    secondary_header->entries_lba = secondary_header->my_lba -
-        GPT_ENTRIES_SECTORS;
-    return GPT_MODIFIED_HEADER2;
-  } else if (valid_headers == MASK_SECONDARY) {
-    Memcpy(primary_header, secondary_header, secondary_header->size);
-    primary_header->my_lba = GPT_PMBR_SECTOR;  /* the second sector on drive */
-    primary_header->entries_lba = primary_header->my_lba + GPT_HEADER_SECTOR;
-    return GPT_MODIFIED_HEADER1;
-  }
-
-  return 0;
-}
-
-/* TODO: HORRIBLY broken non-implemented functions.  These will be
- * fixed as part of a second stage of refactoring to use the new
- * cgptlib_internal functions. */
-uint32_t CheckOverlappedPartition(GptData *gpt) {
-  return 1;
-}
-
-uint32_t CheckValidEntries(GptData *gpt) {
-  return 1;
-}
-
-int NonZeroGuid(const Guid *guid) {
-  return 1;
-}
diff --git a/utility/cgpt/cgpt_tofix.h b/utility/cgpt/cgpt_tofix.h
deleted file mode 100644
index 8e645df..0000000
--- a/utility/cgpt/cgpt_tofix.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef CGPT_TOFIX_H_
-#define CGPT_TOFIX_H_
-
-#include <stdint.h>
-#include "cgptlib.h"
-#include "cgptlib_internal.h"
-#include "gpt.h"
-
-/* TODO: This is stuff copied out of cgptlib.  cgptlib doesn't need it anymore,but currently the cgpt tool does. */
-
-const char *GptError(int errno);
-
-int IsSynonymous(const GptHeader* a, const GptHeader* b);
-uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries);
-uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers);
-void UpdateCrc(GptData *gpt);
-int NonZeroGuid(const Guid *guid);
-uint32_t CheckValidEntries(GptData *gpt);
-uint32_t CheckOverlappedPartition(GptData *gpt);
-
-GptEntry *GetEntry(GptData *gpt, int secondary, int entry_index);
-void SetPriority(GptData *gpt, int secondary, int entry_index, int priority);
-int GetPriority(GptData *gpt, int secondary, int entry_index);
-void SetBad(GptData *gpt, int secondary, int entry_index, int bad);
-int GetBad(GptData *gpt, int secondary, int entry_index);
-void SetTries(GptData *gpt, int secondary, int entry_index, int tries);
-int GetTries(GptData *gpt, int secondary, int entry_index);
-void SetSuccessful(GptData *gpt, int secondary, int entry_index, int success);
-int GetSuccessful(GptData *gpt, int secondary, int entry_index);
-
-/* Get number of entries value in primary header */
-uint32_t GetNumberOfEntries(const GptData *gpt);
-
-
-#endif /* CGPT_TOFIX_H_ */
diff --git a/vboot_firmware/lib/cgptlib/cgptlib_internal.c b/vboot_firmware/lib/cgptlib/cgptlib_internal.c
index 8aff0bd..0a4f46d 100644
--- a/vboot_firmware/lib/cgptlib/cgptlib_internal.c
+++ b/vboot_firmware/lib/cgptlib/cgptlib_internal.c
@@ -57,7 +57,7 @@
     return 1;
 
   /* Reserved fields must be zero. */
-  if (h->reserved)
+  if (h->reserved_zero)
     return 1;
 
   /* TODO: Padding must be set to zero. */
@@ -174,7 +174,7 @@
     return 1;
   if (h1->size != h2->size)
     return 1;
-  if (h1->reserved != h2->reserved)
+  if (h1->reserved_zero != h2->reserved_zero)
     return 1;
   if (h1->first_usable_lba != h2->first_usable_lba)
     return 1;
diff --git a/vboot_firmware/lib/cgptlib/include/gpt.h b/vboot_firmware/lib/cgptlib/include/gpt.h
index a199755..7a1d576 100644
--- a/vboot_firmware/lib/cgptlib/include/gpt.h
+++ b/vboot_firmware/lib/cgptlib/include/gpt.h
@@ -73,7 +73,7 @@
   uint32_t revision;
   uint32_t size;
   uint32_t header_crc32;
-  uint32_t reserved;
+  uint32_t reserved_zero;
   uint64_t my_lba;
   uint64_t alternate_lba;
   uint64_t first_usable_lba;
@@ -84,7 +84,7 @@
   uint32_t number_of_entries;
   uint32_t size_of_entry;
   uint32_t entries_crc32;
-  uint8_t padding[512 - 92]; /* Pad to end of sector */
+  uint8_t reserved_padding[];           /* entire sector reserved for header */
 } GptHeader;
 
 /* GPT partition entry defines the starting and ending LBAs of a partition.
@@ -98,7 +98,8 @@
   uint64_t starting_lba;
   uint64_t ending_lba;
   uint64_t attributes;
-  uint16_t name[36];  /* UTF-16 encoded partition name */
+  uint16_t name[36];                    /* UTF-16 encoded partition name */
+  uint8_t reserved[];                   /* nothing, really */
 } GptEntry;
 
 #endif  /* VBOOT_REFERENCE_CGPTLIB_GPT_H_ */