summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJay Srinivasan <jaysri@chromium.org>2012-01-26 21:50:05 -0800
committerGerrit <chrome-bot@google.com>2012-01-30 19:17:51 -0800
commita05814398202c4147a5e3f28474830ec0a9a0a90 (patch)
tree1273de56f9adbce9a2ab54bc1d74ac655e2f517b
parentee2e590ff0db1f0a0c5f6a8122d7c090ea833924 (diff)
downloadvboot-release-R18-1660.B.tar.gz
Refactor of cgpt tool for 32->64 autoupdate work.release-R18-1660.B
This check-in splits the cgpt into two layers. The top layer (cmd_* files) does the command-line parsing and the bottom layer (cgpt_* files) does the actual cgpt work. This is done so that the bottom layer can be reused for the monolithic C++ post-installer code that will be done in subsequent checkins. BUG=chromium-os:25374 TEST=Tested with existing cgpt unit tests as well as running the cgpt commands manually. Change-Id: I69a31eb3e867a1430cac9a694581331368aa7bb4 Reviewed-on: https://gerrit.chromium.org/gerrit/14940 Reviewed-by: Jay Srinivasan <jaysri@chromium.org> Tested-by: Jay Srinivasan <jaysri@chromium.org> Commit-Ready: Jay Srinivasan <jaysri@chromium.org>
-rw-r--r--cgpt/Makefile9
-rw-r--r--cgpt/cgpt_add.c115
-rw-r--r--cgpt/cgpt_boot.c96
-rw-r--r--cgpt/cgpt_create.c58
-rw-r--r--cgpt/cgpt_find.c224
-rw-r--r--cgpt/cgpt_params.h98
-rw-r--r--cgpt/cgpt_prioritize.c217
-rw-r--r--cgpt/cgpt_repair.c37
-rw-r--r--cgpt/cgpt_show.c346
-rw-r--r--cgpt/cmd_add.c170
-rw-r--r--cgpt/cmd_boot.c102
-rw-r--r--cgpt/cmd_create.c54
-rw-r--r--cgpt/cmd_find.c283
-rw-r--r--cgpt/cmd_prioritize.c230
-rw-r--r--cgpt/cmd_repair.c39
-rw-r--r--cgpt/cmd_show.c336
16 files changed, 1312 insertions, 1102 deletions
diff --git a/cgpt/Makefile b/cgpt/Makefile
index d8c2022d..2bd30299 100644
--- a/cgpt/Makefile
+++ b/cgpt/Makefile
@@ -1,4 +1,4 @@
-# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 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.
@@ -15,6 +15,13 @@ PROGNAME = ${BUILD_ROOT}/cgpt
ALL_SRCS = \
cgpt.c \
+ cgpt_create.c \
+ cgpt_add.c \
+ cgpt_boot.c \
+ cgpt_show.c \
+ cgpt_repair.c \
+ cgpt_prioritize.c \
+ cgpt_find.c \
cmd_show.c \
cmd_repair.c \
cmd_create.c \
diff --git a/cgpt/cgpt_add.c b/cgpt/cgpt_add.c
new file mode 100644
index 00000000..f989fe4d
--- /dev/null
+++ b/cgpt/cgpt_add.c
@@ -0,0 +1,115 @@
+// Copyright (c) 2012 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 <string.h>
+
+#include "cgptlib_internal.h"
+#include "cgpt_params.h"
+
+int cgpt_add(CgptAddParams *params) {
+
+ struct drive drive;
+
+ int gpt_retval;
+ GptEntry *entry;
+ uint32_t index;
+
+ if (params == NULL)
+ return CGPT_FAILED;
+
+ if (CGPT_OK != DriveOpen(params->driveName, &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 (((drive.gpt.valid_headers & MASK_BOTH) != MASK_BOTH) ||
+ ((drive.gpt.valid_entries & MASK_BOTH) != MASK_BOTH)) {
+ Error("one of the GPT header/entries is invalid.\n"
+ "please run 'cgpt repair' before adding anything.\n");
+ return CGPT_FAILED;
+ }
+
+ uint32_t max_part = GetNumberOfEntries(&drive.gpt);
+ if (params->partition) {
+ if (params->partition > max_part) {
+ Error("invalid partition number: %d\n", params->partition);
+ goto bad;
+ }
+ index = params->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)) {
+ params->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 (!params->set_begin || !params->set_size || !params->set_type) {
+ Error("-t, -b, and -s options are required for new partitions\n");
+ goto bad;
+ }
+ if (IsZero(&params->type_guid)) {
+ Error("New partitions must have a type other than \"unused\"\n");
+ goto bad;
+ }
+ if (!params->set_unique)
+ uuid_generate((uint8_t *)&entry->unique);
+ }
+
+ if (params->set_begin)
+ entry->starting_lba = params->begin;
+ if (params->set_size)
+ entry->ending_lba = params->begin + params->size - 1;
+ if (params->set_type)
+ memcpy(&entry->type, &params->type_guid, sizeof(Guid));
+ if (params->set_unique)
+ memcpy(&entry->unique, &params->unique_guid, sizeof(Guid));
+ if (params->label) {
+ if (CGPT_OK != UTF8ToUTF16((uint8_t *)params->label, entry->name,
+ sizeof(entry->name) / sizeof(entry->name[0]))) {
+ Error("The label cannot be converted to UTF16.\n");
+ goto bad;
+ }
+ }
+ if (params->set_raw) {
+ entry->attrs.fields.gpt_att = params->raw_value;
+ } else {
+ if (params->set_successful)
+ SetSuccessful(&drive.gpt, PRIMARY, index, params->successful);
+ if (params->set_tries)
+ SetTries(&drive.gpt, PRIMARY, index, params->tries);
+ if (params->set_priority)
+ SetPriority(&drive.gpt, PRIMARY, index, params->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/cgpt_boot.c b/cgpt/cgpt_boot.c
new file mode 100644
index 00000000..15e98cfa
--- /dev/null
+++ b/cgpt/cgpt_boot.c
@@ -0,0 +1,96 @@
+// Copyright (c) 2012 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 <string.h>
+
+#include "cgptlib_internal.h"
+#include "endian.h"
+#include "cgpt_params.h"
+
+int cgpt_boot(CgptBootParams *params) {
+ struct drive drive;
+ int retval = 1;
+ int gpt_retval= 0;
+
+ if (params == NULL)
+ return CGPT_FAILED;
+
+ if (CGPT_OK != DriveOpen(params->driveName, &drive))
+ return CGPT_FAILED;
+
+ if (CGPT_OK != ReadPMBR(&drive)) {
+ Error("Unable to read PMBR\n");
+ goto done;
+ }
+
+ if (params->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 (params->partition) {
+ if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
+ Error("GptSanityCheck() returned %d: %s\n",
+ gpt_retval, GptError(gpt_retval));
+ goto done;
+ }
+
+ if (params->partition > GetNumberOfEntries(&drive.gpt)) {
+ Error("invalid partition number: %d\n", params->partition);
+ goto done;
+ }
+
+ uint32_t index = params->partition - 1;
+ GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, index);
+ memcpy(&drive.pmbr.boot_guid, &entry->unique, sizeof(Guid));
+ }
+
+ if (params->bootfile) {
+ int fd = open(params->bootfile, O_RDONLY);
+ if (fd < 0) {
+ Error("Can't read %s: %s\n", params->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", params->bootfile, strerror(errno));
+ close(fd);
+ goto done;
+ }
+
+ close(fd);
+ }
+
+ char buf[GUID_STRLEN];
+ GuidToStr(&drive.pmbr.boot_guid, buf, sizeof(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/cgpt_create.c b/cgpt/cgpt_create.c
new file mode 100644
index 00000000..61f1133b
--- /dev/null
+++ b/cgpt/cgpt_create.c
@@ -0,0 +1,58 @@
+// Copyright (c) 2012 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 <string.h>
+
+#include "cgptlib_internal.h"
+#include "cgpt_params.h"
+
+int cgpt_create(CgptCreateParams *params) {
+ struct drive drive;
+
+ if (params == NULL)
+ return CGPT_FAILED;
+
+ if (CGPT_OK != DriveOpen(params->driveName, &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 (!params->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->alternate_lba = drive.gpt.drive_sectors - 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/cgpt_find.c b/cgpt/cgpt_find.c
new file mode 100644
index 00000000..30d0e8b0
--- /dev/null
+++ b/cgpt/cgpt_find.c
@@ -0,0 +1,224 @@
+// Copyright (c) 2012 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 <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "cgptlib_internal.h"
+#include "cgpt_params.h"
+
+#define BUFSIZE 1024
+// FIXME: currently we only support 512-byte sectors.
+#define LBA_SIZE 512
+
+
+// fill comparebuf with the data to be examined, returning true on success.
+static int FillBuffer(CgptFindParams *params, int fd, uint64_t pos,
+ uint64_t count) {
+ uint8_t *bufptr = params->comparebuf;
+
+ if (-1 == lseek(fd, pos, SEEK_SET))
+ return 0;
+
+ // keep reading until done or error
+ while (count) {
+ ssize_t bytes_read = read(fd, bufptr, count);
+ // negative means error, 0 means (unexpected) EOF
+ if (bytes_read <= 0)
+ return 0;
+ count -= bytes_read;
+ bufptr += bytes_read;
+ }
+
+ return 1;
+}
+
+// check partition data content. return true for match, 0 for no match or error
+static int match_content(CgptFindParams *params, struct drive *drive,
+ GptEntry *entry) {
+ uint64_t part_size;
+
+ if (!params->matchlen)
+ return 1;
+
+ // Ensure that the region we want to match against is inside the partition.
+ part_size = LBA_SIZE * (entry->ending_lba - entry->starting_lba + 1);
+ if (params->matchoffset + params->matchlen > part_size) {
+ return 0;
+ }
+
+ // Read the partition data.
+ if (!FillBuffer(params,
+ drive->fd,
+ (LBA_SIZE * entry->starting_lba) + params->matchoffset,
+ params->matchlen)) {
+ Error("unable to read partition data\n");
+ return 0;
+ }
+
+ // Compare it
+ if (0 == memcmp(params->matchbuf, params->comparebuf, params->matchlen)) {
+ return 1;
+ }
+
+ // Nope.
+ return 0;
+}
+
+// This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3, /dev/sda -> /dev/sda3
+static void showmatch(CgptFindParams *params, char *filename,
+ int partnum, GptEntry *entry) {
+ char * format = "%s%d\n";
+ if (strncmp("/dev/mmcblk", filename, 11) == 0)
+ format = "%sp%d\n";
+ if (params->numeric)
+ printf("%d\n", partnum);
+ else
+ printf(format, filename, partnum);
+ if (params->verbose > 0)
+ EntryDetails(entry, partnum - 1, params->numeric);
+}
+
+// This returns true if a GPT partition matches the search criteria. If a match
+// isn't found (or if the file doesn't contain a GPT), it returns false. The
+// filename and partition number that matched is left in a global, since we
+// could have multiple hits.
+static int do_search(CgptFindParams *params, char *fileName) {
+ int retval = 0;
+ int i;
+ struct drive drive;
+ GptEntry *entry;
+ char partlabel[GPT_PARTNAME_LEN];
+
+ if (CGPT_OK != DriveOpen(fileName, &drive))
+ return 0;
+
+ if (GPT_SUCCESS != GptSanityCheck(&drive.gpt)) {
+ (void) DriveClose(&drive, 0);
+ return 0;
+ }
+
+ for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) {
+ entry = GetEntry(&drive.gpt, ANY_VALID, i);
+
+ if (IsZero(&entry->type))
+ continue;
+
+ int found = 0;
+ if ((params->set_unique && GuidEqual(&params->unique_guid, &entry->unique))
+ || (params->set_type && GuidEqual(&params->type_guid, &entry->type))) {
+ found = 1;
+ } else if (params->set_label) {
+ if (CGPT_OK != UTF16ToUTF8(entry->name,
+ sizeof(entry->name) / sizeof(entry->name[0]),
+ (uint8_t *)partlabel, sizeof(partlabel))) {
+ Error("The label cannot be converted from UTF16, so abort.\n");
+ return 0;
+ }
+ if (!strncmp(params->label, partlabel, sizeof(partlabel)))
+ found = 1;
+ }
+ if (found && match_content(params, &drive, entry)) {
+ params->hits++;
+ retval++;
+ showmatch(params, fileName, i+1, entry);
+ if (!params->match_partnum)
+ params->match_partnum = i+1;
+ }
+ }
+
+ (void) DriveClose(&drive, 0);
+
+ return retval;
+}
+
+
+#define PROC_PARTITIONS "/proc/partitions"
+#define DEV_DIR "/dev"
+#define SYS_BLOCK_DIR "/sys/block"
+
+static const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 };
+
+// Given basename "foo", see if we can find a whole, real device by that name.
+// This is copied from the logic in the linux utility 'findfs', although that
+// does more exhaustive searching.
+static char *is_wholedev(const char *basename) {
+ int i;
+ struct stat statbuf;
+ static char pathname[BUFSIZE]; // we'll return this.
+ char tmpname[BUFSIZE];
+
+ // It should be a block device under /dev/,
+ for (i = 0; devdirs[i]; i++) {
+ sprintf(pathname, "%s/%s", devdirs[i], basename);
+
+ if (0 != stat(pathname, &statbuf))
+ continue;
+
+ if (!S_ISBLK(statbuf.st_mode))
+ continue;
+
+ // It should have a symlink called /sys/block/*/device
+ sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename);
+
+ if (0 != lstat(tmpname, &statbuf))
+ continue;
+
+ if (!S_ISLNK(statbuf.st_mode))
+ continue;
+
+ // found it
+ return pathname;
+ }
+
+ return 0;
+}
+
+
+// This scans all the physical devices it can find, looking for a match. It
+// returns true if any matches were found, false otherwise.
+static int scan_real_devs(CgptFindParams *params) {
+ int found = 0;
+ char line[BUFSIZE];
+ char partname[128]; // max size for /proc/partition lines?
+ FILE *fp;
+ char *pathname;
+
+ fp = fopen(PROC_PARTITIONS, "r");
+ if (!fp) {
+ perror("can't read " PROC_PARTITIONS);
+ return found;
+ }
+
+ while (fgets(line, sizeof(line), fp)) {
+ int ma, mi;
+ long long unsigned int sz;
+
+ if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, partname) != 4)
+ continue;
+
+ if ((pathname = is_wholedev(partname))) {
+ if (do_search(params, pathname)) {
+ found++;
+ }
+ }
+ }
+
+ fclose(fp);
+ return found;
+}
+
+
+void cgpt_find(CgptFindParams *params) {
+ if (params == NULL)
+ return;
+
+ if (params->driveName != NULL)
+ do_search(params, params->driveName);
+ else
+ scan_real_devs(params);
+}
diff --git a/cgpt/cgpt_params.h b/cgpt/cgpt_params.h
new file mode 100644
index 00000000..1bfb54d1
--- /dev/null
+++ b/cgpt/cgpt_params.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2012 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_CGPT_CGPT_PARAMS_H_
+#define VBOOT_REFERENCE_CGPT_CGPT_PARAMS_H_
+
+#include "cgpt.h"
+
+// This file defines the internal methods that use the user-mode cgpt programatically.
+// This is the interface for the callers such as the cgpt tool or the C++ post installer
+// executable.
+
+typedef struct CgptCreateParams {
+ char *driveName;
+ int zap;
+} CgptCreateParams;
+
+typedef struct CgptAddParams {
+ char *driveName;
+ uint32_t partition;
+ uint64_t begin;
+ uint64_t size;
+ Guid type_guid;
+ Guid unique_guid;
+ char *label;
+ int successful;
+ int tries;
+ int priority;
+ uint16_t raw_value;
+ int set_begin;
+ int set_size;
+ int set_type;
+ int set_unique;
+ int set_successful;
+ int set_tries;
+ int set_priority;
+ int set_raw;
+} CgptAddParams;
+
+typedef struct CgptShowParams {
+ char *driveName;
+ int numeric;
+ int verbose;
+ int quick;
+ uint32_t partition;
+ int single_item;
+} CgptShowParams;
+
+typedef struct CgptRepairParams {
+ char *driveName;
+ int verbose;
+} CgptRepairParams;
+
+typedef struct CgptBootParams {
+ char *driveName;
+ uint32_t partition;
+ char *bootfile;
+ int create_pmbr;
+} CgptBootParams;
+
+typedef struct CgptPrioritizeParams {
+ char *driveName;
+
+ uint32_t set_partition;
+ int set_friends;
+ int max_priority;
+ int orig_priority;
+} CgptPrioritizeParams;
+
+typedef struct CgptFindParams {
+ char *driveName;
+
+ int verbose;
+ int set_unique;
+ int set_type;
+ int set_label;
+ int oneonly;
+ int numeric;
+ uint8_t *matchbuf;
+ uint64_t matchlen;
+ uint64_t matchoffset;
+ uint8_t *comparebuf;
+ Guid unique_guid;
+ Guid type_guid;
+ char *label;
+ int hits;
+ int match_partnum; // 0 for no match, 1-N for match
+} CgptFindParams;
+
+int cgpt_create(CgptCreateParams *params);
+int cgpt_add(CgptAddParams *params);
+int cgpt_boot(CgptBootParams *params);
+int cgpt_show(CgptShowParams *params);
+int cgpt_repair(CgptRepairParams *params);
+int cgpt_prioritize(CgptPrioritizeParams *params);
+void cgpt_find(CgptFindParams *params);
+#endif // VBOOT_REFERENCE_CGPT_CGPT_PARAMS_H_
diff --git a/cgpt/cgpt_prioritize.c b/cgpt/cgpt_prioritize.c
new file mode 100644
index 00000000..b28e84c1
--- /dev/null
+++ b/cgpt/cgpt_prioritize.c
@@ -0,0 +1,217 @@
+// Copyright (c) 2012 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 <string.h>
+
+#include "cgptlib_internal.h"
+#include "cgpt_params.h"
+
+//////////////////////////////////////////////////////////////////////////////
+// We need a sorted list of priority groups, where each element in the list
+// contains an unordered list of GPT partition numbers.
+
+#define MAX_GROUPS 17 // 0-15, plus one "higher"
+
+typedef struct {
+ int priority; // priority of this group
+ int num_parts; // number of partitions in this group
+ uint32_t *part; // array of partitions in this group
+} group_t;
+
+typedef struct {
+ int max_parts; // max number of partitions in any group
+ int num_groups; // number of non-empty groups
+ group_t group[MAX_GROUPS]; // array of groups
+} group_list_t;
+
+
+static group_list_t *NewGroupList(int max_p) {
+ int i;
+ group_list_t *gl = (group_list_t *)malloc(sizeof(group_list_t));
+ require(gl);
+ gl->max_parts = max_p;
+ gl->num_groups = 0;
+ // reserve space for the maximum number of partitions in every group
+ for (i=0; i<MAX_GROUPS; i++) {
+ gl->group[i].priority = -1;
+ gl->group[i].num_parts = 0;
+ gl->group[i].part = (uint32_t *)malloc(sizeof(uint32_t) * max_p);
+ require(gl->group[i].part);
+ }
+
+ return gl;
+}
+
+static void FreeGroups(group_list_t *gl) {
+ int i;
+ for (i=0; i<MAX_GROUPS; i++)
+ free(gl->group[i].part);
+ free(gl);
+}
+
+static void AddToGroup(group_list_t *gl, int priority, int partition) {
+ int i;
+ // See if I've already got a group with this priority
+ for (i=0; i<gl->num_groups; i++)
+ if (gl->group[i].priority == priority)
+ break;
+ if (i == gl->num_groups) {
+ // no, add a group
+ require(i < MAX_GROUPS);
+ gl->num_groups++;
+ gl->group[i].priority = priority;
+ }
+ // add the partition to it
+ int j = gl->group[i].num_parts;
+ gl->group[i].part[j] = partition;
+ gl->group[i].num_parts++;
+}
+
+static void ChangeGroup(group_list_t *gl, int old_priority, int new_priority) {
+ int i;
+ for (i=0; i<gl->num_groups; i++)
+ if (gl->group[i].priority == old_priority) {
+ gl->group[i].priority = new_priority;
+ break;
+ }
+}
+
+static void SortGroups(group_list_t *gl) {
+ int i, j;
+ group_t tmp;
+
+ // straight insertion sort is fast enough
+ for (i=1; i<gl->num_groups; i++) {
+ tmp = gl->group[i];
+ for (j=i; j && (gl->group[j-1].priority < tmp.priority); j--)
+ gl->group[j] = gl->group[j-1];
+ gl->group[j] = tmp;
+ }
+}
+
+int cgpt_prioritize(CgptPrioritizeParams *params) {
+ struct drive drive;
+
+ int priority;
+
+ int gpt_retval;
+ GptEntry *entry;
+ uint32_t index;
+ uint32_t max_part;
+ int num_kernels;
+ int i,j;
+ group_list_t *groups;
+
+ if (params == NULL)
+ return CGPT_FAILED;
+
+ if (CGPT_OK != DriveOpen(params->driveName, &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;
+ }
+
+ max_part = GetNumberOfEntries(&drive.gpt);
+
+ if (params->set_partition) {
+ if (params->set_partition < 1 || params->set_partition > max_part) {
+ Error("invalid partition number: %d (must be between 1 and %d\n",
+ params->set_partition, max_part);
+ goto bad;
+ }
+ index = params->set_partition - 1;
+ // it must be a kernel
+ entry = GetEntry(&drive.gpt, PRIMARY, index);
+ if (!GuidEqual(&entry->type, &guid_chromeos_kernel)) {
+ Error("partition %d is not a ChromeOS kernel\n", params->set_partition);
+ goto bad;
+ }
+ }
+
+ // How many kernel partitions do I have?
+ num_kernels = 0;
+ for (i = 0; i < max_part; i++) {
+ entry = GetEntry(&drive.gpt, PRIMARY, i);
+ if (GuidEqual(&entry->type, &guid_chromeos_kernel))
+ num_kernels++;
+ }
+
+ if (num_kernels) {
+ // Determine the current priority groups
+ groups = NewGroupList(num_kernels);
+ for (i = 0; i < max_part; i++) {
+ entry = GetEntry(&drive.gpt, PRIMARY, i);
+ if (!GuidEqual(&entry->type, &guid_chromeos_kernel))
+ continue;
+
+ priority = GetPriority(&drive.gpt, PRIMARY, i);
+
+ // Is this partition special?
+ if (params->set_partition && (i+1 == params->set_partition)) {
+ params->orig_priority = priority; // remember the original priority
+ if (params->set_friends)
+ AddToGroup(groups, priority, i); // we'll move them all later
+ else
+ AddToGroup(groups, 99, i); // move only this one
+ } else {
+ AddToGroup(groups, priority, i); // just remember
+ }
+ }
+
+ // If we're including friends, then change the original group priority
+ if (params->set_partition && params->set_friends) {
+ ChangeGroup(groups, params->orig_priority, 99);
+ }
+
+ // Sorting gives the new order. Now we just need to reassign the
+ // priorities.
+ SortGroups(groups);
+
+ // We'll never lower anything to zero, so if the last group is priority zero
+ // we can ignore it.
+ i = groups->num_groups;
+ if (groups->group[i-1].priority == 0)
+ groups->num_groups--;
+
+ // Where do we start?
+ if (params->max_priority)
+ priority = params->max_priority;
+ else
+ priority = groups->num_groups > 15 ? 15 : groups->num_groups;
+
+ // Figure out what the new values should be
+ for (i=0; i<groups->num_groups; i++) {
+ groups->group[i].priority = priority;
+ if (priority > 1)
+ priority--;
+ }
+
+ // Now apply the ranking to the GPT
+ for (i=0; i<groups->num_groups; i++)
+ for (j=0; j<groups->group[i].num_parts; j++)
+ SetPriority(&drive.gpt, PRIMARY,
+ groups->group[i].part[j], groups->group[i].priority);
+
+ FreeGroups(groups);
+ }
+
+ // Write it all out
+ 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);
+
+ return DriveClose(&drive, 1);
+
+bad:
+ (void) DriveClose(&drive, 0);
+ return CGPT_FAILED;
+}
diff --git a/cgpt/cgpt_repair.c b/cgpt/cgpt_repair.c
new file mode 100644
index 00000000..3d7ca64c
--- /dev/null
+++ b/cgpt/cgpt_repair.c
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 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 <string.h>
+
+#include "cgptlib_internal.h"
+#include "cgpt_params.h"
+
+int cgpt_repair(CgptRepairParams *params) {
+ struct drive drive;
+
+ if (params == NULL)
+ return CGPT_FAILED;
+
+ if (CGPT_OK != DriveOpen(params->driveName, &drive))
+ return CGPT_FAILED;
+
+ int gpt_retval = GptSanityCheck(&drive.gpt);
+ if (params->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/cgpt_show.c b/cgpt/cgpt_show.c
new file mode 100644
index 00000000..068895cb
--- /dev/null
+++ b/cgpt/cgpt_show.c
@@ -0,0 +1,346 @@
+// Copyright (c) 2012 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 <string.h>
+
+#include "cgptlib_internal.h"
+#include "cgpt_params.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("%sAlternate LBA: %lld\n", indent, (long long)header->alternate_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, GUID_STRLEN);
+ 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, uint32_t index, int raw) {
+ char contents[256]; // scratch buffer for formatting output
+ uint8_t label[GPT_PARTNAME_LEN];
+
+ if (!raw) {
+ char type[GUID_STRLEN], unique[GUID_STRLEN];
+
+ UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
+ label, sizeof(label));
+ require(snprintf(contents, sizeof(contents),
+ "Label: \"%s\"", label) < sizeof(contents));
+ 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, GUID_STRLEN);
+ printf(PARTITION_MORE, "Type: ", type);
+ }
+ GuidToStr(&entry->unique, unique, GUID_STRLEN);
+ printf(PARTITION_MORE, "UUID: ", unique);
+ if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
+ int tries = (entry->attrs.fields.gpt_att &
+ CGPT_ATTRIBUTE_TRIES_MASK) >>
+ CGPT_ATTRIBUTE_TRIES_OFFSET;
+ int successful = (entry->attrs.fields.gpt_att &
+ CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
+ CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
+ int priority = (entry->attrs.fields.gpt_att &
+ CGPT_ATTRIBUTE_PRIORITY_MASK) >>
+ CGPT_ATTRIBUTE_PRIORITY_OFFSET;
+ require(snprintf(contents, sizeof(contents),
+ "priority=%d tries=%d successful=%d",
+ priority, tries, successful) < sizeof(contents));
+ printf(PARTITION_MORE, "Attr: ", contents);
+ }
+ } else {
+ char type[GUID_STRLEN], unique[GUID_STRLEN];
+
+ UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
+ label, sizeof(label));
+ require(snprintf(contents, sizeof(contents),
+ "Label: \"%s\"", label) < sizeof(contents));
+ printf(PARTITION_FMT, (int)entry->starting_lba,
+ (int)(entry->ending_lba - entry->starting_lba + 1),
+ index+1, contents);
+ GuidToStr(&entry->type, type, GUID_STRLEN);
+ printf(PARTITION_MORE, "Type: ", type);
+ GuidToStr(&entry->unique, unique, GUID_STRLEN);
+ printf(PARTITION_MORE, "UUID: ", unique);
+ require(snprintf(contents, sizeof(contents),
+ "[%x]", entry->attrs.fields.gpt_att) < sizeof(contents));
+ printf(PARTITION_MORE, "Attr: ", contents);
+ }
+}
+
+
+void EntriesDetails(GptData *gpt, const int secondary, int raw) {
+ uint32_t i;
+
+ for (i = 0; i < GetNumberOfEntries(gpt); ++i) {
+ GptEntry *entry;
+ entry = GetEntry(gpt, secondary, i);
+
+ if (IsZero(&entry->type))
+ continue;
+
+ EntryDetails(entry, i, raw);
+ }
+}
+
+int cgpt_show(CgptShowParams *params) {
+ struct drive drive;
+ int gpt_retval;
+
+ if (params == NULL)
+ return CGPT_FAILED;
+
+ if (CGPT_OK != DriveOpen(params->driveName, &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 (params->partition) { // show single partition
+
+ if (params->partition > GetNumberOfEntries(&drive.gpt)) {
+ Error("invalid partition number: %d\n", params->partition);
+ return CGPT_FAILED;
+ }
+
+ uint32_t index = params->partition - 1;
+ GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, index);
+ char buf[256]; // scratch buffer for string conversion
+
+ if (params->single_item) {
+ switch(params->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, sizeof(buf));
+ printf("%s\n", buf);
+ break;
+ case 'u':
+ GuidToStr(&entry->unique, buf, sizeof(buf));
+ printf("%s\n", buf);
+ break;
+ case 'l':
+ UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
+ (uint8_t *)buf, sizeof(buf));
+ printf("%s\n", buf);
+ break;
+ case 'S':
+ printf("%d\n", GetSuccessful(&drive.gpt, ANY_VALID, index));
+ break;
+ case 'T':
+ printf("%d\n", GetTries(&drive.gpt, ANY_VALID, index));
+ break;
+ case 'P':
+ printf("%d\n", GetPriority(&drive.gpt, ANY_VALID, index));
+ break;
+ case 'A':
+ printf("0x%x\n", entry->attrs.fields.gpt_att);
+ break;
+ }
+ } else {
+ printf(TITLE_FMT, "start", "size", "part", "contents");
+ EntryDetails(entry, index, params->numeric);
+ }
+
+ } else if (params->quick) { // show all partitions, quickly
+ uint32_t i;
+ GptEntry *entry;
+ char type[GUID_STRLEN];
+
+ for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) {
+ entry = GetEntry(&drive.gpt, ANY_VALID, i);
+
+ if (IsZero(&entry->type))
+ continue;
+
+ if (!params->numeric && CGPT_OK == ResolveType(&entry->type, type)) {
+ } else {
+ GuidToStr(&entry->type, type, GUID_STRLEN);
+ }
+ 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]; // buffer for formatted PMBR content
+ PMBRToStr(&drive.pmbr, buf, sizeof(buf)); // will exit if buf is too small
+ 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 (params->verbose) {
+ GptHeader *header;
+ char indent[64];
+
+ require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
+ header = (GptHeader*)drive.gpt.primary_header;
+ HeaderDetails(header, indent, params->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, params->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, params->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 (params->verbose) {
+ GptHeader *header;
+ char indent[64];
+
+ require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
+ header = (GptHeader*)drive.gpt.secondary_header;
+ HeaderDetails(header, indent, params->numeric);
+ }
+ }
+ }
+
+ (void) CheckValid(&drive);
+ (void) DriveClose(&drive, 0);
+
+ return CGPT_OK;
+}
diff --git a/cgpt/cmd_add.c b/cgpt/cmd_add.c
index 81b0dfa1..380bc78a 100644
--- a/cgpt/cmd_add.c
+++ b/cgpt/cmd_add.c
@@ -1,16 +1,13 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 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"
+#include "cgpt_params.h"
static void Usage(void)
{
@@ -35,25 +32,9 @@ static void Usage(void)
}
int cmd_add(int argc, char *argv[]) {
- struct drive drive;
- uint32_t 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;
- uint16_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;
+
+ CgptAddParams params;
+ memset(&params, 0, sizeof(params));
int gpt_retval;
GptEntry *entry;
@@ -69,7 +50,7 @@ int cmd_add(int argc, char *argv[]) {
switch (c)
{
case 'i':
- partition = (uint32_t)strtoul(optarg, &e, 0);
+ params.partition = (uint32_t)strtoul(optarg, &e, 0);
if (!*optarg || (e && *e))
{
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
@@ -77,8 +58,8 @@ int cmd_add(int argc, char *argv[]) {
}
break;
case 'b':
- set_begin = 1;
- begin = strtoull(optarg, &e, 0);
+ params.set_begin = 1;
+ params.begin = strtoull(optarg, &e, 0);
if (!*optarg || (e && *e))
{
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
@@ -86,8 +67,8 @@ int cmd_add(int argc, char *argv[]) {
}
break;
case 's':
- set_size = 1;
- size = strtoull(optarg, &e, 0);
+ params.set_size = 1;
+ params.size = strtoull(optarg, &e, 0);
if (!*optarg || (e && *e))
{
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
@@ -95,66 +76,66 @@ int cmd_add(int argc, char *argv[]) {
}
break;
case 't':
- set_type = 1;
- if (CGPT_OK != SupportedType(optarg, &type_guid) &&
- CGPT_OK != StrToGuid(optarg, &type_guid)) {
+ params.set_type = 1;
+ if (CGPT_OK != SupportedType(optarg, &params.type_guid) &&
+ CGPT_OK != StrToGuid(optarg, &params.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)) {
+ params.set_unique = 1;
+ if (CGPT_OK != StrToGuid(optarg, &params.unique_guid)) {
Error("invalid argument to -%c: %s\n", c, optarg);
errorcnt++;
}
break;
case 'l':
- label = optarg;
+ params.label = optarg;
break;
case 'S':
- set_successful = 1;
- successful = (uint32_t)strtoul(optarg, &e, 0);
+ params.set_successful = 1;
+ params.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) {
+ if (params.successful < 0 || params.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);
+ params.set_tries = 1;
+ params.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) {
+ if (params.tries < 0 || params.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);
+ params.set_priority = 1;
+ params.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) {
+ if (params.priority < 0 || params.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);
+ params.set_raw = 1;
+ params.raw_value = strtoull(optarg, &e, 0);
if (!*optarg || (e && *e))
{
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
@@ -184,102 +165,13 @@ int cmd_add(int argc, char *argv[]) {
return CGPT_FAILED;
}
- if (optind >= argc) {
+ 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;
- }
-
- if (((drive.gpt.valid_headers & MASK_BOTH) != MASK_BOTH) ||
- ((drive.gpt.valid_entries & MASK_BOTH) != MASK_BOTH)) {
- Error("one of the GPT header/entries is invalid.\n"
- "please run 'cgpt repair' before adding anything.\n");
- return CGPT_FAILED;
- }
-
- uint32_t 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) {
- if (CGPT_OK != UTF8ToUTF16((uint8_t *)label, entry->name,
- sizeof(entry->name) / sizeof(entry->name[0]))) {
- Error("The label cannot be converted to UTF16.\n");
- goto bad;
- }
- }
- if (set_raw) {
- entry->attrs.fields.gpt_att = 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);
+ params.driveName = argv[optind];
-bad:
- (void) DriveClose(&drive, 0);
- return CGPT_FAILED;
+ return cgpt_add(&params);
}
diff --git a/cgpt/cmd_boot.c b/cgpt/cmd_boot.c
index 669e9ae7..a953688d 100644
--- a/cgpt/cmd_boot.c
+++ b/cgpt/cmd_boot.c
@@ -1,22 +1,13 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 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"
+#include "cgpt_params.h"
static void Usage(void)
{
@@ -34,11 +25,10 @@ static void Usage(void)
int cmd_boot(int argc, char *argv[]) {
struct drive drive;
- uint32_t partition = 0;
- char *bootfile = 0;
- int create_pmbr = 0;
- int retval = 1;
- int gpt_retval;
+
+ CgptBootParams params;
+ memset(&params, 0, sizeof(params));
+
int c;
int errorcnt = 0;
@@ -50,7 +40,7 @@ int cmd_boot(int argc, char *argv[]) {
switch (c)
{
case 'i':
- partition = (uint32_t)strtoul(optarg, &e, 0);
+ params.partition = (uint32_t)strtoul(optarg, &e, 0);
if (!*optarg || (e && *e))
{
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
@@ -58,10 +48,10 @@ int cmd_boot(int argc, char *argv[]) {
}
break;
case 'b':
- bootfile = optarg;
+ params.bootfile = optarg;
break;
case 'p':
- create_pmbr = 1;
+ params.create_pmbr = 1;
break;
case 'h':
@@ -91,77 +81,7 @@ int cmd_boot(int argc, char *argv[]) {
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;
- }
-
- uint32_t index = partition - 1;
- GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, 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[GUID_STRLEN];
- GuidToStr(&drive.pmbr.boot_guid, buf, sizeof(buf));
- printf("%s\n", buf);
-
- // Write it all out
- if (CGPT_OK == WritePMBR(&drive))
- retval = 0;
+ params.driveName = argv[optind];
-done:
- (void) DriveClose(&drive, 1);
- return retval;
+ return cgpt_boot(&params);
}
diff --git a/cgpt/cmd_create.c b/cgpt/cmd_create.c
index 6dabde3a..1e081f8c 100644
--- a/cgpt/cmd_create.c
+++ b/cgpt/cmd_create.c
@@ -1,16 +1,13 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 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"
+#include "cgpt_params.h"
static void Usage(void)
{
@@ -23,7 +20,9 @@ static void Usage(void)
int cmd_create(int argc, char *argv[]) {
struct drive drive;
- int zap = 0;
+
+ CgptCreateParams params;
+ memset(&params, 0, sizeof(params));
int c;
int errorcnt = 0;
@@ -34,7 +33,7 @@ int cmd_create(int argc, char *argv[]) {
switch (c)
{
case 'z':
- zap = 1;
+ params.zap = 1;
break;
case 'h':
@@ -64,44 +63,7 @@ int cmd_create(int argc, char *argv[]) {
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->alternate_lba = drive.gpt.drive_sectors - 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);
- }
+ params.driveName = argv[optind];
- // Write it all out
- return DriveClose(&drive, 1);
+ return cgpt_create(&params);
}
diff --git a/cgpt/cmd_find.c b/cgpt/cmd_find.c
index 7a0523ff..9b945465 100644
--- a/cgpt/cmd_find.c
+++ b/cgpt/cmd_find.c
@@ -1,20 +1,13 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 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 <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <uuid/uuid.h>
-
-#include "cgptlib_internal.h"
+#include "cgpt_params.h"
static void Usage(void)
{
@@ -36,34 +29,6 @@ static void Usage(void)
PrintTypes();
}
-
-// globals
-static int verbose = 0;
-static int set_unique = 0;
-static int set_type = 0;
-static int set_label = 0;
-static int oneonly = 0;
-static int numeric = 0;
-static uint8_t *matchbuf = NULL;
-static uint64_t matchlen = 0;
-static uint64_t matchoffset = 0;
-static uint8_t *comparebuf = NULL;
-
-static Guid unique_guid;
-static Guid type_guid;
-static char *label;
-static int hits = 0;
-
-#define BUFSIZE 1024
-// FIXME: currently we only support 512-byte sectors.
-#define LBA_SIZE 512
-
-
-// remember one of the possibly many hits
-static int match_partnum = 0; // 0 for no match, 1-N for match
-static char match_filename[BUFSIZE]; // matching filename
-
-
// read a file into a buffer, return buffer and update size
static uint8_t *ReadFile(const char *filename, uint64_t *size) {
FILE *f;
@@ -94,203 +59,11 @@ static uint8_t *ReadFile(const char *filename, uint64_t *size) {
return buf;
}
-// fill comparebuf with the data to be examined, returning true on success.
-static int FillBuffer(int fd, uint64_t pos, uint64_t count) {
- uint8_t *bufptr = comparebuf;
-
- if (-1 == lseek(fd, pos, SEEK_SET))
- return 0;
-
- // keep reading until done or error
- while (count) {
- ssize_t bytes_read = read(fd, bufptr, count);
- // negative means error, 0 means (unexpected) EOF
- if (bytes_read <= 0)
- return 0;
- count -= bytes_read;
- bufptr += bytes_read;
- }
-
- return 1;
-}
-
-// check partition data content. return true for match, 0 for no match or error
-static int match_content(struct drive *drive, GptEntry *entry) {
- uint64_t part_size;
-
- if (!matchlen)
- return 1;
-
- // Ensure that the region we want to match against is inside the partition.
- part_size = LBA_SIZE * (entry->ending_lba - entry->starting_lba + 1);
- if (matchoffset + matchlen > part_size) {
- return 0;
- }
-
- // Read the partition data.
- if (!FillBuffer(drive->fd,
- (LBA_SIZE * entry->starting_lba) + matchoffset,
- matchlen)) {
- Error("unable to read partition data\n");
- return 0;
- }
-
- // Compare it
- if (0 == memcmp(matchbuf, comparebuf, matchlen)) {
- return 1;
- }
-
- // Nope.
- return 0;
-}
-
-// This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3, /dev/sda -> /dev/sda3
-static void showmatch(char *filename, int partnum, GptEntry *entry) {
- char * format = "%s%d\n";
- if (strncmp("/dev/mmcblk", filename, 11) == 0)
- format = "%sp%d\n";
- if (numeric)
- printf("%d\n", partnum);
- else
- printf(format, filename, partnum);
- if (verbose > 0)
- EntryDetails(entry, partnum - 1, numeric);
-}
-
-// This returns true if a GPT partition matches the search criteria. If a match
-// isn't found (or if the file doesn't contain a GPT), it returns false. The
-// filename and partition number that matched is left in a global, since we
-// could have multiple hits.
-static int do_search(char *filename) {
- int retval = 0;
- int i;
- struct drive drive;
- GptEntry *entry;
- char partlabel[GPT_PARTNAME_LEN];
-
- if (CGPT_OK != DriveOpen(filename, &drive))
- return 0;
-
- if (GPT_SUCCESS != GptSanityCheck(&drive.gpt)) {
- (void) DriveClose(&drive, 0);
- return 0;
- }
-
- for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) {
- entry = GetEntry(&drive.gpt, ANY_VALID, i);
-
- if (IsZero(&entry->type))
- continue;
-
- int found = 0;
- if ((set_unique && GuidEqual(&unique_guid, &entry->unique)) ||
- (set_type && GuidEqual(&type_guid, &entry->type))) {
- found = 1;
- } else if (set_label) {
- if (CGPT_OK != UTF16ToUTF8(entry->name,
- sizeof(entry->name) / sizeof(entry->name[0]),
- (uint8_t *)partlabel, sizeof(partlabel))) {
- Error("The label cannot be converted from UTF16, so abort.\n");
- return 0;
- }
- if (!strncmp(label, partlabel, sizeof(partlabel))) {
- found = 1;
- }
- }
- if (found && match_content(&drive, entry)) {
- hits++;
- retval++;
- showmatch(filename, i+1, entry);
- if (!match_partnum) {
- match_partnum = i+1;
- strcpy(match_filename, filename);
- }
- }
- }
-
- (void) DriveClose(&drive, 0);
-
- return retval;
-}
-
-
-#define PROC_PARTITIONS "/proc/partitions"
-#define DEV_DIR "/dev"
-#define SYS_BLOCK_DIR "/sys/block"
-
-static const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 };
-
-// Given basename "foo", see if we can find a whole, real device by that name.
-// This is copied from the logic in the linux utility 'findfs', although that
-// does more exhaustive searching.
-static char *is_wholedev(const char *basename) {
- int i;
- struct stat statbuf;
- static char pathname[BUFSIZE]; // we'll return this.
- char tmpname[BUFSIZE];
-
- // It should be a block device under /dev/,
- for (i = 0; devdirs[i]; i++) {
- sprintf(pathname, "%s/%s", devdirs[i], basename);
-
- if (0 != stat(pathname, &statbuf))
- continue;
-
- if (!S_ISBLK(statbuf.st_mode))
- continue;
-
- // It should have a symlink called /sys/block/*/device
- sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename);
-
- if (0 != lstat(tmpname, &statbuf))
- continue;
-
- if (!S_ISLNK(statbuf.st_mode))
- continue;
-
- // found it
- return pathname;
- }
-
- return 0;
-}
-
-
-// This scans all the physical devices it can find, looking for a match. It
-// returns true if any matches were found, false otherwise.
-static int scan_real_devs(void) {
- int found = 0;
- char line[BUFSIZE];
- char partname[128]; // max size for /proc/partition lines?
- FILE *fp;
- char *pathname;
-
- fp = fopen(PROC_PARTITIONS, "r");
- if (!fp) {
- perror("can't read " PROC_PARTITIONS);
- return found;
- }
-
- while (fgets(line, sizeof(line), fp)) {
- int ma, mi;
- long long unsigned int sz;
-
- if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, partname) != 4)
- continue;
-
- if ((pathname = is_wholedev(partname))) {
- if (do_search(pathname)) {
- found++;
- }
- }
- }
-
- fclose(fp);
- return found;
-}
+int cmd_find(int argc, char *argv[]) {
+ CgptFindParams params;
+ memset(&params, 0, sizeof(params));
-int cmd_find(int argc, char *argv[]) {
int i;
int errorcnt = 0;
char *e = 0;
@@ -302,49 +75,49 @@ int cmd_find(int argc, char *argv[]) {
switch (c)
{
case 'v':
- verbose++;
+ params.verbose++;
break;
case 'n':
- numeric = 1;
+ params.numeric = 1;
break;
case '1':
- oneonly = 1;
+ params.oneonly = 1;
break;
case 'l':
- set_label = 1;
- label = optarg;
+ params.set_label = 1;
+ params.label = optarg;
break;
case 't':
- set_type = 1;
- if (CGPT_OK != SupportedType(optarg, &type_guid) &&
- CGPT_OK != StrToGuid(optarg, &type_guid)) {
+ params.set_type = 1;
+ if (CGPT_OK != SupportedType(optarg, &params.type_guid) &&
+ CGPT_OK != StrToGuid(optarg, &params.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)) {
+ params.set_unique = 1;
+ if (CGPT_OK != StrToGuid(optarg, &params.unique_guid)) {
Error("invalid argument to -%c: %s\n", c, optarg);
errorcnt++;
}
break;
case 'M':
- matchbuf = ReadFile(optarg, &matchlen);
- if (!matchbuf || !matchlen) {
+ params.matchbuf = ReadFile(optarg, &params.matchlen);
+ if (!params.matchbuf || !params.matchlen) {
Error("Unable to read from %s\n", optarg);
errorcnt++;
}
// Go ahead and allocate space for the comparison too
- comparebuf = (uint8_t *)malloc(matchlen);
- if (!comparebuf) {
+ params.comparebuf = (uint8_t *)malloc(params.matchlen);
+ if (!params.comparebuf) {
Error("Unable to allocate %" PRIu64 "bytes for comparison buffer\n",
- matchlen);
+ params.matchlen);
errorcnt++;
}
break;
case 'O':
- matchoffset = strtoull(optarg, &e, 0);
+ params.matchoffset = strtoull(optarg, &e, 0);
if (!*optarg || (e && *e)) {
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
errorcnt++;
@@ -367,7 +140,7 @@ int cmd_find(int argc, char *argv[]) {
break;
}
}
- if (!set_unique && !set_type && !set_label) {
+ if (!params.set_unique && !params.set_type && !params.set_label) {
Error("You must specify at least one of -t, -u, or -l\n");
errorcnt++;
}
@@ -378,17 +151,19 @@ int cmd_find(int argc, char *argv[]) {
}
if (optind < argc) {
- for (i=optind; i<argc; i++)
- do_search(argv[i]);
+ for (i=optind; i<argc; i++) {
+ params.driveName = argv[i];
+ cgpt_find(&params);
+ }
} else {
- scan_real_devs();
+ cgpt_find(&params);
}
- if (oneonly && hits != 1) {
+ if (params.oneonly && params.hits != 1) {
return CGPT_FAILED;
}
- if (match_partnum) {
+ if (params.match_partnum) {
return CGPT_OK;
}
diff --git a/cgpt/cmd_prioritize.c b/cgpt/cmd_prioritize.c
index 3f345689..cb655f28 100644
--- a/cgpt/cmd_prioritize.c
+++ b/cgpt/cmd_prioritize.c
@@ -1,16 +1,14 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 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"
+#include "cgpt_params.h"
static void Usage(void)
{
@@ -33,107 +31,12 @@ static void Usage(void)
"\n", progname);
}
-//////////////////////////////////////////////////////////////////////////////
-// I want a sorted list of priority groups, where each element in the list
-// contains an unordered list of GPT partition numbers. This is a stupid
-// implementation, but our needs are simple and don't justify the time or space
-// it would take to write a "better" one.
-#define MAX_GROUPS 17 // 0-15, plus one "higher"
-
-typedef struct {
- int priority; // priority of this group
- int num_parts; // number of partitions in this group
- uint32_t *part; // array of partitions in this group
-} group_t;
-
-typedef struct {
- int max_parts; // max number of partitions in any group
- int num_groups; // number of non-empty groups
- group_t group[MAX_GROUPS]; // array of groups
-} group_list_t;
-
-
-static group_list_t *NewGroupList(int max_p) {
- int i;
- group_list_t *gl = (group_list_t *)malloc(sizeof(group_list_t));
- require(gl);
- gl->max_parts = max_p;
- gl->num_groups = 0;
- // reserve space for the maximum number of partitions in every group
- for (i=0; i<MAX_GROUPS; i++) {
- gl->group[i].priority = -1;
- gl->group[i].num_parts = 0;
- gl->group[i].part = (uint32_t *)malloc(sizeof(uint32_t) * max_p);
- require(gl->group[i].part);
- }
-
- return gl;
-}
-
-static void FreeGroups(group_list_t *gl) {
- int i;
- for (i=0; i<MAX_GROUPS; i++)
- free(gl->group[i].part);
- free(gl);
-}
-
-static void AddToGroup(group_list_t *gl, int priority, int partition) {
- int i;
- // See if I've already got a group with this priority
- for (i=0; i<gl->num_groups; i++)
- if (gl->group[i].priority == priority)
- break;
- if (i == gl->num_groups) {
- // no, add a group
- require(i < MAX_GROUPS);
- gl->num_groups++;
- gl->group[i].priority = priority;
- }
- // add the partition to it
- int j = gl->group[i].num_parts;
- gl->group[i].part[j] = partition;
- gl->group[i].num_parts++;
-}
-
-static void ChangeGroup(group_list_t *gl, int old_priority, int new_priority) {
- int i;
- for (i=0; i<gl->num_groups; i++)
- if (gl->group[i].priority == old_priority) {
- gl->group[i].priority = new_priority;
- break;
- }
-}
-
-static void SortGroups(group_list_t *gl) {
- int i, j;
- group_t tmp;
-
- // straight insertion sort is fast enough
- for (i=1; i<gl->num_groups; i++) {
- tmp = gl->group[i];
- for (j=i; j && (gl->group[j-1].priority < tmp.priority); j--)
- gl->group[j] = gl->group[j-1];
- gl->group[j] = tmp;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-
int cmd_prioritize(int argc, char *argv[]) {
struct drive drive;
- uint32_t set_partition = 0;
- int set_friends = 0;
- int max_priority = 0;
- int priority;
- int orig_priority = 0;
- int gpt_retval;
- GptEntry *entry;
- uint32_t index;
- uint32_t max_part;
- int num_kernels;
- int i,j;
- group_list_t *groups;
+
+ CgptPrioritizeParams params;
+ memset(&params, 0, sizeof(params));
+
int c;
int errorcnt = 0;
@@ -145,7 +48,7 @@ int cmd_prioritize(int argc, char *argv[]) {
switch (c)
{
case 'i':
- set_partition = (uint32_t)strtoul(optarg, &e, 0);
+ params.set_partition = (uint32_t)strtoul(optarg, &e, 0);
if (!*optarg || (e && *e))
{
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
@@ -153,16 +56,16 @@ int cmd_prioritize(int argc, char *argv[]) {
}
break;
case 'f':
- set_friends = 1;
+ params.set_friends = 1;
break;
case 'P':
- max_priority = (int)strtol(optarg, &e, 0);
+ params.max_priority = (int)strtol(optarg, &e, 0);
if (!*optarg || (e && *e))
{
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
errorcnt++;
}
- if (max_priority < 1 || max_priority > 15) {
+ if (params.max_priority < 1 || params.max_priority > 15) {
Error("value for -%c must be between 1 and 15\n", c);
errorcnt++;
}
@@ -190,7 +93,7 @@ int cmd_prioritize(int argc, char *argv[]) {
return CGPT_FAILED;
}
- if (set_friends && !set_partition) {
+ if (params.set_friends && !params.set_partition) {
Error("the -f option is only useful with the -i option\n");
Usage();
return CGPT_FAILED;
@@ -201,114 +104,7 @@ int cmd_prioritize(int argc, char *argv[]) {
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;
- }
-
- max_part = GetNumberOfEntries(&drive.gpt);
-
- if (set_partition) {
- if (set_partition < 1 || set_partition > max_part) {
- Error("invalid partition number: %d (must be between 1 and %d\n",
- set_partition, max_part);
- goto bad;
- }
- index = set_partition - 1;
- // it must be a kernel
- entry = GetEntry(&drive.gpt, PRIMARY, index);
- if (!GuidEqual(&entry->type, &guid_chromeos_kernel)) {
- Error("partition %d is not a ChromeOS kernel\n", set_partition);
- goto bad;
- }
- }
-
- // How many kernel partitions do I have?
- num_kernels = 0;
- for (i = 0; i < max_part; i++) {
- entry = GetEntry(&drive.gpt, PRIMARY, i);
- if (GuidEqual(&entry->type, &guid_chromeos_kernel))
- num_kernels++;
- }
-
- if (!num_kernels)
- // nothing to do, so don't
- goto good;
-
- // Determine the current priority groups
- groups = NewGroupList(num_kernels);
- for (i = 0; i < max_part; i++) {
- entry = GetEntry(&drive.gpt, PRIMARY, i);
- if (!GuidEqual(&entry->type, &guid_chromeos_kernel))
- continue;
-
- priority = GetPriority(&drive.gpt, PRIMARY, i);
-
- // Is this partition special?
- if (set_partition && (i+1 == set_partition)) {
- orig_priority = priority; // remember the original priority
- if (set_friends)
- AddToGroup(groups, priority, i); // we'll move them all later
- else
- AddToGroup(groups, 99, i); // move only this one
- } else {
- AddToGroup(groups, priority, i); // just remember
- }
- }
-
- // If we're including friends, then change the original group priority
- if (set_partition && set_friends) {
- ChangeGroup(groups, orig_priority, 99);
- }
-
- // Sorting gives the new order. Now we just need to reassign the
- // priorities.
- SortGroups(groups);
-
- // We'll never lower anything to zero, so if the last group is priority zero
- // we can ignore it.
- i = groups->num_groups;
- if (groups->group[i-1].priority == 0)
- groups->num_groups--;
-
- // Where do we start?
- if (max_priority)
- priority = max_priority;
- else
- priority = groups->num_groups > 15 ? 15 : groups->num_groups;
-
- // Figure out what the new values should be
- for (i=0; i<groups->num_groups; i++) {
- groups->group[i].priority = priority;
- if (priority > 1)
- priority--;
- }
-
- // Now apply the ranking to the GPT
- for (i=0; i<groups->num_groups; i++)
- for (j=0; j<groups->group[i].num_parts; j++)
- SetPriority(&drive.gpt, PRIMARY,
- groups->group[i].part[j], groups->group[i].priority);
-
- FreeGroups(groups);
-
-
- // Write it all out
-good:
- 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);
-
- return DriveClose(&drive, 1);
+ params.driveName = argv[optind];
-bad:
- (void) DriveClose(&drive, 0);
- return CGPT_FAILED;
+ return cgpt_prioritize(&params);
}
diff --git a/cgpt/cmd_repair.c b/cgpt/cmd_repair.c
index aafdc938..10d4ee8b 100644
--- a/cgpt/cmd_repair.c
+++ b/cgpt/cmd_repair.c
@@ -1,15 +1,13 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 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"
+#include "cgpt_params.h"
static void Usage(void)
{
@@ -22,8 +20,10 @@ static void Usage(void)
int cmd_repair(int argc, char *argv[]) {
struct drive drive;
- int verbose = 0;
-
+
+ CgptRepairParams params;
+ memset(&params, 0, sizeof(params));
+
int c;
int errorcnt = 0;
@@ -33,7 +33,7 @@ int cmd_repair(int argc, char *argv[]) {
switch (c)
{
case 'v':
- verbose++;
+ params.verbose++;
break;
case 'h':
@@ -58,28 +58,7 @@ int cmd_repair(int argc, char *argv[]) {
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");
+ params.driveName = argv[optind];
- return DriveClose(&drive, 1);
+ return cgpt_repair(&params);
}
diff --git a/cgpt/cmd_show.c b/cgpt/cmd_show.c
index 4942251f..509085ee 100644
--- a/cgpt/cmd_show.c
+++ b/cgpt/cmd_show.c
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -7,11 +7,8 @@
#define __STDC_FORMAT_MACROS
#include <getopt.h>
#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-
-#include "cgptlib_internal.h"
+#include "cgpt_params.h"
static void Usage(void)
{
@@ -34,163 +31,11 @@ static void Usage(void)
"\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("%sAlternate LBA: %lld\n", indent, (long long)header->alternate_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, GUID_STRLEN);
- 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, uint32_t index, int raw) {
- char contents[256]; // scratch buffer for formatting output
- uint8_t label[GPT_PARTNAME_LEN];
-
- if (!raw) {
- char type[GUID_STRLEN], unique[GUID_STRLEN];
-
- UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
- label, sizeof(label));
- require(snprintf(contents, sizeof(contents),
- "Label: \"%s\"", label) < sizeof(contents));
- 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, GUID_STRLEN);
- printf(PARTITION_MORE, "Type: ", type);
- }
- GuidToStr(&entry->unique, unique, GUID_STRLEN);
- printf(PARTITION_MORE, "UUID: ", unique);
- if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
- int tries = (entry->attrs.fields.gpt_att &
- CGPT_ATTRIBUTE_TRIES_MASK) >>
- CGPT_ATTRIBUTE_TRIES_OFFSET;
- int successful = (entry->attrs.fields.gpt_att &
- CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
- CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
- int priority = (entry->attrs.fields.gpt_att &
- CGPT_ATTRIBUTE_PRIORITY_MASK) >>
- CGPT_ATTRIBUTE_PRIORITY_OFFSET;
- require(snprintf(contents, sizeof(contents),
- "priority=%d tries=%d successful=%d",
- priority, tries, successful) < sizeof(contents));
- printf(PARTITION_MORE, "Attr: ", contents);
- }
- } else {
- char type[GUID_STRLEN], unique[GUID_STRLEN];
-
- UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
- label, sizeof(label));
- require(snprintf(contents, sizeof(contents),
- "Label: \"%s\"", label) < sizeof(contents));
- printf(PARTITION_FMT, (int)entry->starting_lba,
- (int)(entry->ending_lba - entry->starting_lba + 1),
- index+1, contents);
- GuidToStr(&entry->type, type, GUID_STRLEN);
- printf(PARTITION_MORE, "Type: ", type);
- GuidToStr(&entry->unique, unique, GUID_STRLEN);
- printf(PARTITION_MORE, "UUID: ", unique);
- require(snprintf(contents, sizeof(contents),
- "[%x]", entry->attrs.fields.gpt_att) < sizeof(contents));
- printf(PARTITION_MORE, "Attr: ", contents);
- }
-}
-
-
-void EntriesDetails(GptData *gpt, const int secondary, int raw) {
- uint32_t i;
-
- for (i = 0; i < GetNumberOfEntries(gpt); ++i) {
- GptEntry *entry;
- entry = GetEntry(gpt, secondary, i);
-
- if (IsZero(&entry->type))
- continue;
-
- EntryDetails(entry, i, raw);
- }
-}
-
int cmd_show(int argc, char *argv[]) {
struct drive drive;
- int numeric = 0;
- int verbose = 0;
- int quick = 0;
- uint32_t partition = 0;
- int single_item = 0;
- int gpt_retval;
+
+ CgptShowParams params;
+ memset(&params, 0, sizeof(params));
int c;
int errorcnt = 0;
@@ -202,16 +47,16 @@ int cmd_show(int argc, char *argv[]) {
switch (c)
{
case 'n':
- numeric = 1;
+ params.numeric = 1;
break;
case 'v':
- verbose = 1;
+ params.verbose = 1;
break;
case 'q':
- quick = 1;
+ params.quick = 1;
break;
case 'i':
- partition = (uint32_t)strtoul(optarg, &e, 0);
+ params.partition = (uint32_t)strtoul(optarg, &e, 0);
if (!*optarg || (e && *e))
{
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
@@ -227,7 +72,7 @@ int cmd_show(int argc, char *argv[]) {
case 'T':
case 'P':
case 'A':
- single_item = c;
+ params.single_item = c;
break;
case 'h':
@@ -258,164 +103,7 @@ int cmd_show(int argc, char *argv[]) {
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;
- }
-
- uint32_t index = partition - 1;
- GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, index);
- char buf[256]; // scratch buffer for string conversion
-
- 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, sizeof(buf));
- printf("%s\n", buf);
- break;
- case 'u':
- GuidToStr(&entry->unique, buf, sizeof(buf));
- printf("%s\n", buf);
- break;
- case 'l':
- UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
- (uint8_t *)buf, sizeof(buf));
- printf("%s\n", buf);
- break;
- case 'S':
- printf("%d\n", GetSuccessful(&drive.gpt, ANY_VALID, index));
- break;
- case 'T':
- printf("%d\n", GetTries(&drive.gpt, ANY_VALID, index));
- break;
- case 'P':
- printf("%d\n", GetPriority(&drive.gpt, ANY_VALID, index));
- break;
- case 'A':
- printf("0x%x\n", entry->attrs.fields.gpt_att);
- break;
- }
- } else {
- printf(TITLE_FMT, "start", "size", "part", "contents");
- EntryDetails(entry, index, numeric);
- }
-
- } else if (quick) { // show all partitions, quickly
- uint32_t i;
- GptEntry *entry;
- char type[GUID_STRLEN];
-
- for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) {
- entry = GetEntry(&drive.gpt, ANY_VALID, i);
-
- if (IsZero(&entry->type))
- continue;
-
- if (!numeric && CGPT_OK == ResolveType(&entry->type, type)) {
- } else {
- GuidToStr(&entry->type, type, GUID_STRLEN);
- }
- 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]; // buffer for formatted PMBR content
- PMBRToStr(&drive.pmbr, buf, sizeof(buf)); // will exit if buf is too small
- 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];
-
- require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
- 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];
-
- require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
- header = (GptHeader*)drive.gpt.secondary_header;
- HeaderDetails(header, indent, numeric);
- }
- }
- }
-
- (void) CheckValid(&drive);
- (void) DriveClose(&drive, 0);
+ params.driveName = argv[optind];
- return CGPT_OK;
+ return cgpt_show(&params);
}