| 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 |