fdisk_gpt.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #if ENABLE_FEATURE_GPT_LABEL
  2. /*
  3. * Copyright (C) 2010 Kevin Cernekee <cernekee@gmail.com>
  4. *
  5. * Licensed under GPLv2, see file LICENSE in this source tree.
  6. */
  7. #define GPT_MAGIC 0x5452415020494645ULL
  8. enum {
  9. LEGACY_GPT_TYPE = 0xee,
  10. GPT_MAX_PARTS = 256,
  11. GPT_MAX_PART_ENTRY_LEN = 4096,
  12. GUID_LEN = 16,
  13. };
  14. typedef struct {
  15. uint64_t magic;
  16. uint32_t revision;
  17. uint32_t hdr_size;
  18. uint32_t hdr_crc32;
  19. uint32_t reserved;
  20. uint64_t current_lba;
  21. uint64_t backup_lba;
  22. uint64_t first_usable_lba;
  23. uint64_t last_usable_lba;
  24. uint8_t disk_guid[GUID_LEN];
  25. uint64_t first_part_lba;
  26. uint32_t n_parts;
  27. uint32_t part_entry_len;
  28. uint32_t part_array_crc32;
  29. } gpt_header;
  30. typedef struct {
  31. uint8_t type_guid[GUID_LEN];
  32. uint8_t part_guid[GUID_LEN];
  33. uint64_t lba_start;
  34. uint64_t lba_end;
  35. uint64_t flags;
  36. uint16_t name[36];
  37. } gpt_partition;
  38. static gpt_header *gpt_hdr;
  39. static char *part_array;
  40. static unsigned int n_parts;
  41. static unsigned int part_array_len;
  42. static unsigned int part_entry_len;
  43. static inline gpt_partition *
  44. gpt_part(int i)
  45. {
  46. if (i >= n_parts) {
  47. return NULL;
  48. }
  49. return (gpt_partition *)&part_array[i * part_entry_len];
  50. }
  51. static uint32_t
  52. gpt_crc32(void *buf, int len)
  53. {
  54. return ~crc32_block_endian0(0xffffffff, buf, len, global_crc32_table);
  55. }
  56. static void
  57. gpt_print_guid(uint8_t *buf)
  58. {
  59. printf(
  60. "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  61. buf[3], buf[2], buf[1], buf[0],
  62. buf[5], buf[4],
  63. buf[7], buf[6],
  64. buf[8], buf[9],
  65. buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
  66. }
  67. /* TODO: real unicode support */
  68. static void
  69. gpt_print_wide(uint16_t *s, int max_len)
  70. {
  71. int i = 0;
  72. while (i < max_len) {
  73. if (*s == 0)
  74. return;
  75. fputc(*s, stdout);
  76. s++;
  77. }
  78. }
  79. static void
  80. gpt_list_table(int xtra UNUSED_PARAM)
  81. {
  82. int i;
  83. char numstr6[6];
  84. smart_ulltoa5(total_number_of_sectors * sector_size, numstr6, " KMGTPEZY")[0] = '\0';
  85. printf("Disk %s: %llu sectors, %s\n", disk_device,
  86. (unsigned long long)total_number_of_sectors,
  87. numstr6);
  88. printf("Logical sector size: %u\n", sector_size);
  89. printf("Disk identifier (GUID): ");
  90. gpt_print_guid(gpt_hdr->disk_guid);
  91. printf("\nPartition table holds up to %u entries\n",
  92. (int)SWAP_LE32(gpt_hdr->n_parts));
  93. printf("First usable sector is %llu, last usable sector is %llu\n\n",
  94. (unsigned long long)SWAP_LE64(gpt_hdr->first_usable_lba),
  95. (unsigned long long)SWAP_LE64(gpt_hdr->last_usable_lba));
  96. puts("Number Start (sector) End (sector) Size Code Name");
  97. for (i = 0; i < n_parts; i++) {
  98. gpt_partition *p = gpt_part(i);
  99. if (p->lba_start) {
  100. smart_ulltoa5((1 + SWAP_LE64(p->lba_end) - SWAP_LE64(p->lba_start)) * sector_size,
  101. numstr6, " KMGTPEZY")[0] = '\0';
  102. printf("%4u %15llu %15llu %11s %04x ",
  103. i + 1,
  104. (unsigned long long)SWAP_LE64(p->lba_start),
  105. (unsigned long long)SWAP_LE64(p->lba_end),
  106. numstr6,
  107. 0x0700 /* FIXME */);
  108. gpt_print_wide(p->name, 18);
  109. bb_putchar('\n');
  110. }
  111. }
  112. }
  113. static int
  114. check_gpt_label(void)
  115. {
  116. struct partition *first = pt_offset(MBRbuffer, 0);
  117. struct pte pe;
  118. uint32_t crc;
  119. /* LBA 0 contains the legacy MBR */
  120. if (!valid_part_table_flag(MBRbuffer)
  121. || first->sys_ind != LEGACY_GPT_TYPE
  122. ) {
  123. current_label_type = 0;
  124. return 0;
  125. }
  126. /* LBA 1 contains the GPT header */
  127. read_pte(&pe, 1);
  128. gpt_hdr = (void *)pe.sectorbuffer;
  129. if (gpt_hdr->magic != SWAP_LE64(GPT_MAGIC)) {
  130. current_label_type = 0;
  131. return 0;
  132. }
  133. if (!global_crc32_table) {
  134. global_crc32_table = crc32_filltable(NULL, 0);
  135. }
  136. crc = SWAP_LE32(gpt_hdr->hdr_crc32);
  137. gpt_hdr->hdr_crc32 = 0;
  138. if (gpt_crc32(gpt_hdr, SWAP_LE32(gpt_hdr->hdr_size)) != crc) {
  139. /* FIXME: read the backup table */
  140. puts("\nwarning: GPT header CRC is invalid\n");
  141. }
  142. n_parts = SWAP_LE32(gpt_hdr->n_parts);
  143. part_entry_len = SWAP_LE32(gpt_hdr->part_entry_len);
  144. if (n_parts > GPT_MAX_PARTS
  145. || part_entry_len > GPT_MAX_PART_ENTRY_LEN
  146. || SWAP_LE32(gpt_hdr->hdr_size) > sector_size
  147. ) {
  148. puts("\nwarning: unable to parse GPT disklabel\n");
  149. current_label_type = 0;
  150. return 0;
  151. }
  152. part_array_len = n_parts * part_entry_len;
  153. part_array = xmalloc(part_array_len);
  154. seek_sector(SWAP_LE64(gpt_hdr->first_part_lba));
  155. if (full_read(dev_fd, part_array, part_array_len) != part_array_len) {
  156. fdisk_fatal(unable_to_read);
  157. }
  158. if (gpt_crc32(part_array, part_array_len) != gpt_hdr->part_array_crc32) {
  159. /* FIXME: read the backup table */
  160. puts("\nwarning: GPT array CRC is invalid\n");
  161. }
  162. puts("Found valid GPT with protective MBR; using GPT\n");
  163. current_label_type = LABEL_GPT;
  164. return 1;
  165. }
  166. #endif /* GPT_LABEL */