1a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// Use of this source code is governed by a BSD-style license that can be
3a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// found in the LICENSE file.
4a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
5a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define __STDC_FORMAT_MACROS
6a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
7a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#include <string.h>
8a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
90c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "cgpt.h"
10a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#include "cgptlib_internal.h"
11455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo#include "crc32.h"
120c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "vboot_host.h"
13a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
14a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan/* Generate output like:
15a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan *
16a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan *  [AB-CD-EF-01]   for group = 1
17a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan *  [ABCD-EF01]     for group = 3  (low byte first)
18a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan *
19a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan * Needs (size*3-1+3) bytes of space in 'buf' (included the tailing '\0').
20a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan */
21a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define BUFFER_SIZE(size) (size *3 - 1 + 3)
22a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanstatic short Uint8To2Chars(const uint8_t t) {
23a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  int h = t >> 4;
24a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  int l = t & 0xf;
25a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  h = (h >= 0xA) ? h - 0xA + 'A' : h + '0';
26a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  l = (l >= 0xA) ? l - 0xA + 'A' : l + '0';
27a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  return (h << 8) + l;
28a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
29a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
30a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanstatic void RawDump(const uint8_t *memory, const int size,
31a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                    char *buf, int group) {
32a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  int i, outlen = 0;
33a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  buf[outlen++] = '[';
34a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  for (i = 0; i < size; ++i) {
35a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    short c2 = Uint8To2Chars(memory[i]);
36a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    buf[outlen++] = c2 >> 8;
37a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    buf[outlen++] = c2 & 0xff;
38a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if (i != (size - 1) && ((i + 1) % group) == 0)
39a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      buf[outlen++] = '-';
40a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
41a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  buf[outlen++] = ']';
42a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  buf[outlen++] = '\0';
43a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
44a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
45a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan/* Output formatters */
4682bb80262e87d253731251f829471005e0b9d8e7Shawn Nematbakhsh#define TITLE_FMT      "%12s%12s%8s  %s\n"
4782bb80262e87d253731251f829471005e0b9d8e7Shawn Nematbakhsh#define GPT_FMT        "%12d%12d%8s  %s\n"
4882bb80262e87d253731251f829471005e0b9d8e7Shawn Nematbakhsh#define GPT_MORE       "%12s%12s%8s  ", "", "", ""
4982bb80262e87d253731251f829471005e0b9d8e7Shawn Nematbakhsh#define PARTITION_FMT  "%12d%12d%8d  %s\n"
5082bb80262e87d253731251f829471005e0b9d8e7Shawn Nematbakhsh#define PARTITION_MORE "%12s%12s%8s  %s%s\n", "", "", ""
51a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
521c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulkvoid PrintSignature(const char *indent, const char *sig, size_t n, int raw) {
531c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  size_t i;
54a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("%sSig: ", indent);
55a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (!raw) {
56a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    printf("[");
571c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    for (i = 0; i < n; ++i)
581c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk      printf("%c", sig[i]);
59a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    printf("]");
60a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  } else {
611c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    char *buf = malloc(BUFFER_SIZE(n));
621c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    RawDump((uint8_t *)sig, n, buf, 1);
63a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    printf("%s", buf);
641c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    free(buf);
65a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
66a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("\n");
671c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk}
681c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk
691c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulkstatic void HeaderDetails(GptHeader *header, GptEntry *entries,
701c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk                          const char *indent, int raw) {
711c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  PrintSignature(indent, header->signature, sizeof(header->signature), raw);
72a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
73a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("%sRev: 0x%08x\n", indent, header->revision);
74a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("%sSize: %d\n", indent, header->size);
75455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo  printf("%sHeader CRC: 0x%08x %s\n", indent, header->header_crc32,
76455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo         (HeaderCrc(header) != header->header_crc32) ? "(INVALID)" : "");
77a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("%sMy LBA: %lld\n", indent, (long long)header->my_lba);
78a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("%sAlternate LBA: %lld\n", indent, (long long)header->alternate_lba);
79a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("%sFirst LBA: %lld\n", indent, (long long)header->first_usable_lba);
80a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("%sLast LBA: %lld\n", indent, (long long)header->last_usable_lba);
81a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
82a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  {  /* For disk guid */
83a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    char buf[GUID_STRLEN];
84a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    GuidToStr(&header->disk_uuid, buf, GUID_STRLEN);
85a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    printf("%sDisk UUID: %s\n", indent, buf);
86a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
87a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
88a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("%sEntries LBA: %lld\n", indent, (long long)header->entries_lba);
89a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("%sNumber of entries: %d\n", indent, header->number_of_entries);
90a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  printf("%sSize of entry: %d\n", indent, header->size_of_entry);
91455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo  printf("%sEntries CRC: 0x%08x %s\n", indent, header->entries_crc32,
92455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo         header->entries_crc32 !=
93455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo             Crc32((const uint8_t *)entries,header->size_of_entry *
94455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo                                            header->number_of_entries)
95455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo             ? "INVALID" : ""
96455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo         );
97a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
98a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
99a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanvoid EntryDetails(GptEntry *entry, uint32_t index, int raw) {
100a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  char contents[256];                   // scratch buffer for formatting output
101a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  uint8_t label[GPT_PARTNAME_LEN];
10232fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk  char type[GUID_STRLEN], unique[GUID_STRLEN];
103a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
10432fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk  UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
10532fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk              label, sizeof(label));
10632fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk  require(snprintf(contents, sizeof(contents),
10732fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk                   "Label: \"%s\"", label) < sizeof(contents));
10832fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk  printf(PARTITION_FMT, (int)entry->starting_lba,
10932fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk         (int)(entry->ending_lba - entry->starting_lba + 1),
11032fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk         index+1, contents);
111a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
11232fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk  if (!raw && CGPT_OK == ResolveType(&entry->type, type)) {
11332fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk    printf(PARTITION_MORE, "Type: ", type);
11432fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk  } else {
11532fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk    GuidToStr(&entry->type, type, GUID_STRLEN);
11632fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk    printf(PARTITION_MORE, "Type: ", type);
11732fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk  }
11832fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk  GuidToStr(&entry->unique, unique, GUID_STRLEN);
11932fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk  printf(PARTITION_MORE, "UUID: ", unique);
12032fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk
12132fd6dead10a8255fea27f6e5ce9ba92d8716008Albert Chaulk  if (!raw) {
122a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
123a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      int tries = (entry->attrs.fields.gpt_att &
124a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                   CGPT_ATTRIBUTE_TRIES_MASK) >>
125a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan          CGPT_ATTRIBUTE_TRIES_OFFSET;
126a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      int successful = (entry->attrs.fields.gpt_att &
127a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                        CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
128a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan          CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
129a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      int priority = (entry->attrs.fields.gpt_att &
130a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                      CGPT_ATTRIBUTE_PRIORITY_MASK) >>
131a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan          CGPT_ATTRIBUTE_PRIORITY_OFFSET;
132a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      require(snprintf(contents, sizeof(contents),
133a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                       "priority=%d tries=%d successful=%d",
134a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                       priority, tries, successful) < sizeof(contents));
135a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      printf(PARTITION_MORE, "Attr: ", contents);
136a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
137a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  } else {
138a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    require(snprintf(contents, sizeof(contents),
139a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                     "[%x]", entry->attrs.fields.gpt_att) < sizeof(contents));
140a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    printf(PARTITION_MORE, "Attr: ", contents);
141a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
142a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
143a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
144fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulkvoid EntriesDetails(struct drive *drive, const int secondary, int raw) {
145a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  uint32_t i;
146a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
147fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk  for (i = 0; i < GetNumberOfEntries(drive); ++i) {
148a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    GptEntry *entry;
149fa6b35c1ffa33833b3250a6515869ccd4cb59121Albert Chaulk    entry = GetEntry(&drive->gpt, secondary, i);
150a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
1513f806a2abf07d7b801852a4a6f3a9080a4b5c427Bill Richardson    if (GuidIsZero(&entry->type))
152a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      continue;
153a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
154a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    EntryDetails(entry, i, raw);
155a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
156a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
157a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
15818e03706df6ab4256a89f4e578ecf0f165641c8aBill Richardsonstatic int GptShow(struct drive *drive, CgptShowParams *params) {
1591c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  int gpt_retval;
1601c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) {
161a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    Error("GptSanityCheck() returned %d: %s\n",
162a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan          gpt_retval, GptError(gpt_retval));
163a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    return CGPT_FAILED;
164a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
165a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
166a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  if (params->partition) {                      // show single partition
167a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
1681c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    if (params->partition > GetNumberOfEntries(drive)) {
169a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      Error("invalid partition number: %d\n", params->partition);
170a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      return CGPT_FAILED;
171a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
172a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
173a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    uint32_t index = params->partition - 1;
1741c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    GptEntry *entry = GetEntry(&drive->gpt, ANY_VALID, index);
175a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    char buf[256];                      // scratch buffer for string conversion
176a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
177a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    if (params->single_item) {
178a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      switch(params->single_item) {
179a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      case 'b':
180a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        printf("%" PRId64 "\n", entry->starting_lba);
181a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        break;
18298624d37447d01a9a78d9e0a1f55cbbce2ee99e4Mike Frysinger      case 's': {
18398624d37447d01a9a78d9e0a1f55cbbce2ee99e4Mike Frysinger        uint64_t size = 0;
18498624d37447d01a9a78d9e0a1f55cbbce2ee99e4Mike Frysinger        // If these aren't actually defined, don't show anything
18598624d37447d01a9a78d9e0a1f55cbbce2ee99e4Mike Frysinger        if (entry->ending_lba || entry->starting_lba)
18698624d37447d01a9a78d9e0a1f55cbbce2ee99e4Mike Frysinger          size = entry->ending_lba - entry->starting_lba + 1;
18798624d37447d01a9a78d9e0a1f55cbbce2ee99e4Mike Frysinger        printf("%" PRId64 "\n", size);
188a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        break;
18998624d37447d01a9a78d9e0a1f55cbbce2ee99e4Mike Frysinger      }
190a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      case 't':
191a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        GuidToStr(&entry->type, buf, sizeof(buf));
192a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        printf("%s\n", buf);
193a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        break;
194a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      case 'u':
195a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        GuidToStr(&entry->unique, buf, sizeof(buf));
196a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        printf("%s\n", buf);
197a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        break;
198a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      case 'l':
199a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
200a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan                    (uint8_t *)buf, sizeof(buf));
201a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        printf("%s\n", buf);
202a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        break;
203a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      case 'S':
2041c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk        printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
205a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        break;
206a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      case 'T':
2071c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk        printf("%d\n", GetTries(drive, ANY_VALID, index));
208a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        break;
209a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      case 'P':
2101c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk        printf("%d\n", GetPriority(drive, ANY_VALID, index));
211a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        break;
212a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      case 'A':
213a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        printf("0x%x\n", entry->attrs.fields.gpt_att);
214a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        break;
215a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      }
216a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    } else {
217a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      printf(TITLE_FMT, "start", "size", "part", "contents");
218a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      EntryDetails(entry, index, params->numeric);
219a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
220a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
221a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  } else if (params->quick) {                   // show all partitions, quickly
222a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    uint32_t i;
223a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    GptEntry *entry;
224a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    char type[GUID_STRLEN];
225a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
2261c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    for (i = 0; i < GetNumberOfEntries(drive); ++i) {
2271c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk      entry = GetEntry(&drive->gpt, ANY_VALID, i);
228a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
2293f806a2abf07d7b801852a4a6f3a9080a4b5c427Bill Richardson      if (GuidIsZero(&entry->type))
230a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        continue;
231a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
232a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      if (!params->numeric && CGPT_OK == ResolveType(&entry->type, type)) {
233a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      } else {
234a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan        GuidToStr(&entry->type, type, GUID_STRLEN);
235a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      }
236a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      printf(PARTITION_FMT, (int)entry->starting_lba,
237a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan             (int)(entry->ending_lba - entry->starting_lba + 1),
238a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan             i+1, type);
239a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
240a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  } else {                              // show all partitions
241455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo    GptEntry *entries;
242455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo
2431c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    if (CGPT_OK != ReadPMBR(drive)) {
244a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      Error("Unable to read PMBR\n");
245a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan      return CGPT_FAILED;
246a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
247a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
248a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    printf(TITLE_FMT, "start", "size", "part", "contents");
249a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    char buf[256];                      // buffer for formatted PMBR content
2501c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small
25188458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen    printf(GPT_FMT, 0, GPT_PMBR_SECTORS, "", buf);
252a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
2531c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    if (drive->gpt.valid_headers & MASK_PRIMARY) {
25488458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen      printf(GPT_FMT, (int)GPT_PMBR_SECTORS,
25588458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen             (int)GPT_HEADER_SECTORS, "", "Pri GPT header");
256a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    } else {
25788458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen      printf(GPT_FMT, (int)GPT_PMBR_SECTORS,
25888458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen             (int)GPT_HEADER_SECTORS, "INVALID", "Pri GPT header");
259a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
260a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
261455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo    if (params->debug ||
2621c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk        ((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
263455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo      GptHeader *header;
264455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo      char indent[64];
265455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo
266455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo      require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
2671c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk      header = (GptHeader*)drive->gpt.primary_header;
2681c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk      entries = (GptEntry*)drive->gpt.primary_entries;
269455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo      HeaderDetails(header, entries, indent, params->numeric);
270455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo    }
271455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo
272a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen    GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header;
273a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen    printf(GPT_FMT, (int)primary_header->entries_lba,
2743200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen           (int)CalculateEntriesSectors(primary_header),
2751c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk           drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
276a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan           "Pri GPT table");
277a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
278455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo    if (params->debug ||
2791c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk        (drive->gpt.valid_entries & MASK_PRIMARY))
2801c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk      EntriesDetails(drive, PRIMARY, params->numeric);
281a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
282455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo    /****************************** Secondary *************************/
283a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen    GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
284a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen    printf(GPT_FMT, (int)secondary_header->entries_lba,
2853200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen           (int)CalculateEntriesSectors(secondary_header),
2861c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk           drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
287a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan           "Sec GPT table");
288a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    /* We show secondary table details if any of following is true.
289455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo     *   1. in debug mode.
290455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo     *   2. only secondary is valid.
291455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo     *   3. secondary is not identical to promary.
292a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan     */
293455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo    if (params->debug ||
2941c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk        ((drive->gpt.valid_entries & MASK_SECONDARY) &&
2951c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk         (!(drive->gpt.valid_entries & MASK_PRIMARY) ||
2961c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk          memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries,
2973200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen                 secondary_header->number_of_entries *
2983200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen                 secondary_header->size_of_entry)))) {
2991c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk      EntriesDetails(drive, SECONDARY, params->numeric);
300a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
301a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
3021c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    if (drive->gpt.valid_headers & MASK_SECONDARY)
3036ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen      printf(GPT_FMT, (int)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS),
30488458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen             (int)GPT_HEADER_SECTORS, "", "Sec GPT header");
305a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    else
30688458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen      printf(GPT_FMT, (int)GPT_PMBR_SECTORS,
30788458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen             (int)GPT_HEADER_SECTORS, "INVALID", "Sec GPT header");
308a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    /* We show secondary header if any of following is true:
309455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo     *   1. in debug mode.
310455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo     *   2. only secondary is valid.
311455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo     *   3. secondary is not synonymous to primary.
312a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan     */
313455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo    if (params->debug ||
3141c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk        ((drive->gpt.valid_headers & MASK_SECONDARY) &&
3151c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk         (!(drive->gpt.valid_headers & MASK_PRIMARY) ||
3161c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk          !IsSynonymous((GptHeader*)drive->gpt.primary_header,
3171c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk                        (GptHeader*)drive->gpt.secondary_header)) &&
318455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo         params->verbose)) {
319455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo      GptHeader *header;
320455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo      char indent[64];
321455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo
322455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo      require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
3231c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk      header = (GptHeader*)drive->gpt.secondary_header;
3241c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk      entries = (GptEntry*)drive->gpt.secondary_entries;
325455b119dc0f3cd5538c4a53f0e2ab38534bcdf14Louis Yung-Chieh Lo      HeaderDetails(header, entries, indent, params->numeric);
326a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan    }
327a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  }
328a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
3291c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  CheckValid(drive);
3301c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk
3311c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  return CGPT_OK;
3321c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk}
3331c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk
3341c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulkint CgptShow(CgptShowParams *params) {
3351c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  struct drive drive;
3361c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk
3371c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  if (params == NULL)
3381c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    return CGPT_FAILED;
3391c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk
340ab899591808dd3e5f955ab7693b54a83389cd35fNam T. Nguyen  if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY,
341ab899591808dd3e5f955ab7693b54a83389cd35fNam T. Nguyen                           params->drive_size))
3421c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk    return CGPT_FAILED;
343a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan
3448577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen  if (GptShow(&drive, params))
3458577b5360ca4c9514d9091ed9aded2bb3193f1f0Nam T. Nguyen    return CGPT_FAILED;
3461c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk
3471c568bccc442afd91ea7ee5367668ba9ebc06a40Albert Chaulk  DriveClose(&drive, 0);
348a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan  return CGPT_OK;
349a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan}
350