OLD | NEW |
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cgpt.h" | 5 #include "cgpt.h" |
6 | 6 |
7 #define __STDC_FORMAT_MACROS | 7 #define __STDC_FORMAT_MACROS |
8 #include <getopt.h> | 8 #include <getopt.h> |
9 #include <inttypes.h> | 9 #include <inttypes.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
11 #include <stdlib.h> | 11 #include <stdlib.h> |
12 #include <string.h> | 12 #include <string.h> |
13 | 13 |
14 #include "cgptlib_internal.h" | 14 #include "cgptlib_internal.h" |
15 | 15 |
16 static void Usage(void) | 16 static void Usage(void) |
17 { | 17 { |
18 printf("\nUsage: %s show [OPTIONS] DRIVE\n\n" | 18 printf("\nUsage: %s show [OPTIONS] DRIVE\n\n" |
19 "Display the GPT table\n\n" | 19 "Display the GPT table\n\n" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 #define GPT_FMT "%10d%10d%8s %s\n" | 73 #define GPT_FMT "%10d%10d%8s %s\n" |
74 #define GPT_MORE "%10s%10s%8s ", "", "", "" | 74 #define GPT_MORE "%10s%10s%8s ", "", "", "" |
75 #define PARTITION_FMT "%10d%10d%8d %s\n" | 75 #define PARTITION_FMT "%10d%10d%8d %s\n" |
76 #define PARTITION_MORE "%10s%10s%8s %s%s\n", "", "", "" | 76 #define PARTITION_MORE "%10s%10s%8s %s%s\n", "", "", "" |
77 | 77 |
78 static void HeaderDetails(GptHeader *header, const char *indent, int raw) { | 78 static void HeaderDetails(GptHeader *header, const char *indent, int raw) { |
79 int i; | 79 int i; |
80 | 80 |
81 printf("%sSig: ", indent); | 81 printf("%sSig: ", indent); |
82 if (!raw) { | 82 if (!raw) { |
83 printf("["); | 83 printf("["); |
84 for (i = 0; i < sizeof(header->signature); ++i) | 84 for (i = 0; i < sizeof(header->signature); ++i) |
85 printf("%c", header->signature[i]); | 85 printf("%c", header->signature[i]); |
86 printf("]"); | 86 printf("]"); |
87 } else { | 87 } else { |
88 char buf[BUFFER_SIZE(sizeof(header->signature))]; | 88 char buf[BUFFER_SIZE(sizeof(header->signature))]; |
89 RawDump((uint8_t *)header->signature, sizeof(header->signature), buf, 1); | 89 RawDump((uint8_t *)header->signature, sizeof(header->signature), buf, 1); |
90 printf("%s", buf); | 90 printf("%s", buf); |
91 } | 91 } |
92 printf("\n"); | 92 printf("\n"); |
93 | 93 |
94 printf("%sRev: 0x%08x\n", indent, header->revision); | 94 printf("%sRev: 0x%08x\n", indent, header->revision); |
95 printf("%sSize: %d\n", indent, header->size); | 95 printf("%sSize: %d\n", indent, header->size); |
96 printf("%sHeader CRC: 0x%08x\n", indent, header->header_crc32); | 96 printf("%sHeader CRC: 0x%08x\n", indent, header->header_crc32); |
97 printf("%sMy LBA: %lld\n", indent, (long long)header->my_lba); | 97 printf("%sMy LBA: %lld\n", indent, (long long)header->my_lba); |
98 printf("%sAlternate LBA: %lld\n", indent, (long long)header->alternate_lba); | 98 printf("%sAlternate LBA: %lld\n", indent, (long long)header->alternate_lba); |
99 printf("%sFirst LBA: %lld\n", indent, (long long)header->first_usable_lba); | 99 printf("%sFirst LBA: %lld\n", indent, (long long)header->first_usable_lba); |
100 printf("%sLast LBA: %lld\n", indent, (long long)header->last_usable_lba); | 100 printf("%sLast LBA: %lld\n", indent, (long long)header->last_usable_lba); |
101 | 101 |
102 { /* For disk guid */ | 102 { /* For disk guid */ |
103 char buf[GUID_STRLEN]; | 103 char buf[GUID_STRLEN]; |
104 GuidToStr(&header->disk_uuid, buf); | 104 GuidToStr(&header->disk_uuid, buf, GUID_STRLEN); |
105 printf("%sDisk UUID: %s\n", indent, buf); | 105 printf("%sDisk UUID: %s\n", indent, buf); |
106 } | 106 } |
107 | 107 |
108 printf("%sEntries LBA: %lld\n", indent, (long long)header->entries_lba); | 108 printf("%sEntries LBA: %lld\n", indent, (long long)header->entries_lba); |
109 printf("%sNumber of entries: %d\n", indent, header->number_of_entries); | 109 printf("%sNumber of entries: %d\n", indent, header->number_of_entries); |
110 printf("%sSize of entry: %d\n", indent, header->size_of_entry); | 110 printf("%sSize of entry: %d\n", indent, header->size_of_entry); |
111 printf("%sEntries CRC: 0x%08x\n", indent, header->entries_crc32); | 111 printf("%sEntries CRC: 0x%08x\n", indent, header->entries_crc32); |
112 } | 112 } |
113 | 113 |
114 void EntryDetails(GptEntry *entry, int index, int raw) { | 114 void EntryDetails(GptEntry *entry, uint32_t index, int raw) { |
115 char contents[256]; | 115 char contents[256]; // scratch buffer for formatting output |
116 uint8_t label[sizeof(entry->name) * 3 / 2]; | 116 uint8_t label[GPT_PARTNAME_LEN]; |
117 | 117 |
118 if (!raw) { | 118 if (!raw) { |
119 char type[GUID_STRLEN], unique[GUID_STRLEN];; | 119 char type[GUID_STRLEN], unique[GUID_STRLEN]; |
120 | 120 |
121 UTF16ToUTF8(entry->name, label); | 121 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]), |
122 snprintf(contents, sizeof(contents), "Label: \"%s\"", label); | 122 label, sizeof(label)); |
| 123 require(snprintf(contents, sizeof(contents), |
| 124 "Label: \"%s\"", label) < sizeof(contents)); |
123 printf(PARTITION_FMT, (int)entry->starting_lba, | 125 printf(PARTITION_FMT, (int)entry->starting_lba, |
124 (int)(entry->ending_lba - entry->starting_lba + 1), | 126 (int)(entry->ending_lba - entry->starting_lba + 1), |
125 index+1, contents); | 127 index+1, contents); |
126 if (CGPT_OK == ResolveType(&entry->type, type)) { | 128 if (CGPT_OK == ResolveType(&entry->type, type)) { |
127 printf(PARTITION_MORE, "Type: ", type); | 129 printf(PARTITION_MORE, "Type: ", type); |
128 } else { | 130 } else { |
129 GuidToStr(&entry->type, type); | 131 GuidToStr(&entry->type, type, GUID_STRLEN); |
130 printf(PARTITION_MORE, "Type: ", type); | 132 printf(PARTITION_MORE, "Type: ", type); |
131 } | 133 } |
132 GuidToStr(&entry->unique, unique); | 134 GuidToStr(&entry->unique, unique, GUID_STRLEN); |
133 printf(PARTITION_MORE, "UUID: ", unique); | 135 printf(PARTITION_MORE, "UUID: ", unique); |
134 if (!memcmp(&guid_chromeos_kernel, &entry->type, sizeof(Guid))) { | 136 if (!memcmp(&guid_chromeos_kernel, &entry->type, sizeof(Guid))) { |
135 int tries = (entry->attrs.fields.gpt_att & | 137 int tries = (entry->attrs.fields.gpt_att & |
136 CGPT_ATTRIBUTE_TRIES_MASK) >> | 138 CGPT_ATTRIBUTE_TRIES_MASK) >> |
137 CGPT_ATTRIBUTE_TRIES_OFFSET; | 139 CGPT_ATTRIBUTE_TRIES_OFFSET; |
138 int successful = (entry->attrs.fields.gpt_att & | 140 int successful = (entry->attrs.fields.gpt_att & |
139 CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >> | 141 CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >> |
140 CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET; | 142 CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET; |
141 int priority = (entry->attrs.fields.gpt_att & | 143 int priority = (entry->attrs.fields.gpt_att & |
142 CGPT_ATTRIBUTE_PRIORITY_MASK) >> | 144 CGPT_ATTRIBUTE_PRIORITY_MASK) >> |
143 CGPT_ATTRIBUTE_PRIORITY_OFFSET; | 145 CGPT_ATTRIBUTE_PRIORITY_OFFSET; |
144 snprintf(contents, sizeof(contents), | 146 require(snprintf(contents, sizeof(contents), |
145 "priority=%d tries=%d successful=%d", | 147 "priority=%d tries=%d successful=%d", |
146 priority, tries, successful); | 148 priority, tries, successful) < sizeof(contents)); |
147 printf(PARTITION_MORE, "Attr: ", contents); | 149 printf(PARTITION_MORE, "Attr: ", contents); |
148 } | 150 } |
149 } else { | 151 } else { |
150 char type[GUID_STRLEN], unique[GUID_STRLEN]; | 152 char type[GUID_STRLEN], unique[GUID_STRLEN]; |
151 | 153 |
152 UTF16ToUTF8(entry->name, label); | 154 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]), |
153 snprintf(contents, sizeof(contents), "Label: \"%s\"", label); | 155 label, sizeof(label)); |
| 156 require(snprintf(contents, sizeof(contents), |
| 157 "Label: \"%s\"", label) < sizeof(contents)); |
154 printf(PARTITION_FMT, (int)entry->starting_lba, | 158 printf(PARTITION_FMT, (int)entry->starting_lba, |
155 (int)(entry->ending_lba - entry->starting_lba + 1), | 159 (int)(entry->ending_lba - entry->starting_lba + 1), |
156 index+1, contents); | 160 index+1, contents); |
157 GuidToStr(&entry->type, type); | 161 GuidToStr(&entry->type, type, GUID_STRLEN); |
158 printf(PARTITION_MORE, "Type: ", type); | 162 printf(PARTITION_MORE, "Type: ", type); |
159 GuidToStr(&entry->unique, unique); | 163 GuidToStr(&entry->unique, unique, GUID_STRLEN); |
160 printf(PARTITION_MORE, "UUID: ", unique); | 164 printf(PARTITION_MORE, "UUID: ", unique); |
161 snprintf(contents, sizeof(contents), "[%x]", entry->attrs.fields.gpt_att); | 165 require(snprintf(contents, sizeof(contents), |
| 166 "[%x]", entry->attrs.fields.gpt_att) < sizeof(contents)); |
162 printf(PARTITION_MORE, "Attr: ", contents); | 167 printf(PARTITION_MORE, "Attr: ", contents); |
163 } | 168 } |
164 } | 169 } |
165 | 170 |
166 | 171 |
167 void EntriesDetails(GptData *gpt, const int secondary, int raw) { | 172 void EntriesDetails(GptData *gpt, const int secondary, int raw) { |
168 int i; | 173 uint32_t i; |
169 | 174 |
170 for (i = 0; i < GetNumberOfEntries(gpt); ++i) { | 175 for (i = 0; i < GetNumberOfEntries(gpt); ++i) { |
171 GptEntry *entry; | 176 GptEntry *entry; |
172 entry = GetEntry(gpt, secondary, i); | 177 entry = GetEntry(gpt, secondary, i); |
173 | 178 |
174 if (!memcmp(&guid_unused, &entry->type, sizeof(Guid))) continue; | 179 if (!memcmp(&guid_unused, &entry->type, sizeof(Guid))) continue; |
175 | 180 |
176 EntryDetails(entry, i, raw); | 181 EntryDetails(entry, i, raw); |
177 } | 182 } |
178 } | 183 } |
179 | 184 |
180 int cmd_show(int argc, char *argv[]) { | 185 int cmd_show(int argc, char *argv[]) { |
181 struct drive drive; | 186 struct drive drive; |
182 int numeric = 0; | 187 int numeric = 0; |
183 int verbose = 0; | 188 int verbose = 0; |
184 int quick = 0; | 189 int quick = 0; |
185 int partition = 0; | 190 uint32_t partition = 0; |
186 int single_item = 0; | 191 int single_item = 0; |
187 int gpt_retval; | 192 int gpt_retval; |
188 | 193 |
189 int c; | 194 int c; |
190 int errorcnt = 0; | 195 int errorcnt = 0; |
191 char *e = 0; | 196 char *e = 0; |
192 | 197 |
193 opterr = 0; // quiet, you | 198 opterr = 0; // quiet, you |
194 while ((c=getopt(argc, argv, ":hnvqi:bstulSTPA")) != -1) | 199 while ((c=getopt(argc, argv, ":hnvqi:bstulSTPA")) != -1) |
195 { | 200 { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 return CGPT_FAILED; | 266 return CGPT_FAILED; |
262 } | 267 } |
263 | 268 |
264 if (partition) { // show single partition | 269 if (partition) { // show single partition |
265 | 270 |
266 if (partition > GetNumberOfEntries(&drive.gpt)) { | 271 if (partition > GetNumberOfEntries(&drive.gpt)) { |
267 Error("invalid partition number: %d\n", partition); | 272 Error("invalid partition number: %d\n", partition); |
268 return CGPT_FAILED; | 273 return CGPT_FAILED; |
269 } | 274 } |
270 | 275 |
271 int index = partition - 1; | 276 uint32_t index = partition - 1; |
272 GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index); | 277 GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index); |
273 char buf[256]; | 278 char buf[256]; // scratch buffer for string conversion |
274 | 279 |
275 if (single_item) { | 280 if (single_item) { |
276 switch(single_item) { | 281 switch(single_item) { |
277 case 'b': | 282 case 'b': |
278 printf("%" PRId64 "\n", entry->starting_lba); | 283 printf("%" PRId64 "\n", entry->starting_lba); |
279 break; | 284 break; |
280 case 's': | 285 case 's': |
281 printf("%" PRId64 "\n", entry->ending_lba - entry->starting_lba + 1); | 286 printf("%" PRId64 "\n", entry->ending_lba - entry->starting_lba + 1); |
282 break; | 287 break; |
283 case 't': | 288 case 't': |
284 GuidToStr(&entry->type, buf); | 289 GuidToStr(&entry->type, buf, sizeof(buf)); |
285 printf("%s\n", buf); | 290 printf("%s\n", buf); |
286 break; | 291 break; |
287 case 'u': | 292 case 'u': |
288 GuidToStr(&entry->unique, buf); | 293 GuidToStr(&entry->unique, buf, sizeof(buf)); |
289 printf("%s\n", buf); | 294 printf("%s\n", buf); |
290 break; | 295 break; |
291 case 'l': | 296 case 'l': |
292 UTF16ToUTF8(entry->name, (uint8_t *)buf); | 297 UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]), |
| 298 (uint8_t *)buf, sizeof(buf)); |
293 printf("%s\n", buf); | 299 printf("%s\n", buf); |
294 break; | 300 break; |
295 case 'S': | 301 case 'S': |
296 printf("%d\n", GetSuccessful(&drive.gpt, PRIMARY, index)); | 302 printf("%d\n", GetSuccessful(&drive.gpt, PRIMARY, index)); |
297 break; | 303 break; |
298 case 'T': | 304 case 'T': |
299 printf("%d\n", GetTries(&drive.gpt, PRIMARY, index)); | 305 printf("%d\n", GetTries(&drive.gpt, PRIMARY, index)); |
300 break; | 306 break; |
301 case 'P': | 307 case 'P': |
302 printf("%d\n", GetPriority(&drive.gpt, PRIMARY, index)); | 308 printf("%d\n", GetPriority(&drive.gpt, PRIMARY, index)); |
303 break; | 309 break; |
304 case 'A': | 310 case 'A': |
305 printf("0x%x\n", entry->attrs.fields.gpt_att); | 311 printf("0x%x\n", entry->attrs.fields.gpt_att); |
306 break; | 312 break; |
307 } | 313 } |
308 } else { | 314 } else { |
309 printf(TITLE_FMT, "start", "size", "part", "contents"); | 315 printf(TITLE_FMT, "start", "size", "part", "contents"); |
310 EntryDetails(entry, index, numeric); | 316 EntryDetails(entry, index, numeric); |
311 } | 317 } |
312 | 318 |
313 } else if (quick) { // show all partitions, quickly | 319 } else if (quick) { // show all partitions, quickly |
314 int i; | 320 uint32_t i; |
315 GptEntry *entry; | 321 GptEntry *entry; |
316 char type[GUID_STRLEN]; | 322 char type[GUID_STRLEN]; |
317 | 323 |
318 for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) { | 324 for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) { |
319 entry = GetEntry(&drive.gpt, PRIMARY, i); | 325 entry = GetEntry(&drive.gpt, PRIMARY, i); |
320 | 326 |
321 if (IsZero(&entry->type)) | 327 if (IsZero(&entry->type)) |
322 continue; | 328 continue; |
323 | 329 |
324 if (!numeric && CGPT_OK == ResolveType(&entry->type, type)) { | 330 if (!numeric && CGPT_OK == ResolveType(&entry->type, type)) { |
325 } else { | 331 } else { |
326 GuidToStr(&entry->type, type); | 332 GuidToStr(&entry->type, type, GUID_STRLEN); |
327 } | 333 } |
328 printf(PARTITION_FMT, (int)entry->starting_lba, | 334 printf(PARTITION_FMT, (int)entry->starting_lba, |
329 (int)(entry->ending_lba - entry->starting_lba + 1), | 335 (int)(entry->ending_lba - entry->starting_lba + 1), |
330 i+1, type); | 336 i+1, type); |
331 } | 337 } |
332 | 338 |
333 } else { // show all partitions | 339 } else { // show all partitions |
334 | 340 |
335 if (CGPT_OK != ReadPMBR(&drive)) { | 341 if (CGPT_OK != ReadPMBR(&drive)) { |
336 Error("Unable to read PMBR\n"); | 342 Error("Unable to read PMBR\n"); |
337 return CGPT_FAILED; | 343 return CGPT_FAILED; |
338 } | 344 } |
339 | 345 |
340 printf(TITLE_FMT, "start", "size", "part", "contents"); | 346 printf(TITLE_FMT, "start", "size", "part", "contents"); |
341 char buf[256]; | 347 char buf[256]; // buffer for formatted PMBR content |
342 PMBRToStr(&drive.pmbr, buf); | 348 PMBRToStr(&drive.pmbr, buf, sizeof(buf)); // will exit if buf is too small |
343 printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", buf); | 349 printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", buf); |
344 | 350 |
345 if (drive.gpt.valid_headers & MASK_PRIMARY) { | 351 if (drive.gpt.valid_headers & MASK_PRIMARY) { |
346 printf(GPT_FMT, (int)GPT_PMBR_SECTOR, | 352 printf(GPT_FMT, (int)GPT_PMBR_SECTOR, |
347 (int)GPT_HEADER_SECTOR, "", "Pri GPT header"); | 353 (int)GPT_HEADER_SECTOR, "", "Pri GPT header"); |
348 if (verbose) { | 354 if (verbose) { |
349 GptHeader *header; | 355 GptHeader *header; |
350 char indent[64]; | 356 char indent[64]; |
351 | 357 |
352 snprintf(indent, sizeof(indent), GPT_MORE); | 358 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent)); |
353 header = (GptHeader*)drive.gpt.primary_header; | 359 header = (GptHeader*)drive.gpt.primary_header; |
354 HeaderDetails(header, indent, numeric); | 360 HeaderDetails(header, indent, numeric); |
355 } | 361 } |
356 } else { | 362 } else { |
357 printf(GPT_FMT, (int)GPT_PMBR_SECTOR, | 363 printf(GPT_FMT, (int)GPT_PMBR_SECTOR, |
358 (int)GPT_HEADER_SECTOR, "INVALID", "Pri GPT header"); | 364 (int)GPT_HEADER_SECTOR, "INVALID", "Pri GPT header"); |
359 } | 365 } |
360 | 366 |
361 printf(GPT_FMT, (int)(GPT_PMBR_SECTOR + GPT_HEADER_SECTOR), | 367 printf(GPT_FMT, (int)(GPT_PMBR_SECTOR + GPT_HEADER_SECTOR), |
362 (int)GPT_ENTRIES_SECTORS, | 368 (int)GPT_ENTRIES_SECTORS, |
(...skipping 30 matching lines...) Expand all Loading... |
393 * 2. secondary is not synonymous to primary. | 399 * 2. secondary is not synonymous to primary. |
394 */ | 400 */ |
395 if ((drive.gpt.valid_headers & MASK_SECONDARY) && | 401 if ((drive.gpt.valid_headers & MASK_SECONDARY) && |
396 (!(drive.gpt.valid_headers & MASK_PRIMARY) || | 402 (!(drive.gpt.valid_headers & MASK_PRIMARY) || |
397 !IsSynonymous((GptHeader*)drive.gpt.primary_header, | 403 !IsSynonymous((GptHeader*)drive.gpt.primary_header, |
398 (GptHeader*)drive.gpt.secondary_header))) { | 404 (GptHeader*)drive.gpt.secondary_header))) { |
399 if (verbose) { | 405 if (verbose) { |
400 GptHeader *header; | 406 GptHeader *header; |
401 char indent[64]; | 407 char indent[64]; |
402 | 408 |
403 snprintf(indent, sizeof(indent), GPT_MORE); | 409 require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent)); |
404 header = (GptHeader*)drive.gpt.secondary_header; | 410 header = (GptHeader*)drive.gpt.secondary_header; |
405 HeaderDetails(header, indent, numeric); | 411 HeaderDetails(header, indent, numeric); |
406 } | 412 } |
407 } | 413 } |
408 } | 414 } |
409 | 415 |
410 (void) CheckValid(&drive); | 416 (void) CheckValid(&drive); |
411 (void) DriveClose(&drive, 0); | 417 (void) DriveClose(&drive, 0); |
412 | 418 |
413 return CGPT_OK; | 419 return CGPT_OK; |
414 } | 420 } |
415 | |
416 | |
417 | |
OLD | NEW |