blob: a2b7c95129796a5bc19c2d382fdbdc3d97b083b9 [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 Chaulk494646d2013-07-19 12:56:38 -070076 printf("%sFirst offset: %llu\n", indent,
Albert Chaulk289b6042013-06-25 11:30:46 -070077 (unsigned long long)header->first_offset);
Albert Chaulk494646d2013-07-19 12:56:38 -070078 printf("%sLast offset: %llu\n", indent,
Albert Chaulk289b6042013-06-25 11:30:46 -070079 (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
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700222int MtdShow(struct drive *drive, CgptShowParams *params) {
223 if (params->partition) { // show single partition
224 if (params->partition > GetNumberOfEntries(drive)) {
225 Error("invalid partition number: %d\n", params->partition);
226 return CGPT_FAILED;
227 }
228
229 uint32_t index = params->partition - 1;
230 MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, index);
231 char buf[256]; // scratch buffer for string conversion
232 const Guid *guid;
Albert Chaulk289b6042013-06-25 11:30:46 -0700233 uint64_t start, size;
234
235 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700236
237 if (params->single_item) {
238 switch(params->single_item) {
239 case 'b':
Albert Chaulk289b6042013-06-25 11:30:46 -0700240 printf("%u\n", (int)start);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700241 break;
242 case 's':
Albert Chaulk289b6042013-06-25 11:30:46 -0700243 printf("%u\n", (int)size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700244 break;
245 case 't':
246 guid = LookupGuidForMtdType(MtdGetEntryType(entry));
247 GuidToStr(guid, buf, sizeof(buf));
248 printf("%s\n", buf);
249 break;
250 case 'S':
251 printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
252 break;
253 case 'T':
254 printf("%d\n", GetTries(drive, ANY_VALID, index));
255 break;
256 case 'P':
257 printf("%d\n", GetPriority(drive, ANY_VALID, index));
258 break;
259 case 'A':
260 printf("0x%x\n", entry->flags);
261 break;
262 }
263 } else {
264 printf(TITLE_FMT, "start", "size", "part", "contents");
265 MtdEntryDetails(entry, index, params->numeric);
266 }
267 } else if (params->quick) { // show all partitions, quickly
268 uint32_t i;
269 char type[GUID_STRLEN];
270
271 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
272 MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, i);
273 const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
Albert Chaulk289b6042013-06-25 11:30:46 -0700274 uint64_t start, size;
275
276 MtdGetPartitionSizeInSectors(entry, &start, NULL, &size);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700277
278 if (IsUnused(drive, ANY_VALID, i))
279 continue;
280
281 if (!params->numeric && guid) {
282 ResolveType(guid, type);
283 } else {
284 snprintf(type, sizeof(type), "MTD partition type %d",
285 MtdGetEntryType(entry));
286 }
Albert Chaulk289b6042013-06-25 11:30:46 -0700287 printf(PARTITION_FMT, (int)start, (int)size, i+1, type);
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700288 }
289 } else { // show all partitions
290 if (params->debug || params->verbose) {
291 char indent[64];
292
293 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
294 MtdHeaderDetails(&drive->mtd.primary, indent, 0);
295 }
Albert Chaulk32fd6de2013-07-25 11:32:57 -0700296 printf(TITLE_FMT, "start", "size", "part", "contents");
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700297 MtdEntriesDetails(drive, PRIMARY, params->numeric);
298 }
299
300 return CGPT_OK;
301}
302
303int GptShow(struct drive *drive, CgptShowParams *params) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800304 int gpt_retval;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700305 if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800306 Error("GptSanityCheck() returned %d: %s\n",
307 gpt_retval, GptError(gpt_retval));
308 return CGPT_FAILED;
309 }
310
311 if (params->partition) { // show single partition
312
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700313 if (params->partition > GetNumberOfEntries(drive)) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800314 Error("invalid partition number: %d\n", params->partition);
315 return CGPT_FAILED;
316 }
317
318 uint32_t index = params->partition - 1;
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700319 GptEntry *entry = GetEntry(&drive->gpt, ANY_VALID, index);
Jay Srinivasana0581432012-01-26 21:50:05 -0800320 char buf[256]; // scratch buffer for string conversion
321
322 if (params->single_item) {
323 switch(params->single_item) {
324 case 'b':
325 printf("%" PRId64 "\n", entry->starting_lba);
326 break;
Mike Frysinger98624d32013-05-03 18:05:16 -0400327 case 's': {
328 uint64_t size = 0;
329 // If these aren't actually defined, don't show anything
330 if (entry->ending_lba || entry->starting_lba)
331 size = entry->ending_lba - entry->starting_lba + 1;
332 printf("%" PRId64 "\n", size);
Jay Srinivasana0581432012-01-26 21:50:05 -0800333 break;
Mike Frysinger98624d32013-05-03 18:05:16 -0400334 }
Jay Srinivasana0581432012-01-26 21:50:05 -0800335 case 't':
336 GuidToStr(&entry->type, buf, sizeof(buf));
337 printf("%s\n", buf);
338 break;
339 case 'u':
340 GuidToStr(&entry->unique, buf, sizeof(buf));
341 printf("%s\n", buf);
342 break;
343 case 'l':
344 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
345 (uint8_t *)buf, sizeof(buf));
346 printf("%s\n", buf);
347 break;
348 case 'S':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700349 printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800350 break;
351 case 'T':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700352 printf("%d\n", GetTries(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800353 break;
354 case 'P':
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700355 printf("%d\n", GetPriority(drive, ANY_VALID, index));
Jay Srinivasana0581432012-01-26 21:50:05 -0800356 break;
357 case 'A':
358 printf("0x%x\n", entry->attrs.fields.gpt_att);
359 break;
360 }
361 } else {
362 printf(TITLE_FMT, "start", "size", "part", "contents");
363 EntryDetails(entry, index, params->numeric);
364 }
365
366 } else if (params->quick) { // show all partitions, quickly
367 uint32_t i;
368 GptEntry *entry;
369 char type[GUID_STRLEN];
370
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700371 for (i = 0; i < GetNumberOfEntries(drive); ++i) {
372 entry = GetEntry(&drive->gpt, ANY_VALID, i);
Jay Srinivasana0581432012-01-26 21:50:05 -0800373
Bill Richardson3f806a22013-03-20 15:02:34 -0700374 if (GuidIsZero(&entry->type))
Jay Srinivasana0581432012-01-26 21:50:05 -0800375 continue;
376
377 if (!params->numeric && CGPT_OK == ResolveType(&entry->type, type)) {
378 } else {
379 GuidToStr(&entry->type, type, GUID_STRLEN);
380 }
381 printf(PARTITION_FMT, (int)entry->starting_lba,
382 (int)(entry->ending_lba - entry->starting_lba + 1),
383 i+1, type);
384 }
385 } else { // show all partitions
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800386 GptEntry *entries;
387
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700388 if (CGPT_OK != ReadPMBR(drive)) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800389 Error("Unable to read PMBR\n");
390 return CGPT_FAILED;
391 }
392
393 printf(TITLE_FMT, "start", "size", "part", "contents");
394 char buf[256]; // buffer for formatted PMBR content
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700395 PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small
Jay Srinivasana0581432012-01-26 21:50:05 -0800396 printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", buf);
397
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700398 if (drive->gpt.valid_headers & MASK_PRIMARY) {
Jay Srinivasana0581432012-01-26 21:50:05 -0800399 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
400 (int)GPT_HEADER_SECTOR, "", "Pri GPT header");
Jay Srinivasana0581432012-01-26 21:50:05 -0800401 } else {
402 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
403 (int)GPT_HEADER_SECTOR, "INVALID", "Pri GPT header");
404 }
405
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800406 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700407 ((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800408 GptHeader *header;
409 char indent[64];
410
411 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700412 header = (GptHeader*)drive->gpt.primary_header;
413 entries = (GptEntry*)drive->gpt.primary_entries;
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800414 HeaderDetails(header, entries, indent, params->numeric);
415 }
416
Jay Srinivasana0581432012-01-26 21:50:05 -0800417 printf(GPT_FMT, (int)(GPT_PMBR_SECTOR + GPT_HEADER_SECTOR),
418 (int)GPT_ENTRIES_SECTORS,
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700419 drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
Jay Srinivasana0581432012-01-26 21:50:05 -0800420 "Pri GPT table");
421
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800422 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700423 (drive->gpt.valid_entries & MASK_PRIMARY))
424 EntriesDetails(drive, PRIMARY, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800425
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800426 /****************************** Secondary *************************/
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700427 printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR -
Jay Srinivasana0581432012-01-26 21:50:05 -0800428 GPT_ENTRIES_SECTORS),
429 (int)GPT_ENTRIES_SECTORS,
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700430 drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
Jay Srinivasana0581432012-01-26 21:50:05 -0800431 "Sec GPT table");
432 /* We show secondary table details if any of following is true.
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800433 * 1. in debug mode.
434 * 2. only secondary is valid.
435 * 3. secondary is not identical to promary.
Jay Srinivasana0581432012-01-26 21:50:05 -0800436 */
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800437 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700438 ((drive->gpt.valid_entries & MASK_SECONDARY) &&
439 (!(drive->gpt.valid_entries & MASK_PRIMARY) ||
440 memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries,
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800441 TOTAL_ENTRIES_SIZE)))) {
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700442 EntriesDetails(drive, SECONDARY, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800443 }
444
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700445 if (drive->gpt.valid_headers & MASK_SECONDARY)
446 printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR),
Jay Srinivasana0581432012-01-26 21:50:05 -0800447 (int)GPT_HEADER_SECTOR, "", "Sec GPT header");
448 else
449 printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
450 (int)GPT_HEADER_SECTOR, "INVALID", "Sec GPT header");
451 /* We show secondary header if any of following is true:
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800452 * 1. in debug mode.
453 * 2. only secondary is valid.
454 * 3. secondary is not synonymous to primary.
Jay Srinivasana0581432012-01-26 21:50:05 -0800455 */
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800456 if (params->debug ||
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700457 ((drive->gpt.valid_headers & MASK_SECONDARY) &&
458 (!(drive->gpt.valid_headers & MASK_PRIMARY) ||
459 !IsSynonymous((GptHeader*)drive->gpt.primary_header,
460 (GptHeader*)drive->gpt.secondary_header)) &&
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800461 params->verbose)) {
462 GptHeader *header;
463 char indent[64];
Jay Srinivasana0581432012-01-26 21:50:05 -0800464
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800465 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700466 header = (GptHeader*)drive->gpt.secondary_header;
467 entries = (GptEntry*)drive->gpt.secondary_entries;
Louis Yung-Chieh Lo455b1192012-06-26 14:48:39 +0800468 HeaderDetails(header, entries, indent, params->numeric);
Jay Srinivasana0581432012-01-26 21:50:05 -0800469 }
470 }
471
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700472 CheckValid(drive);
Jay Srinivasana0581432012-01-26 21:50:05 -0800473
474 return CGPT_OK;
475}
Albert Chaulk1c568bc2013-04-02 14:35:39 -0700476
477int CgptShow(CgptShowParams *params) {
478 struct drive drive;
479
480 if (params == NULL)
481 return CGPT_FAILED;
482
483 if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
484 return CGPT_FAILED;
485
486 if (drive.is_mtd) {
487 if (MtdShow(&drive, params))
488 return CGPT_FAILED;
489 } else {
490 if (GptShow(&drive, params))
491 return CGPT_FAILED;
492 }
493
494 DriveClose(&drive, 0);
495 return CGPT_OK;
496}