blob: 78a285c76e6f03a7dad32b710c3b18d22dd88807 [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));
114 char buf[256]; // scratch buffer for formatting output
Albert Chaulk289b6042013-06-25 11:30:46 -0700115 uint64_t start, size;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700116 if (guid) {
117 ResolveType(guid, buf);
118 } else {
119 snprintf(buf, sizeof(buf), "MTD partition type %d", MtdGetEntryType(entry));
120 }
121
Albert Chaulk289b6042013-06-25 11:30:46 -0700122 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
123
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700124 if (!raw) {
Albert Chaulk289b6042013-06-25 11:30:46 -0700125 printf(PARTITION_FMT, (int)start, (int)size, index+1, buf);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700126 } else {
Albert Chaulk289b6042013-06-25 11:30:46 -0700127 printf(PARTITION_FMT, (int)start, (int)size, index+1, buf);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700128 }
129}
130
Jay Srinivasana0581432012-01-26 21:50:05 -0800131void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
132 char contents[256]; // scratch buffer for formatting output
133 uint8_t label[GPT_PARTNAME_LEN];
134
135 if (!raw) {
136 char type[GUID_STRLEN], unique[GUID_STRLEN];
137
138 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
139 label, sizeof(label));
140 require(snprintf(contents, sizeof(contents),
141 "Label: \"%s\"", label) < sizeof(contents));
142 printf(PARTITION_FMT, (int)entry->starting_lba,
143 (int)(entry->ending_lba - entry->starting_lba + 1),
144 index+1, contents);
145 if (CGPT_OK == ResolveType(&entry->type, type)) {
146 printf(PARTITION_MORE, "Type: ", type);
147 } else {
148 GuidToStr(&entry->type, type, GUID_STRLEN);
149 printf(PARTITION_MORE, "Type: ", type);
150 }
151 GuidToStr(&entry->unique, unique, GUID_STRLEN);
152 printf(PARTITION_MORE, "UUID: ", unique);
153 if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
154 int tries = (entry->attrs.fields.gpt_att &
155 CGPT_ATTRIBUTE_TRIES_MASK) >>
156 CGPT_ATTRIBUTE_TRIES_OFFSET;
157 int successful = (entry->attrs.fields.gpt_att &
158 CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
159 CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
160 int priority = (entry->attrs.fields.gpt_att &
161 CGPT_ATTRIBUTE_PRIORITY_MASK) >>
162 CGPT_ATTRIBUTE_PRIORITY_OFFSET;
163 require(snprintf(contents, sizeof(contents),
164 "priority=%d tries=%d successful=%d",
165 priority, tries, successful) < sizeof(contents));
166 printf(PARTITION_MORE, "Attr: ", contents);
167 }
168 } else {
169 char type[GUID_STRLEN], unique[GUID_STRLEN];
170
171 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
172 label, sizeof(label));
173 require(snprintf(contents, sizeof(contents),
174 "Label: \"%s\"", label) < sizeof(contents));
175 printf(PARTITION_FMT, (int)entry->starting_lba,
176 (int)(entry->ending_lba - entry->starting_lba + 1),
177 index+1, contents);
178 GuidToStr(&entry->type, type, GUID_STRLEN);
179 printf(PARTITION_MORE, "Type: ", type);
180 GuidToStr(&entry->unique, unique, GUID_STRLEN);
181 printf(PARTITION_MORE, "UUID: ", unique);
182 require(snprintf(contents, sizeof(contents),
183 "[%x]", entry->attrs.fields.gpt_att) < sizeof(contents));
184 printf(PARTITION_MORE, "Attr: ", contents);
185 }
186}
187
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700188void MtdEntriesDetails(struct drive *drive, int secondary, int raw) {
189 uint32_t i;
190
191 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
192 MtdDiskPartition *entry;
193 entry = MtdGetEntry(&drive->mtd, secondary, i);
194 if (IsUnused(drive, secondary, i))
195 continue;
196 MtdEntryDetails(entry, i, raw);
197 }
198}
Jay Srinivasana0581432012-01-26 21:50:05 -0800199
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700200void EntriesDetails(struct drive *drive, const int secondary, int raw) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800201 uint32_t i;
202
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700203 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800204 GptEntry *entry;
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700205 entry = GetEntry(&drive->gpt, secondary, i);
Jay Srinivasana0581432012-01-26 21:50:05 -0800206
Bill Richardson3f806a22013-03-20 15:02:34 -0700207 if (GuidIsZero(&entry->type))
Jay Srinivasana0581432012-01-26 21:50:05 -0800208 continue;
209
210 EntryDetails(entry, i, raw);
211 }
212}
213
Bill Richardson3f806a22013-03-20 15:02:34 -0700214int CgptGetNumNonEmptyPartitions(CgptShowParams *params) {
Jay Srinivasan250549d2012-02-16 17:40:45 -0800215 struct drive drive;
216 int gpt_retval;
217 int retval;
218
219 if (params == NULL)
220 return CGPT_FAILED;
221
Bill Richardson23429d32012-04-30 11:33:13 -0700222 if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
Jay Srinivasan250549d2012-02-16 17:40:45 -0800223 return CGPT_FAILED;
224
225 if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
226 Error("GptSanityCheck() returned %d: %s\n",
227 gpt_retval, GptError(gpt_retval));
228 retval = CGPT_FAILED;
229 goto done;
230 }
231
232 params->num_partitions = 0;
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700233 int numEntries = GetNumberOfEntries(&drive);
Jay Srinivasan250549d2012-02-16 17:40:45 -0800234 int i;
235 for(i = 0; i < numEntries; i++) {
236 GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, i);
Bill Richardson3f806a22013-03-20 15:02:34 -0700237 if (GuidIsZero(&entry->type))
Jay Srinivasan250549d2012-02-16 17:40:45 -0800238 continue;
239
240 params->num_partitions++;
241 }
242
243 retval = CGPT_OK;
244
245done:
246 DriveClose(&drive, 0);
247 return retval;
248}
249
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700250int MtdShow(struct drive *drive, CgptShowParams *params) {
251 if (params->partition) { // show single partition
252 if (params->partition > GetNumberOfEntries(drive)) {
253 Error("invalid partition number: %d\n", params->partition);
254 return CGPT_FAILED;
255 }
256
257 uint32_t index = params->partition - 1;
258 MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, index);
259 char buf[256]; // scratch buffer for string conversion
260 const Guid *guid;
Albert Chaulk289b6042013-06-25 11:30:46 -0700261 uint64_t start, size;
262
263 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700264
265 if (params->single_item) {
266 switch(params->single_item) {
267 case 'b':
Albert Chaulk289b6042013-06-25 11:30:46 -0700268 printf("%u\n", (int)start);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700269 break;
270 case 's':
Albert Chaulk289b6042013-06-25 11:30:46 -0700271 printf("%u\n", (int)size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700272 break;
273 case 't':
274 guid = LookupGuidForMtdType(MtdGetEntryType(entry));
275 GuidToStr(guid, buf, sizeof(buf));
276 printf("%s\n", buf);
277 break;
278 case 'S':
279 printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
280 break;
281 case 'T':
282 printf("%d\n", GetTries(drive, ANY_VALID, index));
283 break;
284 case 'P':
285 printf("%d\n", GetPriority(drive, ANY_VALID, index));
286 break;
287 case 'A':
288 printf("0x%x\n", entry->flags);
289 break;
290 }
291 } else {
292 printf(TITLE_FMT, "start", "size", "part", "contents");
293 MtdEntryDetails(entry, index, params->numeric);
294 }
295 } else if (params->quick) { // show all partitions, quickly
296 uint32_t i;
297 char type[GUID_STRLEN];
298
299 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
300 MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, i);
301 const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
Albert Chaulk289b6042013-06-25 11:30:46 -0700302 uint64_t start, size;
303
304 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700305
306 if (IsUnused(drive, ANY_VALID, i))
307 continue;
308
309 if (!params->numeric && guid) {
310 ResolveType(guid, type);
311 } else {
312 snprintf(type, sizeof(type), "MTD partition type %d",
313 MtdGetEntryType(entry));
314 }
Albert Chaulk289b6042013-06-25 11:30:46 -0700315 printf(PARTITION_FMT, (int)start, (int)size, i+1, type);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700316 }
317 } else { // show all partitions
318 if (params->debug || params->verbose) {
319 char indent[64];
320
321 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
322 MtdHeaderDetails(&drive->mtd.primary, indent, 0);
323 }
324
325 MtdEntriesDetails(drive, PRIMARY, params->numeric);
326 }
327
328 return CGPT_OK;
329}
330
331int GptShow(struct drive *drive, CgptShowParams *params) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800332 int gpt_retval;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700333 if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800334 Error("GptSanityCheck() returned %d: %s\n",
335 gpt_retval, GptError(gpt_retval));
336 return CGPT_FAILED;
337 }
338
339 if (params->partition) { // show single partition
340
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700341 if (params->partition > GetNumberOfEntries(drive)) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800342 Error("invalid partition number: %d\n", params->partition);
343 return CGPT_FAILED;
344 }
345
346 uint32_t index = params->partition - 1;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700347 GptEntry *entry = GetEntry(&drive->gpt, ANY_VALID, index);
Jay Srinivasana0581432012-01-26 21:50:05 -0800348 char buf[256]; // scratch buffer for string conversion
349
350 if (params->single_item) {
351 switch(params->single_item) {
352 case 'b':
353 printf("%" PRId64 "\n", entry->starting_lba);
354 break;
Mike Frysinger98624d32013-05-03 18:05:16 -0400355 case 's': {
356 uint64_t size = 0;
357 // If these aren't actually defined, don't show anything
358 if (entry->ending_lba || entry->starting_lba)
359 size = entry->ending_lba - entry->starting_lba + 1;
360 printf("%" PRId64 "\n", size);
Jay Srinivasana0581432012-01-26 21:50:05 -0800361 break;
Mike Frysinger98624d32013-05-03 18:05:16 -0400362 }
Jay Srinivasana0581432012-01-26 21:50:05 -0800363 case 't':
364 GuidToStr(&entry->type, buf, sizeof(buf));
365 printf("%s\n", buf);
366 break;
367 case 'u':
368 GuidToStr(&entry->unique, buf, sizeof(buf));
369 printf("%s\n", buf);
370 break;
371 case 'l':
372 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
373 (uint8_t *)buf, sizeof(buf));
374 printf("%s\n", buf);
375 break;
376 case 'S':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700377 printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800378 break;
379 case 'T':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700380 printf("%d\n", GetTries(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800381 break;
382 case 'P':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700383 printf("%d\n", GetPriority(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800384 break;
385 case 'A':
386 printf("0x%x\n", entry->attrs.fields.gpt_att);
387 break;
388 }
389 } else {
390 printf(TITLE_FMT, "start", "size", "part", "contents");
391 EntryDetails(entry, index, params->numeric);
392 }
393
394 } else if (params->quick) { // show all partitions, quickly
395 uint32_t i;
396 GptEntry *entry;
397 char type[GUID_STRLEN];
398
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700399 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
400 entry = GetEntry(&drive->gpt, ANY_VALID, i);
Jay Srinivasana0581432012-01-26 21:50:05 -0800401
Bill Richardson3f806a22013-03-20 15:02:34 -0700402 if (GuidIsZero(&entry->type))
Jay Srinivasana0581432012-01-26 21:50:05 -0800403 continue;
404
405 if (!params->numeric && CGPT_OK == ResolveType(&entry->type, type)) {
406 } else {
407 GuidToStr(&entry->type, type, GUID_STRLEN);
408 }
409 printf(PARTITION_FMT, (int)entry->starting_lba,
410 (int)(entry->ending_lba - entry->starting_lba + 1),
411 i+1, type);
412 }
413 } else { // show all partitions
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800414 GptEntry *entries;
415
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700416 if (CGPT_OK != ReadPMBR(drive)) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800417 Error("Unable to read PMBR\n");
418 return CGPT_FAILED;
419 }
420
421 printf(TITLE_FMT, "start", "size", "part", "contents");
422 char buf[256]; // buffer for formatted PMBR content
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700423 PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small
Jay Srinivasana0581432012-01-26 21:50:05 -0800424 printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", buf);
425
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700426 if (drive->gpt.valid_headers & MASK_PRIMARY) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800427 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
428 (int)GPT_HEADER_SECTOR, "", "Pri GPT header");
Jay Srinivasana0581432012-01-26 21:50:05 -0800429 } else {
430 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
431 (int)GPT_HEADER_SECTOR, "INVALID", "Pri GPT header");
432 }
433
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800434 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700435 ((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800436 GptHeader *header;
437 char indent[64];
438
439 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700440 header = (GptHeader*)drive->gpt.primary_header;
441 entries = (GptEntry*)drive->gpt.primary_entries;
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800442 HeaderDetails(header, entries, indent, params->numeric);
443 }
444
Jay Srinivasana0581432012-01-26 21:50:05 -0800445 printf(GPT_FMT, (int)(GPT_PMBR_SECTOR + GPT_HEADER_SECTOR),
446 (int)GPT_ENTRIES_SECTORS,
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700447 drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
Jay Srinivasana0581432012-01-26 21:50:05 -0800448 "Pri GPT table");
449
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800450 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700451 (drive->gpt.valid_entries & MASK_PRIMARY))
452 EntriesDetails(drive, PRIMARY, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800453
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800454 /****************************** Secondary *************************/
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700455 printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR -
Jay Srinivasana0581432012-01-26 21:50:05 -0800456 GPT_ENTRIES_SECTORS),
457 (int)GPT_ENTRIES_SECTORS,
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700458 drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
Jay Srinivasana0581432012-01-26 21:50:05 -0800459 "Sec GPT table");
460 /* We show secondary table details if any of following is true.
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800461 * 1. in debug mode.
462 * 2. only secondary is valid.
463 * 3. secondary is not identical to promary.
Jay Srinivasana0581432012-01-26 21:50:05 -0800464 */
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800465 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700466 ((drive->gpt.valid_entries & MASK_SECONDARY) &&
467 (!(drive->gpt.valid_entries & MASK_PRIMARY) ||
468 memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries,
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800469 TOTAL_ENTRIES_SIZE)))) {
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700470 EntriesDetails(drive, SECONDARY, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800471 }
472
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700473 if (drive->gpt.valid_headers & MASK_SECONDARY)
474 printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR),
Jay Srinivasana0581432012-01-26 21:50:05 -0800475 (int)GPT_HEADER_SECTOR, "", "Sec GPT header");
476 else
477 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
478 (int)GPT_HEADER_SECTOR, "INVALID", "Sec GPT header");
479 /* We show secondary header if any of following is true:
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800480 * 1. in debug mode.
481 * 2. only secondary is valid.
482 * 3. secondary is not synonymous to primary.
Jay Srinivasana0581432012-01-26 21:50:05 -0800483 */
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800484 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700485 ((drive->gpt.valid_headers & MASK_SECONDARY) &&
486 (!(drive->gpt.valid_headers & MASK_PRIMARY) ||
487 !IsSynonymous((GptHeader*)drive->gpt.primary_header,
488 (GptHeader*)drive->gpt.secondary_header)) &&
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800489 params->verbose)) {
490 GptHeader *header;
491 char indent[64];
Jay Srinivasana0581432012-01-26 21:50:05 -0800492
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800493 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700494 header = (GptHeader*)drive->gpt.secondary_header;
495 entries = (GptEntry*)drive->gpt.secondary_entries;
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800496 HeaderDetails(header, entries, indent, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800497 }
498 }
499
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700500 CheckValid(drive);
Jay Srinivasana0581432012-01-26 21:50:05 -0800501
502 return CGPT_OK;
503}
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700504
505int CgptShow(CgptShowParams *params) {
506 struct drive drive;
507
508 if (params == NULL)
509 return CGPT_FAILED;
510
511 if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
512 return CGPT_FAILED;
513
514 if (drive.is_mtd) {
515 if (MtdShow(&drive, params))
516 return CGPT_FAILED;
517 } else {
518 if (GptShow(&drive, params))
519 return CGPT_FAILED;
520 }
521
522 DriveClose(&drive, 0);
523 return CGPT_OK;
524}