gpt.c revision 1
1N/A libparted - a library for manipulating disk partitions 1N/A original version by Matt Domsch <Matt_Domsch@dell.com> 1N/A Disclaimed into the Public Domain 1N/A Portions Copyright (C) 2001-2003, 2005-2010 Free Software Foundation, Inc. 1N/A EFI GUID Partition Table handling 1N/A Per Intel EFI Specification v1.02 1N/A This program is free software; you can redistribute it and/or modify 1N/A it under the terms of the GNU General Public License as published by 1N/A the Free Software Foundation; either version 3 of the License, or 1N/A (at your option) any later version. 1N/A This program is distributed in the hope that it will be useful, 1N/A but WITHOUT ANY WARRANTY; without even the implied warranty of 1N/A MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1N/A GNU General Public License for more details. 1N/A You should have received a copy of the GNU General Public License 1N/A#
endif /* ENABLE_NLS */ 1N/A/* NOTE: the document that describes revision 1.00 is labelled "version 1.02", 1N/A * so some implementors got confused... 1N/A/* commented out "__attribute__ ((packed))" to work around gcc bug (fixed 1N/A * in gcc3.1): __attribute__ ((packed)) breaks addressing on initialized 1N/A * data. It turns out we don't need it in this case, so it doesn't break 1N/A {
0x00,
0x00,
0x00,
0x00,
0x00,
0x00 }})
1N/A {
0x00,
0xA0,
0xC9,
0x3E,
0xC9,
0x3B }})
1N/A {
0x65,
0x65,
0x64,
0x45,
0x46,
0x49 }})
1N/A {
0x00,
0x08,
0xC7,
0x81,
0xF3,
0x9F }})
1N/A {
0xF9,
0x2D,
0xF0,
0x02,
0x15,
0xAE }})
1N/A {
0xBF,
0xD5,
0x01,
0x79,
0xD6,
0xAC }})
1N/A {
0x68,
0xB6,
0xB7,
0x26,
0x99,
0xC7 }})
1N/A {
0x74,
0x3f,
0x0f,
0x84,
0x91,
0x1e }})
1N/A {
0x09,
0x33,
0xc8,
0x4b,
0x4f,
0x4f }})
1N/A {
0x23,
0x8f,
0x2a,
0x3d,
0xf9,
0x28 }})
1N/A {
0x08,
0x3a,
0xc8,
0x23,
0x09,
0x08 }})
1N/A {
0x7b,
0x03,
0xa0,
0x00,
0x00,
0x00 }})
1N/A {
0x00,
0x30,
0x65,
0x43,
0xEC,
0xAC }})
1N/A {
0x00,
0x30,
0x65,
0x43,
0xEC,
0xAC }})
1N/A These values are only defaults. The actual on-disk structures 1N/A may define different sizes, so use those unless creating a new GPT disk! 1N/A/* Number of actual partition entries should be calculated as: */ 1N/A /* Not used by EFI firmware. Set to 0x80 to indicate that this 1N/A is the bootable legacy partition. */ 1N/A /* Start of partition in CHS address, not used by EFI firmware. */ 1N/A /* Start of partition in CHS address, not used by EFI firmware. */ 1N/A /* Start of partition in CHS address, not used by EFI firmware. */ 1N/A /* OS type. A value of 0xEF defines an EFI system partition. 1N/A Other values are reserved for legacy operating systems, and 1N/A allocated independently of the EFI specification. */ 1N/A /* End of partition in CHS address, not used by EFI firmware. */ 1N/A /* End of partition in CHS address, not used by EFI firmware. */ 1N/A /* End of partition in CHS address, not used by EFI firmware. */ 1N/A /* Starting LBA address of the partition on the disk. Used by 1N/A EFI firmware to define the start of the partition. */ 1N/A /* Size of partition in LBA. Used by EFI firmware to determine 1N/A the size of the partition. */ 1N/A/* Protected Master Boot Record & Legacy MBR share same structure */ 1N/A/* Needs to be packed because the u16s force misalignment. */ 1N/A/* uses libparted's disk_specific field in PedDisk, to store our info */ 1N/A/* uses libparted's disk_specific field in PedPartition, to store our info */ 1N/A * swap_uuid_and_efi_guid() - converts between uuid formats 1N/A * @uuid - uuid_t in either format (converts it to the other) 1N/A * There are two different representations for Globally Unique Identifiers 1N/A * The RFC specifies a UUID as a string of 16 bytes, essentially 1N/A * a big-endian array of char. 1N/A * Intel, in their EFI Specification, references the same RFC, but 1N/A * then defines a GUID as a structure of little-endian fields. 1N/A * Coincidentally, both structures have the same format when unparsed. 1N/A * When read from disk, EFI GUIDs are in struct of little endian format, 1N/A * and need to be converted to be treated as uuid_t in memory. 1N/A * When writing to disk, uuid_ts need to be converted into EFI GUIDs. 1N/A/* returns the EFI-style CRC32 value for buf 1N/A * This function uses the crc32 function by Gary S. Brown, 1N/A * but seeds the function with ~0, and xor's with ~0 at the end. 1N/A/* Compute the crc32 checksum of the partition table header 1N/A and store it in *CRC32. Return 0 upon success. Return 1 1N/A upon failure to allocate space. */ 1N/A/* checks if 'mbr' is a protective MBR partition table */ 1N/A for (i = 0; i <
4; i++)
1N/A _(
"%s contains GPT signatures, indicating that it has " 1N/A "a GPT table. However, it does not have a valid " 1N/A "fake msdos partition table, as it should. Perhaps " 1N/A "it was corrupted -- possibly by a program that " 1N/A "doesn't understand GPT partition tables. Or " 1N/A "perhaps you deleted the GPT table, and are now " 1N/A "using an msdos partition table. Is this a GPT " 1N/A "partition table?"),
1N/A/* Given GUID Partition table header, GPT, read its partition array 1N/A entries from DISK into malloc'd storage. Set *PTES_BYTES to the 1N/A number of bytes required. Upon success, return a pointer to the 1N/A resulting buffer. Otherwise, set errno and return NULL. */ 1N/A * "While the GUID Partition Table Header's size may increase 1N/A * in the future it cannot span more than one block on the 1N/A * device." EFI Specification, version 1.10, 11.2.2.1 1N/A /* The SizeOfPartitionEntry must be a multiple of 8 and 1N/A no smaller than the size of the PartitionEntry structure. 1N/A We also require that be no larger than 1/16th of UINT32_MAX, 1N/A as an additional sanity check. */ 1N/A /* The backup table's AlternateLBA must be 1. */ 1N/A /* The alt_lba must never be the same as my_lba. */ 1N/A _(
"The format of the GPT partition table is version " 1N/A "%x, which is newer than what Parted can " 1N/A "recognise. Please tell us! bug-parted@gnu.org"),
1N/A /* Need to check whether the volume has grown, the LastUsableLBA is 1N/A normally set to disk->dev->length - 2 - ptes_size (at least for parted 1N/A created volumes), where ptes_size is the number of entries * 1N/A size of each entry / sector size or 16k / sector size, whatever the greater. 1N/A If the volume has grown, offer the user the chance to use the new 1N/A space or continue with the current usable area. Only ask once per 1N/A parted invocation. */ 1N/A _(
"Not all of the space available to %s appears " 1N/A "to be used, you can fix the GPT to use all of the " 1N/A "space (an extra %llu blocks) or continue with the " 1N/A/* Read the primary GPT at sector 1 of DEV. 1N/A Verify its CRC and that of its partition entry array. 1N/A If they are valid, read the backup GPT specified by AlternateLBA. 1N/A If not, read the backup GPT in the last sector of the disk. 1N/A Return 1 if any read fails. 1N/A Upon successful verification of the primary GPT, set *PRIMARY_GPT, else NULL. 1N/A Upon successful verification of the backup GPT, set *BACKUP_GPT, else NULL. 1N/A If we've set *BACKUP_GPT to non-NULL, set *BACKUP_LBA to the sector 1N/A number in which it was found. */ 1N/A/************************************************************ 1N/A * Intel is changing the EFI Spec. (after v1.02) to say that a 1N/A * disk is considered to have a GPT label only if the GPT 1N/A * structures are correct, and the MBR is actually a Protective 1N/A * MBR (has one 0xEE type partition). 1N/A * Problem occurs when a GPT-partitioned disk is then 1N/A * edited with a legacy (non-GPT-aware) application, such as 1N/A * fdisk (which doesn't generally erase the PGPT or AGPT). 1N/A * How should such a disk get handled? As a GPT disk (throwing 1N/A * away the fdisk changes), or as an MSDOS disk (throwing away 1N/A * the GPT information). Previously, I've taken the GPT-is-right, 1N/A * MBR is wrong, approach, to stay consistent with the EFI Spec. 1N/A * Intel disagrees, saying the disk should then be treated 1N/A * as having a msdos label, not a GPT label. If this is true, 1N/A * then what's the point of having an AGPT, since if the PGPT 1N/A * is screwed up, likely the PMBR is too, and the PMBR becomes 1N/A * a single point of failure. 1N/A * So, in the Linux kernel, I'm going to test for PMBR, and 1N/A * warn if it's not there, and treat the disk as MSDOS, with a note 1N/A * for users to use Parted to "fix up" their disk if they 1N/A * really want it to be considered GPT. 1N/A ************************************************************/ 1N/A /* motivation: let the user decide about the pmbr... during 1N/A ped_disk_probe(), they probably didn't get a choice... */ 1N/A /* This includes the case in which there used to be a GPT partition 1N/A table here, with an alternate LBA that extended beyond the current 1N/A end-of-device. It's treated as a non-match. */ 1N/A /* Another possibility: 1N/A The primary header is ok, but backup is corrupt. 1N/A In the UEFI spec, this means the primary GUID table 1N/A is officially invalid. */ 1N/A /* Both are valid. */ 1N/A _(
"The backup GPT table is not at the end of the disk, as it " 1N/A "should be. This might mean that another operating system " 1N/A "believes the disk is smaller. Fix, by moving the backup " 1N/A "to the end (and removing the old backup)?")))
1N/A#
endif /* !DISCOVER_ONLY */ 1N/A /* Both are corrupt. */ 1N/A _(
"Both the primary and backup GPT tables " 1N/A "are corrupt. Try making a fresh table, " 1N/A "and using Parted's rescue feature to " 1N/A "recover partitions."));
1N/A /* The primary header is ok, but backup is corrupt. */ 1N/A _(
"The backup GPT table is corrupt, but the " 1N/A "primary appears OK, so that will be used."))
1N/A else /* !primary_gpt && backup_gpt */ 1N/A /* primary GPT corrupt, backup is ok. */ 1N/A _(
"The primary GPT table is corrupt, but the " 1N/A "backup appears OK, so that will be used."))
1N/A _(
"primary partition table array CRC mismatch"));
1N/A/* Write the protective MBR (to keep DOS happy) */ 1N/A /* The UEFI spec is not clear about what to do with the following 1N/A elements of the Protective MBR (pmbr): BootCode (0-440B), 1N/A UniqueMBRSignature (440B-444B) and Unknown (444B-446B). 1N/A With this in mind, we try not to modify these elements. */ 1N/A /* Zero out the legacy partitions. */ 1N/A /* Write protective MBR */ 1N/A /* Write PTH and PTEs */ 1N/A /* FIXME: Caution: this code is nearly identical to what's just below. */ 1N/A /* Write Alternate PTH & PTEs */ 1N/A /* FIXME: Caution: this code is nearly identical to what's just above. */ 1N/A#
endif /* !DISCOVER_ONLY */ 1N/A/* Allocate metadata partitions for the GPTH and PTES */ 1N/A /* metadata at the start of the disk includes the MBR */ 1N/A /* metadata at the end of the disk */ 1N/A /* never change the partition numbers */ 1N/A return 0;
/* used if debug is disabled */ 1N/A * According to the specs the first LBA (LBA0) is not relevant (it exists 1N/A * to maintain compatibility). on the second LBA(LBA1) gpt places the 1N/A * header. The header is as big as the block size. After the header we 1N/A * find the Entry array. Each element of said array, describes each 1N/A * partition. One can have as much elements as can fit between the end of 1N/A * the second LBA (where the header ends) and the FirstUsableLBA. 1N/A * FirstUsableLBA is the first logical block that is used for contents 1N/A * and is defined in header. 1N/A * /---------------------------------------------------\ 1N/A * | BLOCK0 | HEADER | Entry Array | First Usable LBA | 1N/A * \---------------------------------------------------/ 1N/A * /----------/ \----------\ 1N/A * /-----------------------------------------\ 1N/A * | E1 | E2 | E3 |...............| EN | 1N/A * \-----------------------------------------/ 1N/A * The number of possible partitions or supported partitions is: 1N/A * SP = FirstUsableLBA*Blocksize - 2*Blocksize / SizeOfPartitionEntry 1N/A * SP = Blocksize(FirstusableLBA - 2) / SizeOfPartitoinEntry 1N/A _(
"Unable to satisfy all constraints on the partition."));