4 Copyright (C) 2000-2001 Dell Computer Corporation <Matt_Domsch@dell.com>
6 EFI GUID Partition Table handling
7 Per Intel EFI Specification v1.02
8 http://developer.intel.com/technology/efi/efi.htm
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #define _FILE_OFFSET_BITS 64
33 #include <sys/ioctl.h>
41 #if BYTE_ORDER == LITTLE_ENDIAN
42 # define __le16_to_cpu(x) (x)
43 # define __le32_to_cpu(x) (x)
44 # define __le64_to_cpu(x) (x)
45 # define __cpu_to_le32(x) (x)
46 #elif BYTE_ORDER == BIG_ENDIAN
47 # define __le16_to_cpu(x) bswap_16(x)
48 # define __le32_to_cpu(x) bswap_32(x)
49 # define __le64_to_cpu(x) bswap_64(x)
50 # define __cpu_to_le32(x) bswap_32(x)
53 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
54 #define BLKGETSIZE _IO(0x12,96) /* return device size */
55 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
56 #define BLKGETSIZE64 _IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
58 struct blkdev_ioctl_param {
60 size_t content_length;
61 char * block_contents;
65 * efi_crc32() - EFI version of crc32 function
66 * @buf: buffer to calculate crc32 of
67 * @len - length of buf
69 * Description: Returns EFI-style CRC32 value for @buf
71 * This function uses the little endian Ethernet polynomial
72 * but seeds the function with ~0, and xor's with ~0 at the end.
73 * Note, the EFI Specification, v1.02, has a reference to
74 * Dr. Dobbs Journal, May 1994 (actually it's in May 1992).
76 static inline uint32_t
77 efi_crc32(const void *buf, unsigned long len)
79 return (crc32(~0L, buf, len) ^ ~0L);
83 * is_pmbr_valid(): test Protective MBR for validity
84 * @mbr: pointer to a legacy mbr structure
86 * Description: Returns 1 if PMBR is valid, 0 otherwise.
87 * Validity depends on two things:
88 * 1) MSDOS signature is in the last two bytes of the MBR
89 * 2) One partition of type 0xEE is found
92 is_pmbr_valid(legacy_mbr *mbr)
94 int i, found = 0, signature = 0;
97 signature = (__le16_to_cpu(mbr->signature) == MSDOS_MBR_SIGNATURE);
98 for (i = 0; signature && i < 4; i++) {
99 if (mbr->partition[i].sys_type ==
100 EFI_PMBR_OSTYPE_EFI_GPT) {
105 return (signature && found);
109 /************************************************************
112 * - filedes is an open file descriptor, suitable for reading
115 * sector size, or 512.
116 ************************************************************/
118 get_sector_size(int filedes)
120 int rc, sector_size = 512;
122 rc = ioctl(filedes, BLKSSZGET, §or_size);
128 /************************************************************
131 * - filedes is an open file descriptor, suitable for reading
134 * Last LBA value on success
137 * Try getting BLKGETSIZE64 and BLKSSZGET first,
138 * then BLKGETSIZE if necessary.
139 * Kernels 2.4.15-2.4.18 and 2.5.0-2.5.3 have a broken BLKGETSIZE64
140 * which returns the number of 512-byte sectors, not the size of
141 * the disk in bytes. Fixed in kernels 2.4.18-pre8 and 2.5.4-pre3.
142 ************************************************************/
144 _get_num_sectors(int filedes)
146 unsigned long sectors=0;
151 rc = ioctl(filedes, BLKGETSIZE64, &bytes);
153 return bytes / get_sector_size(filedes);
155 rc = ioctl(filedes, BLKGETSIZE, §ors);
162 /************************************************************
163 * last_lba(): return number of last logical block of device
167 * Description: returns Last LBA value on success, 0 on error.
168 * Notes: The value st_blocks gives the size of the file
169 * in 512-byte blocks, which is OK if
170 * EFI_BLOCK_SIZE_SHIFT == 9.
171 ************************************************************/
174 last_lba(int filedes)
177 uint64_t sectors = 0;
179 memset(&s, 0, sizeof (s));
180 rc = fstat(filedes, &s);
182 fprintf(stderr, "last_lba() could not stat: %s\n",
187 if (S_ISBLK(s.st_mode)) {
188 sectors = _get_num_sectors(filedes);
191 "last_lba(): I don't know how to handle files with mode %x\n",
201 read_lastoddsector(int fd, uint64_t lba, void *buffer, size_t count)
204 struct blkdev_ioctl_param ioctl_param;
206 if (!buffer) return 0;
208 ioctl_param.block = 0; /* read the last sector */
209 ioctl_param.content_length = count;
210 ioctl_param.block_contents = buffer;
212 rc = ioctl(fd, BLKGETLASTSECT, &ioctl_param);
213 if (rc == -1) perror("read failed");
219 read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
221 int sector_size = get_sector_size(fd);
222 off_t offset = lba * sector_size;
225 lseek(fd, offset, SEEK_SET);
226 bytesread = read(fd, buffer, bytes);
228 /* Kludge. This is necessary to read/write the last
229 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
230 This is only used by gpt.c, and only to read
231 one sector, so we don't have to be fancy.
233 if (!bytesread && !(last_lba(fd) & 1) && lba == last_lba(fd)) {
234 bytesread = read_lastoddsector(fd, lba, buffer, bytes);
240 * alloc_read_gpt_entries(): reads partition entries from disk
241 * @fd is an open file descriptor to the whole disk
242 * @gpt is a buffer into which the GPT will be put
243 * Description: Returns ptes on success, NULL on error.
244 * Allocates space for PTEs based on information found in @gpt.
245 * Notes: remember to free pte when you're done!
248 alloc_read_gpt_entries(int fd, gpt_header * gpt)
251 size_t count = __le32_to_cpu(gpt->num_partition_entries) *
252 __le32_to_cpu(gpt->sizeof_partition_entry);
254 if (!count) return NULL;
256 pte = (gpt_entry *)malloc(count);
259 memset(pte, 0, count);
261 if (!read_lba(fd, __le64_to_cpu(gpt->partition_entry_lba), pte,
270 * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
271 * @fd is an open file descriptor to the whole disk
272 * @lba is the Logical Block Address of the partition table
274 * Description: returns GPT header on success, NULL on error. Allocates
275 * and fills a GPT header starting at @ from @bdev.
276 * Note: remember to free gpt when finished with it.
279 alloc_read_gpt_header(int fd, uint64_t lba)
283 malloc(sizeof (gpt_header));
286 memset(gpt, 0, sizeof (*gpt));
287 if (!read_lba(fd, lba, gpt, sizeof (gpt_header))) {
296 * is_gpt_valid() - tests one GPT header and PTEs for validity
297 * @fd is an open file descriptor to the whole disk
298 * @lba is the logical block address of the GPT header to test
299 * @gpt is a GPT header ptr, filled on return.
300 * @ptes is a PTEs ptr, filled on return.
302 * Description: returns 1 if valid, 0 on error.
303 * If valid, returns pointers to newly allocated GPT header and PTEs.
306 is_gpt_valid(int fd, uint64_t lba,
307 gpt_header ** gpt, gpt_entry ** ptes)
309 int rc = 0; /* default to not valid */
310 uint32_t crc, origcrc;
314 if (!(*gpt = alloc_read_gpt_header(fd, lba)))
317 /* Check the GUID Partition Table signature */
318 if (__le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
320 printf("GUID Partition Table Header signature is wrong: %" PRIx64" != %" PRIx64 "\n",
321 __le64_to_cpu((*gpt)->signature), GUID_PT_HEADER_SIGNATURE);
328 /* Check the GUID Partition Table Header CRC */
329 origcrc = __le32_to_cpu((*gpt)->header_crc32);
330 (*gpt)->header_crc32 = 0;
331 crc = efi_crc32(*gpt, __le32_to_cpu((*gpt)->header_size));
332 if (crc != origcrc) {
333 // printf( "GPTH CRC check failed, %x != %x.\n", origcrc, crc);
334 (*gpt)->header_crc32 = __cpu_to_le32(origcrc);
339 (*gpt)->header_crc32 = __cpu_to_le32(origcrc);
341 /* Check that the my_lba entry points to the LBA
342 * that contains the GPT we read */
343 if (__le64_to_cpu((*gpt)->my_lba) != lba) {
345 printf( "my_lba % PRIx64 "x != lba %"PRIx64 "x.\n",
346 __le64_to_cpu((*gpt)->my_lba), lba);
353 if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) {
359 /* Check the GUID Partition Entry Array CRC */
360 crc = efi_crc32(*ptes,
361 __le32_to_cpu((*gpt)->num_partition_entries) *
362 __le32_to_cpu((*gpt)->sizeof_partition_entry));
363 if (crc != __le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
364 // printf("GUID Partitition Entry Array CRC check failed.\n");
372 /* We're done, all's well */
376 * compare_gpts() - Search disk for valid GPT headers and PTEs
377 * @pgpt is the primary GPT header
378 * @agpt is the alternate GPT header
379 * @lastlba is the last LBA number
380 * Description: Returns nothing. Sanity checks pgpt and agpt fields
381 * and prints warnings on discrepancies.
385 compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
390 if (__le64_to_cpu(pgpt->my_lba) != __le64_to_cpu(agpt->alternate_lba)) {
393 "GPT:Primary header LBA != Alt. header alternate_lba\n");
395 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
396 __le64_to_cpu(pgpt->my_lba),
397 __le64_to_cpu(agpt->alternate_lba));
400 if (__le64_to_cpu(pgpt->alternate_lba) != __le64_to_cpu(agpt->my_lba)) {
403 "GPT:Primary header alternate_lba != Alt. header my_lba\n");
405 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
406 __le64_to_cpu(pgpt->alternate_lba),
407 __le64_to_cpu(agpt->my_lba));
410 if (__le64_to_cpu(pgpt->first_usable_lba) !=
411 __le64_to_cpu(agpt->first_usable_lba)) {
413 fprintf(stderr, "GPT:first_usable_lbas don't match.\n");
415 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
416 __le64_to_cpu(pgpt->first_usable_lba),
417 __le64_to_cpu(agpt->first_usable_lba));
420 if (__le64_to_cpu(pgpt->last_usable_lba) !=
421 __le64_to_cpu(agpt->last_usable_lba)) {
423 fprintf(stderr, "GPT:last_usable_lbas don't match.\n");
425 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
426 __le64_to_cpu(pgpt->last_usable_lba),
427 __le64_to_cpu(agpt->last_usable_lba));
430 if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
432 fprintf(stderr, "GPT:disk_guids don't match.\n");
434 if (__le32_to_cpu(pgpt->num_partition_entries) !=
435 __le32_to_cpu(agpt->num_partition_entries)) {
437 fprintf(stderr, "GPT:num_partition_entries don't match: "
439 __le32_to_cpu(pgpt->num_partition_entries),
440 __le32_to_cpu(agpt->num_partition_entries));
442 if (__le32_to_cpu(pgpt->sizeof_partition_entry) !=
443 __le32_to_cpu(agpt->sizeof_partition_entry)) {
446 "GPT:sizeof_partition_entry values don't match: "
448 __le32_to_cpu(pgpt->sizeof_partition_entry),
449 __le32_to_cpu(agpt->sizeof_partition_entry));
451 if (__le32_to_cpu(pgpt->partition_entry_array_crc32) !=
452 __le32_to_cpu(agpt->partition_entry_array_crc32)) {
455 "GPT:partition_entry_array_crc32 values don't match: "
457 __le32_to_cpu(pgpt->partition_entry_array_crc32),
458 __le32_to_cpu(agpt->partition_entry_array_crc32));
460 if (__le64_to_cpu(pgpt->alternate_lba) != lastlba) {
463 "GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
465 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
466 __le64_to_cpu(pgpt->alternate_lba), lastlba);
470 if (__le64_to_cpu(agpt->my_lba) != lastlba) {
473 "GPT:Alternate GPT header not at the end of the disk.\n");
475 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
476 __le64_to_cpu(agpt->my_lba), lastlba);
482 "GPT: Use GNU Parted to correct GPT errors.\n");
487 * find_valid_gpt() - Search disk for valid GPT headers and PTEs
488 * @fd is an open file descriptor to the whole disk
489 * @gpt is a GPT header ptr, filled on return.
490 * @ptes is a PTEs ptr, filled on return.
491 * Description: Returns 1 if valid, 0 on error.
492 * If valid, returns pointers to newly allocated GPT header and PTEs.
493 * Validity depends on finding either the Primary GPT header and PTEs valid,
494 * or the Alternate GPT header and PTEs valid, and the PMBR valid.
497 find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
499 extern int force_gpt;
500 int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
501 gpt_header *pgpt = NULL, *agpt = NULL;
502 gpt_entry *pptes = NULL, *aptes = NULL;
503 legacy_mbr *legacymbr = NULL;
508 lastlba = last_lba(fd);
509 good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA,
512 good_agpt = is_gpt_valid(fd,
513 __le64_to_cpu(pgpt->alternate_lba),
516 good_agpt = is_gpt_valid(fd, lastlba,
521 good_agpt = is_gpt_valid(fd, lastlba,
525 /* The obviously unsuccessful case */
526 if (!good_pgpt && !good_agpt) {
530 /* This will be added to the EFI Spec. per Intel after v1.02. */
531 legacymbr = malloc(sizeof (*legacymbr));
533 memset(legacymbr, 0, sizeof (*legacymbr));
534 read_lba(fd, 0, (uint8_t *) legacymbr,
535 sizeof (*legacymbr));
536 good_pmbr = is_pmbr_valid(legacymbr);
541 /* Failure due to bad PMBR */
542 if ((good_pgpt || good_agpt) && !good_pmbr && !force_gpt) {
544 " Warning: Disk has a valid GPT signature "
545 "but invalid PMBR.\n"
546 " Assuming this disk is *not* a GPT disk anymore.\n"
547 " Use gpt kernel option to override. "
548 "Use GNU Parted to correct disk.\n");
552 /* Would fail due to bad PMBR, but force GPT anyhow */
553 if ((good_pgpt || good_agpt) && !good_pmbr && force_gpt) {
555 " Warning: Disk has a valid GPT signature but "
557 " Use GNU Parted to correct disk.\n"
558 " gpt option taken, disk treated as GPT.\n");
561 compare_gpts(pgpt, agpt, lastlba);
564 if (good_pgpt && (good_pmbr || force_gpt)) {
567 if (agpt) { free(agpt); agpt = NULL; }
568 if (aptes) { free(aptes); aptes = NULL; }
571 "Alternate GPT is invalid, "
572 "using primary GPT.\n");
576 else if (good_agpt && (good_pmbr || force_gpt)) {
579 if (pgpt) { free(pgpt); pgpt = NULL; }
580 if (pptes) { free(pptes); pptes = NULL; }
582 "Primary GPT is invalid, using alternate GPT.\n");
587 if (pgpt) { free(pgpt); pgpt=NULL; }
588 if (agpt) { free(agpt); agpt=NULL; }
589 if (pptes) { free(pptes); pptes=NULL; }
590 if (aptes) { free(aptes); aptes=NULL; }
599 * @all - slice with start/size of whole disk
601 * 0 if this isn't our partition table
602 * number of partitions if successful
606 read_gpt_pt (int fd, struct slice all, struct slice *sp, int ns)
608 gpt_header *gpt = NULL;
609 gpt_entry *ptes = NULL;
612 int last_used_index=-1;
614 if (!find_valid_gpt (fd, &gpt, &ptes) || !gpt || !ptes) {
622 for (i = 0; i < __le32_to_cpu(gpt->num_partition_entries) && i < ns; i++) {
623 if (!efi_guidcmp (NULL_GUID, ptes[i].partition_type_guid)) {
628 sp[n].start = __le64_to_cpu(ptes[i].starting_lba);
629 sp[n].size = __le64_to_cpu(ptes[i].ending_lba) -
630 __le64_to_cpu(ptes[i].starting_lba) + 1;
637 return last_used_index+1;