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