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>
37 #include <asm/byteorder.h>
40 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
41 #define BLKGETSIZE _IO(0x12,96) /* return device size */
42 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
43 #define BLKGETSIZE64 _IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
45 struct blkdev_ioctl_param {
47 size_t content_length;
48 char * block_contents;
52 * efi_crc32() - EFI version of crc32 function
53 * @buf: buffer to calculate crc32 of
54 * @len - length of buf
56 * Description: Returns EFI-style CRC32 value for @buf
58 * This function uses the little endian Ethernet polynomial
59 * but seeds the function with ~0, and xor's with ~0 at the end.
60 * Note, the EFI Specification, v1.02, has a reference to
61 * Dr. Dobbs Journal, May 1994 (actually it's in May 1992).
63 static inline uint32_t
64 efi_crc32(const void *buf, unsigned long len)
66 return (crc32(~0L, buf, len) ^ ~0L);
70 * is_pmbr_valid(): test Protective MBR for validity
71 * @mbr: pointer to a legacy mbr structure
73 * Description: Returns 1 if PMBR is valid, 0 otherwise.
74 * Validity depends on two things:
75 * 1) MSDOS signature is in the last two bytes of the MBR
76 * 2) One partition of type 0xEE is found
79 is_pmbr_valid(legacy_mbr *mbr)
81 int i, found = 0, signature = 0;
84 signature = (__le16_to_cpu(mbr->signature) == MSDOS_MBR_SIGNATURE);
85 for (i = 0; signature && i < 4; i++) {
86 if (mbr->partition[i].sys_type ==
87 EFI_PMBR_OSTYPE_EFI_GPT) {
92 return (signature && found);
96 /************************************************************
99 * - filedes is an open file descriptor, suitable for reading
102 * sector size, or 512.
103 ************************************************************/
105 get_sector_size(int filedes)
107 int rc, sector_size = 512;
109 rc = ioctl(filedes, BLKSSZGET, §or_size);
115 /************************************************************
118 * - filedes is an open file descriptor, suitable for reading
121 * Last LBA value on success
124 * Try getting BLKGETSIZE64 and BLKSSZGET first,
125 * then BLKGETSIZE if necessary.
126 * Kernels 2.4.15-2.4.18 and 2.5.0-2.5.3 have a broken BLKGETSIZE64
127 * which returns the number of 512-byte sectors, not the size of
128 * the disk in bytes. Fixed in kernels 2.4.18-pre8 and 2.5.4-pre3.
129 ************************************************************/
131 _get_num_sectors(int filedes)
133 unsigned long sectors=0;
138 rc = ioctl(filedes, BLKGETSIZE64, &bytes);
140 return bytes / get_sector_size(filedes);
142 rc = ioctl(filedes, BLKGETSIZE, §ors);
149 /************************************************************
150 * last_lba(): return number of last logical block of device
154 * Description: returns Last LBA value on success, 0 on error.
155 * Notes: The value st_blocks gives the size of the file
156 * in 512-byte blocks, which is OK if
157 * EFI_BLOCK_SIZE_SHIFT == 9.
158 ************************************************************/
161 last_lba(int filedes)
164 uint64_t sectors = 0;
166 memset(&s, 0, sizeof (s));
167 rc = fstat(filedes, &s);
169 fprintf(stderr, "last_lba() could not stat: %s\n",
174 if (S_ISBLK(s.st_mode)) {
175 sectors = _get_num_sectors(filedes);
178 "last_lba(): I don't know how to handle files with mode %x\n",
188 read_lastoddsector(int fd, uint64_t lba, void *buffer, size_t count)
191 struct blkdev_ioctl_param ioctl_param;
193 if (!buffer) return 0;
195 ioctl_param.block = 0; /* read the last sector */
196 ioctl_param.content_length = count;
197 ioctl_param.block_contents = buffer;
199 rc = ioctl(fd, BLKGETLASTSECT, &ioctl_param);
200 if (rc == -1) perror("read failed");
206 read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
208 int sector_size = get_sector_size(fd);
209 off_t offset = lba * sector_size;
212 lseek(fd, offset, SEEK_SET);
213 bytesread = read(fd, buffer, bytes);
215 /* Kludge. This is necessary to read/write the last
216 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
217 This is only used by gpt.c, and only to read
218 one sector, so we don't have to be fancy.
220 if (!bytesread && !(last_lba(fd) & 1) && lba == last_lba(fd)) {
221 bytesread = read_lastoddsector(fd, lba, buffer, bytes);
227 * alloc_read_gpt_entries(): reads partition entries from disk
228 * @fd is an open file descriptor to the whole disk
229 * @gpt is a buffer into which the GPT will be put
230 * Description: Returns ptes on success, NULL on error.
231 * Allocates space for PTEs based on information found in @gpt.
232 * Notes: remember to free pte when you're done!
235 alloc_read_gpt_entries(int fd, gpt_header * gpt)
238 size_t count = __le32_to_cpu(gpt->num_partition_entries) *
239 __le32_to_cpu(gpt->sizeof_partition_entry);
241 if (!count) return NULL;
243 pte = (gpt_entry *)malloc(count);
246 memset(pte, 0, count);
248 if (!read_lba(fd, __le64_to_cpu(gpt->partition_entry_lba), pte,
257 * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
258 * @fd is an open file descriptor to the whole disk
259 * @lba is the Logical Block Address of the partition table
261 * Description: returns GPT header on success, NULL on error. Allocates
262 * and fills a GPT header starting at @ from @bdev.
263 * Note: remember to free gpt when finished with it.
266 alloc_read_gpt_header(int fd, uint64_t lba)
270 malloc(sizeof (gpt_header));
273 memset(gpt, 0, sizeof (*gpt));
274 if (!read_lba(fd, lba, gpt, sizeof (gpt_header))) {
283 * is_gpt_valid() - tests one GPT header and PTEs for validity
284 * @fd is an open file descriptor to the whole disk
285 * @lba is the logical block address of the GPT header to test
286 * @gpt is a GPT header ptr, filled on return.
287 * @ptes is a PTEs ptr, filled on return.
289 * Description: returns 1 if valid, 0 on error.
290 * If valid, returns pointers to newly allocated GPT header and PTEs.
293 is_gpt_valid(int fd, uint64_t lba,
294 gpt_header ** gpt, gpt_entry ** ptes)
296 int rc = 0; /* default to not valid */
297 uint32_t crc, origcrc;
301 if (!(*gpt = alloc_read_gpt_header(fd, lba)))
304 /* Check the GUID Partition Table signature */
305 if (__le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
307 printf("GUID Partition Table Header signature is wrong: %" PRIx64" != %" PRIx64 "\n",
308 __le64_to_cpu((*gpt)->signature), GUID_PT_HEADER_SIGNATURE);
315 /* Check the GUID Partition Table Header CRC */
316 origcrc = __le32_to_cpu((*gpt)->header_crc32);
317 (*gpt)->header_crc32 = 0;
318 crc = efi_crc32(*gpt, __le32_to_cpu((*gpt)->header_size));
319 if (crc != origcrc) {
320 // printf( "GPTH CRC check failed, %x != %x.\n", origcrc, crc);
321 (*gpt)->header_crc32 = __cpu_to_le32(origcrc);
326 (*gpt)->header_crc32 = __cpu_to_le32(origcrc);
328 /* Check that the my_lba entry points to the LBA
329 * that contains the GPT we read */
330 if (__le64_to_cpu((*gpt)->my_lba) != lba) {
332 printf( "my_lba % PRIx64 "x != lba %"PRIx64 "x.\n",
333 __le64_to_cpu((*gpt)->my_lba), lba);
340 if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) {
346 /* Check the GUID Partition Entry Array CRC */
347 crc = efi_crc32(*ptes,
348 __le32_to_cpu((*gpt)->num_partition_entries) *
349 __le32_to_cpu((*gpt)->sizeof_partition_entry));
350 if (crc != __le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
351 // printf("GUID Partitition Entry Array CRC check failed.\n");
359 /* We're done, all's well */
363 * compare_gpts() - Search disk for valid GPT headers and PTEs
364 * @pgpt is the primary GPT header
365 * @agpt is the alternate GPT header
366 * @lastlba is the last LBA number
367 * Description: Returns nothing. Sanity checks pgpt and agpt fields
368 * and prints warnings on discrepancies.
372 compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
377 if (__le64_to_cpu(pgpt->my_lba) != __le64_to_cpu(agpt->alternate_lba)) {
380 "GPT:Primary header LBA != Alt. header alternate_lba\n");
382 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
383 __le64_to_cpu(pgpt->my_lba),
384 __le64_to_cpu(agpt->alternate_lba));
387 if (__le64_to_cpu(pgpt->alternate_lba) != __le64_to_cpu(agpt->my_lba)) {
390 "GPT:Primary header alternate_lba != Alt. header my_lba\n");
392 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
393 __le64_to_cpu(pgpt->alternate_lba),
394 __le64_to_cpu(agpt->my_lba));
397 if (__le64_to_cpu(pgpt->first_usable_lba) !=
398 __le64_to_cpu(agpt->first_usable_lba)) {
400 fprintf(stderr, "GPT:first_usable_lbas don't match.\n");
402 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
403 __le64_to_cpu(pgpt->first_usable_lba),
404 __le64_to_cpu(agpt->first_usable_lba));
407 if (__le64_to_cpu(pgpt->last_usable_lba) !=
408 __le64_to_cpu(agpt->last_usable_lba)) {
410 fprintf(stderr, "GPT:last_usable_lbas don't match.\n");
412 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
413 __le64_to_cpu(pgpt->last_usable_lba),
414 __le64_to_cpu(agpt->last_usable_lba));
417 if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
419 fprintf(stderr, "GPT:disk_guids don't match.\n");
421 if (__le32_to_cpu(pgpt->num_partition_entries) !=
422 __le32_to_cpu(agpt->num_partition_entries)) {
424 fprintf(stderr, "GPT:num_partition_entries don't match: "
426 __le32_to_cpu(pgpt->num_partition_entries),
427 __le32_to_cpu(agpt->num_partition_entries));
429 if (__le32_to_cpu(pgpt->sizeof_partition_entry) !=
430 __le32_to_cpu(agpt->sizeof_partition_entry)) {
433 "GPT:sizeof_partition_entry values don't match: "
435 __le32_to_cpu(pgpt->sizeof_partition_entry),
436 __le32_to_cpu(agpt->sizeof_partition_entry));
438 if (__le32_to_cpu(pgpt->partition_entry_array_crc32) !=
439 __le32_to_cpu(agpt->partition_entry_array_crc32)) {
442 "GPT:partition_entry_array_crc32 values don't match: "
444 __le32_to_cpu(pgpt->partition_entry_array_crc32),
445 __le32_to_cpu(agpt->partition_entry_array_crc32));
447 if (__le64_to_cpu(pgpt->alternate_lba) != lastlba) {
450 "GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
452 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
453 __le64_to_cpu(pgpt->alternate_lba), lastlba);
457 if (__le64_to_cpu(agpt->my_lba) != lastlba) {
460 "GPT:Alternate GPT header not at the end of the disk.\n");
462 fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
463 __le64_to_cpu(agpt->my_lba), lastlba);
469 "GPT: Use GNU Parted to correct GPT errors.\n");
474 * find_valid_gpt() - Search disk for valid GPT headers and PTEs
475 * @fd is an open file descriptor to the whole disk
476 * @gpt is a GPT header ptr, filled on return.
477 * @ptes is a PTEs ptr, filled on return.
478 * Description: Returns 1 if valid, 0 on error.
479 * If valid, returns pointers to newly allocated GPT header and PTEs.
480 * Validity depends on finding either the Primary GPT header and PTEs valid,
481 * or the Alternate GPT header and PTEs valid, and the PMBR valid.
484 find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
486 extern int force_gpt;
487 int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
488 gpt_header *pgpt = NULL, *agpt = NULL;
489 gpt_entry *pptes = NULL, *aptes = NULL;
490 legacy_mbr *legacymbr = NULL;
495 lastlba = last_lba(fd);
496 good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA,
499 good_agpt = is_gpt_valid(fd,
500 __le64_to_cpu(pgpt->alternate_lba),
503 good_agpt = is_gpt_valid(fd, lastlba,
508 good_agpt = is_gpt_valid(fd, lastlba,
512 /* The obviously unsuccessful case */
513 if (!good_pgpt && !good_agpt) {
517 /* This will be added to the EFI Spec. per Intel after v1.02. */
518 legacymbr = malloc(sizeof (*legacymbr));
520 memset(legacymbr, 0, sizeof (*legacymbr));
521 read_lba(fd, 0, (uint8_t *) legacymbr,
522 sizeof (*legacymbr));
523 good_pmbr = is_pmbr_valid(legacymbr);
528 /* Failure due to bad PMBR */
529 if ((good_pgpt || good_agpt) && !good_pmbr && !force_gpt) {
531 " Warning: Disk has a valid GPT signature "
532 "but invalid PMBR.\n"
533 " Assuming this disk is *not* a GPT disk anymore.\n"
534 " Use gpt kernel option to override. "
535 "Use GNU Parted to correct disk.\n");
539 /* Would fail due to bad PMBR, but force GPT anyhow */
540 if ((good_pgpt || good_agpt) && !good_pmbr && force_gpt) {
542 " Warning: Disk has a valid GPT signature but "
544 " Use GNU Parted to correct disk.\n"
545 " gpt option taken, disk treated as GPT.\n");
548 compare_gpts(pgpt, agpt, lastlba);
551 if (good_pgpt && (good_pmbr || force_gpt)) {
554 if (agpt) { free(agpt); agpt = NULL; }
555 if (aptes) { free(aptes); aptes = NULL; }
558 "Alternate GPT is invalid, "
559 "using primary GPT.\n");
563 else if (good_agpt && (good_pmbr || force_gpt)) {
566 if (pgpt) { free(pgpt); pgpt = NULL; }
567 if (pptes) { free(pptes); pptes = NULL; }
569 "Primary GPT is invalid, using alternate GPT.\n");
574 if (pgpt) { free(pgpt); pgpt=NULL; }
575 if (agpt) { free(agpt); agpt=NULL; }
576 if (pptes) { free(pptes); pptes=NULL; }
577 if (aptes) { free(aptes); aptes=NULL; }
586 * @all - slice with start/size of whole disk
588 * 0 if this isn't our partition table
589 * number of partitions if successful
593 read_gpt_pt (int fd, struct slice all, struct slice *sp, int ns)
595 gpt_header *gpt = NULL;
596 gpt_entry *ptes = NULL;
599 int last_used_index=-1;
601 if (!find_valid_gpt (fd, &gpt, &ptes) || !gpt || !ptes) {
609 for (i = 0; i < __le32_to_cpu(gpt->num_partition_entries) && i < ns; i++) {
610 if (!efi_guidcmp (NULL_GUID, ptes[i].partition_type_guid)) {
615 sp[n].start = __le64_to_cpu(ptes[i].starting_lba);
616 sp[n].size = __le64_to_cpu(ptes[i].ending_lba) -
617 __le64_to_cpu(ptes[i].starting_lba) + 1;
624 return last_used_index+1;