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
32 #include <sys/ioctl.h>
36 #include <sys/utsname.h>
37 #include <asm/byteorder.h>
41 #include "efibootmgr.h"
43 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
44 #define BLKGETSIZE _IO(0x12,96) /* return device size */
45 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
46 #define BLKGETSIZE64 _IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
48 struct blkdev_ioctl_param {
50 size_t content_length;
51 char * block_contents;
55 * efi_crc32() - EFI version of crc32 function
56 * @buf: buffer to calculate crc32 of
57 * @len - length of buf
59 * Description: Returns EFI-style CRC32 value for @buf
61 * This function uses the little endian Ethernet polynomial
62 * but seeds the function with ~0, and xor's with ~0 at the end.
63 * Note, the EFI Specification, v1.02, has a reference to
64 * Dr. Dobbs Journal, May 1994 (actually it's in May 1992).
66 static inline uint32_t
67 efi_crc32(const void *buf, unsigned long len)
69 return (crc32(buf, len, ~0L) ^ ~0L);
73 * is_pmbr_valid(): test Protective MBR for validity
74 * @mbr: pointer to a legacy mbr structure
76 * Description: Returns 1 if PMBR is valid, 0 otherwise.
77 * Validity depends on two things:
78 * 1) MSDOS signature is in the last two bytes of the MBR
79 * 2) One partition of type 0xEE is found
82 is_pmbr_valid(legacy_mbr *mbr)
84 int i, found = 0, signature = 0;
87 signature = (__le16_to_cpu(mbr->signature) == MSDOS_MBR_SIGNATURE);
88 for (i = 0; signature && i < 4; i++) {
89 if (mbr->partition[i].os_type ==
90 EFI_PMBR_OSTYPE_EFI_GPT) {
95 return (signature && found);
99 * kernel_has_blkgetsize64()
101 * Returns: 0 on false, 1 on true
102 * True means kernel is 2.4.x, x>=18, or
107 kernel_has_blkgetsize64(void)
109 int major=0, minor=0, patch=0, parsed;
113 memset(&u, 0, sizeof(u));
117 parsed = sscanf(u.release, "%d.%d.%d", &major, &minor, &patch);
118 if (parsed < 3) return 0;
119 if (major > 2) return 1;
120 if (major == 2 && minor > 5) return 1;
121 if (major == 2 && minor == 5 && patch >= 4) return 1;
122 if (major == 2 && minor == 4 && patch >= 18) return 1;
127 /************************************************************
130 * - filedes is an open file descriptor, suitable for reading
133 * Last LBA value on success
136 * Try getting BLKGETSIZE64 and BLKSSZGET first,
137 * then BLKGETSIZE if necessary.
138 * Kernels 2.4.15-2.4.18 and 2.5.0-2.5.3 have a broken BLKGETSIZE64
139 * which returns the number of 512-byte sectors, not the size of
140 * the disk in bytes. Fixed in kernels 2.4.18-pre8 and 2.5.4-pre3.
141 ************************************************************/
143 _get_num_sectors(int filedes)
145 unsigned long sectors=0;
148 if (kernel_has_blkgetsize64()) {
149 rc = ioctl(filedes, BLKGETSIZE64, &bytes);
151 return bytes / get_sector_size(filedes);
154 rc = ioctl(filedes, BLKGETSIZE, §ors);
161 /************************************************************
162 * last_lba(): return number of last logical block of device
166 * Description: returns Last LBA value on success, 0 on error.
167 * Notes: The value st_blocks gives the size of the file
168 * in 512-byte blocks, which is OK if
169 * EFI_BLOCK_SIZE_SHIFT == 9.
170 ************************************************************/
173 last_lba(int filedes)
176 uint64_t sectors = 0;
178 memset(&s, 0, sizeof (s));
179 rc = fstat(filedes, &s);
181 fprintf(stderr, "last_lba() could not stat: %s\n",
186 if (S_ISBLK(s.st_mode)) {
187 sectors = _get_num_sectors(filedes);
190 "last_lba(): I don't know how to handle files with mode %x\n",
200 read_lastoddsector(int fd, uint64_t lba, void *buffer, size_t count)
203 struct blkdev_ioctl_param ioctl_param;
205 if (!buffer) return 0;
207 ioctl_param.block = 0; /* read the last sector */
208 ioctl_param.content_length = count;
209 ioctl_param.block_contents = buffer;
211 rc = ioctl(fd, BLKGETLASTSECT, &ioctl_param);
212 if (rc == -1) perror("read failed");
218 read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
220 int sector_size = get_sector_size(fd);
221 off_t offset = lba * sector_size;
226 if (bytes % sector_size)
229 unaligned = malloc(bytes+sector_size-1);
231 (((unsigned long)unaligned + sector_size - 1) &
232 ~(unsigned long)(sector_size-1));
233 memset(aligned, 0, bytes);
236 lseek(fd, offset, SEEK_SET);
237 bytesread = read(fd, aligned, bytes);
238 memcpy(buffer, aligned, bytesread);
240 /* Kludge. This is necessary to read/write the last
241 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
242 This is only used by gpt.c, and only to read
243 one sector, so we don't have to be fancy.
245 if (!bytesread && !(last_lba(fd) & 1) && lba == last_lba(fd)) {
246 bytesread = read_lastoddsector(fd, lba, buffer, bytes);
252 * alloc_read_gpt_entries(): reads partition entries from disk
253 * @fd is an open file descriptor to the whole disk
254 * @gpt is a buffer into which the GPT will be put
255 * Description: Returns ptes on success, NULL on error.
256 * Allocates space for PTEs based on information found in @gpt.
257 * Notes: remember to free pte when you're done!
260 alloc_read_gpt_entries(int fd, gpt_header * gpt)
263 size_t count = __le32_to_cpu(gpt->num_partition_entries) *
264 __le32_to_cpu(gpt->sizeof_partition_entry);
266 if (!count) return NULL;
268 pte = (gpt_entry *)malloc(count);
271 memset(pte, 0, count);
273 if (!read_lba(fd, __le64_to_cpu(gpt->partition_entry_lba), pte,
282 * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
283 * @fd is an open file descriptor to the whole disk
284 * @lba is the Logical Block Address of the partition table
286 * Description: returns GPT header on success, NULL on error. Allocates
287 * and fills a GPT header starting at @ from @bdev.
288 * Note: remember to free gpt when finished with it.
291 alloc_read_gpt_header(int fd, uint64_t lba)
295 malloc(sizeof (gpt_header));
298 memset(gpt, 0, sizeof (*gpt));
299 if (!read_lba(fd, lba, gpt, sizeof (gpt_header))) {
308 * is_gpt_valid() - tests one GPT header and PTEs for validity
309 * @fd is an open file descriptor to the whole disk
310 * @lba is the logical block address of the GPT header to test
311 * @gpt is a GPT header ptr, filled on return.
312 * @ptes is a PTEs ptr, filled on return.
314 * Description: returns 1 if valid, 0 on error.
315 * If valid, returns pointers to newly allocated GPT header and PTEs.
318 is_gpt_valid(int fd, uint64_t lba,
319 gpt_header ** gpt, gpt_entry ** ptes)
321 int rc = 0; /* default to not valid */
322 uint32_t crc, origcrc;
326 if (!(*gpt = alloc_read_gpt_header(fd, lba)))
329 /* Check the GUID Partition Table signature */
330 if (__le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
332 printf("GUID Partition Table Header signature is wrong: %" PRIx64" != %" PRIx64 "\n",
333 __le64_to_cpu((*gpt)->signature), GUID_PT_HEADER_SIGNATURE);
340 /* Check the GUID Partition Table Header CRC */
341 origcrc = __le32_to_cpu((*gpt)->header_crc32);
342 (*gpt)->header_crc32 = 0;
343 crc = efi_crc32(*gpt, __le32_to_cpu((*gpt)->header_size));
344 if (crc != origcrc) {
345 // printf( "GPTH CRC check failed, %x != %x.\n", origcrc, crc);
346 (*gpt)->header_crc32 = __cpu_to_le32(origcrc);
351 (*gpt)->header_crc32 = __cpu_to_le32(origcrc);
353 /* Check that the my_lba entry points to the LBA
354 * that contains the GPT we read */
355 if (__le64_to_cpu((*gpt)->my_lba) != lba) {
356 // printf( "my_lba % PRIx64 "x != lba %"PRIx64 "x.\n", __le64_to_cpu((*gpt)->my_lba), lba);
362 if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) {
368 /* Check the GUID Partition Entry Array CRC */
369 crc = efi_crc32(*ptes,
370 __le32_to_cpu((*gpt)->num_partition_entries) *
371 __le32_to_cpu((*gpt)->sizeof_partition_entry));
372 if (crc != __le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
373 // printf("GUID Partitition Entry Array CRC check failed.\n");
381 /* We're done, all's well */
385 * compare_gpts() - Search disk for valid GPT headers and PTEs
386 * @pgpt is the primary GPT header
387 * @agpt is the alternate GPT header
388 * @lastlba is the last LBA number
389 * Description: Returns nothing. Sanity checks pgpt and agpt fields
390 * and prints warnings on discrepancies.
394 compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
399 if (__le64_to_cpu(pgpt->my_lba) != __le64_to_cpu(agpt->alternate_lba)) {
401 "GPT:Primary header LBA != Alt. header alternate_lba\n");
402 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
403 __le64_to_cpu(pgpt->my_lba),
404 __le64_to_cpu(agpt->alternate_lba));
407 if (__le64_to_cpu(pgpt->alternate_lba) != __le64_to_cpu(agpt->my_lba)) {
409 "GPT:Primary header alternate_lba != Alt. header my_lba\n");
410 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
411 __le64_to_cpu(pgpt->alternate_lba),
412 __le64_to_cpu(agpt->my_lba));
415 if (__le64_to_cpu(pgpt->first_usable_lba) !=
416 __le64_to_cpu(agpt->first_usable_lba)) {
417 fprintf(stderr, "GPT:first_usable_lbas don't match.\n");
418 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
419 __le64_to_cpu(pgpt->first_usable_lba),
420 __le64_to_cpu(agpt->first_usable_lba));
423 if (__le64_to_cpu(pgpt->last_usable_lba) !=
424 __le64_to_cpu(agpt->last_usable_lba)) {
425 fprintf(stderr, "GPT:last_usable_lbas don't match.\n");
426 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
427 __le64_to_cpu(pgpt->last_usable_lba),
428 __le64_to_cpu(agpt->last_usable_lba));
431 if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
432 fprintf(stderr, "GPT:disk_guids don't match.\n");
435 if (__le32_to_cpu(pgpt->num_partition_entries) !=
436 __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));
443 if (__le32_to_cpu(pgpt->sizeof_partition_entry) !=
444 __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));
452 if (__le32_to_cpu(pgpt->partition_entry_array_crc32) !=
453 __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));
461 if (__le64_to_cpu(pgpt->alternate_lba) != lastlba) {
463 "GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
464 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
465 __le64_to_cpu(pgpt->alternate_lba), lastlba);
469 if (__le64_to_cpu(agpt->my_lba) != lastlba) {
471 "GPT:Alternate GPT header not at the end of the disk.\n");
472 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
473 __le64_to_cpu(agpt->my_lba), lastlba);
479 "GPT: Use GNU Parted to correct GPT errors.\n");
484 * find_valid_gpt() - Search disk for valid GPT headers and PTEs
485 * @fd is an open file descriptor to the whole disk
486 * @gpt is a GPT header ptr, filled on return.
487 * @ptes is a PTEs ptr, filled on return.
488 * Description: Returns 1 if valid, 0 on error.
489 * If valid, returns pointers to newly allocated GPT header and PTEs.
490 * Validity depends on finding either the Primary GPT header and PTEs valid,
491 * or the Alternate GPT header and PTEs valid, and the PMBR valid.
494 find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
496 int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
497 gpt_header *pgpt = NULL, *agpt = NULL;
498 gpt_entry *pptes = NULL, *aptes = NULL;
499 legacy_mbr *legacymbr = NULL;
504 lastlba = last_lba(fd);
505 good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA,
508 good_agpt = is_gpt_valid(fd,
509 __le64_to_cpu(pgpt->alternate_lba),
512 good_agpt = is_gpt_valid(fd, lastlba,
517 good_agpt = is_gpt_valid(fd, lastlba,
521 /* The obviously unsuccessful case */
522 if (!good_pgpt && !good_agpt) {
526 /* This will be added to the EFI Spec. per Intel after v1.02. */
527 legacymbr = malloc(sizeof (*legacymbr));
529 memset(legacymbr, 0, sizeof (*legacymbr));
530 read_lba(fd, 0, (uint8_t *) legacymbr,
531 sizeof (*legacymbr));
532 good_pmbr = is_pmbr_valid(legacymbr);
537 /* Failure due to bad PMBR */
538 if ((good_pgpt || good_agpt) && !good_pmbr && !opts.forcegpt) {
540 " Warning: Disk has a valid GPT signature "
541 "but invalid PMBR.\n"
542 " Assuming this disk is *not* a GPT disk anymore.\n"
543 " Use gpt kernel option to override. "
544 "Use GNU Parted to correct disk.\n");
548 /* Would fail due to bad PMBR, but force GPT anyhow */
549 if ((good_pgpt || good_agpt) && !good_pmbr && opts.forcegpt) {
551 " Warning: Disk has a valid GPT signature but "
553 " Use GNU Parted to correct disk.\n"
554 " gpt option taken, disk treated as GPT.\n");
557 compare_gpts(pgpt, agpt, lastlba);
560 if (good_pgpt && (good_pmbr || opts.forcegpt)) {
563 if (agpt) { free(agpt); agpt = NULL; }
564 if (aptes) { free(aptes); aptes = NULL; }
567 "Alternate GPT is invalid, "
568 "using primary GPT.\n");
572 else if (good_agpt && (good_pmbr || opts.forcegpt)) {
575 if (pgpt) { free(pgpt); pgpt = NULL; }
576 if (pptes) { free(pptes); pptes = NULL; }
578 "Primary GPT is invalid, using alternate GPT.\n");
583 if (pgpt) { free(pgpt); pgpt=NULL; }
584 if (agpt) { free(agpt); agpt=NULL; }
585 if (pptes) { free(pptes); pptes=NULL; }
586 if (aptes) { free(aptes); aptes=NULL; }
593 /************************************************************
594 * gpt_disk_get_partition_info()
596 * - open file descriptor fd
597 * - start, size, signature, mbr_type, signature_type
598 * Modifies: all these
601 * non-zero on failure
603 ************************************************************/
605 gpt_disk_get_partition_info(int fd,
607 uint64_t * start, uint64_t * size,
609 uint8_t * mbr_type, uint8_t * signature_type)
611 gpt_header *gpt = NULL;
612 gpt_entry *ptes = NULL, *p;
614 if (!find_valid_gpt(fd, &gpt, &ptes))
618 *signature_type = 0x02;
620 if (num > 0 && num <= __le32_to_cpu(gpt->num_partition_entries)) {
622 *start = __le64_to_cpu(p->starting_lba);
623 *size = __le64_to_cpu(p->ending_lba) -
624 __le64_to_cpu(p->starting_lba) + 1;
625 memcpy(signature, &p->unique_partition_guid,
626 sizeof (p->unique_partition_guid));
629 *size = last_lba(fd) + 1;
630 memcpy(signature, &gpt->disk_guid, sizeof (gpt->disk_guid));
636 * Overrides for Emacs so that we follow Linus's tabbing style.
637 * Emacs will notice this stuff at the end of the file and automatically
638 * adjust the settings for this buffer only. This must remain at the end
640 * ---------------------------------------------------------------------------
643 * c-brace-imaginary-offset: 0
645 * c-argdecl-indent: 4
647 * c-continued-statement-offset: 4
648 * c-continued-brace-offset: 0
649 * indent-tabs-mode: nil