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 inline gpt_partition
*
55 return (gpt_partition
*)&part_array
[i
* part_entry_len
];
59 gpt_crc32(void *buf
, int len
)
61 return ~crc32_block_endian0(0xffffffff, buf
, len
, global_crc32_table
);
65 gpt_print_guid(uint8_t *buf
)
68 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
69 buf
[3], buf
[2], buf
[1], buf
[0],
73 buf
[10], buf
[11], buf
[12], buf
[13], buf
[14], buf
[15]);
76 /* TODO: real unicode support */
78 gpt_print_wide(uint16_t *s
, int max_len
)
91 gpt_list_table(int xtra UNUSED_PARAM
)
98 smart_ulltoa5((unsigned long long)total_number_of_sectors
* sector_size
,
99 numstr6
, " KMGTPEZY");
100 printf("Disk %s: %llu sectors, %s\n", disk_device
,
101 (unsigned long long)total_number_of_sectors
,
103 printf("Logical sector size: %u\n", sector_size
);
104 printf("Disk identifier (GUID): ");
105 gpt_print_guid(gpt_hdr
->disk_guid
);
106 printf("\nPartition table holds up to %u entries\n",
107 (int)SWAP_LE32(gpt_hdr
->n_parts
));
108 printf("First usable sector is %llu, last usable sector is %llu\n\n",
109 (unsigned long long)SWAP_LE64(gpt_hdr
->first_usable_lba
),
110 (unsigned long long)SWAP_LE64(gpt_hdr
->last_usable_lba
));
112 printf("Number Start (sector) End (sector) Size Code Name\n");
113 for (i
= 0; i
< n_parts
; i
++) {
114 gpt_partition
*p
= gpt_part(i
);
116 smart_ulltoa5((1 + SWAP_LE64(p
->lba_end
)
117 - SWAP_LE64(p
->lba_start
)) * sector_size
,
118 numstr6
, " KMGTPEZY");
119 printf("%4u %15llu %15llu %11s %04x ",
121 (unsigned long long)SWAP_LE64(p
->lba_start
),
122 (unsigned long long)SWAP_LE64(p
->lba_end
),
125 gpt_print_wide(p
->name
, 18);
132 check_gpt_label(void)
134 struct partition
*first
= pt_offset(MBRbuffer
, 0);
138 /* LBA 0 contains the legacy MBR */
140 if (!valid_part_table_flag(MBRbuffer
)
141 || first
->sys_ind
!= LEGACY_GPT_TYPE
143 current_label_type
= 0;
147 /* LBA 1 contains the GPT header */
150 gpt_hdr
= (void *)pe
.sectorbuffer
;
152 if (gpt_hdr
->magic
!= SWAP_LE64(GPT_MAGIC
)) {
153 current_label_type
= 0;
157 if (!global_crc32_table
) {
158 global_crc32_table
= crc32_filltable(NULL
, 0);
161 crc
= SWAP_LE32(gpt_hdr
->hdr_crc32
);
162 gpt_hdr
->hdr_crc32
= 0;
163 if (gpt_crc32(gpt_hdr
, SWAP_LE32(gpt_hdr
->hdr_size
)) != crc
) {
164 /* FIXME: read the backup table */
165 puts("\nwarning: GPT header CRC is invalid\n");
168 n_parts
= SWAP_LE32(gpt_hdr
->n_parts
);
169 part_entry_len
= SWAP_LE32(gpt_hdr
->part_entry_len
);
170 if (n_parts
> GPT_MAX_PARTS
171 || part_entry_len
> GPT_MAX_PART_ENTRY_LEN
172 || SWAP_LE32(gpt_hdr
->hdr_size
) > sector_size
174 puts("\nwarning: unable to parse GPT disklabel\n");
175 current_label_type
= 0;
179 part_array_len
= n_parts
* part_entry_len
;
180 part_array
= xmalloc(part_array_len
);
181 seek_sector(SWAP_LE64(gpt_hdr
->first_part_lba
));
182 if (full_read(dev_fd
, part_array
, part_array_len
) != part_array_len
) {
183 fdisk_fatal(unable_to_read
);
186 if (gpt_crc32(part_array
, part_array_len
) != gpt_hdr
->part_array_crc32
) {
187 /* FIXME: read the backup table */
188 puts("\nwarning: GPT array CRC is invalid\n");
191 puts("Found valid GPT with protective MBR; using GPT\n");
193 current_label_type
= LABEL_GPT
;
197 #endif /* GPT_LABEL */