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
30 #include <sys/ioctl.h>
34 #include <sys/utsname.h>
35 #include <asm/byteorder.h>
39 #include "efibootmgr.h"
41 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
42 #define BLKGETSIZE _IO(0x12,96) /* return device size */
43 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
44 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t) /* return device size in bytes (u64 *arg) */
46 struct blkdev_ioctl_param {
48 size_t content_length;
49 char * block_contents;
53 * efi_crc32() - EFI version of crc32 function
54 * @buf: buffer to calculate crc32 of
55 * @len - length of buf
57 * Description: Returns EFI-style CRC32 value for @buf
59 * This function uses the little endian Ethernet polynomial
60 * but seeds the function with ~0, and xor's with ~0 at the end.
61 * Note, the EFI Specification, v1.02, has a reference to
62 * Dr. Dobbs Journal, May 1994 (actually it's in May 1992).
64 static inline uint32_t
65 efi_crc32(const void *buf, unsigned long len)
67 return (crc32(buf, len, ~0L) ^ ~0L);
71 * is_pmbr_valid(): test Protective MBR for validity
72 * @mbr: pointer to a legacy mbr structure
74 * Description: Returns 1 if PMBR is valid, 0 otherwise.
75 * Validity depends on two things:
76 * 1) MSDOS signature is in the last two bytes of the MBR
77 * 2) One partition of type 0xEE is found
80 is_pmbr_valid(legacy_mbr *mbr)
82 int i, found = 0, signature = 0;
85 signature = (__le16_to_cpu(mbr->signature) == MSDOS_MBR_SIGNATURE);
86 for (i = 0; signature && i < 4; i++) {
87 if (mbr->partition[i].os_type ==
88 EFI_PMBR_OSTYPE_EFI_GPT) {
93 return (signature && found);
97 * kernel_has_blkgetsize64()
99 * Returns: 0 on false, 1 on true
100 * True means kernel is 2.4.x, x>=18, or
105 kernel_has_blkgetsize64(void)
107 int major=0, minor=0, patch=0, parsed;
111 memset(&u, 0, sizeof(u));
115 parsed = sscanf(u.release, "%d.%d.%d", &major, &minor, &patch);
116 if (parsed < 3) return 0;
117 if (major > 2) return 1;
118 if (major == 2 && minor > 5) return 1;
119 if (major == 2 && minor == 5 && patch >= 4) return 1;
120 if (major == 2 && minor == 4 && patch >= 18) return 1;
125 /************************************************************
128 * - filedes is an open file descriptor, suitable for reading
131 * Last LBA value on success
134 * Try getting BLKGETSIZE64 and BLKSSZGET first,
135 * then BLKGETSIZE if necessary.
136 * Kernels 2.4.15-2.4.18 and 2.5.0-2.5.3 have a broken BLKGETSIZE64
137 * which returns the number of 512-byte sectors, not the size of
138 * the disk in bytes. Fixed in kernels 2.4.18-pre8 and 2.5.4-pre3.
139 ************************************************************/
141 _get_num_sectors(int filedes)
143 unsigned long sectors=0;
146 if (kernel_has_blkgetsize64()) {
147 rc = ioctl(filedes, BLKGETSIZE64, &bytes);
149 return bytes / get_sector_size(filedes);
152 rc = ioctl(filedes, BLKGETSIZE, §ors);
159 /************************************************************
160 * last_lba(): return number of last logical block of device
164 * Description: returns Last LBA value on success, 0 on error.
165 * Notes: The value st_blocks gives the size of the file
166 * in 512-byte blocks, which is OK if
167 * EFI_BLOCK_SIZE_SHIFT == 9.
168 ************************************************************/
171 last_lba(int filedes)
174 uint64_t sectors = 0;
176 memset(&s, 0, sizeof (s));
177 rc = fstat(filedes, &s);
179 fprintf(stderr, "last_lba() could not stat: %s\n",
184 if (S_ISBLK(s.st_mode)) {
185 sectors = _get_num_sectors(filedes);
188 "last_lba(): I don't know how to handle files with mode %x\n",
198 read_lastoddsector(int fd, uint64_t lba, void *buffer, size_t count)
201 struct blkdev_ioctl_param ioctl_param;
203 if (!buffer) return 0;
205 ioctl_param.block = 0; /* read the last sector */
206 ioctl_param.content_length = count;
207 ioctl_param.block_contents = buffer;
209 rc = ioctl(fd, BLKGETLASTSECT, &ioctl_param);
210 if (rc == -1) perror("read failed");
216 read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
218 int sector_size = get_sector_size(fd);
219 off_t offset = lba * sector_size;
224 if (bytes % sector_size)
227 unaligned = malloc(bytes+sector_size-1);
229 (((unsigned long)unaligned + sector_size - 1) &
230 ~(unsigned long)(sector_size-1));
231 memset(aligned, 0, bytes);
234 lseek(fd, offset, SEEK_SET);
235 bytesread = read(fd, aligned, bytes);
236 memcpy(buffer, aligned, bytesread);
239 /* Kludge. This is necessary to read/write the last
240 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
241 This is only used by gpt.c, and only to read
242 one sector, so we don't have to be fancy.
244 if (!bytesread && !(last_lba(fd) & 1) && lba == last_lba(fd)) {
245 bytesread = read_lastoddsector(fd, lba, buffer, bytes);
251 * alloc_read_gpt_entries(): reads partition entries from disk
252 * @fd is an open file descriptor to the whole disk
253 * @gpt is a buffer into which the GPT will be put
254 * Description: Returns ptes on success, NULL on error.
255 * Allocates space for PTEs based on information found in @gpt.
256 * Notes: remember to free pte when you're done!
259 alloc_read_gpt_entries(int fd, gpt_header * gpt)
262 size_t count = __le32_to_cpu(gpt->num_partition_entries) *
263 __le32_to_cpu(gpt->sizeof_partition_entry);
265 if (!count) return NULL;
267 pte = (gpt_entry *)malloc(count);
270 memset(pte, 0, count);
272 if (!read_lba(fd, __le64_to_cpu(gpt->partition_entry_lba), pte,
281 * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
282 * @fd is an open file descriptor to the whole disk
283 * @lba is the Logical Block Address of the partition table
285 * Description: returns GPT header on success, NULL on error. Allocates
286 * and fills a GPT header starting at @ from @bdev.
287 * Note: remember to free gpt when finished with it.
290 alloc_read_gpt_header(int fd, uint64_t lba)
294 malloc(sizeof (gpt_header));
297 memset(gpt, 0, sizeof (*gpt));
298 if (!read_lba(fd, lba, gpt, sizeof (gpt_header))) {
307 * is_gpt_valid() - tests one GPT header and PTEs for validity
308 * @fd is an open file descriptor to the whole disk
309 * @lba is the logical block address of the GPT header to test
310 * @gpt is a GPT header ptr, filled on return.
311 * @ptes is a PTEs ptr, filled on return.
313 * Description: returns 1 if valid, 0 on error.
314 * If valid, returns pointers to newly allocated GPT header and PTEs.
317 is_gpt_valid(int fd, uint64_t lba,
318 gpt_header ** gpt, gpt_entry ** ptes)
320 int rc = 0; /* default to not valid */
321 uint32_t crc, origcrc;
325 if (!(*gpt = alloc_read_gpt_header(fd, lba)))
328 /* Check the GUID Partition Table signature */
329 if (__le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
331 printf("GUID Partition Table Header signature is wrong: %" PRIx64" != %" PRIx64 "\n",
332 __le64_to_cpu((*gpt)->signature), GUID_PT_HEADER_SIGNATURE);
339 /* Check the GUID Partition Table Header CRC */
340 origcrc = __le32_to_cpu((*gpt)->header_crc32);
341 (*gpt)->header_crc32 = 0;
342 crc = efi_crc32(*gpt, __le32_to_cpu((*gpt)->header_size));
343 if (crc != origcrc) {
344 // printf( "GPTH CRC check failed, %x != %x.\n", origcrc, crc);
345 (*gpt)->header_crc32 = __cpu_to_le32(origcrc);
350 (*gpt)->header_crc32 = __cpu_to_le32(origcrc);
352 /* Check that the my_lba entry points to the LBA
353 * that contains the GPT we read */
354 if (__le64_to_cpu((*gpt)->my_lba) != lba) {
355 // printf( "my_lba % PRIx64 "x != lba %"PRIx64 "x.\n", __le64_to_cpu((*gpt)->my_lba), lba);
361 if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) {
367 /* Check the GUID Partition Entry Array CRC */
368 crc = efi_crc32(*ptes,
369 __le32_to_cpu((*gpt)->num_partition_entries) *
370 __le32_to_cpu((*gpt)->sizeof_partition_entry));
371 if (crc != __le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
372 // printf("GUID Partitition Entry Array CRC check failed.\n");
380 /* We're done, all's well */
384 * compare_gpts() - Search disk for valid GPT headers and PTEs
385 * @pgpt is the primary GPT header
386 * @agpt is the alternate GPT header
387 * @lastlba is the last LBA number
388 * Description: Returns nothing. Sanity checks pgpt and agpt fields
389 * and prints warnings on discrepancies.
393 compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
398 if (__le64_to_cpu(pgpt->my_lba) != __le64_to_cpu(agpt->alternate_lba)) {
400 "GPT:Primary header LBA != Alt. header alternate_lba\n");
401 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
402 __le64_to_cpu(pgpt->my_lba),
403 __le64_to_cpu(agpt->alternate_lba));
406 if (__le64_to_cpu(pgpt->alternate_lba) != __le64_to_cpu(agpt->my_lba)) {
408 "GPT:Primary header alternate_lba != Alt. header my_lba\n");
409 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
410 __le64_to_cpu(pgpt->alternate_lba),
411 __le64_to_cpu(agpt->my_lba));
414 if (__le64_to_cpu(pgpt->first_usable_lba) !=
415 __le64_to_cpu(agpt->first_usable_lba)) {
416 fprintf(stderr, "GPT:first_usable_lbas don't match.\n");
417 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
418 __le64_to_cpu(pgpt->first_usable_lba),
419 __le64_to_cpu(agpt->first_usable_lba));
422 if (__le64_to_cpu(pgpt->last_usable_lba) !=
423 __le64_to_cpu(agpt->last_usable_lba)) {
424 fprintf(stderr, "GPT:last_usable_lbas don't match.\n");
425 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" 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)) {
431 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)) {
436 fprintf(stderr, "GPT:num_partition_entries don't match: "
438 __le32_to_cpu(pgpt->num_partition_entries),
439 __le32_to_cpu(agpt->num_partition_entries));
442 if (__le32_to_cpu(pgpt->sizeof_partition_entry) !=
443 __le32_to_cpu(agpt->sizeof_partition_entry)) {
445 "GPT:sizeof_partition_entry values don't match: "
447 __le32_to_cpu(pgpt->sizeof_partition_entry),
448 __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)) {
454 "GPT:partition_entry_array_crc32 values don't match: "
456 __le32_to_cpu(pgpt->partition_entry_array_crc32),
457 __le32_to_cpu(agpt->partition_entry_array_crc32));
460 if (__le64_to_cpu(pgpt->alternate_lba) != lastlba) {
462 "GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
463 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
464 __le64_to_cpu(pgpt->alternate_lba), lastlba);
468 if (__le64_to_cpu(agpt->my_lba) != lastlba) {
470 "GPT:Alternate GPT header not at the end of the disk.\n");
471 fprintf(stderr, "GPT:0x%" PRIx64 " != 0x%" PRIx64 "\n",
472 __le64_to_cpu(agpt->my_lba), lastlba);
478 "GPT: Use GNU Parted to correct GPT errors.\n");
483 * find_valid_gpt() - Search disk for valid GPT headers and PTEs
484 * @fd is an open file descriptor to the whole disk
485 * @gpt is a GPT header ptr, filled on return.
486 * @ptes is a PTEs ptr, filled on return.
487 * Description: Returns 1 if valid, 0 on error.
488 * If valid, returns pointers to newly allocated GPT header and PTEs.
489 * Validity depends on finding either the Primary GPT header and PTEs valid,
490 * or the Alternate GPT header and PTEs valid, and the PMBR valid.
493 find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
495 int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
496 gpt_header *pgpt = NULL, *agpt = NULL;
497 gpt_entry *pptes = NULL, *aptes = NULL;
498 legacy_mbr *legacymbr = NULL;
503 lastlba = last_lba(fd);
504 good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA,
507 good_agpt = is_gpt_valid(fd,
508 __le64_to_cpu(pgpt->alternate_lba),
511 good_agpt = is_gpt_valid(fd, lastlba,
516 good_agpt = is_gpt_valid(fd, lastlba,
520 /* The obviously unsuccessful case */
521 if (!good_pgpt && !good_agpt) {
525 /* This will be added to the EFI Spec. per Intel after v1.02. */
526 legacymbr = malloc(sizeof (*legacymbr));
528 memset(legacymbr, 0, sizeof (*legacymbr));
529 read_lba(fd, 0, (uint8_t *) legacymbr,
530 sizeof (*legacymbr));
531 good_pmbr = is_pmbr_valid(legacymbr);
536 /* Failure due to bad PMBR */
537 if ((good_pgpt || good_agpt) && !good_pmbr && !opts.forcegpt) {
539 " Warning: Disk has a valid GPT signature "
540 "but invalid PMBR.\n"
541 " Assuming this disk is *not* a GPT disk anymore.\n"
542 " Use gpt kernel option to override. "
543 "Use GNU Parted to correct disk.\n");
547 /* Would fail due to bad PMBR, but force GPT anyhow */
548 if ((good_pgpt || good_agpt) && !good_pmbr && opts.forcegpt) {
550 " Warning: Disk has a valid GPT signature but "
552 " Use GNU Parted to correct disk.\n"
553 " gpt option taken, disk treated as GPT.\n");
556 compare_gpts(pgpt, agpt, lastlba);
559 if (good_pgpt && (good_pmbr || opts.forcegpt)) {
562 if (agpt) { free(agpt); agpt = NULL; }
563 if (aptes) { free(aptes); aptes = NULL; }
566 "Alternate GPT is invalid, "
567 "using primary GPT.\n");
571 else if (good_agpt && (good_pmbr || opts.forcegpt)) {
574 if (pgpt) { free(pgpt); pgpt = NULL; }
575 if (pptes) { free(pptes); pptes = NULL; }
577 "Primary GPT is invalid, using alternate GPT.\n");
582 if (pgpt) { free(pgpt); pgpt=NULL; }
583 if (agpt) { free(agpt); agpt=NULL; }
584 if (pptes) { free(pptes); pptes=NULL; }
585 if (aptes) { free(aptes); aptes=NULL; }
592 /************************************************************
593 * gpt_disk_get_partition_info()
595 * - open file descriptor fd
596 * - start, size, signature, mbr_type, signature_type
597 * Modifies: all these
600 * non-zero on failure
602 ************************************************************/
604 gpt_disk_get_partition_info(int fd,
606 uint64_t * start, uint64_t * size,
608 uint8_t * mbr_type, uint8_t * signature_type)
610 gpt_header *gpt = NULL;
611 gpt_entry *ptes = NULL, *p;
613 if (!find_valid_gpt(fd, &gpt, &ptes))
617 *signature_type = 0x02;
619 if (num > 0 && num <= __le32_to_cpu(gpt->num_partition_entries)) {
621 *start = __le64_to_cpu(p->starting_lba);
622 *size = __le64_to_cpu(p->ending_lba) -
623 __le64_to_cpu(p->starting_lba) + 1;
624 memcpy(signature, &p->unique_partition_guid,
625 sizeof (p->unique_partition_guid));
627 fprintf (stderr,"partition %d is not valid\n", num);
634 * Overrides for Emacs so that we follow Linus's tabbing style.
635 * Emacs will notice this stuff at the end of the file and automatically
636 * adjust the settings for this buffer only. This must remain at the end
638 * ---------------------------------------------------------------------------
641 * c-brace-imaginary-offset: 0
643 * c-argdecl-indent: 4
645 * c-continued-statement-offset: 4
646 * c-continued-brace-offset: 0
647 * indent-tabs-mode: nil