Blame view

block/partitions/efi.c 22.7 KB
a497ee34a   Christoph Hellwig   block: switch all...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
  /************************************************************
   * EFI GUID Partition Table handling
7d13af327   Karel Zak   partitions: use s...
4
5
6
7
   *
   * http://www.uefi.org/specs/
   * http://www.intel.com/technology/efi/
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
   * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com>
   *   Copyright 2000,2001,2002,2004 Dell Inc.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
   * TODO:
   *
   * Changelog:
70f637e90   Davidlohr Bueso   partitions/efi: s...
14
15
16
   * Mon August 5th, 2013 Davidlohr Bueso <davidlohr@hp.com>
   * - detect hybrid MBRs, tighter pMBR checking & cleanups.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
   * 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.
   *
   ************************************************************/
49204c116   Antti P Miettinen   block/partitions/...
85
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  #include <linux/crc32.h>
eec7ecfed   Will Drewry   genhd, efi: add e...
87
  #include <linux/ctype.h>
7d13af327   Karel Zak   partitions: use s...
88
  #include <linux/math64.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
89
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
  #include "check.h"
  #include "efi.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  /* 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
16e155652   Fabian Frederick   block/partitions/...
109
   * @len: length of buf
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
   *
   * 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.
   */
1493bf217   Tejun Heo   block: use struct...
133
  static u64 last_lba(struct block_device *bdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
  {
  	if (!bdev || !bdev->bd_inode)
  		return 0;
7d13af327   Karel Zak   partitions: use s...
137
138
  	return div_u64(bdev->bd_inode->i_size,
  		       bdev_logical_block_size(bdev)) - 1ULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  }
c2ebdc243   Davidlohr Bueso   partitions/efi: u...
140
  static inline int pmbr_part_valid(gpt_mbr_record *part)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  {
33afd7a7d   Davidlohr Bueso   partitions/efi: c...
142
143
144
145
146
147
  	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;
b05ebbbbe   Davidlohr Bueso   partitions/efi: d...
148
  	return GPT_MBR_PROTECTIVE;
33afd7a7d   Davidlohr Bueso   partitions/efi: c...
149
150
  invalid:
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
155
  }
  
  /**
   * is_pmbr_valid(): test Protective MBR for validity
   * @mbr: pointer to a legacy mbr structure
27a7c6421   Davidlohr Bueso   partitions/efi: a...
156
   * @total_sectors: amount of sectors in the device
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
   *
b05ebbbbe   Davidlohr Bueso   partitions/efi: d...
158
159
160
   * Description: Checks for a valid protective or hybrid
   * master boot record (MBR). The validity of a pMBR depends
   * on all of the following properties:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
   *  1) MSDOS signature is in the last two bytes of the MBR
   *  2) One partition of type 0xEE is found
b05ebbbbe   Davidlohr Bueso   partitions/efi: d...
163
164
165
166
167
168
169
   *
   * 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.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
   */
27a7c6421   Davidlohr Bueso   partitions/efi: a...
171
  static int is_pmbr_valid(legacy_mbr *mbr, sector_t total_sectors)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  {
6b02fa59a   Davidlohr Bueso   partitions/efi: l...
173
  	uint32_t sz = 0;
27a7c6421   Davidlohr Bueso   partitions/efi: a...
174
  	int i, part = 0, ret = 0; /* invalid by default */
b05ebbbbe   Davidlohr Bueso   partitions/efi: d...
175

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  	if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
b05ebbbbe   Davidlohr Bueso   partitions/efi: d...
177
178
179
180
181
  		goto done;
  
  	for (i = 0; i < 4; i++) {
  		ret = pmbr_part_valid(&mbr->partition_record[i]);
  		if (ret == GPT_MBR_PROTECTIVE) {
27a7c6421   Davidlohr Bueso   partitions/efi: a...
182
  			part = i;
b05ebbbbe   Davidlohr Bueso   partitions/efi: d...
183
184
185
186
187
188
189
190
191
192
193
194
  			/*
  			 * 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:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  	for (i = 0; i < 4; i++)
b05ebbbbe   Davidlohr Bueso   partitions/efi: d...
196
197
198
199
  		if ((mbr->partition_record[i].os_type !=
  			EFI_PMBR_OSTYPE_EFI_GPT) &&
  		    (mbr->partition_record[i].os_type != 0x00))
  			ret = GPT_MBR_HYBRID;
27a7c6421   Davidlohr Bueso   partitions/efi: a...
200
201
202
203
  
  	/*
  	 * Protective MBRs take up the lesser of the whole disk
  	 * or 2 TiB (32bit LBA), ignoring the rest of the disk.
6b02fa59a   Davidlohr Bueso   partitions/efi: l...
204
205
206
  	 * Some partitioning programs, nonetheless, choose to set
  	 * the size to the maximum 32-bit limitation, disregarding
  	 * the disk size.
27a7c6421   Davidlohr Bueso   partitions/efi: a...
207
208
  	 *
  	 * Hybrid MBRs do not necessarily comply with this.
87fc0ad2a   Doug Anderson   block/partitions/...
209
210
211
  	 *
  	 * Consider a bad value here to be a warning to support dd'ing
  	 * an image from a smaller disk to a larger disk.
27a7c6421   Davidlohr Bueso   partitions/efi: a...
212
213
  	 */
  	if (ret == GPT_MBR_PROTECTIVE) {
6b02fa59a   Davidlohr Bueso   partitions/efi: l...
214
215
  		sz = le32_to_cpu(mbr->partition_record[part].size_in_lba);
  		if (sz != (uint32_t) total_sectors - 1 && sz != 0xFFFFFFFF)
87fc0ad2a   Doug Anderson   block/partitions/...
216
217
218
219
  			pr_debug("GPT: mbr size in lba (%u) different than whole disk (%u).
  ",
  				 sz, min_t(uint32_t,
  					   total_sectors - 1, 0xFFFFFFFF));
27a7c6421   Davidlohr Bueso   partitions/efi: a...
220
  	}
b05ebbbbe   Davidlohr Bueso   partitions/efi: d...
221
222
  done:
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
  }
  
  /**
   * read_lba(): Read bytes from disk, starting at given LBA
16e155652   Fabian Frederick   block/partitions/...
227
228
229
230
   * @state: disk parsed partitions
   * @lba: the Logical Block Address of the partition table
   * @buffer: destination buffer
   * @count: bytes to read
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
   *
1493bf217   Tejun Heo   block: use struct...
232
   * Description: Reads @count bytes from @state->bdev into @buffer.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
   * Returns number of bytes read on success, 0 on error.
   */
1493bf217   Tejun Heo   block: use struct...
235
236
  static size_t read_lba(struct parsed_partitions *state,
  		       u64 lba, u8 *buffer, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
  {
  	size_t totalreadcount = 0;
1493bf217   Tejun Heo   block: use struct...
239
  	struct block_device *bdev = state->bdev;
7d13af327   Karel Zak   partitions: use s...
240
  	sector_t n = lba * (bdev_logical_block_size(bdev) / 512);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241

1493bf217   Tejun Heo   block: use struct...
242
  	if (!buffer || lba > last_lba(bdev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
                  return 0;
  
  	while (count) {
  		int copied = 512;
  		Sector sect;
1493bf217   Tejun Heo   block: use struct...
248
  		unsigned char *data = read_part_sector(state, n++, &sect);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  		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
16e155652   Fabian Frederick   block/partitions/...
264
265
   * @state: disk parsed partitions
   * @gpt: GPT header
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
268
269
270
   * 
   * 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!
   */
1493bf217   Tejun Heo   block: use struct...
271
272
  static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state,
  					 gpt_header *gpt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
  {
  	size_t count;
  	gpt_entry *pte;
1493bf217   Tejun Heo   block: use struct...
276
277
  
  	if (!gpt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
  		return NULL;
c5082b70a   Alden Tondettar   partitions/efi: F...
279
  	count = (size_t)le32_to_cpu(gpt->num_partition_entries) *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
                  le32_to_cpu(gpt->sizeof_partition_entry);
  	if (!count)
  		return NULL;
ea56505be   Philippe De Muyter   partitions/efi.c:...
283
  	pte = kmalloc(count, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
  	if (!pte)
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286

1493bf217   Tejun Heo   block: use struct...
287
  	if (read_lba(state, le64_to_cpu(gpt->partition_entry_lba),
70f637e90   Davidlohr Bueso   partitions/efi: s...
288
  			(u8 *) pte, count) < count) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
290
291
292
293
294
295
296
297
  		kfree(pte);
                  pte=NULL;
  		return NULL;
  	}
  	return pte;
  }
  
  /**
   * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
16e155652   Fabian Frederick   block/partitions/...
298
299
   * @state: disk parsed partitions
   * @lba: the Logical Block Address of the partition table
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
   * 
   * Description: returns GPT header on success, NULL on error.   Allocates
1493bf217   Tejun Heo   block: use struct...
302
   * and fills a GPT header starting at @ from @state->bdev.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
   * Note: remember to free gpt when finished with it.
   */
1493bf217   Tejun Heo   block: use struct...
305
306
  static gpt_header *alloc_read_gpt_header(struct parsed_partitions *state,
  					 u64 lba)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
  {
  	gpt_header *gpt;
1493bf217   Tejun Heo   block: use struct...
309
  	unsigned ssz = bdev_logical_block_size(state->bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310

ea56505be   Philippe De Muyter   partitions/efi.c:...
311
  	gpt = kmalloc(ssz, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
  	if (!gpt)
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314

1493bf217   Tejun Heo   block: use struct...
315
  	if (read_lba(state, lba, (u8 *) gpt, ssz) < ssz) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
319
320
321
322
323
324
325
  		kfree(gpt);
                  gpt=NULL;
  		return NULL;
  	}
  
  	return gpt;
  }
  
  /**
   * is_gpt_valid() - tests one GPT header and PTEs for validity
16e155652   Fabian Frederick   block/partitions/...
326
327
328
329
   * @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.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
332
333
   *
   * Description: returns 1 if valid,  0 on error.
   * If valid, returns pointers to newly allocated GPT header and PTEs.
   */
1493bf217   Tejun Heo   block: use struct...
334
335
  static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
  			gpt_header **gpt, gpt_entry **ptes)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
  {
  	u32 crc, origcrc;
c5082b70a   Alden Tondettar   partitions/efi: F...
338
  	u64 lastlba, pt_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339

1493bf217   Tejun Heo   block: use struct...
340
  	if (!ptes)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
  		return 0;
1493bf217   Tejun Heo   block: use struct...
342
  	if (!(*gpt = alloc_read_gpt_header(state, lba)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
346
  		return 0;
  
  	/* Check the GUID Partition Table signature */
  	if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
d99169626   Thomas Gleixner   fs/partitions/efi...
347
348
349
350
351
  		pr_debug("GUID Partition Table Header signature is wrong:"
  			 "%lld != %lld
  ",
  			 (unsigned long long)le64_to_cpu((*gpt)->signature),
  			 (unsigned long long)GPT_HEADER_SIGNATURE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
  		goto fail;
  	}
8b8a6e188   Peter Jones   block/partitions/...
354
  	/* Check the GUID Partition Table header size is too big */
3eb8e74ec   Timo Warns   fs/partitions/efi...
355
356
  	if (le32_to_cpu((*gpt)->header_size) >
  			bdev_logical_block_size(state->bdev)) {
8b8a6e188   Peter Jones   block/partitions/...
357
358
  		pr_debug("GUID Partition Table Header size is too large: %u > %u
  ",
3eb8e74ec   Timo Warns   fs/partitions/efi...
359
360
361
362
  			le32_to_cpu((*gpt)->header_size),
  			bdev_logical_block_size(state->bdev));
  		goto fail;
  	}
8b8a6e188   Peter Jones   block/partitions/...
363
364
365
366
367
368
369
370
  	/* 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
  ",
  			le32_to_cpu((*gpt)->header_size),
  			sizeof(gpt_header));
  		goto fail;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
375
376
  	/* 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) {
d99169626   Thomas Gleixner   fs/partitions/efi...
377
378
379
  		pr_debug("GUID Partition Table Header CRC is wrong: %x != %x
  ",
  			 crc, origcrc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
381
382
383
384
385
386
  		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) {
d99169626   Thomas Gleixner   fs/partitions/efi...
387
388
389
390
  		pr_debug("GPT my_lba incorrect: %lld != %lld
  ",
  			 (unsigned long long)le64_to_cpu((*gpt)->my_lba),
  			 (unsigned long long)lba);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
393
394
395
396
  		goto fail;
  	}
  
  	/* Check the first_usable_lba and last_usable_lba are
  	 * within the disk.
  	 */
1493bf217   Tejun Heo   block: use struct...
397
  	lastlba = last_lba(state->bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
  	if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) {
d99169626   Thomas Gleixner   fs/partitions/efi...
399
400
401
402
  		pr_debug("GPT: first_usable_lba incorrect: %lld > %lld
  ",
  			 (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba),
  			 (unsigned long long)lastlba);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
  		goto fail;
  	}
  	if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) {
d99169626   Thomas Gleixner   fs/partitions/efi...
406
407
408
409
  		pr_debug("GPT: last_usable_lba incorrect: %lld > %lld
  ",
  			 (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
  			 (unsigned long long)lastlba);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
  		goto fail;
  	}
aa054bc93   Davidlohr Bueso   partitions/efi: c...
412
413
414
415
416
417
418
  	if (le64_to_cpu((*gpt)->last_usable_lba) < le64_to_cpu((*gpt)->first_usable_lba)) {
  		pr_debug("GPT: last_usable_lba incorrect: %lld > %lld
  ",
  			 (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
  			 (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba));
  		goto fail;
  	}
fa039d5f6   Timo Warns   Validate size of ...
419
420
  	/* Check that sizeof_partition_entry has the correct value */
  	if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) {
c19ca6cb4   Masanari Iida   treewide: Fix typ...
421
422
  		pr_debug("GUID Partition Entry Size check failed.
  ");
fa039d5f6   Timo Warns   Validate size of ...
423
424
  		goto fail;
  	}
c5082b70a   Alden Tondettar   partitions/efi: F...
425
426
427
428
429
430
431
432
433
  	/* 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
  ",
  			 (unsigned long long)pt_size, KMALLOC_MAX_SIZE);
  		goto fail;
  	}
1493bf217   Tejun Heo   block: use struct...
434
  	if (!(*ptes = alloc_read_gpt_entries(state, *gpt)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
437
  		goto fail;
  
  	/* Check the GUID Partition Entry Array CRC */
c5082b70a   Alden Tondettar   partitions/efi: F...
438
  	crc = efi_crc32((const unsigned char *) (*ptes), pt_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
  
  	if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
c19ca6cb4   Masanari Iida   treewide: Fix typ...
441
442
  		pr_debug("GUID Partition Entry Array CRC check failed.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
  		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
16e155652   Fabian Frederick   block/partitions/...
460
461
   * @pte:pte to check
   * @lastlba: last lba of the disk
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
   *
   * 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
16e155652   Fabian Frederick   block/partitions/...
477
478
479
480
   * @pgpt: primary GPT header
   * @agpt: alternate GPT header
   * @lastlba: last LBA number
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
485
486
487
488
489
490
491
   * 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)) {
b4bc4a18a   Andrew Morton   block/partitions/...
492
493
494
495
  		pr_warn("GPT:Primary header LBA != Alt. header alternate_lba
  ");
  		pr_warn("GPT:%lld != %lld
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
498
499
500
  		       (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)) {
b4bc4a18a   Andrew Morton   block/partitions/...
501
502
503
504
  		pr_warn("GPT:Primary header alternate_lba != Alt. header my_lba
  ");
  		pr_warn("GPT:%lld != %lld
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
506
507
508
509
510
  		       (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)) {
b4bc4a18a   Andrew Morton   block/partitions/...
511
512
513
514
  		pr_warn("GPT:first_usable_lbas don't match.
  ");
  		pr_warn("GPT:%lld != %lld
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
519
520
  		       (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)) {
b4bc4a18a   Andrew Morton   block/partitions/...
521
522
523
524
  		pr_warn("GPT:last_usable_lbas don't match.
  ");
  		pr_warn("GPT:%lld != %lld
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
527
528
529
  		       (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)) {
b4bc4a18a   Andrew Morton   block/partitions/...
530
531
  		pr_warn("GPT:disk_guids don't match.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
533
534
535
  		error_found++;
  	}
  	if (le32_to_cpu(pgpt->num_partition_entries) !=
              le32_to_cpu(agpt->num_partition_entries)) {
b4bc4a18a   Andrew Morton   block/partitions/...
536
  		pr_warn("GPT:num_partition_entries don't match: "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
539
540
541
542
543
544
  		       "0x%x != 0x%x
  ",
  		       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)) {
b4bc4a18a   Andrew Morton   block/partitions/...
545
  		pr_warn("GPT:sizeof_partition_entry values don't match: "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
548
549
550
551
552
553
  		       "0x%x != 0x%x
  ",
                         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)) {
b4bc4a18a   Andrew Morton   block/partitions/...
554
  		pr_warn("GPT:partition_entry_array_crc32 values don't match: "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
556
557
558
559
560
561
  		       "0x%x != 0x%x
  ",
                         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) {
b4bc4a18a   Andrew Morton   block/partitions/...
562
563
564
565
  		pr_warn("GPT:Primary header thinks Alt. header is not at the end of the disk.
  ");
  		pr_warn("GPT:%lld != %lld
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
567
568
569
570
571
  			(unsigned long long)le64_to_cpu(pgpt->alternate_lba),
  			(unsigned long long)lastlba);
  		error_found++;
  	}
  
  	if (le64_to_cpu(agpt->my_lba) != lastlba) {
b4bc4a18a   Andrew Morton   block/partitions/...
572
573
574
575
  		pr_warn("GPT:Alternate GPT header not at the end of the disk.
  ");
  		pr_warn("GPT:%lld != %lld
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
577
578
579
580
581
  			(unsigned long long)le64_to_cpu(agpt->my_lba),
  			(unsigned long long)lastlba);
  		error_found++;
  	}
  
  	if (error_found)
b4bc4a18a   Andrew Morton   block/partitions/...
582
583
  		pr_warn("GPT: Use GNU Parted to correct GPT errors.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
585
586
587
588
  	return;
  }
  
  /**
   * find_valid_gpt() - Search disk for valid GPT headers and PTEs
16e155652   Fabian Frederick   block/partitions/...
589
590
591
592
   * @state: disk parsed partitions
   * @gpt: GPT header ptr, filled on return.
   * @ptes: PTEs ptr, filled on return.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
594
595
596
597
598
599
600
601
602
   * 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.
   */
1493bf217   Tejun Heo   block: use struct...
603
604
  static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
  			  gpt_entry **ptes)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
607
608
  {
  	int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
  	gpt_header *pgpt = NULL, *agpt = NULL;
  	gpt_entry *pptes = NULL, *aptes = NULL;
4c64c30a5   Olaf Hering   small cleanup in ...
609
  	legacy_mbr *legacymbr;
27a7c6421   Davidlohr Bueso   partitions/efi: a...
610
  	sector_t total_sectors = i_size_read(state->bdev->bd_inode) >> 9;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
  	u64 lastlba;
1493bf217   Tejun Heo   block: use struct...
612
613
  
  	if (!ptes)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
  		return 0;
1493bf217   Tejun Heo   block: use struct...
615
  	lastlba = last_lba(state->bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
          if (!force_gpt) {
b05ebbbbe   Davidlohr Bueso   partitions/efi: d...
617
618
619
620
621
622
  		/* 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));
27a7c6421   Davidlohr Bueso   partitions/efi: a...
623
  		good_pmbr = is_pmbr_valid(legacymbr, total_sectors);
b05ebbbbe   Davidlohr Bueso   partitions/efi: d...
624
625
626
627
628
629
630
631
632
633
  		kfree(legacymbr);
  
  		if (!good_pmbr)
  			goto fail;
  
  		pr_debug("Device has a %s MBR
  ",
  			 good_pmbr == GPT_MBR_PROTECTIVE ?
  						"protective" : "hybrid");
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634

1493bf217   Tejun Heo   block: use struct...
635
  	good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
637
  				 &pgpt, &pptes);
          if (good_pgpt)
1493bf217   Tejun Heo   block: use struct...
638
  		good_agpt = is_gpt_valid(state,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
640
641
  					 le64_to_cpu(pgpt->alternate_lba),
  					 &agpt, &aptes);
          if (!good_agpt && force_gpt)
1493bf217   Tejun Heo   block: use struct...
642
                  good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
644
645
646
647
648
649
650
651
652
653
654
655
  
          /* 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);
70f637e90   Davidlohr Bueso   partitions/efi: s...
656
  		if (!good_agpt)
b4bc4a18a   Andrew Morton   block/partitions/...
657
658
                          pr_warn("Alternate GPT is invalid, using primary GPT.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
662
663
664
665
                  return 1;
          }
          else if (good_agpt) {
                  *gpt  = agpt;
                  *ptes = aptes;
                  kfree(pgpt);
                  kfree(pptes);
b4bc4a18a   Andrew Morton   block/partitions/...
666
667
  		pr_warn("Primary GPT is invalid, using alternate GPT.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
670
671
672
673
674
675
676
677
678
679
680
681
                  return 1;
          }
  
   fail:
          kfree(pgpt);
          kfree(agpt);
          kfree(pptes);
          kfree(aptes);
          *gpt = NULL;
          *ptes = NULL;
          return 0;
  }
  
  /**
d5528d5e9   Nikolai Merinov   partitions/efi: F...
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
   * utf16_le_to_7bit(): Naively converts a UTF-16LE string to 7-bit ASCII characters
   * @in: input UTF-16LE string
   * @size: size of the input string
   * @out: output string ptr, should be capable to store @size+1 characters
   *
   * Description: Converts @size UTF16-LE symbols from @in string to 7-bit
   * ASCII characters and stores them to @out. Adds trailing zero to @out array.
   */
  static void utf16_le_to_7bit(const __le16 *in, unsigned int size, u8 *out)
  {
  	unsigned int i = 0;
  
  	out[size] = 0;
  
  	while (i < size) {
  		u8 c = le16_to_cpu(in[i]) & 0xff;
  
  		if (c && !isprint(c))
  			c = '!';
  		out[i] = c;
  		i++;
  	}
  }
  
  /**
1493bf217   Tejun Heo   block: use struct...
707
   * efi_partition(struct parsed_partitions *state)
16e155652   Fabian Frederick   block/partitions/...
708
   * @state: disk parsed partitions
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
   *
   * 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
   *
   */
1493bf217   Tejun Heo   block: use struct...
725
  int efi_partition(struct parsed_partitions *state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
727
728
729
  {
  	gpt_header *gpt = NULL;
  	gpt_entry *ptes = NULL;
  	u32 i;
1493bf217   Tejun Heo   block: use struct...
730
  	unsigned ssz = bdev_logical_block_size(state->bdev) / 512;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731

1493bf217   Tejun Heo   block: use struct...
732
  	if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
735
736
  		kfree(gpt);
  		kfree(ptes);
  		return 0;
  	}
d99169626   Thomas Gleixner   fs/partitions/efi...
737
738
  	pr_debug("GUID Partition Table is valid!  Yea!
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
740
  
  	for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
eec7ecfed   Will Drewry   genhd, efi: add e...
741
  		struct partition_meta_info *info;
eec7ecfed   Will Drewry   genhd, efi: add e...
742
  		unsigned label_max;
7d13af327   Karel Zak   partitions: use s...
743
744
745
  		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;
1493bf217   Tejun Heo   block: use struct...
746
  		if (!is_pte_valid(&ptes[i], last_lba(state->bdev)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
747
  			continue;
7d13af327   Karel Zak   partitions: use s...
748
  		put_partition(state, i+1, start * ssz, size * ssz);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
750
  
  		/* If this is a RAID volume, tell md */
70f637e90   Davidlohr Bueso   partitions/efi: s...
751
  		if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID))
cc9106247   Cesar Eduardo Barros   fs/partitions: us...
752
  			state->parts[i + 1].flags = ADDPART_FLAG_RAID;
eec7ecfed   Will Drewry   genhd, efi: add e...
753
754
  
  		info = &state->parts[i + 1].info;
26e022727   Borislav Petkov   efi: Rename efi_g...
755
  		efi_guid_to_str(&ptes[i].unique_partition_guid, info->uuid);
eec7ecfed   Will Drewry   genhd, efi: add e...
756
757
  
  		/* Naively convert UTF16-LE to 7 bits. */
49204c116   Antti P Miettinen   block/partitions/...
758
759
  		label_max = min(ARRAY_SIZE(info->volname) - 1,
  				ARRAY_SIZE(ptes[i].partition_name));
d5528d5e9   Nikolai Merinov   partitions/efi: F...
760
  		utf16_le_to_7bit(ptes[i].partition_name, label_max, info->volname);
eec7ecfed   Will Drewry   genhd, efi: add e...
761
  		state->parts[i + 1].has_info = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
763
764
  	}
  	kfree(ptes);
  	kfree(gpt);
9c867fbe0   Alexey Dobriyan   partitions: fix s...
765
766
  	strlcat(state->pp_buf, "
  ", PAGE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
768
  	return 1;
  }