blob: 41f9d0073f7b537bf81cfbf0c6b380fee2a1658f [file] [log] [blame]
Jay Srinivasana0581432012-01-26 21:50:05 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Jay Srinivasana0581432012-01-26 21:50:05 -08005#define __STDC_FORMAT_MACROS
6
7#include <string.h>
8
Bill Richardson0c3ba242013-03-29 11:09:30 -07009#include "cgpt.h"
Jay Srinivasana0581432012-01-26 21:50:05 -080010#include "cgptlib_internal.h"
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +080011#include "crc32.h"
Bill Richardson0c3ba242013-03-29 11:09:30 -070012#include "vboot_host.h"
Jay Srinivasana0581432012-01-26 21:50:05 -080013
Jay Srinivasana0581432012-01-26 21:50:05 -080014/* Generate output like:
15 *
16 * [AB-CD-EF-01] for group = 1
17 * [ABCD-EF01] for group = 3 (low byte first)
18 *
19 * Needs (size*3-1+3) bytes of space in 'buf' (included the tailing '\0').
20 */
21#define BUFFER_SIZE(size) (size *3 - 1 + 3)
22static short Uint8To2Chars(const uint8_t t) {
23 int h = t >> 4;
24 int l = t & 0xf;
25 h = (h >= 0xA) ? h - 0xA + 'A' : h + '0';
26 l = (l >= 0xA) ? l - 0xA + 'A' : l + '0';
27 return (h << 8) + l;
28}
29
30static void RawDump(const uint8_t *memory, const int size,
31 char *buf, int group) {
32 int i, outlen = 0;
33 buf[outlen++] = '[';
34 for (i = 0; i < size; ++i) {
35 short c2 = Uint8To2Chars(memory[i]);
36 buf[outlen++] = c2 >> 8;
37 buf[outlen++] = c2 & 0xff;
38 if (i != (size - 1) && ((i + 1) % group) == 0)
39 buf[outlen++] = '-';
40 }
41 buf[outlen++] = ']';
42 buf[outlen++] = '\0';
43}
44
45/* Output formatters */
Shawn Nematbakhsh82bb8022012-07-30 15:05:59 -070046#define TITLE_FMT "%12s%12s%8s %s\n"
47#define GPT_FMT "%12d%12d%8s %s\n"
48#define GPT_MORE "%12s%12s%8s ", "", "", ""
49#define PARTITION_FMT "%12d%12d%8d %s\n"
50#define PARTITION_MORE "%12s%12s%8s %s%s\n", "", "", ""
Jay Srinivasana0581432012-01-26 21:50:05 -080051
Albert Chaulk1c568bc2013-04-02 14:35:39 -070052void PrintSignature(const char *indent, const char *sig, size_t n, int raw) {
53 size_t i;
Jay Srinivasana0581432012-01-26 21:50:05 -080054 printf("%sSig: ", indent);
55 if (!raw) {
56 printf("[");
Albert Chaulk1c568bc2013-04-02 14:35:39 -070057 for (i = 0; i < n; ++i)
58 printf("%c", sig[i]);
Jay Srinivasana0581432012-01-26 21:50:05 -080059 printf("]");
60 } else {
Albert Chaulk1c568bc2013-04-02 14:35:39 -070061 char *buf = malloc(BUFFER_SIZE(n));
62 RawDump((uint8_t *)sig, n, buf, 1);
Jay Srinivasana0581432012-01-26 21:50:05 -080063 printf("%s", buf);
Albert Chaulk1c568bc2013-04-02 14:35:39 -070064 free(buf);
Jay Srinivasana0581432012-01-26 21:50:05 -080065 }
66 printf("\n");
Albert Chaulk1c568bc2013-04-02 14:35:39 -070067}
68
69void MtdHeaderDetails(MtdDiskLayout *header, const char *indent, int raw) {
70 PrintSignature(indent, (char*)header->signature, sizeof(header->signature),
71 raw);
72
73 printf("%sSize: %d\n", indent, header->size);
74 printf("%sCRC: 0x%08x %s\n", indent, header->crc32,
75 (MtdHeaderCrc(header) != header->crc32) ? "(INVALID)" : "");
Albert Chaulk289b6042013-06-25 11:30:46 -070076 printf("%sFirst LBA: %llu\n", indent,
77 (unsigned long long)header->first_offset);
78 printf("%sLast LBA: %llu\n", indent,
79 (unsigned long long)header->last_offset);
Albert Chaulk1c568bc2013-04-02 14:35:39 -070080}
81
82static void HeaderDetails(GptHeader *header, GptEntry *entries,
83 const char *indent, int raw) {
84 PrintSignature(indent, header->signature, sizeof(header->signature), raw);
Jay Srinivasana0581432012-01-26 21:50:05 -080085
86 printf("%sRev: 0x%08x\n", indent, header->revision);
87 printf("%sSize: %d\n", indent, header->size);
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +080088 printf("%sHeader CRC: 0x%08x %s\n", indent, header->header_crc32,
89 (HeaderCrc(header) != header->header_crc32) ? "(INVALID)" : "");
Jay Srinivasana0581432012-01-26 21:50:05 -080090 printf("%sMy LBA: %lld\n", indent, (long long)header->my_lba);
91 printf("%sAlternate LBA: %lld\n", indent, (long long)header->alternate_lba);
92 printf("%sFirst LBA: %lld\n", indent, (long long)header->first_usable_lba);
93 printf("%sLast LBA: %lld\n", indent, (long long)header->last_usable_lba);
94
95 { /* For disk guid */
96 char buf[GUID_STRLEN];
97 GuidToStr(&header->disk_uuid, buf, GUID_STRLEN);
98 printf("%sDisk UUID: %s\n", indent, buf);
99 }
100
101 printf("%sEntries LBA: %lld\n", indent, (long long)header->entries_lba);
102 printf("%sNumber of entries: %d\n", indent, header->number_of_entries);
103 printf("%sSize of entry: %d\n", indent, header->size_of_entry);
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800104 printf("%sEntries CRC: 0x%08x %s\n", indent, header->entries_crc32,
105 header->entries_crc32 !=
106 Crc32((const uint8_t *)entries,header->size_of_entry *
107 header->number_of_entries)
108 ? "INVALID" : ""
109 );
Jay Srinivasana0581432012-01-26 21:50:05 -0800110}
111
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700112void MtdEntryDetails(MtdDiskPartition *entry, uint32_t index, int raw) {
113 const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700114 char type[256];
115 char contents[256];
116 char name[sizeof(entry->label) + 1];
Albert Chaulk289b6042013-06-25 11:30:46 -0700117 uint64_t start, size;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700118 if (guid) {
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700119 ResolveType(guid, type);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700120 } else {
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700121 snprintf(type, sizeof(type), "MTD partition type %d",
122 MtdGetEntryType(entry));
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700123 }
124
Albert Chaulk289b6042013-06-25 11:30:46 -0700125 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
126
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700127 // Provide a NUL if we are at maximum size.
128 name[sizeof(name)-1] = '\0';
129 memcpy(name, entry->label, sizeof(entry->label));
130 require(snprintf(contents, sizeof(contents),
131 "Label: \"%s\"", name) < sizeof(contents));
132
133 printf(PARTITION_FMT, (int)start, (int)size, index+1, contents);
134 printf(PARTITION_MORE, "Type: ", type);
135
136 if (raw && MtdGetEntryType(entry) == MTD_PARTITION_TYPE_CHROMEOS_KERNEL) {
137 int tries = MtdGetEntryTries(entry);
138 int successful = MtdGetEntrySuccessful(entry);
139 int priority = MtdGetEntryPriority(entry);
140 require(snprintf(contents, sizeof(contents),
141 "priority=%d tries=%d successful=%d",
142 priority, tries, successful) < sizeof(contents));
143 printf(PARTITION_MORE, "Attr: ", contents);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700144 } else {
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700145 require(snprintf(contents, sizeof(contents),
146 "[%x]", entry->flags) < sizeof(contents));
147 printf(PARTITION_MORE, "Attr: ", contents);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700148 }
149}
150
Jay Srinivasana0581432012-01-26 21:50:05 -0800151void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
152 char contents[256]; // scratch buffer for formatting output
153 uint8_t label[GPT_PARTNAME_LEN];
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700154 char type[GUID_STRLEN], unique[GUID_STRLEN];
155
156 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
157 label, sizeof(label));
158 require(snprintf(contents, sizeof(contents),
159 "Label: \"%s\"", label) < sizeof(contents));
160 printf(PARTITION_FMT, (int)entry->starting_lba,
161 (int)(entry->ending_lba - entry->starting_lba + 1),
162 index+1, contents);
163
164 if (!raw && CGPT_OK == ResolveType(&entry->type, type)) {
165 printf(PARTITION_MORE, "Type: ", type);
166 } else {
167 GuidToStr(&entry->type, type, GUID_STRLEN);
168 printf(PARTITION_MORE, "Type: ", type);
169 }
170 GuidToStr(&entry->unique, unique, GUID_STRLEN);
171 printf(PARTITION_MORE, "UUID: ", unique);
Jay Srinivasana0581432012-01-26 21:50:05 -0800172
173 if (!raw) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800174 if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
175 int tries = (entry->attrs.fields.gpt_att &
176 CGPT_ATTRIBUTE_TRIES_MASK) >>
177 CGPT_ATTRIBUTE_TRIES_OFFSET;
178 int successful = (entry->attrs.fields.gpt_att &
179 CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
180 CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
181 int priority = (entry->attrs.fields.gpt_att &
182 CGPT_ATTRIBUTE_PRIORITY_MASK) >>
183 CGPT_ATTRIBUTE_PRIORITY_OFFSET;
184 require(snprintf(contents, sizeof(contents),
185 "priority=%d tries=%d successful=%d",
186 priority, tries, successful) < sizeof(contents));
187 printf(PARTITION_MORE, "Attr: ", contents);
188 }
189 } else {
Jay Srinivasana0581432012-01-26 21:50:05 -0800190 require(snprintf(contents, sizeof(contents),
191 "[%x]", entry->attrs.fields.gpt_att) < sizeof(contents));
192 printf(PARTITION_MORE, "Attr: ", contents);
193 }
194}
195
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700196void MtdEntriesDetails(struct drive *drive, int secondary, int raw) {
197 uint32_t i;
198
199 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
200 MtdDiskPartition *entry;
201 entry = MtdGetEntry(&drive->mtd, secondary, i);
202 if (IsUnused(drive, secondary, i))
203 continue;
204 MtdEntryDetails(entry, i, raw);
205 }
206}
Jay Srinivasana0581432012-01-26 21:50:05 -0800207
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700208void EntriesDetails(struct drive *drive, const int secondary, int raw) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800209 uint32_t i;
210
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700211 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800212 GptEntry *entry;
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700213 entry = GetEntry(&drive->gpt, secondary, i);
Jay Srinivasana0581432012-01-26 21:50:05 -0800214
Bill Richardson3f806a22013-03-20 15:02:34 -0700215 if (GuidIsZero(&entry->type))
Jay Srinivasana0581432012-01-26 21:50:05 -0800216 continue;
217
218 EntryDetails(entry, i, raw);
219 }
220}
221
Bill Richardson3f806a22013-03-20 15:02:34 -0700222int CgptGetNumNonEmptyPartitions(CgptShowParams *params) {
Jay Srinivasan250549d2012-02-16 17:40:45 -0800223 struct drive drive;
224 int gpt_retval;
225 int retval;
226
227 if (params == NULL)
228 return CGPT_FAILED;
229
Bill Richardson23429d32012-04-30 11:33:13 -0700230 if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
Jay Srinivasan250549d2012-02-16 17:40:45 -0800231 return CGPT_FAILED;
232
233 if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
234 Error("GptSanityCheck() returned %d: %s\n",
235 gpt_retval, GptError(gpt_retval));
236 retval = CGPT_FAILED;
237 goto done;
238 }
239
240 params->num_partitions = 0;
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700241 int numEntries = GetNumberOfEntries(&drive);
Jay Srinivasan250549d2012-02-16 17:40:45 -0800242 int i;
243 for(i = 0; i < numEntries; i++) {
244 GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, i);
Bill Richardson3f806a22013-03-20 15:02:34 -0700245 if (GuidIsZero(&entry->type))
Jay Srinivasan250549d2012-02-16 17:40:45 -0800246 continue;
247
248 params->num_partitions++;
249 }
250
251 retval = CGPT_OK;
252
253done:
254 DriveClose(&drive, 0);
255 return retval;
256}
257
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700258int MtdShow(struct drive *drive, CgptShowParams *params) {
259 if (params->partition) { // show single partition
260 if (params->partition > GetNumberOfEntries(drive)) {
261 Error("invalid partition number: %d\n", params->partition);
262 return CGPT_FAILED;
263 }
264
265 uint32_t index = params->partition - 1;
266 MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, index);
267 char buf[256]; // scratch buffer for string conversion
268 const Guid *guid;
Albert Chaulk289b6042013-06-25 11:30:46 -0700269 uint64_t start, size;
270
271 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700272
273 if (params->single_item) {
274 switch(params->single_item) {
275 case 'b':
Albert Chaulk289b6042013-06-25 11:30:46 -0700276 printf("%u\n", (int)start);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700277 break;
278 case 's':
Albert Chaulk289b6042013-06-25 11:30:46 -0700279 printf("%u\n", (int)size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700280 break;
281 case 't':
282 guid = LookupGuidForMtdType(MtdGetEntryType(entry));
283 GuidToStr(guid, buf, sizeof(buf));
284 printf("%s\n", buf);
285 break;
286 case 'S':
287 printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
288 break;
289 case 'T':
290 printf("%d\n", GetTries(drive, ANY_VALID, index));
291 break;
292 case 'P':
293 printf("%d\n", GetPriority(drive, ANY_VALID, index));
294 break;
295 case 'A':
296 printf("0x%x\n", entry->flags);
297 break;
298 }
299 } else {
300 printf(TITLE_FMT, "start", "size", "part", "contents");
301 MtdEntryDetails(entry, index, params->numeric);
302 }
303 } else if (params->quick) { // show all partitions, quickly
304 uint32_t i;
305 char type[GUID_STRLEN];
306
307 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
308 MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, i);
309 const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
Albert Chaulk289b6042013-06-25 11:30:46 -0700310 uint64_t start, size;
311
312 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700313
314 if (IsUnused(drive, ANY_VALID, i))
315 continue;
316
317 if (!params->numeric && guid) {
318 ResolveType(guid, type);
319 } else {
320 snprintf(type, sizeof(type), "MTD partition type %d",
321 MtdGetEntryType(entry));
322 }
Albert Chaulk289b6042013-06-25 11:30:46 -0700323 printf(PARTITION_FMT, (int)start, (int)size, i+1, type);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700324 }
325 } else { // show all partitions
326 if (params->debug || params->verbose) {
327 char indent[64];
328
329 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
330 MtdHeaderDetails(&drive->mtd.primary, indent, 0);
331 }
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700332 printf(TITLE_FMT, "start", "size", "part", "contents");
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700333 MtdEntriesDetails(drive, PRIMARY, params->numeric);
334 }
335
336 return CGPT_OK;
337}
338
339int GptShow(struct drive *drive, CgptShowParams *params) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800340 int gpt_retval;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700341 if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800342 Error("GptSanityCheck() returned %d: %s\n",
343 gpt_retval, GptError(gpt_retval));
344 return CGPT_FAILED;
345 }
346
347 if (params->partition) { // show single partition
348
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700349 if (params->partition > GetNumberOfEntries(drive)) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800350 Error("invalid partition number: %d\n", params->partition);
351 return CGPT_FAILED;
352 }
353
354 uint32_t index = params->partition - 1;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700355 GptEntry *entry = GetEntry(&drive->gpt, ANY_VALID, index);
Jay Srinivasana0581432012-01-26 21:50:05 -0800356 char buf[256]; // scratch buffer for string conversion
357
358 if (params->single_item) {
359 switch(params->single_item) {
360 case 'b':
361 printf("%" PRId64 "\n", entry->starting_lba);
362 break;
Mike Frysinger98624d32013-05-03 18:05:16 -0400363 case 's': {
364 uint64_t size = 0;
365 // If these aren't actually defined, don't show anything
366 if (entry->ending_lba || entry->starting_lba)
367 size = entry->ending_lba - entry->starting_lba + 1;
368 printf("%" PRId64 "\n", size);
Jay Srinivasana0581432012-01-26 21:50:05 -0800369 break;
Mike Frysinger98624d32013-05-03 18:05:16 -0400370 }
Jay Srinivasana0581432012-01-26 21:50:05 -0800371 case 't':
372 GuidToStr(&entry->type, buf, sizeof(buf));
373 printf("%s\n", buf);
374 break;
375 case 'u':
376 GuidToStr(&entry->unique, buf, sizeof(buf));
377 printf("%s\n", buf);
378 break;
379 case 'l':
380 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
381 (uint8_t *)buf, sizeof(buf));
382 printf("%s\n", buf);
383 break;
384 case 'S':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700385 printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800386 break;
387 case 'T':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700388 printf("%d\n", GetTries(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800389 break;
390 case 'P':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700391 printf("%d\n", GetPriority(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800392 break;
393 case 'A':
394 printf("0x%x\n", entry->attrs.fields.gpt_att);
395 break;
396 }
397 } else {
398 printf(TITLE_FMT, "start", "size", "part", "contents");
399 EntryDetails(entry, index, params->numeric);
400 }
401
402 } else if (params->quick) { // show all partitions, quickly
403 uint32_t i;
404 GptEntry *entry;
405 char type[GUID_STRLEN];
406
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700407 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
408 entry = GetEntry(&drive->gpt, ANY_VALID, i);
Jay Srinivasana0581432012-01-26 21:50:05 -0800409
Bill Richardson3f806a22013-03-20 15:02:34 -0700410 if (GuidIsZero(&entry->type))
Jay Srinivasana0581432012-01-26 21:50:05 -0800411 continue;
412
413 if (!params->numeric && CGPT_OK == ResolveType(&entry->type, type)) {
414 } else {
415 GuidToStr(&entry->type, type, GUID_STRLEN);
416 }
417 printf(PARTITION_FMT, (int)entry->starting_lba,
418 (int)(entry->ending_lba - entry->starting_lba + 1),
419 i+1, type);
420 }
421 } else { // show all partitions
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800422 GptEntry *entries;
423
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700424 if (CGPT_OK != ReadPMBR(drive)) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800425 Error("Unable to read PMBR\n");
426 return CGPT_FAILED;
427 }
428
429 printf(TITLE_FMT, "start", "size", "part", "contents");
430 char buf[256]; // buffer for formatted PMBR content
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700431 PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small
Jay Srinivasana0581432012-01-26 21:50:05 -0800432 printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", buf);
433
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700434 if (drive->gpt.valid_headers & MASK_PRIMARY) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800435 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
436 (int)GPT_HEADER_SECTOR, "", "Pri GPT header");
Jay Srinivasana0581432012-01-26 21:50:05 -0800437 } else {
438 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
439 (int)GPT_HEADER_SECTOR, "INVALID", "Pri GPT header");
440 }
441
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800442 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700443 ((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800444 GptHeader *header;
445 char indent[64];
446
447 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700448 header = (GptHeader*)drive->gpt.primary_header;
449 entries = (GptEntry*)drive->gpt.primary_entries;
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800450 HeaderDetails(header, entries, indent, params->numeric);
451 }
452
Jay Srinivasana0581432012-01-26 21:50:05 -0800453 printf(GPT_FMT, (int)(GPT_PMBR_SECTOR + GPT_HEADER_SECTOR),
454 (int)GPT_ENTRIES_SECTORS,
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700455 drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
Jay Srinivasana0581432012-01-26 21:50:05 -0800456 "Pri GPT table");
457
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800458 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700459 (drive->gpt.valid_entries & MASK_PRIMARY))
460 EntriesDetails(drive, PRIMARY, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800461
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800462 /****************************** Secondary *************************/
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700463 printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR -
Jay Srinivasana0581432012-01-26 21:50:05 -0800464 GPT_ENTRIES_SECTORS),
465 (int)GPT_ENTRIES_SECTORS,
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700466 drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
Jay Srinivasana0581432012-01-26 21:50:05 -0800467 "Sec GPT table");
468 /* We show secondary table details if any of following is true.
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800469 * 1. in debug mode.
470 * 2. only secondary is valid.
471 * 3. secondary is not identical to promary.
Jay Srinivasana0581432012-01-26 21:50:05 -0800472 */
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800473 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700474 ((drive->gpt.valid_entries & MASK_SECONDARY) &&
475 (!(drive->gpt.valid_entries & MASK_PRIMARY) ||
476 memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries,
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800477 TOTAL_ENTRIES_SIZE)))) {
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700478 EntriesDetails(drive, SECONDARY, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800479 }
480
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700481 if (drive->gpt.valid_headers & MASK_SECONDARY)
482 printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR),
Jay Srinivasana0581432012-01-26 21:50:05 -0800483 (int)GPT_HEADER_SECTOR, "", "Sec GPT header");
484 else
485 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
486 (int)GPT_HEADER_SECTOR, "INVALID", "Sec GPT header");
487 /* We show secondary header if any of following is true:
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800488 * 1. in debug mode.
489 * 2. only secondary is valid.
490 * 3. secondary is not synonymous to primary.
Jay Srinivasana0581432012-01-26 21:50:05 -0800491 */
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800492 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700493 ((drive->gpt.valid_headers & MASK_SECONDARY) &&
494 (!(drive->gpt.valid_headers & MASK_PRIMARY) ||
495 !IsSynonymous((GptHeader*)drive->gpt.primary_header,
496 (GptHeader*)drive->gpt.secondary_header)) &&
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800497 params->verbose)) {
498 GptHeader *header;
499 char indent[64];
Jay Srinivasana0581432012-01-26 21:50:05 -0800500
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800501 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700502 header = (GptHeader*)drive->gpt.secondary_header;
503 entries = (GptEntry*)drive->gpt.secondary_entries;
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800504 HeaderDetails(header, entries, indent, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800505 }
506 }
507
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700508 CheckValid(drive);
Jay Srinivasana0581432012-01-26 21:50:05 -0800509
510 return CGPT_OK;
511}
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700512
513int CgptShow(CgptShowParams *params) {
514 struct drive drive;
515
516 if (params == NULL)
517 return CGPT_FAILED;
518
519 if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
520 return CGPT_FAILED;
521
522 if (drive.is_mtd) {
523 if (MtdShow(&drive, params))
524 return CGPT_FAILED;
525 } else {
526 if (GptShow(&drive, params))
527 return CGPT_FAILED;
528 }
529
530 DriveClose(&drive, 0);
531 return CGPT_OK;
532}