efi.c 22.9 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
/************************************************************
 * EFI GUID Partition Table handling
3
4
5
6
 *
 * http://www.uefi.org/specs/
 * http://www.intel.com/technology/efi/
 *
Linus Torvalds's avatar
Linus Torvalds committed
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com>
 *   Copyright 2000,2001,2002,2004 Dell Inc.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 * TODO:
 *
 * Changelog:
28
29
30
 * Mon August 5th, 2013 Davidlohr Bueso <davidlohr@hp.com>
 * - detect hybrid MBRs, tighter pMBR checking & cleanups.
 *
Linus Torvalds's avatar
Linus Torvalds committed
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 * Mon Nov 09 2004 Matt Domsch <Matt_Domsch@dell.com>
 * - test for valid PMBR and valid PGPT before ever reading
 *   AGPT, allow override with 'gpt' kernel command line option.
 * - check for first/last_usable_lba outside of size of disk
 *
 * Tue  Mar 26 2002 Matt Domsch <Matt_Domsch@dell.com>
 * - Ported to 2.5.7-pre1 and 2.5.7-dj2
 * - Applied patch to avoid fault in alternate header handling
 * - cleaned up find_valid_gpt
 * - On-disk structure and copy in memory is *always* LE now - 
 *   swab fields as needed
 * - remove print_gpt_header()
 * - only use first max_p partition entries, to keep the kernel minor number
 *   and partition numbers tied.
 *
 * Mon  Feb 04 2002 Matt Domsch <Matt_Domsch@dell.com>
 * - Removed __PRIPTR_PREFIX - not being used
 *
 * Mon  Jan 14 2002 Matt Domsch <Matt_Domsch@dell.com>
 * - Ported to 2.5.2-pre11 + library crc32 patch Linus applied
 *
 * Thu Dec 6 2001 Matt Domsch <Matt_Domsch@dell.com>
 * - Added compare_gpts().
 * - moved le_efi_guid_to_cpus() back into this file.  GPT is the only
 *   thing that keeps EFI GUIDs on disk.
 * - Changed gpt structure names and members to be simpler and more Linux-like.
 * 
 * Wed Oct 17 2001 Matt Domsch <Matt_Domsch@dell.com>
 * - Removed CONFIG_DEVFS_VOLUMES_UUID code entirely per Martin Wilck
 *
 * Wed Oct 10 2001 Matt Domsch <Matt_Domsch@dell.com>
 * - Changed function comments to DocBook style per Andreas Dilger suggestion.
 *
 * Mon Oct 08 2001 Matt Domsch <Matt_Domsch@dell.com>
 * - Change read_lba() to use the page cache per Al Viro's work.
 * - print u64s properly on all architectures
 * - fixed debug_printk(), now Dprintk()
 *
 * Mon Oct 01 2001 Matt Domsch <Matt_Domsch@dell.com>
 * - Style cleanups
 * - made most functions static
 * - Endianness addition
 * - remove test for second alternate header, as it's not per spec,
 *   and is unnecessary.  There's now a method to read/write the last
 *   sector of an odd-sized disk from user space.  No tools have ever
 *   been released which used this code, so it's effectively dead.
 * - Per Asit Mallick of Intel, added a test for a valid PMBR.
 * - Added kernel command line option 'gpt' to override valid PMBR test.
 *
 * Wed Jun  6 2001 Martin Wilck <Martin.Wilck@Fujitsu-Siemens.com>
 * - added devfs volume UUID support (/dev/volumes/uuids) for
 *   mounting file systems by the partition GUID. 
 *
 * Tue Dec  5 2000 Matt Domsch <Matt_Domsch@dell.com>
 * - Moved crc32() to linux/lib, added efi_crc32().
 *
 * Thu Nov 30 2000 Matt Domsch <Matt_Domsch@dell.com>
 * - Replaced Intel's CRC32 function with an equivalent
 *   non-license-restricted version.
 *
 * Wed Oct 25 2000 Matt Domsch <Matt_Domsch@dell.com>
 * - Fixed the last_lba() call to return the proper last block
 *
 * Thu Oct 12 2000 Matt Domsch <Matt_Domsch@dell.com>
 * - Thanks to Andries Brouwer for his debugging assistance.
 * - Code works, detects all the partitions.
 *
 ************************************************************/
99
#include <linux/kernel.h>
Linus Torvalds's avatar
Linus Torvalds committed
100
#include <linux/crc32.h>
101
#include <linux/ctype.h>
102
#include <linux/math64.h>
103
#include <linux/slab.h>
Linus Torvalds's avatar
Linus Torvalds committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "check.h"
#include "efi.h"

/* This allows a kernel command line option 'gpt' to override
 * the test for invalid PMBR.  Not __initdata because reloading
 * the partition tables happens after init too.
 */
static int force_gpt;
static int __init
force_gpt_fn(char *str)
{
	force_gpt = 1;
	return 1;
}
__setup("gpt", force_gpt_fn);


/**
 * efi_crc32() - EFI version of crc32 function
 * @buf: buffer to calculate crc32 of
124
 * @len: length of buf
Linus Torvalds's avatar
Linus Torvalds committed
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
 *
 * Description: Returns EFI-style CRC32 value for @buf
 * 
 * This function uses the little endian Ethernet polynomial
 * but seeds the function with ~0, and xor's with ~0 at the end.
 * Note, the EFI Specification, v1.02, has a reference to
 * Dr. Dobbs Journal, May 1994 (actually it's in May 1992).
 */
static inline u32
efi_crc32(const void *buf, unsigned long len)
{
	return (crc32(~0L, buf, len) ^ ~0L);
}

/**
 * last_lba(): return number of last logical block of device
 * @bdev: block device
 * 
 * Description: Returns last LBA value on success, 0 on error.
 * This is stored (by sd and ide-geometry) in
 *  the part[0] entry for this disk, and is the number of
 *  physical sectors available on the disk.
 */
148
static u64 last_lba(struct block_device *bdev)
Linus Torvalds's avatar
Linus Torvalds committed
149
150
151
{
	if (!bdev || !bdev->bd_inode)
		return 0;
152
153
	return div_u64(bdev->bd_inode->i_size,
		       bdev_logical_block_size(bdev)) - 1ULL;
Linus Torvalds's avatar
Linus Torvalds committed
154
155
}

156
static inline int pmbr_part_valid(gpt_mbr_record *part)
Linus Torvalds's avatar
Linus Torvalds committed
157
{
158
159
160
161
162
163
164
	if (part->os_type != EFI_PMBR_OSTYPE_EFI_GPT)
		goto invalid;

	/* set to 0x00000001 (i.e., the LBA of the GPT Partition Header) */
	if (le32_to_cpu(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA)
		goto invalid;

165
	return GPT_MBR_PROTECTIVE;
166
167
invalid:
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
168
169
170
171
172
}

/**
 * is_pmbr_valid(): test Protective MBR for validity
 * @mbr: pointer to a legacy mbr structure
173
 * @total_sectors: amount of sectors in the device
Linus Torvalds's avatar
Linus Torvalds committed
174
 *
175
176
177
 * Description: Checks for a valid protective or hybrid
 * master boot record (MBR). The validity of a pMBR depends
 * on all of the following properties:
Linus Torvalds's avatar
Linus Torvalds committed
178
179
 *  1) MSDOS signature is in the last two bytes of the MBR
 *  2) One partition of type 0xEE is found
180
181
182
183
184
185
186
 *
 * In addition, a hybrid MBR will have up to three additional
 * primary partitions, which point to the same space that's
 * marked out by up to three GPT partitions.
 *
 * Returns 0 upon invalid MBR, or GPT_MBR_PROTECTIVE or
 * GPT_MBR_HYBRID depending on the device layout.
Linus Torvalds's avatar
Linus Torvalds committed
187
 */
188
static int is_pmbr_valid(legacy_mbr *mbr, sector_t total_sectors)
Linus Torvalds's avatar
Linus Torvalds committed
189
{
190
	uint32_t sz = 0;
191
	int i, part = 0, ret = 0; /* invalid by default */
192

Linus Torvalds's avatar
Linus Torvalds committed
193
	if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
194
195
196
197
198
		goto done;

	for (i = 0; i < 4; i++) {
		ret = pmbr_part_valid(&mbr->partition_record[i]);
		if (ret == GPT_MBR_PROTECTIVE) {
199
			part = i;
200
201
202
203
204
205
206
207
208
209
210
211
			/*
			 * Ok, we at least know that there's a protective MBR,
			 * now check if there are other partition types for
			 * hybrid MBR.
			 */
			goto check_hybrid;
		}
	}

	if (ret != GPT_MBR_PROTECTIVE)
		goto done;
check_hybrid:
Linus Torvalds's avatar
Linus Torvalds committed
212
	for (i = 0; i < 4; i++)
213
214
215
216
		if ((mbr->partition_record[i].os_type !=
			EFI_PMBR_OSTYPE_EFI_GPT) &&
		    (mbr->partition_record[i].os_type != 0x00))
			ret = GPT_MBR_HYBRID;
217
218
219
220

	/*
	 * Protective MBRs take up the lesser of the whole disk
	 * or 2 TiB (32bit LBA), ignoring the rest of the disk.
221
222
223
	 * Some partitioning programs, nonetheless, choose to set
	 * the size to the maximum 32-bit limitation, disregarding
	 * the disk size.
224
225
	 *
	 * Hybrid MBRs do not necessarily comply with this.
226
227
228
	 *
	 * Consider a bad value here to be a warning to support dd'ing
	 * an image from a smaller disk to a larger disk.
229
230
	 */
	if (ret == GPT_MBR_PROTECTIVE) {
231
232
		sz = le32_to_cpu(mbr->partition_record[part].size_in_lba);
		if (sz != (uint32_t) total_sectors - 1 && sz != 0xFFFFFFFF)
233
234
235
			pr_debug("GPT: mbr size in lba (%u) different than whole disk (%u).\n",
				 sz, min_t(uint32_t,
					   total_sectors - 1, 0xFFFFFFFF));
236
	}
237
238
done:
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
239
240
241
242
}

/**
 * read_lba(): Read bytes from disk, starting at given LBA
243
244
245
246
 * @state: disk parsed partitions
 * @lba: the Logical Block Address of the partition table
 * @buffer: destination buffer
 * @count: bytes to read
Linus Torvalds's avatar
Linus Torvalds committed
247
 *
248
 * Description: Reads @count bytes from @state->bdev into @buffer.
Linus Torvalds's avatar
Linus Torvalds committed
249
250
 * Returns number of bytes read on success, 0 on error.
 */
251
252
static size_t read_lba(struct parsed_partitions *state,
		       u64 lba, u8 *buffer, size_t count)
Linus Torvalds's avatar
Linus Torvalds committed
253
254
{
	size_t totalreadcount = 0;
255
	struct block_device *bdev = state->bdev;
256
	sector_t n = lba * (bdev_logical_block_size(bdev) / 512);
Linus Torvalds's avatar
Linus Torvalds committed
257

258
	if (!buffer || lba > last_lba(bdev))
Linus Torvalds's avatar
Linus Torvalds committed
259
260
261
262
263
                return 0;

	while (count) {
		int copied = 512;
		Sector sect;
264
		unsigned char *data = read_part_sector(state, n++, &sect);
Linus Torvalds's avatar
Linus Torvalds committed
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
		if (!data)
			break;
		if (copied > count)
			copied = count;
		memcpy(buffer, data, copied);
		put_dev_sector(sect);
		buffer += copied;
		totalreadcount +=copied;
		count -= copied;
	}
	return totalreadcount;
}

/**
 * alloc_read_gpt_entries(): reads partition entries from disk
280
281
 * @state: disk parsed partitions
 * @gpt: GPT header
Linus Torvalds's avatar
Linus Torvalds committed
282
283
284
285
286
 * 
 * Description: Returns ptes on success,  NULL on error.
 * Allocates space for PTEs based on information found in @gpt.
 * Notes: remember to free pte when you're done!
 */
287
288
static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state,
					 gpt_header *gpt)
Linus Torvalds's avatar
Linus Torvalds committed
289
290
291
{
	size_t count;
	gpt_entry *pte;
292
293

	if (!gpt)
Linus Torvalds's avatar
Linus Torvalds committed
294
295
		return NULL;

296
	count = (size_t)le32_to_cpu(gpt->num_partition_entries) *
Linus Torvalds's avatar
Linus Torvalds committed
297
298
299
                le32_to_cpu(gpt->sizeof_partition_entry);
	if (!count)
		return NULL;
300
	pte = kmalloc(count, GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
301
302
303
	if (!pte)
		return NULL;

304
	if (read_lba(state, le64_to_cpu(gpt->partition_entry_lba),
305
			(u8 *) pte, count) < count) {
Linus Torvalds's avatar
Linus Torvalds committed
306
307
308
309
310
311
312
313
314
		kfree(pte);
                pte=NULL;
		return NULL;
	}
	return pte;
}

/**
 * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
315
316
 * @state: disk parsed partitions
 * @lba: the Logical Block Address of the partition table
Linus Torvalds's avatar
Linus Torvalds committed
317
318
 * 
 * Description: returns GPT header on success, NULL on error.   Allocates
319
 * and fills a GPT header starting at @ from @state->bdev.
Linus Torvalds's avatar
Linus Torvalds committed
320
321
 * Note: remember to free gpt when finished with it.
 */
322
323
static gpt_header *alloc_read_gpt_header(struct parsed_partitions *state,
					 u64 lba)
Linus Torvalds's avatar
Linus Torvalds committed
324
325
{
	gpt_header *gpt;
326
	unsigned ssz = bdev_logical_block_size(state->bdev);
Linus Torvalds's avatar
Linus Torvalds committed
327

328
	gpt = kmalloc(ssz, GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
329
330
331
	if (!gpt)
		return NULL;

332
	if (read_lba(state, lba, (u8 *) gpt, ssz) < ssz) {
Linus Torvalds's avatar
Linus Torvalds committed
333
334
335
336
337
338
339
340
341
342
		kfree(gpt);
                gpt=NULL;
		return NULL;
	}

	return gpt;
}

/**
 * is_gpt_valid() - tests one GPT header and PTEs for validity
343
344
345
346
 * @state: disk parsed partitions
 * @lba: logical block address of the GPT header to test
 * @gpt: GPT header ptr, filled on return.
 * @ptes: PTEs ptr, filled on return.
Linus Torvalds's avatar
Linus Torvalds committed
347
348
349
350
 *
 * Description: returns 1 if valid,  0 on error.
 * If valid, returns pointers to newly allocated GPT header and PTEs.
 */
351
352
static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
			gpt_header **gpt, gpt_entry **ptes)
Linus Torvalds's avatar
Linus Torvalds committed
353
354
{
	u32 crc, origcrc;
355
	u64 lastlba, pt_size;
Linus Torvalds's avatar
Linus Torvalds committed
356

357
	if (!ptes)
Linus Torvalds's avatar
Linus Torvalds committed
358
		return 0;
359
	if (!(*gpt = alloc_read_gpt_header(state, lba)))
Linus Torvalds's avatar
Linus Torvalds committed
360
361
362
363
		return 0;

	/* Check the GUID Partition Table signature */
	if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
364
365
366
367
		pr_debug("GUID Partition Table Header signature is wrong:"
			 "%lld != %lld\n",
			 (unsigned long long)le64_to_cpu((*gpt)->signature),
			 (unsigned long long)GPT_HEADER_SIGNATURE);
Linus Torvalds's avatar
Linus Torvalds committed
368
369
370
		goto fail;
	}

371
	/* Check the GUID Partition Table header size is too big */
372
373
	if (le32_to_cpu((*gpt)->header_size) >
			bdev_logical_block_size(state->bdev)) {
374
		pr_debug("GUID Partition Table Header size is too large: %u > %u\n",
375
376
377
378
379
			le32_to_cpu((*gpt)->header_size),
			bdev_logical_block_size(state->bdev));
		goto fail;
	}

380
381
382
383
384
385
386
387
	/* Check the GUID Partition Table header size is too small */
	if (le32_to_cpu((*gpt)->header_size) < sizeof(gpt_header)) {
		pr_debug("GUID Partition Table Header size is too small: %u < %zu\n",
			le32_to_cpu((*gpt)->header_size),
			sizeof(gpt_header));
		goto fail;
	}

Linus Torvalds's avatar
Linus Torvalds committed
388
389
390
391
392
393
	/* Check the GUID Partition Table CRC */
	origcrc = le32_to_cpu((*gpt)->header_crc32);
	(*gpt)->header_crc32 = 0;
	crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size));

	if (crc != origcrc) {
394
395
		pr_debug("GUID Partition Table Header CRC is wrong: %x != %x\n",
			 crc, origcrc);
Linus Torvalds's avatar
Linus Torvalds committed
396
397
398
399
400
401
402
		goto fail;
	}
	(*gpt)->header_crc32 = cpu_to_le32(origcrc);

	/* Check that the my_lba entry points to the LBA that contains
	 * the GUID Partition Table */
	if (le64_to_cpu((*gpt)->my_lba) != lba) {
403
404
405
		pr_debug("GPT my_lba incorrect: %lld != %lld\n",
			 (unsigned long long)le64_to_cpu((*gpt)->my_lba),
			 (unsigned long long)lba);
Linus Torvalds's avatar
Linus Torvalds committed
406
407
408
409
410
411
		goto fail;
	}

	/* Check the first_usable_lba and last_usable_lba are
	 * within the disk.
	 */
412
	lastlba = last_lba(state->bdev);
Linus Torvalds's avatar
Linus Torvalds committed
413
	if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) {
414
415
416
		pr_debug("GPT: first_usable_lba incorrect: %lld > %lld\n",
			 (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba),
			 (unsigned long long)lastlba);
Linus Torvalds's avatar
Linus Torvalds committed
417
418
419
		goto fail;
	}
	if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) {
420
421
422
		pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n",
			 (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
			 (unsigned long long)lastlba);
Linus Torvalds's avatar
Linus Torvalds committed
423
424
		goto fail;
	}
425
426
427
428
429
430
	if (le64_to_cpu((*gpt)->last_usable_lba) < le64_to_cpu((*gpt)->first_usable_lba)) {
		pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n",
			 (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
			 (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba));
		goto fail;
	}
431
432
	/* Check that sizeof_partition_entry has the correct value */
	if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) {
Masanari Iida's avatar
Masanari Iida committed
433
		pr_debug("GUID Partition Entry Size check failed.\n");
434
435
436
		goto fail;
	}

437
438
439
440
441
442
443
444
445
	/* Sanity check partition table size */
	pt_size = (u64)le32_to_cpu((*gpt)->num_partition_entries) *
		le32_to_cpu((*gpt)->sizeof_partition_entry);
	if (pt_size > KMALLOC_MAX_SIZE) {
		pr_debug("GUID Partition Table is too large: %llu > %lu bytes\n",
			 (unsigned long long)pt_size, KMALLOC_MAX_SIZE);
		goto fail;
	}

446
	if (!(*ptes = alloc_read_gpt_entries(state, *gpt)))
Linus Torvalds's avatar
Linus Torvalds committed
447
448
449
		goto fail;

	/* Check the GUID Partition Entry Array CRC */
450
	crc = efi_crc32((const unsigned char *) (*ptes), pt_size);
Linus Torvalds's avatar
Linus Torvalds committed
451
452

	if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
Masanari Iida's avatar
Masanari Iida committed
453
		pr_debug("GUID Partition Entry Array CRC check failed.\n");
Linus Torvalds's avatar
Linus Torvalds committed
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
		goto fail_ptes;
	}

	/* We're done, all's well */
	return 1;

 fail_ptes:
	kfree(*ptes);
	*ptes = NULL;
 fail:
	kfree(*gpt);
	*gpt = NULL;
	return 0;
}

/**
 * is_pte_valid() - tests one PTE for validity
471
472
 * @pte:pte to check
 * @lastlba: last lba of the disk
Linus Torvalds's avatar
Linus Torvalds committed
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
 *
 * Description: returns 1 if valid,  0 on error.
 */
static inline int
is_pte_valid(const gpt_entry *pte, const u64 lastlba)
{
	if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) ||
	    le64_to_cpu(pte->starting_lba) > lastlba         ||
	    le64_to_cpu(pte->ending_lba)   > lastlba)
		return 0;
	return 1;
}

/**
 * compare_gpts() - Search disk for valid GPT headers and PTEs
488
489
490
491
 * @pgpt: primary GPT header
 * @agpt: alternate GPT header
 * @lastlba: last LBA number
 *
Linus Torvalds's avatar
Linus Torvalds committed
492
493
494
495
496
497
498
499
500
501
502
 * Description: Returns nothing.  Sanity checks pgpt and agpt fields
 * and prints warnings on discrepancies.
 * 
 */
static void
compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
{
	int error_found = 0;
	if (!pgpt || !agpt)
		return;
	if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) {
503
504
		pr_warn("GPT:Primary header LBA != Alt. header alternate_lba\n");
		pr_warn("GPT:%lld != %lld\n",
Linus Torvalds's avatar
Linus Torvalds committed
505
506
507
508
509
		       (unsigned long long)le64_to_cpu(pgpt->my_lba),
                       (unsigned long long)le64_to_cpu(agpt->alternate_lba));
		error_found++;
	}
	if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) {
510
511
		pr_warn("GPT:Primary header alternate_lba != Alt. header my_lba\n");
		pr_warn("GPT:%lld != %lld\n",
Linus Torvalds's avatar
Linus Torvalds committed
512
513
514
515
516
517
		       (unsigned long long)le64_to_cpu(pgpt->alternate_lba),
                       (unsigned long long)le64_to_cpu(agpt->my_lba));
		error_found++;
	}
	if (le64_to_cpu(pgpt->first_usable_lba) !=
            le64_to_cpu(agpt->first_usable_lba)) {
518
519
		pr_warn("GPT:first_usable_lbas don't match.\n");
		pr_warn("GPT:%lld != %lld\n",
Linus Torvalds's avatar
Linus Torvalds committed
520
521
522
523
524
525
		       (unsigned long long)le64_to_cpu(pgpt->first_usable_lba),
                       (unsigned long long)le64_to_cpu(agpt->first_usable_lba));
		error_found++;
	}
	if (le64_to_cpu(pgpt->last_usable_lba) !=
            le64_to_cpu(agpt->last_usable_lba)) {
526
527
		pr_warn("GPT:last_usable_lbas don't match.\n");
		pr_warn("GPT:%lld != %lld\n",
Linus Torvalds's avatar
Linus Torvalds committed
528
529
530
531
532
		       (unsigned long long)le64_to_cpu(pgpt->last_usable_lba),
                       (unsigned long long)le64_to_cpu(agpt->last_usable_lba));
		error_found++;
	}
	if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
533
		pr_warn("GPT:disk_guids don't match.\n");
Linus Torvalds's avatar
Linus Torvalds committed
534
535
536
537
		error_found++;
	}
	if (le32_to_cpu(pgpt->num_partition_entries) !=
            le32_to_cpu(agpt->num_partition_entries)) {
538
		pr_warn("GPT:num_partition_entries don't match: "
Linus Torvalds's avatar
Linus Torvalds committed
539
540
541
542
543
544
545
		       "0x%x != 0x%x\n",
		       le32_to_cpu(pgpt->num_partition_entries),
		       le32_to_cpu(agpt->num_partition_entries));
		error_found++;
	}
	if (le32_to_cpu(pgpt->sizeof_partition_entry) !=
            le32_to_cpu(agpt->sizeof_partition_entry)) {
546
		pr_warn("GPT:sizeof_partition_entry values don't match: "
Linus Torvalds's avatar
Linus Torvalds committed
547
548
549
550
551
552
553
		       "0x%x != 0x%x\n",
                       le32_to_cpu(pgpt->sizeof_partition_entry),
		       le32_to_cpu(agpt->sizeof_partition_entry));
		error_found++;
	}
	if (le32_to_cpu(pgpt->partition_entry_array_crc32) !=
            le32_to_cpu(agpt->partition_entry_array_crc32)) {
554
		pr_warn("GPT:partition_entry_array_crc32 values don't match: "
Linus Torvalds's avatar
Linus Torvalds committed
555
556
557
558
559
560
		       "0x%x != 0x%x\n",
                       le32_to_cpu(pgpt->partition_entry_array_crc32),
		       le32_to_cpu(agpt->partition_entry_array_crc32));
		error_found++;
	}
	if (le64_to_cpu(pgpt->alternate_lba) != lastlba) {
561
562
		pr_warn("GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
		pr_warn("GPT:%lld != %lld\n",
Linus Torvalds's avatar
Linus Torvalds committed
563
564
565
566
567
568
			(unsigned long long)le64_to_cpu(pgpt->alternate_lba),
			(unsigned long long)lastlba);
		error_found++;
	}

	if (le64_to_cpu(agpt->my_lba) != lastlba) {
569
570
		pr_warn("GPT:Alternate GPT header not at the end of the disk.\n");
		pr_warn("GPT:%lld != %lld\n",
Linus Torvalds's avatar
Linus Torvalds committed
571
572
573
574
575
576
			(unsigned long long)le64_to_cpu(agpt->my_lba),
			(unsigned long long)lastlba);
		error_found++;
	}

	if (error_found)
577
		pr_warn("GPT: Use GNU Parted to correct GPT errors.\n");
Linus Torvalds's avatar
Linus Torvalds committed
578
579
580
581
582
	return;
}

/**
 * find_valid_gpt() - Search disk for valid GPT headers and PTEs
583
584
585
586
 * @state: disk parsed partitions
 * @gpt: GPT header ptr, filled on return.
 * @ptes: PTEs ptr, filled on return.
 *
Linus Torvalds's avatar
Linus Torvalds committed
587
588
589
590
591
592
593
594
595
596
 * Description: Returns 1 if valid, 0 on error.
 * If valid, returns pointers to newly allocated GPT header and PTEs.
 * Validity depends on PMBR being valid (or being overridden by the
 * 'gpt' kernel command line option) and finding either the Primary
 * GPT header and PTEs valid, or the Alternate GPT header and PTEs
 * valid.  If the Primary GPT header is not valid, the Alternate GPT header
 * is not checked unless the 'gpt' kernel command line option is passed.
 * This protects against devices which misreport their size, and forces
 * the user to decide to use the Alternate GPT.
 */
597
598
static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
			  gpt_entry **ptes)
Linus Torvalds's avatar
Linus Torvalds committed
599
600
601
602
{
	int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
	gpt_header *pgpt = NULL, *agpt = NULL;
	gpt_entry *pptes = NULL, *aptes = NULL;
603
	legacy_mbr *legacymbr;
604
	sector_t total_sectors = i_size_read(state->bdev->bd_inode) >> 9;
Linus Torvalds's avatar
Linus Torvalds committed
605
	u64 lastlba;
606
607

	if (!ptes)
Linus Torvalds's avatar
Linus Torvalds committed
608
609
		return 0;

610
	lastlba = last_lba(state->bdev);
Linus Torvalds's avatar
Linus Torvalds committed
611
        if (!force_gpt) {
612
613
614
615
616
617
		/* This will be added to the EFI Spec. per Intel after v1.02. */
		legacymbr = kzalloc(sizeof(*legacymbr), GFP_KERNEL);
		if (!legacymbr)
			goto fail;

		read_lba(state, 0, (u8 *)legacymbr, sizeof(*legacymbr));
618
		good_pmbr = is_pmbr_valid(legacymbr, total_sectors);
619
620
621
622
623
624
625
626
627
		kfree(legacymbr);

		if (!good_pmbr)
			goto fail;

		pr_debug("Device has a %s MBR\n",
			 good_pmbr == GPT_MBR_PROTECTIVE ?
						"protective" : "hybrid");
	}
Linus Torvalds's avatar
Linus Torvalds committed
628

629
	good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA,
Linus Torvalds's avatar
Linus Torvalds committed
630
631
				 &pgpt, &pptes);
        if (good_pgpt)
632
		good_agpt = is_gpt_valid(state,
Linus Torvalds's avatar
Linus Torvalds committed
633
634
635
					 le64_to_cpu(pgpt->alternate_lba),
					 &agpt, &aptes);
        if (!good_agpt && force_gpt)
636
                good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes);
Linus Torvalds's avatar
Linus Torvalds committed
637
638
639
640
641
642
643
644
645
646
647
648
649

        /* The obviously unsuccessful case */
        if (!good_pgpt && !good_agpt)
                goto fail;

        compare_gpts(pgpt, agpt, lastlba);

        /* The good cases */
        if (good_pgpt) {
                *gpt  = pgpt;
                *ptes = pptes;
                kfree(agpt);
                kfree(aptes);
650
		if (!good_agpt)
651
                        pr_warn("Alternate GPT is invalid, using primary GPT.\n");
Linus Torvalds's avatar
Linus Torvalds committed
652
653
654
655
656
657
658
                return 1;
        }
        else if (good_agpt) {
                *gpt  = agpt;
                *ptes = aptes;
                kfree(pgpt);
                kfree(pptes);
659
		pr_warn("Primary GPT is invalid, using alternate GPT.\n");
Linus Torvalds's avatar
Linus Torvalds committed
660
661
662
663
664
665
666
667
668
669
670
671
672
673
                return 1;
        }

 fail:
        kfree(pgpt);
        kfree(agpt);
        kfree(pptes);
        kfree(aptes);
        *gpt = NULL;
        *ptes = NULL;
        return 0;
}

/**
674
 * efi_partition(struct parsed_partitions *state)
675
 * @state: disk parsed partitions
Linus Torvalds's avatar
Linus Torvalds committed
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
 *
 * Description: called from check.c, if the disk contains GPT
 * partitions, sets up partition entries in the kernel.
 *
 * If the first block on the disk is a legacy MBR,
 * it will get handled by msdos_partition().
 * If it's a Protective MBR, we'll handle it here.
 *
 * We do not create a Linux partition for GPT, but
 * only for the actual data partitions.
 * Returns:
 * -1 if unable to read the partition table
 *  0 if this isn't our partition table
 *  1 if successful
 *
 */
692
int efi_partition(struct parsed_partitions *state)
Linus Torvalds's avatar
Linus Torvalds committed
693
694
695
696
{
	gpt_header *gpt = NULL;
	gpt_entry *ptes = NULL;
	u32 i;
697
	unsigned ssz = bdev_logical_block_size(state->bdev) / 512;
Linus Torvalds's avatar
Linus Torvalds committed
698

699
	if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) {
Linus Torvalds's avatar
Linus Torvalds committed
700
701
702
703
704
		kfree(gpt);
		kfree(ptes);
		return 0;
	}

705
	pr_debug("GUID Partition Table is valid!  Yea!\n");
Linus Torvalds's avatar
Linus Torvalds committed
706
707

	for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
708
709
710
		struct partition_meta_info *info;
		unsigned label_count = 0;
		unsigned label_max;
711
712
713
714
		u64 start = le64_to_cpu(ptes[i].starting_lba);
		u64 size = le64_to_cpu(ptes[i].ending_lba) -
			   le64_to_cpu(ptes[i].starting_lba) + 1ULL;

715
		if (!is_pte_valid(&ptes[i], last_lba(state->bdev)))
Linus Torvalds's avatar
Linus Torvalds committed
716
717
			continue;

718
		put_partition(state, i+1, start * ssz, size * ssz);
Linus Torvalds's avatar
Linus Torvalds committed
719
720

		/* If this is a RAID volume, tell md */
721
		if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID))
722
			state->parts[i + 1].flags = ADDPART_FLAG_RAID;
723
724

		info = &state->parts[i + 1].info;
725
		efi_guid_to_str(&ptes[i].unique_partition_guid, info->uuid);
726
727

		/* Naively convert UTF16-LE to 7 bits. */
728
729
		label_max = min(ARRAY_SIZE(info->volname) - 1,
				ARRAY_SIZE(ptes[i].partition_name));
730
731
732
733
734
735
736
737
738
		info->volname[label_max] = 0;
		while (label_count < label_max) {
			u8 c = ptes[i].partition_name[label_count] & 0xff;
			if (c && !isprint(c))
				c = '!';
			info->volname[label_count] = c;
			label_count++;
		}
		state->parts[i + 1].has_info = true;
Linus Torvalds's avatar
Linus Torvalds committed
739
740
741
	}
	kfree(ptes);
	kfree(gpt);
742
	strlcat(state->pp_buf, "\n", PAGE_SIZE);
Linus Torvalds's avatar
Linus Torvalds committed
743
744
	return 1;
}