xref: /aosp_15_r20/external/vboot_reference/cgpt/cgpt_show.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2012 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker  * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker  */
5*8617a60dSAndroid Build Coastguard Worker 
6*8617a60dSAndroid Build Coastguard Worker #define __STDC_FORMAT_MACROS
7*8617a60dSAndroid Build Coastguard Worker 
8*8617a60dSAndroid Build Coastguard Worker #include <string.h>
9*8617a60dSAndroid Build Coastguard Worker 
10*8617a60dSAndroid Build Coastguard Worker #include "cgpt.h"
11*8617a60dSAndroid Build Coastguard Worker #include "cgptlib_internal.h"
12*8617a60dSAndroid Build Coastguard Worker #include "crc32.h"
13*8617a60dSAndroid Build Coastguard Worker #include "vboot_host.h"
14*8617a60dSAndroid Build Coastguard Worker 
15*8617a60dSAndroid Build Coastguard Worker /* Generate output like:
16*8617a60dSAndroid Build Coastguard Worker  *
17*8617a60dSAndroid Build Coastguard Worker  *  [AB-CD-EF-01]   for group = 1
18*8617a60dSAndroid Build Coastguard Worker  *  [ABCD-EF01]     for group = 3  (low byte first)
19*8617a60dSAndroid Build Coastguard Worker  *
20*8617a60dSAndroid Build Coastguard Worker  * Needs (size*3-1+3) bytes of space in 'buf' (included the tailing '\0').
21*8617a60dSAndroid Build Coastguard Worker  */
22*8617a60dSAndroid Build Coastguard Worker #define BUFFER_SIZE(size) (size *3 - 1 + 3)
Uint8To2Chars(const uint8_t t)23*8617a60dSAndroid Build Coastguard Worker static short Uint8To2Chars(const uint8_t t) {
24*8617a60dSAndroid Build Coastguard Worker   int h = t >> 4;
25*8617a60dSAndroid Build Coastguard Worker   int l = t & 0xf;
26*8617a60dSAndroid Build Coastguard Worker   h = (h >= 0xA) ? h - 0xA + 'A' : h + '0';
27*8617a60dSAndroid Build Coastguard Worker   l = (l >= 0xA) ? l - 0xA + 'A' : l + '0';
28*8617a60dSAndroid Build Coastguard Worker   return (h << 8) + l;
29*8617a60dSAndroid Build Coastguard Worker }
30*8617a60dSAndroid Build Coastguard Worker 
RawDump(const uint8_t * memory,const int size,char * buf,int group)31*8617a60dSAndroid Build Coastguard Worker static void RawDump(const uint8_t *memory, const int size,
32*8617a60dSAndroid Build Coastguard Worker                     char *buf, int group) {
33*8617a60dSAndroid Build Coastguard Worker   int i, outlen = 0;
34*8617a60dSAndroid Build Coastguard Worker   buf[outlen++] = '[';
35*8617a60dSAndroid Build Coastguard Worker   for (i = 0; i < size; ++i) {
36*8617a60dSAndroid Build Coastguard Worker     short c2 = Uint8To2Chars(memory[i]);
37*8617a60dSAndroid Build Coastguard Worker     buf[outlen++] = c2 >> 8;
38*8617a60dSAndroid Build Coastguard Worker     buf[outlen++] = c2 & 0xff;
39*8617a60dSAndroid Build Coastguard Worker     if (i != (size - 1) && ((i + 1) % group) == 0)
40*8617a60dSAndroid Build Coastguard Worker       buf[outlen++] = '-';
41*8617a60dSAndroid Build Coastguard Worker   }
42*8617a60dSAndroid Build Coastguard Worker   buf[outlen++] = ']';
43*8617a60dSAndroid Build Coastguard Worker   buf[outlen++] = '\0';
44*8617a60dSAndroid Build Coastguard Worker }
45*8617a60dSAndroid Build Coastguard Worker 
46*8617a60dSAndroid Build Coastguard Worker /* Output formatters */
47*8617a60dSAndroid Build Coastguard Worker #define TITLE_FMT      "%12s%12s%8s  %s\n"
48*8617a60dSAndroid Build Coastguard Worker #define GPT_FMT        "%12"PRId64"%12"PRId64"%8s  %s\n"
49*8617a60dSAndroid Build Coastguard Worker #define GPT_MORE       "%12s%12s%8s  ", "", "", ""
50*8617a60dSAndroid Build Coastguard Worker #define PARTITION_FMT  "%12"PRId64"%12"PRId64"%8d  %s\n"
51*8617a60dSAndroid Build Coastguard Worker #define PARTITION_MORE "%12s%12s%8s  %s%s\n", "", "", ""
52*8617a60dSAndroid Build Coastguard Worker 
PrintSignature(const char * indent,const char * sig,size_t n,int raw)53*8617a60dSAndroid Build Coastguard Worker static void PrintSignature(const char *indent, const char *sig, size_t n,
54*8617a60dSAndroid Build Coastguard Worker                            int raw) {
55*8617a60dSAndroid Build Coastguard Worker   size_t i;
56*8617a60dSAndroid Build Coastguard Worker   printf("%sSig: ", indent);
57*8617a60dSAndroid Build Coastguard Worker   if (!raw) {
58*8617a60dSAndroid Build Coastguard Worker     printf("[");
59*8617a60dSAndroid Build Coastguard Worker     for (i = 0; i < n; ++i)
60*8617a60dSAndroid Build Coastguard Worker       printf("%c", sig[i]);
61*8617a60dSAndroid Build Coastguard Worker     printf("]");
62*8617a60dSAndroid Build Coastguard Worker   } else {
63*8617a60dSAndroid Build Coastguard Worker     char *buf = malloc(BUFFER_SIZE(n));
64*8617a60dSAndroid Build Coastguard Worker     RawDump((uint8_t *)sig, n, buf, 1);
65*8617a60dSAndroid Build Coastguard Worker     printf("%s", buf);
66*8617a60dSAndroid Build Coastguard Worker     free(buf);
67*8617a60dSAndroid Build Coastguard Worker   }
68*8617a60dSAndroid Build Coastguard Worker   printf("\n");
69*8617a60dSAndroid Build Coastguard Worker }
70*8617a60dSAndroid Build Coastguard Worker 
HeaderDetails(GptHeader * header,GptEntry * entries,const char * indent,int raw)71*8617a60dSAndroid Build Coastguard Worker static void HeaderDetails(GptHeader *header, GptEntry *entries,
72*8617a60dSAndroid Build Coastguard Worker                           const char *indent, int raw) {
73*8617a60dSAndroid Build Coastguard Worker   PrintSignature(indent, header->signature, sizeof(header->signature), raw);
74*8617a60dSAndroid Build Coastguard Worker 
75*8617a60dSAndroid Build Coastguard Worker   printf("%sRev: 0x%08x\n", indent, header->revision);
76*8617a60dSAndroid Build Coastguard Worker   printf("%sSize: %d (blocks)\n", indent, header->size);
77*8617a60dSAndroid Build Coastguard Worker   printf("%sHeader CRC: 0x%08x %s\n", indent, header->header_crc32,
78*8617a60dSAndroid Build Coastguard Worker          (HeaderCrc(header) != header->header_crc32) ? "(INVALID)" : "");
79*8617a60dSAndroid Build Coastguard Worker   printf("%sMy LBA: %lld\n", indent, (long long)header->my_lba);
80*8617a60dSAndroid Build Coastguard Worker   printf("%sAlternate LBA: %lld\n", indent, (long long)header->alternate_lba);
81*8617a60dSAndroid Build Coastguard Worker   printf("%sFirst LBA: %lld\n", indent, (long long)header->first_usable_lba);
82*8617a60dSAndroid Build Coastguard Worker   printf("%sLast LBA: %lld\n", indent, (long long)header->last_usable_lba);
83*8617a60dSAndroid Build Coastguard Worker 
84*8617a60dSAndroid Build Coastguard Worker   {  /* For disk guid */
85*8617a60dSAndroid Build Coastguard Worker     char buf[GUID_STRLEN];
86*8617a60dSAndroid Build Coastguard Worker     GuidToStr(&header->disk_uuid, buf, GUID_STRLEN);
87*8617a60dSAndroid Build Coastguard Worker     printf("%sDisk UUID: %s\n", indent, buf);
88*8617a60dSAndroid Build Coastguard Worker   }
89*8617a60dSAndroid Build Coastguard Worker 
90*8617a60dSAndroid Build Coastguard Worker   printf("%sEntries LBA: %lld\n", indent, (long long)header->entries_lba);
91*8617a60dSAndroid Build Coastguard Worker   printf("%sNumber of entries: %d\n", indent, header->number_of_entries);
92*8617a60dSAndroid Build Coastguard Worker   printf("%sSize of entry: %d\n", indent, header->size_of_entry);
93*8617a60dSAndroid Build Coastguard Worker   printf("%sEntries CRC: 0x%08x %s\n", indent, header->entries_crc32,
94*8617a60dSAndroid Build Coastguard Worker          header->entries_crc32 !=
95*8617a60dSAndroid Build Coastguard Worker              Crc32((const uint8_t *)entries,header->size_of_entry *
96*8617a60dSAndroid Build Coastguard Worker                                             header->number_of_entries)
97*8617a60dSAndroid Build Coastguard Worker              ? "INVALID" : ""
98*8617a60dSAndroid Build Coastguard Worker          );
99*8617a60dSAndroid Build Coastguard Worker }
100*8617a60dSAndroid Build Coastguard Worker 
EntryDetails(GptEntry * entry,uint32_t index,int raw)101*8617a60dSAndroid Build Coastguard Worker void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
102*8617a60dSAndroid Build Coastguard Worker   char contents[256];                   // scratch buffer for formatting output
103*8617a60dSAndroid Build Coastguard Worker   uint8_t label[GPT_PARTNAME_LEN];
104*8617a60dSAndroid Build Coastguard Worker   char type[GUID_STRLEN], unique[GUID_STRLEN];
105*8617a60dSAndroid Build Coastguard Worker   int clen;
106*8617a60dSAndroid Build Coastguard Worker 
107*8617a60dSAndroid Build Coastguard Worker   UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
108*8617a60dSAndroid Build Coastguard Worker               label, sizeof(label));
109*8617a60dSAndroid Build Coastguard Worker   require(snprintf(contents, sizeof(contents),
110*8617a60dSAndroid Build Coastguard Worker                    "Label: \"%s\"", label) < sizeof(contents));
111*8617a60dSAndroid Build Coastguard Worker   printf(PARTITION_FMT, (uint64_t)entry->starting_lba,
112*8617a60dSAndroid Build Coastguard Worker          (uint64_t)(entry->ending_lba - entry->starting_lba + 1),
113*8617a60dSAndroid Build Coastguard Worker          index+1, contents);
114*8617a60dSAndroid Build Coastguard Worker 
115*8617a60dSAndroid Build Coastguard Worker   if (!raw && CGPT_OK == ResolveType(&entry->type, type)) {
116*8617a60dSAndroid Build Coastguard Worker     printf(PARTITION_MORE, "Type: ", type);
117*8617a60dSAndroid Build Coastguard Worker   } else {
118*8617a60dSAndroid Build Coastguard Worker     GuidToStr(&entry->type, type, GUID_STRLEN);
119*8617a60dSAndroid Build Coastguard Worker     printf(PARTITION_MORE, "Type: ", type);
120*8617a60dSAndroid Build Coastguard Worker   }
121*8617a60dSAndroid Build Coastguard Worker   GuidToStr(&entry->unique, unique, GUID_STRLEN);
122*8617a60dSAndroid Build Coastguard Worker   printf(PARTITION_MORE, "UUID: ", unique);
123*8617a60dSAndroid Build Coastguard Worker 
124*8617a60dSAndroid Build Coastguard Worker   clen = 0;
125*8617a60dSAndroid Build Coastguard Worker   if (!raw) {
126*8617a60dSAndroid Build Coastguard Worker     if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
127*8617a60dSAndroid Build Coastguard Worker       int tries = (entry->attrs.fields.gpt_att &
128*8617a60dSAndroid Build Coastguard Worker                    CGPT_ATTRIBUTE_TRIES_MASK) >>
129*8617a60dSAndroid Build Coastguard Worker           CGPT_ATTRIBUTE_TRIES_OFFSET;
130*8617a60dSAndroid Build Coastguard Worker       int successful = (entry->attrs.fields.gpt_att &
131*8617a60dSAndroid Build Coastguard Worker                         CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
132*8617a60dSAndroid Build Coastguard Worker           CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
133*8617a60dSAndroid Build Coastguard Worker       int priority = (entry->attrs.fields.gpt_att &
134*8617a60dSAndroid Build Coastguard Worker                       CGPT_ATTRIBUTE_PRIORITY_MASK) >>
135*8617a60dSAndroid Build Coastguard Worker           CGPT_ATTRIBUTE_PRIORITY_OFFSET;
136*8617a60dSAndroid Build Coastguard Worker       int error_counter = (entry->attrs.fields.gpt_att &
137*8617a60dSAndroid Build Coastguard Worker                            CGPT_ATTRIBUTE_ERROR_COUNTER_MASK) >>
138*8617a60dSAndroid Build Coastguard Worker           CGPT_ATTRIBUTE_ERROR_COUNTER_OFFSET;
139*8617a60dSAndroid Build Coastguard Worker       clen = snprintf(contents, sizeof(contents),
140*8617a60dSAndroid Build Coastguard Worker                       "priority=%d tries=%d successful=%d error_counter=%d ",
141*8617a60dSAndroid Build Coastguard Worker                       priority, tries, successful, error_counter);
142*8617a60dSAndroid Build Coastguard Worker     }
143*8617a60dSAndroid Build Coastguard Worker 
144*8617a60dSAndroid Build Coastguard Worker     if (entry->attrs.fields.required) {
145*8617a60dSAndroid Build Coastguard Worker       clen += snprintf(contents + clen, sizeof(contents) - clen,
146*8617a60dSAndroid Build Coastguard Worker                        "required=%d ", entry->attrs.fields.required);
147*8617a60dSAndroid Build Coastguard Worker       require(clen < sizeof(contents));
148*8617a60dSAndroid Build Coastguard Worker     }
149*8617a60dSAndroid Build Coastguard Worker 
150*8617a60dSAndroid Build Coastguard Worker     if (entry->attrs.fields.efi_ignore) {
151*8617a60dSAndroid Build Coastguard Worker       clen += snprintf(contents + clen, sizeof(contents) - clen,
152*8617a60dSAndroid Build Coastguard Worker                        "efi_ignore=%d ", entry->attrs.fields.efi_ignore);
153*8617a60dSAndroid Build Coastguard Worker       require(clen < sizeof(contents));
154*8617a60dSAndroid Build Coastguard Worker     }
155*8617a60dSAndroid Build Coastguard Worker 
156*8617a60dSAndroid Build Coastguard Worker     if (entry->attrs.fields.legacy_boot) {
157*8617a60dSAndroid Build Coastguard Worker       clen += snprintf(contents + clen, sizeof(contents) - clen,
158*8617a60dSAndroid Build Coastguard Worker                        "legacy_boot=%d ", entry->attrs.fields.legacy_boot);
159*8617a60dSAndroid Build Coastguard Worker       require(clen < sizeof(contents));
160*8617a60dSAndroid Build Coastguard Worker     }
161*8617a60dSAndroid Build Coastguard Worker   } else {
162*8617a60dSAndroid Build Coastguard Worker     clen = snprintf(contents, sizeof(contents),
163*8617a60dSAndroid Build Coastguard Worker                     "[%x]", entry->attrs.fields.gpt_att);
164*8617a60dSAndroid Build Coastguard Worker   }
165*8617a60dSAndroid Build Coastguard Worker   require(clen < sizeof(contents));
166*8617a60dSAndroid Build Coastguard Worker   if (clen)
167*8617a60dSAndroid Build Coastguard Worker     printf(PARTITION_MORE, "Attr: ", contents);
168*8617a60dSAndroid Build Coastguard Worker }
169*8617a60dSAndroid Build Coastguard Worker 
EntriesDetails(struct drive * drive,const int secondary,int raw)170*8617a60dSAndroid Build Coastguard Worker static void EntriesDetails(struct drive *drive, const int secondary, int raw) {
171*8617a60dSAndroid Build Coastguard Worker   uint32_t i;
172*8617a60dSAndroid Build Coastguard Worker 
173*8617a60dSAndroid Build Coastguard Worker   for (i = 0; i < GetNumberOfEntries(drive); ++i) {
174*8617a60dSAndroid Build Coastguard Worker     GptEntry *entry;
175*8617a60dSAndroid Build Coastguard Worker     entry = GetEntry(&drive->gpt, secondary, i);
176*8617a60dSAndroid Build Coastguard Worker 
177*8617a60dSAndroid Build Coastguard Worker     if (GuidIsZero(&entry->type))
178*8617a60dSAndroid Build Coastguard Worker       continue;
179*8617a60dSAndroid Build Coastguard Worker 
180*8617a60dSAndroid Build Coastguard Worker     EntryDetails(entry, i, raw);
181*8617a60dSAndroid Build Coastguard Worker   }
182*8617a60dSAndroid Build Coastguard Worker }
183*8617a60dSAndroid Build Coastguard Worker 
GptShow(struct drive * drive,CgptShowParams * params)184*8617a60dSAndroid Build Coastguard Worker static int GptShow(struct drive *drive, CgptShowParams *params) {
185*8617a60dSAndroid Build Coastguard Worker   int gpt_retval;
186*8617a60dSAndroid Build Coastguard Worker   if (GPT_SUCCESS != (gpt_retval = GptValidityCheck(&drive->gpt))) {
187*8617a60dSAndroid Build Coastguard Worker     Error("GptValidityCheck() returned %d: %s\n",
188*8617a60dSAndroid Build Coastguard Worker           gpt_retval, GptError(gpt_retval));
189*8617a60dSAndroid Build Coastguard Worker     return CGPT_FAILED;
190*8617a60dSAndroid Build Coastguard Worker   }
191*8617a60dSAndroid Build Coastguard Worker 
192*8617a60dSAndroid Build Coastguard Worker   if (params->partition) {                      // show single partition
193*8617a60dSAndroid Build Coastguard Worker 
194*8617a60dSAndroid Build Coastguard Worker     if (params->partition > GetNumberOfEntries(drive)) {
195*8617a60dSAndroid Build Coastguard Worker       Error("invalid partition number: %d\n", params->partition);
196*8617a60dSAndroid Build Coastguard Worker       return CGPT_FAILED;
197*8617a60dSAndroid Build Coastguard Worker     }
198*8617a60dSAndroid Build Coastguard Worker 
199*8617a60dSAndroid Build Coastguard Worker     uint32_t index = params->partition - 1;
200*8617a60dSAndroid Build Coastguard Worker     GptEntry *entry = GetEntry(&drive->gpt, ANY_VALID, index);
201*8617a60dSAndroid Build Coastguard Worker     char buf[256];                      // scratch buffer for string conversion
202*8617a60dSAndroid Build Coastguard Worker 
203*8617a60dSAndroid Build Coastguard Worker     if (params->single_item) {
204*8617a60dSAndroid Build Coastguard Worker       switch(params->single_item) {
205*8617a60dSAndroid Build Coastguard Worker       case 'b':
206*8617a60dSAndroid Build Coastguard Worker         printf("%" PRId64 "\n", entry->starting_lba);
207*8617a60dSAndroid Build Coastguard Worker         break;
208*8617a60dSAndroid Build Coastguard Worker       case 's': {
209*8617a60dSAndroid Build Coastguard Worker         uint64_t size = 0;
210*8617a60dSAndroid Build Coastguard Worker         // If these aren't actually defined, don't show anything
211*8617a60dSAndroid Build Coastguard Worker         if (entry->ending_lba || entry->starting_lba)
212*8617a60dSAndroid Build Coastguard Worker           size = entry->ending_lba - entry->starting_lba + 1;
213*8617a60dSAndroid Build Coastguard Worker         printf("%" PRId64 "\n", size);
214*8617a60dSAndroid Build Coastguard Worker         break;
215*8617a60dSAndroid Build Coastguard Worker       }
216*8617a60dSAndroid Build Coastguard Worker       case 't':
217*8617a60dSAndroid Build Coastguard Worker         GuidToStr(&entry->type, buf, sizeof(buf));
218*8617a60dSAndroid Build Coastguard Worker         printf("%s\n", buf);
219*8617a60dSAndroid Build Coastguard Worker         break;
220*8617a60dSAndroid Build Coastguard Worker       case 'u':
221*8617a60dSAndroid Build Coastguard Worker         GuidToStr(&entry->unique, buf, sizeof(buf));
222*8617a60dSAndroid Build Coastguard Worker         printf("%s\n", buf);
223*8617a60dSAndroid Build Coastguard Worker         break;
224*8617a60dSAndroid Build Coastguard Worker       case 'l':
225*8617a60dSAndroid Build Coastguard Worker         UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
226*8617a60dSAndroid Build Coastguard Worker                     (uint8_t *)buf, sizeof(buf));
227*8617a60dSAndroid Build Coastguard Worker         printf("%s\n", buf);
228*8617a60dSAndroid Build Coastguard Worker         break;
229*8617a60dSAndroid Build Coastguard Worker       case 'S':
230*8617a60dSAndroid Build Coastguard Worker         printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
231*8617a60dSAndroid Build Coastguard Worker         break;
232*8617a60dSAndroid Build Coastguard Worker       case 'T':
233*8617a60dSAndroid Build Coastguard Worker         printf("%d\n", GetTries(drive, ANY_VALID, index));
234*8617a60dSAndroid Build Coastguard Worker         break;
235*8617a60dSAndroid Build Coastguard Worker       case 'P':
236*8617a60dSAndroid Build Coastguard Worker         printf("%d\n", GetPriority(drive, ANY_VALID, index));
237*8617a60dSAndroid Build Coastguard Worker         break;
238*8617a60dSAndroid Build Coastguard Worker       case 'R':
239*8617a60dSAndroid Build Coastguard Worker         printf("%d\n", GetRequired(drive, ANY_VALID, index));
240*8617a60dSAndroid Build Coastguard Worker         break;
241*8617a60dSAndroid Build Coastguard Worker       case 'B':
242*8617a60dSAndroid Build Coastguard Worker         printf("%d\n", GetLegacyBoot(drive, ANY_VALID, index));
243*8617a60dSAndroid Build Coastguard Worker         break;
244*8617a60dSAndroid Build Coastguard Worker       case 'A':
245*8617a60dSAndroid Build Coastguard Worker         printf("%#x\n", entry->attrs.fields.gpt_att);
246*8617a60dSAndroid Build Coastguard Worker         break;
247*8617a60dSAndroid Build Coastguard Worker       }
248*8617a60dSAndroid Build Coastguard Worker     } else {
249*8617a60dSAndroid Build Coastguard Worker       printf(TITLE_FMT, "start", "size", "part", "contents");
250*8617a60dSAndroid Build Coastguard Worker       EntryDetails(entry, index, params->numeric);
251*8617a60dSAndroid Build Coastguard Worker     }
252*8617a60dSAndroid Build Coastguard Worker 
253*8617a60dSAndroid Build Coastguard Worker   } else if (params->quick) {                   // show all partitions, quickly
254*8617a60dSAndroid Build Coastguard Worker     uint32_t i;
255*8617a60dSAndroid Build Coastguard Worker     GptEntry *entry;
256*8617a60dSAndroid Build Coastguard Worker     char type[GUID_STRLEN];
257*8617a60dSAndroid Build Coastguard Worker 
258*8617a60dSAndroid Build Coastguard Worker     for (i = 0; i < GetNumberOfEntries(drive); ++i) {
259*8617a60dSAndroid Build Coastguard Worker       entry = GetEntry(&drive->gpt, ANY_VALID, i);
260*8617a60dSAndroid Build Coastguard Worker 
261*8617a60dSAndroid Build Coastguard Worker       if (GuidIsZero(&entry->type))
262*8617a60dSAndroid Build Coastguard Worker         continue;
263*8617a60dSAndroid Build Coastguard Worker 
264*8617a60dSAndroid Build Coastguard Worker       if (!params->numeric && CGPT_OK == ResolveType(&entry->type, type)) {
265*8617a60dSAndroid Build Coastguard Worker       } else {
266*8617a60dSAndroid Build Coastguard Worker         GuidToStr(&entry->type, type, GUID_STRLEN);
267*8617a60dSAndroid Build Coastguard Worker       }
268*8617a60dSAndroid Build Coastguard Worker       printf(PARTITION_FMT, (uint64_t)entry->starting_lba,
269*8617a60dSAndroid Build Coastguard Worker              (uint64_t)(entry->ending_lba - entry->starting_lba + 1),
270*8617a60dSAndroid Build Coastguard Worker              i+1, type);
271*8617a60dSAndroid Build Coastguard Worker     }
272*8617a60dSAndroid Build Coastguard Worker   } else {                              // show all partitions
273*8617a60dSAndroid Build Coastguard Worker     GptEntry *entries;
274*8617a60dSAndroid Build Coastguard Worker 
275*8617a60dSAndroid Build Coastguard Worker     if (params->debug || params->verbose) {
276*8617a60dSAndroid Build Coastguard Worker       printf("Drive details:\n");
277*8617a60dSAndroid Build Coastguard Worker       printf("    Total Size (bytes): %" PRIu64 "\n", drive->size);
278*8617a60dSAndroid Build Coastguard Worker       printf("    LBA Size (bytes): %d\n", drive->gpt.sector_bytes);
279*8617a60dSAndroid Build Coastguard Worker       if (drive->gpt.flags & GPT_FLAG_EXTERNAL) {
280*8617a60dSAndroid Build Coastguard Worker         printf("    Drive (where GPT lives) Size (blocks): %" PRIu64 "\n",
281*8617a60dSAndroid Build Coastguard Worker                drive->gpt.gpt_drive_sectors);
282*8617a60dSAndroid Build Coastguard Worker         printf("    Drive (where partitions live) Size (blocks): %" PRIu64 "\n",
283*8617a60dSAndroid Build Coastguard Worker                drive->gpt.streaming_drive_sectors);
284*8617a60dSAndroid Build Coastguard Worker       } else {
285*8617a60dSAndroid Build Coastguard Worker         // We know gpt_drive_sectors == streaming_drive_sectors here.
286*8617a60dSAndroid Build Coastguard Worker         printf("    Drive Size (blocks): %" PRIu64 "\n",
287*8617a60dSAndroid Build Coastguard Worker                drive->gpt.gpt_drive_sectors);
288*8617a60dSAndroid Build Coastguard Worker       }
289*8617a60dSAndroid Build Coastguard Worker       printf("\n");
290*8617a60dSAndroid Build Coastguard Worker     }
291*8617a60dSAndroid Build Coastguard Worker 
292*8617a60dSAndroid Build Coastguard Worker     if (CGPT_OK != ReadPMBR(drive)) {
293*8617a60dSAndroid Build Coastguard Worker       Error("Unable to read PMBR\n");
294*8617a60dSAndroid Build Coastguard Worker       return CGPT_FAILED;
295*8617a60dSAndroid Build Coastguard Worker     }
296*8617a60dSAndroid Build Coastguard Worker 
297*8617a60dSAndroid Build Coastguard Worker     printf(TITLE_FMT, "start", "size", "part", "contents");
298*8617a60dSAndroid Build Coastguard Worker     char buf[256];                      // buffer for formatted PMBR content
299*8617a60dSAndroid Build Coastguard Worker     PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small
300*8617a60dSAndroid Build Coastguard Worker     printf(GPT_FMT, (uint64_t)0, (uint64_t)GPT_PMBR_SECTORS, "", buf);
301*8617a60dSAndroid Build Coastguard Worker 
302*8617a60dSAndroid Build Coastguard Worker     if (drive->gpt.ignored & MASK_PRIMARY) {
303*8617a60dSAndroid Build Coastguard Worker       printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
304*8617a60dSAndroid Build Coastguard Worker              (uint64_t)GPT_HEADER_SECTORS, "IGNORED", "Pri GPT header");
305*8617a60dSAndroid Build Coastguard Worker     } else {
306*8617a60dSAndroid Build Coastguard Worker       if (drive->gpt.valid_headers & MASK_PRIMARY) {
307*8617a60dSAndroid Build Coastguard Worker         printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
308*8617a60dSAndroid Build Coastguard Worker                (uint64_t)GPT_HEADER_SECTORS, "", "Pri GPT header");
309*8617a60dSAndroid Build Coastguard Worker       } else {
310*8617a60dSAndroid Build Coastguard Worker         printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
311*8617a60dSAndroid Build Coastguard Worker                (uint64_t)GPT_HEADER_SECTORS, "INVALID", "Pri GPT header");
312*8617a60dSAndroid Build Coastguard Worker       }
313*8617a60dSAndroid Build Coastguard Worker 
314*8617a60dSAndroid Build Coastguard Worker       if (params->debug ||
315*8617a60dSAndroid Build Coastguard Worker           ((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
316*8617a60dSAndroid Build Coastguard Worker         GptHeader *header;
317*8617a60dSAndroid Build Coastguard Worker         char indent[64];
318*8617a60dSAndroid Build Coastguard Worker 
319*8617a60dSAndroid Build Coastguard Worker         require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
320*8617a60dSAndroid Build Coastguard Worker         header = (GptHeader*)drive->gpt.primary_header;
321*8617a60dSAndroid Build Coastguard Worker         entries = (GptEntry*)drive->gpt.primary_entries;
322*8617a60dSAndroid Build Coastguard Worker         HeaderDetails(header, entries, indent, params->numeric);
323*8617a60dSAndroid Build Coastguard Worker       }
324*8617a60dSAndroid Build Coastguard Worker 
325*8617a60dSAndroid Build Coastguard Worker       GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header;
326*8617a60dSAndroid Build Coastguard Worker       printf(GPT_FMT, (uint64_t)primary_header->entries_lba,
327*8617a60dSAndroid Build Coastguard Worker              (uint64_t)CalculateEntriesSectors(primary_header,
328*8617a60dSAndroid Build Coastguard Worker                          drive->gpt.sector_bytes),
329*8617a60dSAndroid Build Coastguard Worker              drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
330*8617a60dSAndroid Build Coastguard Worker              "Pri GPT table");
331*8617a60dSAndroid Build Coastguard Worker 
332*8617a60dSAndroid Build Coastguard Worker       if (params->debug ||
333*8617a60dSAndroid Build Coastguard Worker           (drive->gpt.valid_entries & MASK_PRIMARY))
334*8617a60dSAndroid Build Coastguard Worker         EntriesDetails(drive, PRIMARY, params->numeric);
335*8617a60dSAndroid Build Coastguard Worker     }
336*8617a60dSAndroid Build Coastguard Worker 
337*8617a60dSAndroid Build Coastguard Worker     /****************************** Secondary *************************/
338*8617a60dSAndroid Build Coastguard Worker     if (drive->gpt.ignored & MASK_SECONDARY) {
339*8617a60dSAndroid Build Coastguard Worker       printf(GPT_FMT,
340*8617a60dSAndroid Build Coastguard Worker              (uint64_t)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS),
341*8617a60dSAndroid Build Coastguard Worker              (uint64_t)GPT_HEADER_SECTORS, "IGNORED", "Sec GPT header");
342*8617a60dSAndroid Build Coastguard Worker     } else {
343*8617a60dSAndroid Build Coastguard Worker       GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
344*8617a60dSAndroid Build Coastguard Worker       printf(GPT_FMT, (uint64_t)secondary_header->entries_lba,
345*8617a60dSAndroid Build Coastguard Worker              (uint64_t)CalculateEntriesSectors(secondary_header,
346*8617a60dSAndroid Build Coastguard Worker                          drive->gpt.sector_bytes),
347*8617a60dSAndroid Build Coastguard Worker              drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
348*8617a60dSAndroid Build Coastguard Worker              "Sec GPT table");
349*8617a60dSAndroid Build Coastguard Worker       /* We show secondary table details if any of following is true.
350*8617a60dSAndroid Build Coastguard Worker        *   1. in debug mode.
351*8617a60dSAndroid Build Coastguard Worker        *   2. primary table is being ignored
352*8617a60dSAndroid Build Coastguard Worker        *   3. only secondary is valid.
353*8617a60dSAndroid Build Coastguard Worker        *   4. secondary is not identical to primary.
354*8617a60dSAndroid Build Coastguard Worker        */
355*8617a60dSAndroid Build Coastguard Worker       if (params->debug || (drive->gpt.ignored & MASK_PRIMARY) ||
356*8617a60dSAndroid Build Coastguard Worker           ((drive->gpt.valid_entries & MASK_SECONDARY) &&
357*8617a60dSAndroid Build Coastguard Worker            (!(drive->gpt.valid_entries & MASK_PRIMARY) ||
358*8617a60dSAndroid Build Coastguard Worker             memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries,
359*8617a60dSAndroid Build Coastguard Worker                    secondary_header->number_of_entries *
360*8617a60dSAndroid Build Coastguard Worker                    secondary_header->size_of_entry)))) {
361*8617a60dSAndroid Build Coastguard Worker         EntriesDetails(drive, SECONDARY, params->numeric);
362*8617a60dSAndroid Build Coastguard Worker       }
363*8617a60dSAndroid Build Coastguard Worker 
364*8617a60dSAndroid Build Coastguard Worker       if (drive->gpt.valid_headers & MASK_SECONDARY) {
365*8617a60dSAndroid Build Coastguard Worker         printf(GPT_FMT,
366*8617a60dSAndroid Build Coastguard Worker                (uint64_t)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS),
367*8617a60dSAndroid Build Coastguard Worker                (uint64_t)GPT_HEADER_SECTORS, "", "Sec GPT header");
368*8617a60dSAndroid Build Coastguard Worker       } else {
369*8617a60dSAndroid Build Coastguard Worker         printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
370*8617a60dSAndroid Build Coastguard Worker                (uint64_t)GPT_HEADER_SECTORS, "INVALID", "Sec GPT header");
371*8617a60dSAndroid Build Coastguard Worker       }
372*8617a60dSAndroid Build Coastguard Worker       /* We show secondary header if any of following is true:
373*8617a60dSAndroid Build Coastguard Worker        *   1. in debug mode.
374*8617a60dSAndroid Build Coastguard Worker        *   2. primary table is being ignored
375*8617a60dSAndroid Build Coastguard Worker        *   3. only secondary is valid.
376*8617a60dSAndroid Build Coastguard Worker        *   4. secondary is not synonymous to primary and not ignored.
377*8617a60dSAndroid Build Coastguard Worker        */
378*8617a60dSAndroid Build Coastguard Worker       if (params->debug || (drive->gpt.ignored & MASK_PRIMARY) ||
379*8617a60dSAndroid Build Coastguard Worker           ((drive->gpt.valid_headers & MASK_SECONDARY) &&
380*8617a60dSAndroid Build Coastguard Worker            (!(drive->gpt.valid_headers & MASK_PRIMARY) ||
381*8617a60dSAndroid Build Coastguard Worker             !IsSynonymous((GptHeader*)drive->gpt.primary_header,
382*8617a60dSAndroid Build Coastguard Worker                           (GptHeader*)drive->gpt.secondary_header)) &&
383*8617a60dSAndroid Build Coastguard Worker            params->verbose)) {
384*8617a60dSAndroid Build Coastguard Worker         GptHeader *header;
385*8617a60dSAndroid Build Coastguard Worker         char indent[64];
386*8617a60dSAndroid Build Coastguard Worker 
387*8617a60dSAndroid Build Coastguard Worker         require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
388*8617a60dSAndroid Build Coastguard Worker         header = (GptHeader*)drive->gpt.secondary_header;
389*8617a60dSAndroid Build Coastguard Worker         entries = (GptEntry*)drive->gpt.secondary_entries;
390*8617a60dSAndroid Build Coastguard Worker         HeaderDetails(header, entries, indent, params->numeric);
391*8617a60dSAndroid Build Coastguard Worker       }
392*8617a60dSAndroid Build Coastguard Worker     }
393*8617a60dSAndroid Build Coastguard Worker   }
394*8617a60dSAndroid Build Coastguard Worker 
395*8617a60dSAndroid Build Coastguard Worker   CheckValid(drive);
396*8617a60dSAndroid Build Coastguard Worker 
397*8617a60dSAndroid Build Coastguard Worker   return CGPT_OK;
398*8617a60dSAndroid Build Coastguard Worker }
399*8617a60dSAndroid Build Coastguard Worker 
CgptShow(CgptShowParams * params)400*8617a60dSAndroid Build Coastguard Worker int CgptShow(CgptShowParams *params) {
401*8617a60dSAndroid Build Coastguard Worker   struct drive drive;
402*8617a60dSAndroid Build Coastguard Worker 
403*8617a60dSAndroid Build Coastguard Worker   if (params == NULL)
404*8617a60dSAndroid Build Coastguard Worker     return CGPT_FAILED;
405*8617a60dSAndroid Build Coastguard Worker 
406*8617a60dSAndroid Build Coastguard Worker   if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY,
407*8617a60dSAndroid Build Coastguard Worker                            params->drive_size))
408*8617a60dSAndroid Build Coastguard Worker     return CGPT_FAILED;
409*8617a60dSAndroid Build Coastguard Worker 
410*8617a60dSAndroid Build Coastguard Worker   int ret = GptShow(&drive, params);
411*8617a60dSAndroid Build Coastguard Worker   DriveClose(&drive, 0);
412*8617a60dSAndroid Build Coastguard Worker   return ret;
413*8617a60dSAndroid Build Coastguard Worker }
414