diff options
| author | Kevin Cernekee <cernekee@gmail.com> | 2010-10-25 02:00:24 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-10-25 02:00:24 +0200 |
| commit | ccb070450e79c33fb3f755dbea2fdd979f09d3fb (patch) | |
| tree | ed842febd5fa0b19bbb7e42d2d98d59f6e3c5c8d | |
| parent | 3b060528a26830ee26aab4e9829ac3a310f06218 (diff) | |
| download | busybox-w32-ccb070450e79c33fb3f755dbea2fdd979f09d3fb.tar.gz busybox-w32-ccb070450e79c33fb3f755dbea2fdd979f09d3fb.tar.bz2 busybox-w32-ccb070450e79c33fb3f755dbea2fdd979f09d3fb.zip | |
fdisk: initial stab at GPT partition support
Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | include/libbb.h | 7 | ||||
| -rw-r--r-- | libbb/human_readable.c | 4 | ||||
| -rw-r--r-- | util-linux/Config.src | 8 | ||||
| -rw-r--r-- | util-linux/fdisk.c | 79 | ||||
| -rw-r--r-- | util-linux/fdisk_gpt.c | 203 |
5 files changed, 275 insertions, 26 deletions
diff --git a/include/libbb.h b/include/libbb.h index bd1d586c7..d14728ed0 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
| @@ -746,7 +746,7 @@ char *itoa(int n) FAST_FUNC; | |||
| 746 | char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) FAST_FUNC; | 746 | char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) FAST_FUNC; |
| 747 | char *itoa_to_buf(int n, char *buf, unsigned buflen) FAST_FUNC; | 747 | char *itoa_to_buf(int n, char *buf, unsigned buflen) FAST_FUNC; |
| 748 | /* Intelligent formatters of bignums */ | 748 | /* Intelligent formatters of bignums */ |
| 749 | void smart_ulltoa4(unsigned long long ul, char buf[5], const char *scale) FAST_FUNC; | 749 | void smart_ulltoa4(unsigned long long ul, char buf[4], const char *scale) FAST_FUNC; |
| 750 | void smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) FAST_FUNC; | 750 | void smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) FAST_FUNC; |
| 751 | /* If block_size == 0, display size without fractional part, | 751 | /* If block_size == 0, display size without fractional part, |
| 752 | * else display (size * block_size) with one decimal digit. | 752 | * else display (size * block_size) with one decimal digit. |
| @@ -1543,7 +1543,10 @@ void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC; | |||
| 1543 | void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; | 1543 | void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; |
| 1544 | void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; | 1544 | void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; |
| 1545 | 1545 | ||
| 1546 | 1546 | /* TODO: add global crc32_table pointer and create | |
| 1547 | * LE and BE functions to calculate crc32 over given bytes. | ||
| 1548 | * Currently we have about five reimplementations... | ||
| 1549 | */ | ||
| 1547 | uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; | 1550 | uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; |
| 1548 | 1551 | ||
| 1549 | typedef struct masks_labels_t { | 1552 | typedef struct masks_labels_t { |
diff --git a/libbb/human_readable.c b/libbb/human_readable.c index 22dc5d23f..50cbe41bb 100644 --- a/libbb/human_readable.c +++ b/libbb/human_readable.c | |||
| @@ -94,7 +94,7 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val, | |||
| 94 | 94 | ||
| 95 | /* Convert unsigned long long value into compact 5-char representation. | 95 | /* Convert unsigned long long value into compact 5-char representation. |
| 96 | * String is not terminated (buf[5] is untouched) */ | 96 | * String is not terminated (buf[5] is untouched) */ |
| 97 | void FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[6], const char *scale) | 97 | void FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) |
| 98 | { | 98 | { |
| 99 | const char *fmt; | 99 | const char *fmt; |
| 100 | char c; | 100 | char c; |
| @@ -150,7 +150,7 @@ void FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[6], const char *sca | |||
| 150 | /* Convert unsigned long long value into compact 4-char | 150 | /* Convert unsigned long long value into compact 4-char |
| 151 | * representation. Examples: "1234", "1.2k", " 27M", "123T" | 151 | * representation. Examples: "1234", "1.2k", " 27M", "123T" |
| 152 | * String is not terminated (buf[4] is untouched) */ | 152 | * String is not terminated (buf[4] is untouched) */ |
| 153 | void FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[5], const char *scale) | 153 | void FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[4], const char *scale) |
| 154 | { | 154 | { |
| 155 | const char *fmt; | 155 | const char *fmt; |
| 156 | char c; | 156 | char c; |
diff --git a/util-linux/Config.src b/util-linux/Config.src index afa30923b..19b309e57 100644 --- a/util-linux/Config.src +++ b/util-linux/Config.src | |||
| @@ -181,6 +181,14 @@ config FEATURE_OSF_LABEL | |||
| 181 | Enabling this option allows you to create or change BSD disklabels | 181 | Enabling this option allows you to create or change BSD disklabels |
| 182 | and define and edit BSD disk slices. | 182 | and define and edit BSD disk slices. |
| 183 | 183 | ||
| 184 | config FEATURE_GPT_LABEL | ||
| 185 | bool "Support GPT disklabels" | ||
| 186 | default n | ||
| 187 | depends on FDISK && FEATURE_FDISK_WRITABLE | ||
| 188 | help | ||
| 189 | Enabling this option allows you to view GUID Partition Table | ||
| 190 | disklabels. | ||
| 191 | |||
| 184 | config FEATURE_FDISK_ADVANCED | 192 | config FEATURE_FDISK_ADVANCED |
| 185 | bool "Support expert mode" | 193 | bool "Support expert mode" |
| 186 | default y | 194 | default y |
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index b6417a355..3f2e0d3ae 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c | |||
| @@ -107,12 +107,30 @@ struct partition { | |||
| 107 | unsigned char size4[4]; /* nr of sectors in partition */ | 107 | unsigned char size4[4]; /* nr of sectors in partition */ |
| 108 | } PACKED; | 108 | } PACKED; |
| 109 | 109 | ||
| 110 | /* | ||
| 111 | * per partition table entry data | ||
| 112 | * | ||
| 113 | * The four primary partitions have the same sectorbuffer (MBRbuffer) | ||
| 114 | * and have NULL ext_pointer. | ||
| 115 | * Each logical partition table entry has two pointers, one for the | ||
| 116 | * partition and one link to the next one. | ||
| 117 | */ | ||
| 118 | struct pte { | ||
| 119 | struct partition *part_table; /* points into sectorbuffer */ | ||
| 120 | struct partition *ext_pointer; /* points into sectorbuffer */ | ||
| 121 | sector_t offset_from_dev_start; /* disk sector number */ | ||
| 122 | char *sectorbuffer; /* disk sector contents */ | ||
| 123 | #if ENABLE_FEATURE_FDISK_WRITABLE | ||
| 124 | char changed; /* boolean */ | ||
| 125 | #endif | ||
| 126 | }; | ||
| 127 | |||
| 110 | #define unable_to_open "can't open '%s'" | 128 | #define unable_to_open "can't open '%s'" |
| 111 | #define unable_to_read "can't read from %s" | 129 | #define unable_to_read "can't read from %s" |
| 112 | #define unable_to_seek "can't seek on %s" | 130 | #define unable_to_seek "can't seek on %s" |
| 113 | 131 | ||
| 114 | enum label_type { | 132 | enum label_type { |
| 115 | LABEL_DOS, LABEL_SUN, LABEL_SGI, LABEL_AIX, LABEL_OSF | 133 | LABEL_DOS, LABEL_SUN, LABEL_SGI, LABEL_AIX, LABEL_OSF, LABEL_GPT |
| 116 | }; | 134 | }; |
| 117 | 135 | ||
| 118 | #define LABEL_IS_DOS (LABEL_DOS == current_label_type) | 136 | #define LABEL_IS_DOS (LABEL_DOS == current_label_type) |
| @@ -149,6 +167,14 @@ enum label_type { | |||
| 149 | #define STATIC_OSF extern | 167 | #define STATIC_OSF extern |
| 150 | #endif | 168 | #endif |
| 151 | 169 | ||
| 170 | #if ENABLE_FEATURE_GPT_LABEL | ||
| 171 | #define LABEL_IS_GPT (LABEL_GPT == current_label_type) | ||
| 172 | #define STATIC_GPT static | ||
| 173 | #else | ||
| 174 | #define LABEL_IS_GPT 0 | ||
| 175 | #define STATIC_GPT extern | ||
| 176 | #endif | ||
| 177 | |||
| 152 | enum action { OPEN_MAIN, TRY_ONLY, CREATE_EMPTY_DOS, CREATE_EMPTY_SUN }; | 178 | enum action { OPEN_MAIN, TRY_ONLY, CREATE_EMPTY_DOS, CREATE_EMPTY_SUN }; |
| 153 | 179 | ||
| 154 | static void update_units(void); | 180 | static void update_units(void); |
| @@ -162,6 +188,7 @@ static sector_t read_int(sector_t low, sector_t dflt, sector_t high, sector_t ba | |||
| 162 | #endif | 188 | #endif |
| 163 | static const char *partition_type(unsigned char type); | 189 | static const char *partition_type(unsigned char type); |
| 164 | static void get_geometry(void); | 190 | static void get_geometry(void); |
| 191 | static void read_pte(struct pte *pe, sector_t offset); | ||
| 165 | #if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE | 192 | #if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE |
| 166 | static int get_boot(enum action what); | 193 | static int get_boot(enum action what); |
| 167 | #else | 194 | #else |
| @@ -174,24 +201,6 @@ static int get_boot(void); | |||
| 174 | static sector_t get_start_sect(const struct partition *p); | 201 | static sector_t get_start_sect(const struct partition *p); |
| 175 | static sector_t get_nr_sects(const struct partition *p); | 202 | static sector_t get_nr_sects(const struct partition *p); |
| 176 | 203 | ||
| 177 | /* | ||
| 178 | * per partition table entry data | ||
| 179 | * | ||
| 180 | * The four primary partitions have the same sectorbuffer (MBRbuffer) | ||
| 181 | * and have NULL ext_pointer. | ||
| 182 | * Each logical partition table entry has two pointers, one for the | ||
| 183 | * partition and one link to the next one. | ||
| 184 | */ | ||
| 185 | struct pte { | ||
| 186 | struct partition *part_table; /* points into sectorbuffer */ | ||
| 187 | struct partition *ext_pointer; /* points into sectorbuffer */ | ||
| 188 | sector_t offset_from_dev_start; /* disk sector number */ | ||
| 189 | char *sectorbuffer; /* disk sector contents */ | ||
| 190 | #if ENABLE_FEATURE_FDISK_WRITABLE | ||
| 191 | char changed; /* boolean */ | ||
| 192 | #endif | ||
| 193 | }; | ||
| 194 | |||
| 195 | /* DOS partition types */ | 204 | /* DOS partition types */ |
| 196 | 205 | ||
| 197 | static const char *const i386_sys_types[] = { | 206 | static const char *const i386_sys_types[] = { |
| @@ -653,6 +662,8 @@ STATIC_OSF void bsd_select(void); | |||
| 653 | STATIC_OSF void xbsd_print_disklabel(int); | 662 | STATIC_OSF void xbsd_print_disklabel(int); |
| 654 | #include "fdisk_osf.c" | 663 | #include "fdisk_osf.c" |
| 655 | 664 | ||
| 665 | #include "fdisk_gpt.c" | ||
| 666 | |||
| 656 | #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL | 667 | #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL |
| 657 | static uint16_t | 668 | static uint16_t |
| 658 | fdisk_swap16(uint16_t x) | 669 | fdisk_swap16(uint16_t x) |
| @@ -833,6 +844,11 @@ menu(void) | |||
| 833 | puts("o\tcreate a new empty DOS partition table"); | 844 | puts("o\tcreate a new empty DOS partition table"); |
| 834 | puts("q\tquit without saving changes"); | 845 | puts("q\tquit without saving changes"); |
| 835 | puts("s\tcreate a new empty Sun disklabel"); /* sun */ | 846 | puts("s\tcreate a new empty Sun disklabel"); /* sun */ |
| 847 | } else if (LABEL_IS_GPT) { | ||
| 848 | puts("o\tcreate a new empty DOS partition table"); | ||
| 849 | puts("p\tprint the partition table"); | ||
| 850 | puts("q\tquit without saving changes"); | ||
| 851 | puts("s\tcreate a new empty Sun disklabel"); /* sun */ | ||
| 836 | } else { | 852 | } else { |
| 837 | puts("a\ttoggle a bootable flag"); | 853 | puts("a\ttoggle a bootable flag"); |
| 838 | puts("b\tedit bsd disklabel"); | 854 | puts("b\tedit bsd disklabel"); |
| @@ -1308,7 +1324,18 @@ get_geometry(void) | |||
| 1308 | 1324 | ||
| 1309 | /* | 1325 | /* |
| 1310 | * Opens disk_device and optionally reads MBR. | 1326 | * Opens disk_device and optionally reads MBR. |
| 1311 | * FIXME: document what each 'what' value will do! | 1327 | * If what == OPEN_MAIN: |
| 1328 | * Open device, read MBR. Abort program on short read. Create empty | ||
| 1329 | * disklabel if the on-disk structure is invalid (WRITABLE mode). | ||
| 1330 | * If what == TRY_ONLY: | ||
| 1331 | * Open device, read MBR. Return an error if anything is out of place. | ||
| 1332 | * Do not create an empty disklabel. This is used for the "list" | ||
| 1333 | * operations: "fdisk -l /dev/sda" and "fdisk -l" (all devices). | ||
| 1334 | * If what == CREATE_EMPTY_*: | ||
| 1335 | * This means that get_boot() was called recursively from create_*label(). | ||
| 1336 | * Do not re-open the device; just set up the ptes array and print | ||
| 1337 | * geometry warnings. | ||
| 1338 | * | ||
| 1312 | * Returns: | 1339 | * Returns: |
| 1313 | * -1: no 0xaa55 flag present (possibly entire disk BSD) | 1340 | * -1: no 0xaa55 flag present (possibly entire disk BSD) |
| 1314 | * 0: found or created label | 1341 | * 0: found or created label |
| @@ -1390,6 +1417,10 @@ static int get_boot(void) | |||
| 1390 | if (check_aix_label()) | 1417 | if (check_aix_label()) |
| 1391 | return 0; | 1418 | return 0; |
| 1392 | #endif | 1419 | #endif |
| 1420 | #if ENABLE_FEATURE_GPT_LABEL | ||
| 1421 | if (check_gpt_label()) | ||
| 1422 | return 0; | ||
| 1423 | #endif | ||
| 1393 | #if ENABLE_FEATURE_OSF_LABEL | 1424 | #if ENABLE_FEATURE_OSF_LABEL |
| 1394 | if (check_osf_label()) { | 1425 | if (check_osf_label()) { |
| 1395 | possibly_osf_label = 1; | 1426 | possibly_osf_label = 1; |
| @@ -1409,7 +1440,7 @@ static int get_boot(void) | |||
| 1409 | if (!valid_part_table_flag(MBRbuffer)) { | 1440 | if (!valid_part_table_flag(MBRbuffer)) { |
| 1410 | if (what == OPEN_MAIN) { | 1441 | if (what == OPEN_MAIN) { |
| 1411 | printf("Device contains neither a valid DOS " | 1442 | printf("Device contains neither a valid DOS " |
| 1412 | "partition table, nor Sun, SGI or OSF " | 1443 | "partition table, nor Sun, SGI, OSF or GPT " |
| 1413 | "disklabel\n"); | 1444 | "disklabel\n"); |
| 1414 | #ifdef __sparc__ | 1445 | #ifdef __sparc__ |
| 1415 | IF_FEATURE_SUN_LABEL(create_sunlabel();) | 1446 | IF_FEATURE_SUN_LABEL(create_sunlabel();) |
| @@ -2056,10 +2087,14 @@ list_table(int xtra) | |||
| 2056 | sun_list_table(xtra); | 2087 | sun_list_table(xtra); |
| 2057 | return; | 2088 | return; |
| 2058 | } | 2089 | } |
| 2059 | if (LABEL_IS_SUN) { | 2090 | if (LABEL_IS_SGI) { |
| 2060 | sgi_list_table(xtra); | 2091 | sgi_list_table(xtra); |
| 2061 | return; | 2092 | return; |
| 2062 | } | 2093 | } |
| 2094 | if (LABEL_IS_GPT) { | ||
| 2095 | gpt_list_table(xtra); | ||
| 2096 | return; | ||
| 2097 | } | ||
| 2063 | 2098 | ||
| 2064 | list_disk_geometry(); | 2099 | list_disk_geometry(); |
| 2065 | 2100 | ||
diff --git a/util-linux/fdisk_gpt.c b/util-linux/fdisk_gpt.c new file mode 100644 index 000000000..98803ec88 --- /dev/null +++ b/util-linux/fdisk_gpt.c | |||
| @@ -0,0 +1,203 @@ | |||
| 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 | ||
| 9 | enum { | ||
| 10 | LEGACY_GPT_TYPE = 0xee, | ||
| 11 | GPT_MAX_PARTS = 256, | ||
| 12 | GPT_MAX_PART_ENTRY_LEN = 4096, | ||
| 13 | GUID_LEN = 16, | ||
| 14 | }; | ||
| 15 | |||
| 16 | typedef 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 | |||
| 33 | typedef 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 | |||
| 42 | static gpt_header *gpt_hdr; | ||
| 43 | |||
| 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; | ||
| 48 | |||
| 49 | static uint32_t *crc32_table; | ||
| 50 | |||
| 51 | static inline gpt_partition * | ||
| 52 | gpt_part(int i) | ||
| 53 | { | ||
| 54 | if (i >= n_parts) { | ||
| 55 | return NULL; | ||
| 56 | } | ||
| 57 | return (gpt_partition *)&part_array[i * part_entry_len]; | ||
| 58 | } | ||
| 59 | |||
| 60 | /* TODO: move to libbb */ | ||
| 61 | static uint32_t | ||
| 62 | gpt_crc32(void *buf, int len) | ||
| 63 | { | ||
| 64 | uint32_t crc = 0xffffffff; | ||
| 65 | |||
| 66 | for (; len > 0; len--, buf++) { | ||
| 67 | crc = crc32_table[(crc ^ *((char *)buf)) & 0xff] ^ (crc >> 8); | ||
| 68 | } | ||
| 69 | return crc ^ 0xffffffff; | ||
| 70 | } | ||
| 71 | |||
| 72 | static void | ||
| 73 | gpt_print_guid(uint8_t *buf) | ||
| 74 | { | ||
| 75 | printf( | ||
| 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], | ||
| 78 | buf[5], buf[4], | ||
| 79 | buf[7], buf[6], | ||
| 80 | buf[8], buf[9], | ||
| 81 | buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); | ||
| 82 | } | ||
| 83 | |||
| 84 | /* TODO: real unicode support */ | ||
| 85 | static void | ||
| 86 | gpt_print_wide(uint16_t *s, int max_len) | ||
| 87 | { | ||
| 88 | int i = 0; | ||
| 89 | |||
| 90 | while (i < max_len) { | ||
| 91 | if (*s == 0) | ||
| 92 | return; | ||
| 93 | fputc(*s, stdout); | ||
| 94 | s++; | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | static void | ||
| 99 | gpt_list_table(int xtra UNUSED_PARAM) | ||
| 100 | { | ||
| 101 | int i; | ||
| 102 | char numstr6[6]; | ||
| 103 | |||
| 104 | numstr6[5] = '\0'; | ||
| 105 | |||
| 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, | ||
| 109 | numstr6); | ||
| 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)); | ||
| 118 | |||
| 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); | ||
| 122 | if (p->lba_start) { | ||
| 123 | smart_ulltoa5(1 + SWAP_LE64(p->lba_end) - SWAP_LE64(p->lba_start), | ||
| 124 | numstr6, " KMGTPEZY"); | ||
| 125 | printf("%4u %15llu %15llu %11s %04x ", | ||
| 126 | i + 1, | ||
| 127 | (unsigned long long)SWAP_LE64(p->lba_start), | ||
| 128 | (unsigned long long)SWAP_LE64(p->lba_end), | ||
| 129 | numstr6, | ||
| 130 | 0x0700 /* FIXME */); | ||
| 131 | gpt_print_wide(p->name, 18); | ||
| 132 | printf("\n"); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | static int | ||
| 138 | check_gpt_label(void) | ||
| 139 | { | ||
| 140 | struct partition *first = pt_offset(MBRbuffer, 0); | ||
| 141 | struct pte pe; | ||
| 142 | uint32_t crc; | ||
| 143 | |||
| 144 | /* LBA 0 contains the legacy MBR */ | ||
| 145 | |||
| 146 | if (!valid_part_table_flag(MBRbuffer) | ||
| 147 | || first->sys_ind != LEGACY_GPT_TYPE | ||
| 148 | ) { | ||
| 149 | current_label_type = 0; | ||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | /* LBA 1 contains the GPT header */ | ||
| 154 | |||
| 155 | read_pte(&pe, 1); | ||
| 156 | gpt_hdr = (void *)pe.sectorbuffer; | ||
| 157 | |||
| 158 | if (gpt_hdr->magic != SWAP_LE64(GPT_MAGIC)) { | ||
| 159 | current_label_type = 0; | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | if (!crc32_table) { | ||
| 164 | crc32_table = crc32_filltable(NULL, 0); | ||
| 165 | } | ||
| 166 | |||
| 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"); | ||
| 172 | } | ||
| 173 | |||
| 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 | ||
| 179 | ) { | ||
| 180 | puts("\nwarning: unable to parse GPT disklabel\n"); | ||
| 181 | current_label_type = 0; | ||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | |||
| 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); | ||
| 190 | } | ||
| 191 | |||
| 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"); | ||
| 195 | } | ||
| 196 | |||
| 197 | puts("Found valid GPT with protective MBR; using GPT\n"); | ||
| 198 | |||
| 199 | current_label_type = LABEL_GPT; | ||
| 200 | return 1; | ||
| 201 | } | ||
| 202 | |||
| 203 | #endif /* GPT_LABEL */ | ||
