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 * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c | 5 * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c |
6 * files for more details. | 6 * files for more details. |
7 */ | 7 */ |
8 /* To compile on host without compatility to BSD, we include | 8 /* To compile on host without compatility to BSD, we include |
9 * endian.h under chroot. */ | 9 * endian.h under chroot. */ |
10 #define _BSD_SOURCE | 10 #define _BSD_SOURCE |
(...skipping 20 matching lines...) Expand all Loading... |
31 | 31 |
32 /* For usage print */ | 32 /* For usage print */ |
33 const char* progname; | 33 const char* progname; |
34 | 34 |
35 /* Lists all command here. */ | 35 /* Lists all command here. */ |
36 struct { | 36 struct { |
37 const char *name; | 37 const char *name; |
38 int (*fp)(int argc, char *argv[]); | 38 int (*fp)(int argc, char *argv[]); |
39 const char *comment; | 39 const char *comment; |
40 } cmds[] = { | 40 } cmds[] = { |
| 41 {"add", CgptAdm, "Add a partition to drive"}, |
| 42 {"delete", CgptAdm, "Delete a partition on drive"}, |
| 43 {"modify", CgptAdm, "Modify the partition on drive"}, |
41 {"attribute", CgptAttribute, "Update GPT attribute bits " | 44 {"attribute", CgptAttribute, "Update GPT attribute bits " |
42 "(for ChromeOS kernel entry only)"}, | 45 "(for ChromeOS kernel entry only)"}, |
| 46 {"dev", CgptDev, "Developper mode"}, |
43 {"repair", CgptRepair, "Repair primary and secondary headers and tables"}, | 47 {"repair", CgptRepair, "Repair primary and secondary headers and tables"}, |
44 {"show", CgptShow, "Show partition details"}, | 48 {"show", CgptShow, "Show partition details"}, |
45 }; | 49 }; |
46 | 50 |
47 /* Shows main menu. If 'message' is non-NULL, shows it as header. Then, this | 51 /* Shows main menu. If 'message' is non-NULL, shows it as header. Then, this |
48 * traverses cmds[] and shows supported commands and their comments. */ | 52 * traverses cmds[] and shows supported commands and their comments. */ |
49 void Usage(const char *message) { | 53 void Usage(const char *message) { |
50 int i; | 54 int i; |
51 | 55 |
52 if (message) printf("%s\n", message); | 56 if (message) printf("%s\n", message); |
53 printf("Usage: %s COMMAND [OPTIONS]\n\n" | 57 printf("Usage: %s COMMAND [OPTIONS]\n\n" |
54 "Supported commands:\n\n", | 58 "Supported COMMANDs:\n\n", |
55 progname); | 59 progname); |
56 for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) { | 60 for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) { |
57 printf(" %-10s %s\n", cmds[i].name, cmds[i].comment); | 61 printf(" %-10s %s\n", cmds[i].name, cmds[i].comment); |
58 } | 62 } |
59 printf("\nFor more detailed usage, use %s COMMAND --help.\n\n", progname); | 63 printf("\nFor more detailed usage, use %s COMMAND --help.\n\n", progname); |
60 } | 64 } |
61 | 65 |
62 /* GUID conversion functions. Accepted format: | 66 /* GUID conversion functions. Accepted format: |
63 * | 67 * |
64 * "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" | 68 * "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" |
| 69 * |
| 70 * Returns CGPT_OK if parsing is successful; otherwise CGPT_FAILED. |
65 */ | 71 */ |
66 void StrToGuid(const char *str, Guid *guid) { | 72 int StrToGuid(const char *str, Guid *guid) { |
67 uint32_t time_low, time_mid, time_high_and_version; | 73 uint32_t time_low, time_mid, time_high_and_version; |
68 | 74 |
69 sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", | 75 if (11 > sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", |
70 &time_low, | 76 &time_low, |
71 (unsigned int *)&time_mid, | 77 (unsigned int *)&time_mid, |
72 (unsigned int *)&time_high_and_version, | 78 (unsigned int *)&time_high_and_version, |
73 (unsigned int *)&guid->u.Uuid.clock_seq_high_and_reserved, | 79 (unsigned int *)&guid->u.Uuid.clock_seq_high_and_reserved, |
74 (unsigned int *)&guid->u.Uuid.clock_seq_low, | 80 (unsigned int *)&guid->u.Uuid.clock_seq_low, |
75 (unsigned int *)&guid->u.Uuid.node[0], | 81 (unsigned int *)&guid->u.Uuid.node[0], |
76 (unsigned int *)&guid->u.Uuid.node[1], | 82 (unsigned int *)&guid->u.Uuid.node[1], |
77 (unsigned int *)&guid->u.Uuid.node[2], | 83 (unsigned int *)&guid->u.Uuid.node[2], |
78 (unsigned int *)&guid->u.Uuid.node[3], | 84 (unsigned int *)&guid->u.Uuid.node[3], |
79 (unsigned int *)&guid->u.Uuid.node[4], | 85 (unsigned int *)&guid->u.Uuid.node[4], |
80 (unsigned int *)&guid->u.Uuid.node[5]); | 86 (unsigned int *)&guid->u.Uuid.node[5])) return CGPT_FAILED; |
81 | 87 |
82 guid->u.Uuid.time_low = htole32(time_low); | 88 guid->u.Uuid.time_low = htole32(time_low); |
83 guid->u.Uuid.time_mid = htole16(time_mid); | 89 guid->u.Uuid.time_mid = htole16(time_mid); |
84 guid->u.Uuid.time_high_and_version = htole16(time_high_and_version); | 90 guid->u.Uuid.time_high_and_version = htole16(time_high_and_version); |
| 91 |
| 92 return CGPT_OK; |
85 } | 93 } |
86 | 94 |
87 void GuidToStr(const Guid *guid, char *str) { | 95 void GuidToStr(const Guid *guid, char *str) { |
88 sprintf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", | 96 sprintf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", |
89 le32toh(guid->u.Uuid.time_low), le16toh(guid->u.Uuid.time_mid), | 97 le32toh(guid->u.Uuid.time_low), le16toh(guid->u.Uuid.time_mid), |
90 le16toh(guid->u.Uuid.time_high_and_version), | 98 le16toh(guid->u.Uuid.time_high_and_version), |
91 guid->u.Uuid.clock_seq_high_and_reserved, guid->u.Uuid.clock_seq_low, | 99 guid->u.Uuid.clock_seq_high_and_reserved, guid->u.Uuid.clock_seq_low, |
92 guid->u.Uuid.node[0], guid->u.Uuid.node[1], guid->u.Uuid.node[2], | 100 guid->u.Uuid.node[0], guid->u.Uuid.node[1], guid->u.Uuid.node[2], |
93 guid->u.Uuid.node[3], guid->u.Uuid.node[4], guid->u.Uuid.node[5]); | 101 guid->u.Uuid.node[3], guid->u.Uuid.node[4], guid->u.Uuid.node[5]); |
94 } | 102 } |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 utf16[s16idx++] = htole16(0xdc00 | (utfchar & 0x3ff)); | 195 utf16[s16idx++] = htole16(0xdc00 | (utfchar & 0x3ff)); |
188 } else { | 196 } else { |
189 utf16[s16idx++] = htole16(utfchar); | 197 utf16[s16idx++] = htole16(utfchar); |
190 } | 198 } |
191 } | 199 } |
192 } while (c != 0 && s16idx < SIZEOF_GPTENTRY_NAME); | 200 } while (c != 0 && s16idx < SIZEOF_GPTENTRY_NAME); |
193 if (s16idx < SIZEOF_GPTENTRY_NAME) | 201 if (s16idx < SIZEOF_GPTENTRY_NAME) |
194 utf16[s16idx++] = 0; | 202 utf16[s16idx++] = 0; |
195 } | 203 } |
196 | 204 |
| 205 struct { |
| 206 Guid type; |
| 207 char *name; |
| 208 char *description; |
| 209 } supported_types[] = { |
| 210 {GPT_ENT_TYPE_UNUSED, "unused", "Unused partition"}, |
| 211 {GPT_ENT_TYPE_EFI, "efi", "EFI partition"}, |
| 212 {GPT_ENT_TYPE_CHROMEOS_KERNEL, "croskern", "ChromeOS kernel"}, |
| 213 {GPT_ENT_TYPE_CHROMEOS_ROOTFS, "crosroot", "ChromeOS rootfs"}, |
| 214 {GPT_ENT_TYPE_CHROMEOS_RESERVED, "crosresv", "ChromeOS reserved"}, |
| 215 }; |
| 216 |
| 217 /* Resolves human-readable GPT type. |
| 218 * Returns CGPT_OK if found. |
| 219 * Returns CGPT_FAILED if no known type found. */ |
| 220 int ResolveType(const Guid *type, char *buf) { |
| 221 int i; |
| 222 for (i = 0; i < ARRAY_COUNT(supported_types); ++i) { |
| 223 if (!Memcmp(type, &supported_types[i].type, sizeof(Guid))) { |
| 224 strcpy(buf, supported_types[i].description); |
| 225 return CGPT_OK; |
| 226 } |
| 227 } |
| 228 return CGPT_FAILED; |
| 229 } |
| 230 |
| 231 int SupportedType(const char *name, Guid *type) { |
| 232 int i; |
| 233 for (i = 0; i < ARRAY_COUNT(supported_types); ++i) { |
| 234 if (!strcmp(name, supported_types[i].name)) { |
| 235 Memcpy(type, &supported_types[i].type, sizeof(Guid)); |
| 236 return CGPT_OK; |
| 237 } |
| 238 } |
| 239 return CGPT_FAILED; |
| 240 } |
| 241 |
| 242 void PrintTypes(void) { |
| 243 int i; |
| 244 printf("\n* For --type option, you can use the following alias, " |
| 245 "instead of hex values:\n"); |
| 246 for (i = 0; i < ARRAY_COUNT(supported_types); ++i) { |
| 247 printf(" %-10s %s\n", supported_types[i].name, |
| 248 supported_types[i].description); |
| 249 } |
| 250 printf("\n"); |
| 251 } |
| 252 |
197 /* Loads sectors from 'fd'. | 253 /* Loads sectors from 'fd'. |
198 * *buf is pointed to an allocated memory when returned, and should be | 254 * *buf is pointed to an allocated memory when returned, and should be |
199 * freed by cgpt_close(). | 255 * freed by cgpt_close(). |
200 * | 256 * |
201 * fd -- file descriptot. | 257 * fd -- file descriptot. |
202 * buf -- pointer to buffer pointer | 258 * buf -- pointer to buffer pointer |
203 * sector -- offset of starting sector (in sectors) | 259 * sector -- offset of starting sector (in sectors) |
204 * sector_bytes -- bytes per sector | 260 * sector_bytes -- bytes per sector |
205 * sector_count -- number of sectors to load | 261 * sector_count -- number of sectors to load |
206 * | 262 * |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 if (nwrote < count) | 316 if (nwrote < count) |
261 return CGPT_FAILED; | 317 return CGPT_FAILED; |
262 | 318 |
263 return CGPT_OK; | 319 return CGPT_OK; |
264 } | 320 } |
265 | 321 |
266 int CheckValid(const struct drive *drive) { | 322 int CheckValid(const struct drive *drive) { |
267 if ((drive->gpt.valid_headers != MASK_BOTH) || | 323 if ((drive->gpt.valid_headers != MASK_BOTH) || |
268 (drive->gpt.valid_entries != MASK_BOTH)) { | 324 (drive->gpt.valid_entries != MASK_BOTH)) { |
269 printf("\n[ERROR] any of GPT header/entries is invalid, " | 325 printf("\n[ERROR] any of GPT header/entries is invalid, " |
270 "please run --repair first\n"); | 326 "please run '%s repair' first\n", progname); |
271 return CGPT_FAILED; | 327 return CGPT_FAILED; |
272 } | 328 } |
273 return CGPT_OK; | 329 return CGPT_OK; |
274 } | 330 } |
275 | 331 |
276 /* Opens a block device (a regular file works well too). | 332 /* Opens a block device (a regular file works well too). |
277 * | 333 * |
278 * Returns CGPT_FAILED if any error happens. | 334 * Returns CGPT_FAILED if any error happens. |
279 * Returns CGPT_OK if success and information are stored in 'drive'. */ | 335 * Returns CGPT_OK if success and information are stored in 'drive'. */ |
280 int DriveOpen(const char *drive_path, struct drive *drive) { | 336 int DriveOpen(const char *drive_path, struct drive *drive) { |
(...skipping 28 matching lines...) Expand all Loading... |
309 } else { | 365 } else { |
310 drive->gpt.sector_bytes = 512; /* bytes */ | 366 drive->gpt.sector_bytes = 512; /* bytes */ |
311 drive->size = stat.st_size; | 367 drive->size = stat.st_size; |
312 } | 368 } |
313 if (drive->size % drive->gpt.sector_bytes) { | 369 if (drive->size % drive->gpt.sector_bytes) { |
314 printf("[ERROR] Media size (%llu) is not the multiple of sector size(%d)\n", | 370 printf("[ERROR] Media size (%llu) is not the multiple of sector size(%d)\n", |
315 (long long unsigned int)drive->size, drive->gpt.sector_bytes); | 371 (long long unsigned int)drive->size, drive->gpt.sector_bytes); |
316 goto error_close; | 372 goto error_close; |
317 } | 373 } |
318 drive->gpt.drive_sectors = drive->size / drive->gpt.sector_bytes; | 374 drive->gpt.drive_sectors = drive->size / drive->gpt.sector_bytes; |
319 debug("drive: size:%llu sector_size:%d num_sector:%llu\n", | |
320 (long long unsigned int)drive->size, drive->gpt.sector_bytes, | |
321 (long long unsigned int)drive->gpt.drive_sectors); | |
322 | 375 |
323 Load(drive->fd, &drive->gpt.primary_header, GPT_PMBR_SECTOR, | 376 Load(drive->fd, &drive->gpt.primary_header, GPT_PMBR_SECTOR, |
324 drive->gpt.sector_bytes, GPT_HEADER_SECTOR); | 377 drive->gpt.sector_bytes, GPT_HEADER_SECTOR); |
325 Load(drive->fd, &drive->gpt.secondary_header, | 378 Load(drive->fd, &drive->gpt.secondary_header, |
326 drive->gpt.drive_sectors - GPT_PMBR_SECTOR, | 379 drive->gpt.drive_sectors - GPT_PMBR_SECTOR, |
327 drive->gpt.sector_bytes, GPT_HEADER_SECTOR); | 380 drive->gpt.sector_bytes, GPT_HEADER_SECTOR); |
328 Load(drive->fd, &drive->gpt.primary_entries, | 381 Load(drive->fd, &drive->gpt.primary_entries, |
329 GPT_PMBR_SECTOR + GPT_HEADER_SECTOR, | 382 GPT_PMBR_SECTOR + GPT_HEADER_SECTOR, |
330 drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS); | 383 drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS); |
331 Load(drive->fd, &drive->gpt.secondary_entries, | 384 Load(drive->fd, &drive->gpt.secondary_entries, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 | 436 |
384 drive->inited = 0; | 437 drive->inited = 0; |
385 return CGPT_OK; | 438 return CGPT_OK; |
386 } | 439 } |
387 | 440 |
388 int main(int argc, char *argv[]) { | 441 int main(int argc, char *argv[]) { |
389 char *cmd; | 442 char *cmd; |
390 int i; | 443 int i; |
391 | 444 |
392 progname = argv[0]; | 445 progname = argv[0]; |
| 446 printf("Copyright (c) 2010 The Chromium OS Authors. All rights reserved.\n"); |
393 cmd = argv[optind++]; | 447 cmd = argv[optind++]; |
394 for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) { | 448 for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) { |
395 if (cmd && !strcmp(cmds[i].name, cmd)) | 449 if (cmd && !strcmp(cmds[i].name, cmd)) |
396 return cmds[i].fp(argc, argv); | 450 return cmds[i].fp(argc, argv); |
397 } | 451 } |
398 | 452 |
399 Usage(0); | 453 Usage(0); |
400 return CGPT_FAILED; | 454 return CGPT_FAILED; |
401 } | 455 } |
OLD | NEW |