blob: f5d6001e3e68a4a60cdaf20a63b15248f7d91f61 [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
Bill Richardson18e03702014-06-23 17:48:33 -070069static void MtdHeaderDetails(MtdDiskLayout *header, const char *indent,
70 int raw) {
Albert Chaulk1c568bc2013-04-02 14:35:39 -070071 PrintSignature(indent, (char*)header->signature, sizeof(header->signature),
72 raw);
73
74 printf("%sSize: %d\n", indent, header->size);
75 printf("%sCRC: 0x%08x %s\n", indent, header->crc32,
76 (MtdHeaderCrc(header) != header->crc32) ? "(INVALID)" : "");
Albert Chaulk494646d2013-07-19 12:56:38 -070077 printf("%sFirst offset: %llu\n", indent,
Albert Chaulk289b6042013-06-25 11:30:46 -070078 (unsigned long long)header->first_offset);
Albert Chaulk494646d2013-07-19 12:56:38 -070079 printf("%sLast offset: %llu\n", indent,
Albert Chaulk289b6042013-06-25 11:30:46 -070080 (unsigned long long)header->last_offset);
Albert Chaulk1c568bc2013-04-02 14:35:39 -070081}
82
83static void HeaderDetails(GptHeader *header, GptEntry *entries,
84 const char *indent, int raw) {
85 PrintSignature(indent, header->signature, sizeof(header->signature), raw);
Jay Srinivasana0581432012-01-26 21:50:05 -080086
87 printf("%sRev: 0x%08x\n", indent, header->revision);
88 printf("%sSize: %d\n", indent, header->size);
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +080089 printf("%sHeader CRC: 0x%08x %s\n", indent, header->header_crc32,
90 (HeaderCrc(header) != header->header_crc32) ? "(INVALID)" : "");
Jay Srinivasana0581432012-01-26 21:50:05 -080091 printf("%sMy LBA: %lld\n", indent, (long long)header->my_lba);
92 printf("%sAlternate LBA: %lld\n", indent, (long long)header->alternate_lba);
93 printf("%sFirst LBA: %lld\n", indent, (long long)header->first_usable_lba);
94 printf("%sLast LBA: %lld\n", indent, (long long)header->last_usable_lba);
95
96 { /* For disk guid */
97 char buf[GUID_STRLEN];
98 GuidToStr(&header->disk_uuid, buf, GUID_STRLEN);
99 printf("%sDisk UUID: %s\n", indent, buf);
100 }
101
102 printf("%sEntries LBA: %lld\n", indent, (long long)header->entries_lba);
103 printf("%sNumber of entries: %d\n", indent, header->number_of_entries);
104 printf("%sSize of entry: %d\n", indent, header->size_of_entry);
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800105 printf("%sEntries CRC: 0x%08x %s\n", indent, header->entries_crc32,
106 header->entries_crc32 !=
107 Crc32((const uint8_t *)entries,header->size_of_entry *
108 header->number_of_entries)
109 ? "INVALID" : ""
110 );
Jay Srinivasana0581432012-01-26 21:50:05 -0800111}
112
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700113void MtdEntryDetails(MtdDiskPartition *entry, uint32_t index, int raw) {
114 const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700115 char type[256];
116 char contents[256];
117 char name[sizeof(entry->label) + 1];
Albert Chaulk289b6042013-06-25 11:30:46 -0700118 uint64_t start, size;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700119 if (guid) {
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700120 ResolveType(guid, type);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700121 } else {
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700122 snprintf(type, sizeof(type), "MTD partition type %d",
123 MtdGetEntryType(entry));
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700124 }
125
Albert Chaulk289b6042013-06-25 11:30:46 -0700126 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
127
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700128 // Provide a NUL if we are at maximum size.
129 name[sizeof(name)-1] = '\0';
130 memcpy(name, entry->label, sizeof(entry->label));
131 require(snprintf(contents, sizeof(contents),
132 "Label: \"%s\"", name) < sizeof(contents));
133
134 printf(PARTITION_FMT, (int)start, (int)size, index+1, contents);
135 printf(PARTITION_MORE, "Type: ", type);
136
137 if (raw && MtdGetEntryType(entry) == MTD_PARTITION_TYPE_CHROMEOS_KERNEL) {
138 int tries = MtdGetEntryTries(entry);
139 int successful = MtdGetEntrySuccessful(entry);
140 int priority = MtdGetEntryPriority(entry);
141 require(snprintf(contents, sizeof(contents),
142 "priority=%d tries=%d successful=%d",
143 priority, tries, successful) < sizeof(contents));
144 printf(PARTITION_MORE, "Attr: ", contents);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700145 } else {
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700146 require(snprintf(contents, sizeof(contents),
147 "[%x]", entry->flags) < sizeof(contents));
148 printf(PARTITION_MORE, "Attr: ", contents);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700149 }
150}
151
Jay Srinivasana0581432012-01-26 21:50:05 -0800152void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
153 char contents[256]; // scratch buffer for formatting output
154 uint8_t label[GPT_PARTNAME_LEN];
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700155 char type[GUID_STRLEN], unique[GUID_STRLEN];
156
157 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
158 label, sizeof(label));
159 require(snprintf(contents, sizeof(contents),
160 "Label: \"%s\"", label) < sizeof(contents));
161 printf(PARTITION_FMT, (int)entry->starting_lba,
162 (int)(entry->ending_lba - entry->starting_lba + 1),
163 index+1, contents);
164
165 if (!raw && CGPT_OK == ResolveType(&entry->type, type)) {
166 printf(PARTITION_MORE, "Type: ", type);
167 } else {
168 GuidToStr(&entry->type, type, GUID_STRLEN);
169 printf(PARTITION_MORE, "Type: ", type);
170 }
171 GuidToStr(&entry->unique, unique, GUID_STRLEN);
172 printf(PARTITION_MORE, "UUID: ", unique);
Jay Srinivasana0581432012-01-26 21:50:05 -0800173
174 if (!raw) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800175 if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
176 int tries = (entry->attrs.fields.gpt_att &
177 CGPT_ATTRIBUTE_TRIES_MASK) >>
178 CGPT_ATTRIBUTE_TRIES_OFFSET;
179 int successful = (entry->attrs.fields.gpt_att &
180 CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
181 CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
182 int priority = (entry->attrs.fields.gpt_att &
183 CGPT_ATTRIBUTE_PRIORITY_MASK) >>
184 CGPT_ATTRIBUTE_PRIORITY_OFFSET;
185 require(snprintf(contents, sizeof(contents),
186 "priority=%d tries=%d successful=%d",
187 priority, tries, successful) < sizeof(contents));
188 printf(PARTITION_MORE, "Attr: ", contents);
189 }
190 } else {
Jay Srinivasana0581432012-01-26 21:50:05 -0800191 require(snprintf(contents, sizeof(contents),
192 "[%x]", entry->attrs.fields.gpt_att) < sizeof(contents));
193 printf(PARTITION_MORE, "Attr: ", contents);
194 }
195}
196
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700197void MtdEntriesDetails(struct drive *drive, int secondary, int raw) {
198 uint32_t i;
199
200 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
201 MtdDiskPartition *entry;
202 entry = MtdGetEntry(&drive->mtd, secondary, i);
203 if (IsUnused(drive, secondary, i))
204 continue;
205 MtdEntryDetails(entry, i, raw);
206 }
207}
Jay Srinivasana0581432012-01-26 21:50:05 -0800208
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700209void EntriesDetails(struct drive *drive, const int secondary, int raw) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800210 uint32_t i;
211
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700212 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800213 GptEntry *entry;
Albert Chaulkfa6b35c2013-03-26 13:43:02 -0700214 entry = GetEntry(&drive->gpt, secondary, i);
Jay Srinivasana0581432012-01-26 21:50:05 -0800215
Bill Richardson3f806a22013-03-20 15:02:34 -0700216 if (GuidIsZero(&entry->type))
Jay Srinivasana0581432012-01-26 21:50:05 -0800217 continue;
218
219 EntryDetails(entry, i, raw);
220 }
221}
222
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700223int MtdShow(struct drive *drive, CgptShowParams *params) {
224 if (params->partition) { // show single partition
225 if (params->partition > GetNumberOfEntries(drive)) {
226 Error("invalid partition number: %d\n", params->partition);
227 return CGPT_FAILED;
228 }
229
230 uint32_t index = params->partition - 1;
231 MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, index);
232 char buf[256]; // scratch buffer for string conversion
233 const Guid *guid;
Albert Chaulk289b6042013-06-25 11:30:46 -0700234 uint64_t start, size;
235
236 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700237
238 if (params->single_item) {
239 switch(params->single_item) {
240 case 'b':
Albert Chaulk289b6042013-06-25 11:30:46 -0700241 printf("%u\n", (int)start);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700242 break;
243 case 's':
Albert Chaulk289b6042013-06-25 11:30:46 -0700244 printf("%u\n", (int)size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700245 break;
246 case 't':
247 guid = LookupGuidForMtdType(MtdGetEntryType(entry));
248 GuidToStr(guid, buf, sizeof(buf));
249 printf("%s\n", buf);
250 break;
251 case 'S':
252 printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
253 break;
254 case 'T':
255 printf("%d\n", GetTries(drive, ANY_VALID, index));
256 break;
257 case 'P':
258 printf("%d\n", GetPriority(drive, ANY_VALID, index));
259 break;
260 case 'A':
261 printf("0x%x\n", entry->flags);
262 break;
263 }
264 } else {
265 printf(TITLE_FMT, "start", "size", "part", "contents");
266 MtdEntryDetails(entry, index, params->numeric);
267 }
268 } else if (params->quick) { // show all partitions, quickly
269 uint32_t i;
270 char type[GUID_STRLEN];
271
272 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
273 MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, i);
274 const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
Albert Chaulk289b6042013-06-25 11:30:46 -0700275 uint64_t start, size;
276
277 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700278
279 if (IsUnused(drive, ANY_VALID, i))
280 continue;
281
282 if (!params->numeric && guid) {
283 ResolveType(guid, type);
284 } else {
285 snprintf(type, sizeof(type), "MTD partition type %d",
286 MtdGetEntryType(entry));
287 }
Albert Chaulk289b6042013-06-25 11:30:46 -0700288 printf(PARTITION_FMT, (int)start, (int)size, i+1, type);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700289 }
290 } else { // show all partitions
291 if (params->debug || params->verbose) {
292 char indent[64];
293
294 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
295 MtdHeaderDetails(&drive->mtd.primary, indent, 0);
296 }
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700297 printf(TITLE_FMT, "start", "size", "part", "contents");
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700298 MtdEntriesDetails(drive, PRIMARY, params->numeric);
299 }
300
301 return CGPT_OK;
302}
303
Bill Richardson18e03702014-06-23 17:48:33 -0700304static int GptShow(struct drive *drive, CgptShowParams *params) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800305 int gpt_retval;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700306 if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800307 Error("GptSanityCheck() returned %d: %s\n",
308 gpt_retval, GptError(gpt_retval));
309 return CGPT_FAILED;
310 }
311
312 if (params->partition) { // show single partition
313
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700314 if (params->partition > GetNumberOfEntries(drive)) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800315 Error("invalid partition number: %d\n", params->partition);
316 return CGPT_FAILED;
317 }
318
319 uint32_t index = params->partition - 1;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700320 GptEntry *entry = GetEntry(&drive->gpt, ANY_VALID, index);
Jay Srinivasana0581432012-01-26 21:50:05 -0800321 char buf[256]; // scratch buffer for string conversion
322
323 if (params->single_item) {
324 switch(params->single_item) {
325 case 'b':
326 printf("%" PRId64 "\n", entry->starting_lba);
327 break;
Mike Frysinger98624d32013-05-03 18:05:16 -0400328 case 's': {
329 uint64_t size = 0;
330 // If these aren't actually defined, don't show anything
331 if (entry->ending_lba || entry->starting_lba)
332 size = entry->ending_lba - entry->starting_lba + 1;
333 printf("%" PRId64 "\n", size);
Jay Srinivasana0581432012-01-26 21:50:05 -0800334 break;
Mike Frysinger98624d32013-05-03 18:05:16 -0400335 }
Jay Srinivasana0581432012-01-26 21:50:05 -0800336 case 't':
337 GuidToStr(&entry->type, buf, sizeof(buf));
338 printf("%s\n", buf);
339 break;
340 case 'u':
341 GuidToStr(&entry->unique, buf, sizeof(buf));
342 printf("%s\n", buf);
343 break;
344 case 'l':
345 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
346 (uint8_t *)buf, sizeof(buf));
347 printf("%s\n", buf);
348 break;
349 case 'S':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700350 printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800351 break;
352 case 'T':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700353 printf("%d\n", GetTries(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800354 break;
355 case 'P':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700356 printf("%d\n", GetPriority(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800357 break;
358 case 'A':
359 printf("0x%x\n", entry->attrs.fields.gpt_att);
360 break;
361 }
362 } else {
363 printf(TITLE_FMT, "start", "size", "part", "contents");
364 EntryDetails(entry, index, params->numeric);
365 }
366
367 } else if (params->quick) { // show all partitions, quickly
368 uint32_t i;
369 GptEntry *entry;
370 char type[GUID_STRLEN];
371
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700372 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
373 entry = GetEntry(&drive->gpt, ANY_VALID, i);
Jay Srinivasana0581432012-01-26 21:50:05 -0800374
Bill Richardson3f806a22013-03-20 15:02:34 -0700375 if (GuidIsZero(&entry->type))
Jay Srinivasana0581432012-01-26 21:50:05 -0800376 continue;
377
378 if (!params->numeric && CGPT_OK == ResolveType(&entry->type, type)) {
379 } else {
380 GuidToStr(&entry->type, type, GUID_STRLEN);
381 }
382 printf(PARTITION_FMT, (int)entry->starting_lba,
383 (int)(entry->ending_lba - entry->starting_lba + 1),
384 i+1, type);
385 }
386 } else { // show all partitions
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800387 GptEntry *entries;
388
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700389 if (CGPT_OK != ReadPMBR(drive)) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800390 Error("Unable to read PMBR\n");
391 return CGPT_FAILED;
392 }
393
394 printf(TITLE_FMT, "start", "size", "part", "contents");
395 char buf[256]; // buffer for formatted PMBR content
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700396 PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small
Jay Srinivasana0581432012-01-26 21:50:05 -0800397 printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", buf);
398
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700399 if (drive->gpt.valid_headers & MASK_PRIMARY) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800400 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
401 (int)GPT_HEADER_SECTOR, "", "Pri GPT header");
Jay Srinivasana0581432012-01-26 21:50:05 -0800402 } else {
403 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
404 (int)GPT_HEADER_SECTOR, "INVALID", "Pri GPT header");
405 }
406
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800407 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700408 ((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800409 GptHeader *header;
410 char indent[64];
411
412 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700413 header = (GptHeader*)drive->gpt.primary_header;
414 entries = (GptEntry*)drive->gpt.primary_entries;
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800415 HeaderDetails(header, entries, indent, params->numeric);
416 }
417
Jay Srinivasana0581432012-01-26 21:50:05 -0800418 printf(GPT_FMT, (int)(GPT_PMBR_SECTOR + GPT_HEADER_SECTOR),
419 (int)GPT_ENTRIES_SECTORS,
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700420 drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
Jay Srinivasana0581432012-01-26 21:50:05 -0800421 "Pri GPT table");
422
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800423 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700424 (drive->gpt.valid_entries & MASK_PRIMARY))
425 EntriesDetails(drive, PRIMARY, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800426
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800427 /****************************** Secondary *************************/
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700428 printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR -
Jay Srinivasana0581432012-01-26 21:50:05 -0800429 GPT_ENTRIES_SECTORS),
430 (int)GPT_ENTRIES_SECTORS,
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700431 drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
Jay Srinivasana0581432012-01-26 21:50:05 -0800432 "Sec GPT table");
433 /* We show secondary table details if any of following is true.
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800434 * 1. in debug mode.
435 * 2. only secondary is valid.
436 * 3. secondary is not identical to promary.
Jay Srinivasana0581432012-01-26 21:50:05 -0800437 */
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800438 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700439 ((drive->gpt.valid_entries & MASK_SECONDARY) &&
440 (!(drive->gpt.valid_entries & MASK_PRIMARY) ||
441 memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries,
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800442 TOTAL_ENTRIES_SIZE)))) {
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700443 EntriesDetails(drive, SECONDARY, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800444 }
445
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700446 if (drive->gpt.valid_headers & MASK_SECONDARY)
447 printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR),
Jay Srinivasana0581432012-01-26 21:50:05 -0800448 (int)GPT_HEADER_SECTOR, "", "Sec GPT header");
449 else
450 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
451 (int)GPT_HEADER_SECTOR, "INVALID", "Sec GPT header");
452 /* We show secondary header if any of following is true:
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800453 * 1. in debug mode.
454 * 2. only secondary is valid.
455 * 3. secondary is not synonymous to primary.
Jay Srinivasana0581432012-01-26 21:50:05 -0800456 */
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800457 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700458 ((drive->gpt.valid_headers & MASK_SECONDARY) &&
459 (!(drive->gpt.valid_headers & MASK_PRIMARY) ||
460 !IsSynonymous((GptHeader*)drive->gpt.primary_header,
461 (GptHeader*)drive->gpt.secondary_header)) &&
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800462 params->verbose)) {
463 GptHeader *header;
464 char indent[64];
Jay Srinivasana0581432012-01-26 21:50:05 -0800465
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800466 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700467 header = (GptHeader*)drive->gpt.secondary_header;
468 entries = (GptEntry*)drive->gpt.secondary_entries;
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800469 HeaderDetails(header, entries, indent, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800470 }
471 }
472
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700473 CheckValid(drive);
Jay Srinivasana0581432012-01-26 21:50:05 -0800474
475 return CGPT_OK;
476}
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700477
478int CgptShow(CgptShowParams *params) {
479 struct drive drive;
480
481 if (params == NULL)
482 return CGPT_FAILED;
483
484 if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
485 return CGPT_FAILED;
486
487 if (drive.is_mtd) {
488 if (MtdShow(&drive, params))
489 return CGPT_FAILED;
490 } else {
491 if (GptShow(&drive, params))
492 return CGPT_FAILED;
493 }
494
495 DriveClose(&drive, 0);
496 return CGPT_OK;
497}