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