(root)/
util-linux-2.39/
libblkid/
src/
partitions/
gpt.c
       1  /*
       2   * EFI GPT partition parsing code
       3   *
       4   * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
       5   *
       6   * This file may be redistributed under the terms of the
       7   * GNU Lesser General Public License.
       8   *
       9   * This code is not copy & past from any other implementation.
      10   *
      11   * For more information about GPT start your study at:
      12   * http://en.wikipedia.org/wiki/GUID_Partition_Table
      13   * http://technet.microsoft.com/en-us/library/cc739412(WS.10).aspx
      14   */
      15  #include <stdio.h>
      16  #include <string.h>
      17  #include <stdlib.h>
      18  #include <stdint.h>
      19  #include <stddef.h>
      20  #include <limits.h>
      21  #include <inttypes.h>
      22  
      23  #include "partitions.h"
      24  #include "crc32.h"
      25  
      26  #define GPT_PRIMARY_LBA	1
      27  
      28  /* Signature - “EFI PART” */
      29  #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
      30  #define GPT_HEADER_SIGNATURE_STR "EFI PART"
      31  
      32  /* basic types */
      33  typedef uint16_t efi_char16_t;
      34  
      35  /* UUID */
      36  typedef struct {
      37  	uint32_t time_low;
      38  	uint16_t time_mid;
      39  	uint16_t time_hi_and_version;
      40  	uint8_t clock_seq_hi;
      41  	uint8_t clock_seq_low;
      42  	uint8_t node[6];
      43  } efi_guid_t;
      44  
      45  
      46  #define GPT_UNUSED_ENTRY_GUID \
      47  	    ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
      48  	                    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
      49  struct gpt_header {
      50  	uint64_t	signature;		/* "EFI PART" */
      51  	uint32_t	revision;
      52  	uint32_t	header_size;		/* usually 92 bytes */
      53  	uint32_t	header_crc32;		/* checksum of header with this
      54  						 * field zeroed during calculation */
      55  	uint32_t	reserved1;
      56  
      57  	uint64_t	my_lba;			/* location of this header copy */
      58  	uint64_t	alternate_lba;		/* location of the other header copy */
      59  	uint64_t	first_usable_lba;	/* first usable LBA for partitions */
      60  	uint64_t	last_usable_lba;	/* last usable LBA for partitions */
      61  
      62  	efi_guid_t	disk_guid;		/* disk UUID */
      63  
      64  	uint64_t	partition_entries_lba;	/* always 2 in primary header copy */
      65  	uint32_t	num_partition_entries;
      66  	uint32_t	sizeof_partition_entry;
      67  	uint32_t	partition_entry_array_crc32;
      68  
      69  	/*
      70  	 * The rest of the block is reserved by UEFI and must be zero. EFI
      71  	 * standard handles this by:
      72  	 *
      73  	 * uint8_t		reserved2[ BLKSSZGET - 92 ];
      74  	 *
      75  	 * This definition is useless in practice. It is necessary to read
      76  	 * whole block from the device rather than sizeof(struct gpt_header)
      77  	 * only.
      78  	 */
      79  } __attribute__ ((packed));
      80  
      81  /*** not used
      82  struct gpt_entry_attributes {
      83  	uint64_t	required_to_function:1;
      84  	uint64_t	reserved:47;
      85          uint64_t	type_guid_specific:16;
      86  } __attribute__ ((packed));
      87  ***/
      88  
      89  struct gpt_entry {
      90  	efi_guid_t	partition_type_guid;	/* type UUID */
      91  	efi_guid_t	unique_partition_guid;	/* partition UUID */
      92  	uint64_t	starting_lba;
      93  	uint64_t	ending_lba;
      94  
      95  	/*struct gpt_entry_attributes	attributes;*/
      96  
      97  	uint64_t	attributes;
      98  
      99  	efi_char16_t	partition_name[72 / sizeof(efi_char16_t)]; /* UTF-16LE string*/
     100  } __attribute__ ((packed));
     101  
     102  
     103  /*
     104   * EFI uses crc32 with ~0 seed and xor's with ~0 at the end.
     105   */
     106  static inline uint32_t count_crc32(const unsigned char *buf, size_t len,
     107  				   size_t exclude_off, size_t exclude_len)
     108  {
     109  	return (ul_crc32_exclude_offset(~0L, buf, len, exclude_off, exclude_len) ^ ~0L);
     110  }
     111  
     112  static inline unsigned char *get_lba_buffer(blkid_probe pr,
     113  					uint64_t lba, size_t bytes)
     114  {
     115  	return blkid_probe_get_buffer(pr,
     116  			blkid_probe_get_sectorsize(pr) * lba, bytes);
     117  }
     118  
     119  static inline int guidcmp(efi_guid_t left, efi_guid_t right)
     120  {
     121  	return memcmp(&left, &right, sizeof (efi_guid_t));
     122  }
     123  
     124  /*
     125   * UUID is traditionally 16 byte big-endian array, except Intel EFI
     126   * specification where the UUID is a structure of little-endian fields.
     127   */
     128  static void swap_efi_guid(efi_guid_t *uid)
     129  {
     130  	uid->time_low = swab32(uid->time_low);
     131  	uid->time_mid = swab16(uid->time_mid);
     132  	uid->time_hi_and_version = swab16(uid->time_hi_and_version);
     133  }
     134  
     135  static int last_lba(blkid_probe pr, uint64_t *lba)
     136  {
     137  	uint64_t sz = blkid_probe_get_size(pr);
     138  	unsigned int ssz = blkid_probe_get_sectorsize(pr);
     139  
     140  	if (sz < ssz)
     141  		return -1;
     142  
     143  	*lba = (sz / ssz) - 1ULL;
     144  	return 0;
     145  }
     146  
     147  /*
     148   * Protective (legacy) MBR.
     149   *
     150   * This MBR contains standard DOS partition table with a single partition, type
     151   * of 0xEE.  The partition usually encompassing the entire GPT drive - or 2TiB
     152   * for large disks.
     153   *
     154   * Note that Apple uses GPT/MBR hybrid disks, where the DOS partition table is
     155   * synchronized with GPT. This synchronization has many restriction of course
     156   * (due DOS PT limitations).
     157   *
     158   * Note that the PMBR detection is optional (enabled by default) and could be
     159   * disabled by BLKID_PARTS_FOPCE_GPT flag (see also blkid_partitions_set_flags()).
     160   */
     161  static int is_pmbr_valid(blkid_probe pr, int *has)
     162  {
     163  	int flags = blkid_partitions_get_flags(pr);
     164  	unsigned char *data;
     165  	struct dos_partition *p;
     166  	int i;
     167  
     168  	if (has)
     169  		*has = 0;
     170  	else if (flags & BLKID_PARTS_FORCE_GPT)
     171  		return 1;			/* skip PMBR check */
     172  
     173  	data = blkid_probe_get_sector(pr, 0);
     174  	if (!data) {
     175  		if (errno)
     176  			return -errno;
     177  		goto failed;
     178  	}
     179  
     180  	if (!mbr_is_valid_magic(data))
     181  		goto failed;
     182  
     183  	for (i = 0, p = mbr_get_partition(data, 0); i < 4; i++, p++) {
     184  		if (p->sys_ind == MBR_GPT_PARTITION) {
     185  			DBG(LOWPROBE, ul_debug(" #%d valid PMBR partition", i + 1));
     186  			goto ok;
     187  		}
     188  	}
     189  failed:
     190  	return 0;
     191  ok:
     192  	if (has)
     193  		*has = 1;
     194  	return 1;
     195  }
     196  
     197  /*
     198   * Reads GPT header to @hdr and returns a pointer to @hdr or NULL in case of
     199   * error. The function also returns GPT entries in @ents.
     200   *
     201   * Note, this function does not allocate any memory. The GPT header has fixed
     202   * size so we use stack, and @ents returns memory from libblkid buffer (so the
     203   * next blkid_probe_get_buffer() will overwrite this buffer).
     204   *
     205   * This function checks validity of header and entries array. A corrupted
     206   * header is not returned.
     207   */
     208  static struct gpt_header *get_gpt_header(
     209  				blkid_probe pr, struct gpt_header *hdr,
     210  				struct gpt_entry **ents, uint64_t lba,
     211  				uint64_t lastlba)
     212  {
     213  	struct gpt_header *h;
     214  	uint32_t crc;
     215  	uint64_t lu, fu;
     216  	uint64_t esz;
     217  	uint32_t hsz, ssz;
     218  
     219  	ssz = blkid_probe_get_sectorsize(pr);
     220  
     221  	DBG(LOWPROBE, ul_debug(" checking for GPT header at %"PRIu64, lba));
     222  
     223  	/* whole sector is allocated for GPT header */
     224  	h = (struct gpt_header *) get_lba_buffer(pr, lba, ssz);
     225  	if (!h)
     226  		return NULL;
     227  
     228  	if (le64_to_cpu(h->signature) != GPT_HEADER_SIGNATURE)
     229  		return NULL;
     230  
     231  	hsz = le32_to_cpu(h->header_size);
     232  
     233  	/* EFI: The HeaderSize must be greater than 92 and must be less
     234  	 *      than or equal to the logical block size.
     235  	 */
     236  	if (hsz > ssz || hsz < sizeof(*h))
     237  		return NULL;
     238  
     239  	/* Header has to be verified when header_crc32 is zero */
     240  	crc = count_crc32((unsigned char *) h, hsz,
     241  			offsetof(struct gpt_header, header_crc32),
     242  			sizeof(h->header_crc32));
     243  
     244  	if (!blkid_probe_verify_csum(pr, crc, le32_to_cpu(h->header_crc32))) {
     245  		DBG(LOWPROBE, ul_debug("GPT header corrupted"));
     246  		return NULL;
     247  	}
     248  
     249  	/* Valid header has to be at MyLBA */
     250  	if (le64_to_cpu(h->my_lba) != lba) {
     251  		DBG(LOWPROBE, ul_debug(
     252  			"GPT->MyLBA mismatch with real position"));
     253  		return NULL;
     254  	}
     255  
     256  	fu = le64_to_cpu(h->first_usable_lba);
     257  	lu = le64_to_cpu(h->last_usable_lba);
     258  
     259  	/* Check if First and Last usable LBA makes sense */
     260  	if (lu < fu || fu > lastlba || lu > lastlba) {
     261  		DBG(LOWPROBE, ul_debug(
     262  			"GPT->{First,Last}UsableLBA out of range"));
     263  		return NULL;
     264  	}
     265  
     266  	/* The header has to be outside usable range */
     267  	if (fu < lba && lba < lu) {
     268  		DBG(LOWPROBE, ul_debug("GPT header is inside usable area"));
     269  		return NULL;
     270  	}
     271  
     272  	/* Size of blocks with GPT entries */
     273  	esz = (uint64_t)le32_to_cpu(h->num_partition_entries) *
     274  		le32_to_cpu(h->sizeof_partition_entry);
     275  
     276  	if (esz == 0 || esz >= UINT32_MAX ||
     277  	    le32_to_cpu(h->sizeof_partition_entry) != sizeof(struct gpt_entry)) {
     278  		DBG(LOWPROBE, ul_debug("GPT entries undefined"));
     279  		return NULL;
     280  	}
     281  
     282  	/* The header seems valid, save it
     283  	 * (we don't care about zeros in hdr->reserved2 area) */
     284  	memcpy(hdr, h, sizeof(*h));
     285  	h = hdr;
     286  
     287  	/* Read GPT entries */
     288  	*ents = (struct gpt_entry *) get_lba_buffer(pr,
     289  				le64_to_cpu(h->partition_entries_lba), esz);
     290  	if (!*ents) {
     291  		DBG(LOWPROBE, ul_debug("GPT entries unreadable"));
     292  		return NULL;
     293  	}
     294  
     295  	/* Validate entries */
     296  	crc = count_crc32((unsigned char *) *ents, esz, 0, 0);
     297  	if (crc != le32_to_cpu(h->partition_entry_array_crc32)) {
     298  		DBG(LOWPROBE, ul_debug("GPT entries corrupted"));
     299  		return NULL;
     300  	}
     301  
     302  	return h;
     303  }
     304  
     305  static int probe_gpt_pt(blkid_probe pr,
     306  		const struct blkid_idmag *mag __attribute__((__unused__)))
     307  {
     308  	uint64_t lastlba = 0, lba;
     309  	struct gpt_header hdr, *h;
     310  	struct gpt_entry *e;
     311  	blkid_parttable tab = NULL;
     312  	blkid_partlist ls;
     313  	uint64_t fu, lu;
     314  	uint32_t ssf, i;
     315  	efi_guid_t guid;
     316  	int ret;
     317  
     318  	if (last_lba(pr, &lastlba))
     319  		goto nothing;
     320  
     321  	ret = is_pmbr_valid(pr, NULL);
     322  	if (ret < 0)
     323  		return ret;
     324  	if (ret == 0)
     325  		goto nothing;
     326  
     327  	errno = 0;
     328  	h = get_gpt_header(pr, &hdr, &e, (lba = GPT_PRIMARY_LBA), lastlba);
     329  	if (!h && !errno)
     330  		h = get_gpt_header(pr, &hdr, &e, (lba = lastlba), lastlba);
     331  
     332  	if (!h) {
     333  		if (errno)
     334  			return -errno;
     335  		goto nothing;
     336  	}
     337  
     338  	blkid_probe_use_wiper(pr, lba * blkid_probe_get_size(pr), 8);
     339  
     340  	if (blkid_probe_set_magic(pr, blkid_probe_get_sectorsize(pr) * lba,
     341  			      sizeof(GPT_HEADER_SIGNATURE_STR) - 1,
     342  			      (unsigned char *) GPT_HEADER_SIGNATURE_STR))
     343  		goto err;
     344  
     345  	guid = h->disk_guid;
     346  	swap_efi_guid(&guid);
     347  
     348  	if (blkid_partitions_need_typeonly(pr)) {
     349  		/* Non-binary interface -- caller does not ask for details
     350  		 * about partitions, just set generic variables only. */
     351  		blkid_partitions_set_ptuuid(pr, (unsigned char *) &guid);
     352  		return BLKID_PROBE_OK;
     353  	}
     354  
     355  	ls = blkid_probe_get_partlist(pr);
     356  	if (!ls)
     357  		goto nothing;
     358  
     359  	tab = blkid_partlist_new_parttable(ls, "gpt",
     360  				blkid_probe_get_sectorsize(pr) * lba);
     361  	if (!tab)
     362  		goto err;
     363  
     364  	blkid_parttable_set_uuid(tab, (const unsigned char *) &guid);
     365  
     366  	ssf = blkid_probe_get_sectorsize(pr) / 512;
     367  
     368  	fu = le64_to_cpu(h->first_usable_lba);
     369  	lu = le64_to_cpu(h->last_usable_lba);
     370  
     371  	for (i = 0; i < le32_to_cpu(h->num_partition_entries); i++, e++) {
     372  
     373  		blkid_partition par;
     374  		uint64_t start = le64_to_cpu(e->starting_lba);
     375  		uint64_t size = le64_to_cpu(e->ending_lba) -
     376  					le64_to_cpu(e->starting_lba) + 1ULL;
     377  
     378  		/* 00000000-0000-0000-0000-000000000000 entry */
     379  		if (!guidcmp(e->partition_type_guid, GPT_UNUSED_ENTRY_GUID)) {
     380  			blkid_partlist_increment_partno(ls);
     381  			continue;
     382  		}
     383  		/* the partition has to inside usable range */
     384  		if (start < fu || start + size - 1 > lu) {
     385  			DBG(LOWPROBE, ul_debug(
     386  				"GPT entry[%d] overflows usable area - ignore",
     387  				i));
     388  			blkid_partlist_increment_partno(ls);
     389  			continue;
     390  		}
     391  
     392  		par = blkid_partlist_add_partition(ls, tab,
     393  					start * ssf, size * ssf);
     394  		if (!par)
     395  			goto err;
     396  
     397  		blkid_partition_set_utf8name(par,
     398  			(unsigned char *) e->partition_name,
     399  			sizeof(e->partition_name), UL_ENCODE_UTF16LE);
     400  
     401  		guid = e->unique_partition_guid;
     402  		swap_efi_guid(&guid);
     403  		blkid_partition_set_uuid(par, (const unsigned char *) &guid);
     404  
     405  		guid = e->partition_type_guid;
     406  		swap_efi_guid(&guid);
     407  		blkid_partition_set_type_uuid(par, (const unsigned char *) &guid);
     408  
     409  		blkid_partition_set_flags(par, le64_to_cpu(e->attributes));
     410  	}
     411  
     412  	return BLKID_PROBE_OK;
     413  
     414  nothing:
     415  	return BLKID_PROBE_NONE;
     416  
     417  err:
     418  	return -ENOMEM;
     419  }
     420  
     421  
     422  const struct blkid_idinfo gpt_pt_idinfo =
     423  {
     424  	.name		= "gpt",
     425  	.probefunc	= probe_gpt_pt,
     426  
     427  	/*
     428  	 * It would be possible to check for DOS signature (0xAA55), but
     429  	 * unfortunately almost all EFI GPT implementations allow to optionally
     430  	 * skip the legacy MBR. We follows this behavior and MBR is optional.
     431  	 * See is_valid_pmbr().
     432  	 *
     433  	 * It means we have to always call probe_gpt_pt().
     434  	 */
     435  	.magics		= BLKID_NONE_MAGIC
     436  };
     437  
     438  
     439  
     440  /* probe for *alone* protective MBR */
     441  static int probe_pmbr_pt(blkid_probe pr,
     442  		const struct blkid_idmag *mag __attribute__((__unused__)))
     443  {
     444  	int has = 0;
     445  	struct gpt_entry *e;
     446  	uint64_t lastlba = 0;
     447  	struct gpt_header hdr;
     448  
     449  	if (last_lba(pr, &lastlba))
     450  		goto nothing;
     451  
     452  	is_pmbr_valid(pr, &has);
     453  	if (!has)
     454  		goto nothing;
     455  
     456  	if (!get_gpt_header(pr, &hdr, &e, GPT_PRIMARY_LBA, lastlba) &&
     457  	    !get_gpt_header(pr, &hdr, &e, lastlba, lastlba))
     458  		return 0;
     459  nothing:
     460  	return 1;
     461  }
     462  
     463  const struct blkid_idinfo pmbr_pt_idinfo =
     464  {
     465  	.name		= "PMBR",
     466  	.probefunc	= probe_pmbr_pt,
     467  	.magics		=
     468  	{
     469  		{ .magic = "\x55\xAA", .len = 2, .sboff = 510 },
     470  		{ NULL }
     471  	}
     472  };
     473