1 #if ENABLE_FEATURE_GPT_LABEL
3 * Copyright (C) 2010 Kevin Cernekee <cernekee@gmail.com>
5 * Licensed under GPLv2, see file LICENSE in this source tree.
8 #define GPT_MAGIC 0x5452415020494645ULL
10 LEGACY_GPT_TYPE = 0xee,
12 GPT_MAX_PART_ENTRY_LEN = 4096,
24 uint64_t first_usable_lba;
25 uint64_t last_usable_lba;
26 uint8_t disk_guid[GUID_LEN];
27 uint64_t first_part_lba;
29 uint32_t part_entry_len;
30 uint32_t part_array_crc32;
34 uint8_t type_guid[GUID_LEN];
35 uint8_t part_guid[GUID_LEN];
42 static gpt_header *gpt_hdr;
44 static char *part_array;
45 static unsigned int n_parts;
46 static unsigned int part_array_len;
47 static unsigned int part_entry_len;
49 static uint32_t *crc32_table;
51 static inline gpt_partition *
57 return (gpt_partition *)&part_array[i * part_entry_len];
60 /* TODO: move to libbb */
62 gpt_crc32(void *buf, int len)
64 uint32_t crc = 0xffffffff;
66 for (; len > 0; len--, buf++) {
67 crc = crc32_table[(crc ^ *((char *)buf)) & 0xff] ^ (crc >> 8);
69 return crc ^ 0xffffffff;
73 gpt_print_guid(uint8_t *buf)
76 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
77 buf[3], buf[2], buf[1], buf[0],
81 buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
84 /* TODO: real unicode support */
86 gpt_print_wide(uint16_t *s, int max_len)
99 gpt_list_table(int xtra UNUSED_PARAM)
106 smart_ulltoa5(total_number_of_sectors, numstr6, " KMGTPEZY");
107 printf("Disk %s: %llu sectors, %s\n", disk_device,
108 (unsigned long long)total_number_of_sectors,
110 printf("Logical sector size: %u\n", sector_size);
111 printf("Disk identifier (GUID): ");
112 gpt_print_guid(gpt_hdr->disk_guid);
113 printf("\nPartition table holds up to %u entries\n",
114 (int)SWAP_LE32(gpt_hdr->n_parts));
115 printf("First usable sector is %llu, last usable sector is %llu\n\n",
116 (unsigned long long)SWAP_LE64(gpt_hdr->first_usable_lba),
117 (unsigned long long)SWAP_LE64(gpt_hdr->last_usable_lba));
119 printf("Number Start (sector) End (sector) Size Code Name\n");
120 for (i = 0; i < n_parts; i++) {
121 gpt_partition *p = gpt_part(i);
123 smart_ulltoa5(1 + SWAP_LE64(p->lba_end) - SWAP_LE64(p->lba_start),
124 numstr6, " KMGTPEZY");
125 printf("%4u %15llu %15llu %11s %04x ",
127 (unsigned long long)SWAP_LE64(p->lba_start),
128 (unsigned long long)SWAP_LE64(p->lba_end),
131 gpt_print_wide(p->name, 18);
138 check_gpt_label(void)
140 struct partition *first = pt_offset(MBRbuffer, 0);
144 /* LBA 0 contains the legacy MBR */
146 if (!valid_part_table_flag(MBRbuffer)
147 || first->sys_ind != LEGACY_GPT_TYPE
149 current_label_type = 0;
153 /* LBA 1 contains the GPT header */
156 gpt_hdr = (void *)pe.sectorbuffer;
158 if (gpt_hdr->magic != SWAP_LE64(GPT_MAGIC)) {
159 current_label_type = 0;
164 crc32_table = crc32_filltable(NULL, 0);
167 crc = SWAP_LE32(gpt_hdr->hdr_crc32);
168 gpt_hdr->hdr_crc32 = 0;
169 if (gpt_crc32(gpt_hdr, SWAP_LE32(gpt_hdr->hdr_size)) != crc) {
170 /* FIXME: read the backup table */
171 puts("\nwarning: GPT header CRC is invalid\n");
174 n_parts = SWAP_LE32(gpt_hdr->n_parts);
175 part_entry_len = SWAP_LE32(gpt_hdr->part_entry_len);
176 if (n_parts > GPT_MAX_PARTS
177 || part_entry_len > GPT_MAX_PART_ENTRY_LEN
178 || SWAP_LE32(gpt_hdr->hdr_size) > sector_size
180 puts("\nwarning: unable to parse GPT disklabel\n");
181 current_label_type = 0;
185 part_array_len = n_parts * part_entry_len;
186 part_array = xmalloc(part_array_len);
187 seek_sector(SWAP_LE64(gpt_hdr->first_part_lba));
188 if (full_read(dev_fd, part_array, part_array_len) != part_array_len) {
189 fdisk_fatal(unable_to_read);
192 if (gpt_crc32(part_array, part_array_len) != gpt_hdr->part_array_crc32) {
193 /* FIXME: read the backup table */
194 puts("\nwarning: GPT array CRC is invalid\n");
197 puts("Found valid GPT with protective MBR; using GPT\n");
199 current_label_type = LABEL_GPT;
203 #endif /* GPT_LABEL */