Blame view
block/partitions/efi.c
22.7 KB
a497ee34a block: switch all... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4c Linux-2.6.12-rc2 |
2 3 |
/************************************************************ * EFI GUID Partition Table handling |
7d13af327 partitions: use s... |
4 5 6 7 |
* * http://www.uefi.org/specs/ * http://www.intel.com/technology/efi/ * |
1da177e4c 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 Linux-2.6.12-rc2 |
11 12 13 |
* TODO: * * Changelog: |
70f637e90 partitions/efi: s... |
14 15 16 |
* Mon August 5th, 2013 Davidlohr Bueso <davidlohr@hp.com> * - detect hybrid MBRs, tighter pMBR checking & cleanups. * |
1da177e4c 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 block/partitions/... |
85 |
#include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
86 |
#include <linux/crc32.h> |
eec7ecfed genhd, efi: add e... |
87 |
#include <linux/ctype.h> |
7d13af327 partitions: use s... |
88 |
#include <linux/math64.h> |
5a0e3ad6a include cleanup: ... |
89 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
90 91 |
#include "check.h" #include "efi.h" |
1da177e4c 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 block/partitions/... |
109 |
* @len: length of buf |
1da177e4c 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 block: use struct... |
133 |
static u64 last_lba(struct block_device *bdev) |
1da177e4c Linux-2.6.12-rc2 |
134 135 136 |
{ if (!bdev || !bdev->bd_inode) return 0; |
7d13af327 partitions: use s... |
137 138 |
return div_u64(bdev->bd_inode->i_size, bdev_logical_block_size(bdev)) - 1ULL; |
1da177e4c Linux-2.6.12-rc2 |
139 |
} |
c2ebdc243 partitions/efi: u... |
140 |
static inline int pmbr_part_valid(gpt_mbr_record *part) |
1da177e4c Linux-2.6.12-rc2 |
141 |
{ |
33afd7a7d 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 partitions/efi: d... |
148 |
return GPT_MBR_PROTECTIVE; |
33afd7a7d partitions/efi: c... |
149 150 |
invalid: return 0; |
1da177e4c 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 partitions/efi: a... |
156 |
* @total_sectors: amount of sectors in the device |
1da177e4c Linux-2.6.12-rc2 |
157 |
* |
b05ebbbbe 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 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 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 Linux-2.6.12-rc2 |
170 |
*/ |
27a7c6421 partitions/efi: a... |
171 |
static int is_pmbr_valid(legacy_mbr *mbr, sector_t total_sectors) |
1da177e4c Linux-2.6.12-rc2 |
172 |
{ |
6b02fa59a partitions/efi: l... |
173 |
uint32_t sz = 0; |
27a7c6421 partitions/efi: a... |
174 |
int i, part = 0, ret = 0; /* invalid by default */ |
b05ebbbbe partitions/efi: d... |
175 |
|
1da177e4c Linux-2.6.12-rc2 |
176 |
if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) |
b05ebbbbe 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 partitions/efi: a... |
182 |
part = i; |
b05ebbbbe 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 Linux-2.6.12-rc2 |
195 |
for (i = 0; i < 4; i++) |
b05ebbbbe 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 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 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 partitions/efi: a... |
207 208 |
* * Hybrid MBRs do not necessarily comply with this. |
87fc0ad2a 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 partitions/efi: a... |
212 213 |
*/ if (ret == GPT_MBR_PROTECTIVE) { |
6b02fa59a 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 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 partitions/efi: a... |
220 |
} |
b05ebbbbe partitions/efi: d... |
221 222 |
done: return ret; |
1da177e4c Linux-2.6.12-rc2 |
223 224 225 226 |
} /** * read_lba(): Read bytes from disk, starting at given LBA |
16e155652 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 Linux-2.6.12-rc2 |
231 |
* |
1493bf217 block: use struct... |
232 |
* Description: Reads @count bytes from @state->bdev into @buffer. |
1da177e4c Linux-2.6.12-rc2 |
233 234 |
* Returns number of bytes read on success, 0 on error. */ |
1493bf217 block: use struct... |
235 236 |
static size_t read_lba(struct parsed_partitions *state, u64 lba, u8 *buffer, size_t count) |
1da177e4c Linux-2.6.12-rc2 |
237 238 |
{ size_t totalreadcount = 0; |
1493bf217 block: use struct... |
239 |
struct block_device *bdev = state->bdev; |
7d13af327 partitions: use s... |
240 |
sector_t n = lba * (bdev_logical_block_size(bdev) / 512); |
1da177e4c Linux-2.6.12-rc2 |
241 |
|
1493bf217 block: use struct... |
242 |
if (!buffer || lba > last_lba(bdev)) |
1da177e4c Linux-2.6.12-rc2 |
243 244 245 246 247 |
return 0; while (count) { int copied = 512; Sector sect; |
1493bf217 block: use struct... |
248 |
unsigned char *data = read_part_sector(state, n++, §); |
1da177e4c 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 block/partitions/... |
264 265 |
* @state: disk parsed partitions * @gpt: GPT header |
1da177e4c 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 block: use struct... |
271 272 |
static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state, gpt_header *gpt) |
1da177e4c Linux-2.6.12-rc2 |
273 274 275 |
{ size_t count; gpt_entry *pte; |
1493bf217 block: use struct... |
276 277 |
if (!gpt) |
1da177e4c Linux-2.6.12-rc2 |
278 |
return NULL; |
c5082b70a partitions/efi: F... |
279 |
count = (size_t)le32_to_cpu(gpt->num_partition_entries) * |
1da177e4c Linux-2.6.12-rc2 |
280 281 282 |
le32_to_cpu(gpt->sizeof_partition_entry); if (!count) return NULL; |
ea56505be partitions/efi.c:... |
283 |
pte = kmalloc(count, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
284 285 |
if (!pte) return NULL; |
1da177e4c Linux-2.6.12-rc2 |
286 |
|
1493bf217 block: use struct... |
287 |
if (read_lba(state, le64_to_cpu(gpt->partition_entry_lba), |
70f637e90 partitions/efi: s... |
288 |
(u8 *) pte, count) < count) { |
1da177e4c 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 block/partitions/... |
298 299 |
* @state: disk parsed partitions * @lba: the Logical Block Address of the partition table |
1da177e4c Linux-2.6.12-rc2 |
300 301 |
* * Description: returns GPT header on success, NULL on error. Allocates |
1493bf217 block: use struct... |
302 |
* and fills a GPT header starting at @ from @state->bdev. |
1da177e4c Linux-2.6.12-rc2 |
303 304 |
* Note: remember to free gpt when finished with it. */ |
1493bf217 block: use struct... |
305 306 |
static gpt_header *alloc_read_gpt_header(struct parsed_partitions *state, u64 lba) |
1da177e4c Linux-2.6.12-rc2 |
307 308 |
{ gpt_header *gpt; |
1493bf217 block: use struct... |
309 |
unsigned ssz = bdev_logical_block_size(state->bdev); |
1da177e4c Linux-2.6.12-rc2 |
310 |
|
ea56505be partitions/efi.c:... |
311 |
gpt = kmalloc(ssz, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
312 313 |
if (!gpt) return NULL; |
1da177e4c Linux-2.6.12-rc2 |
314 |
|
1493bf217 block: use struct... |
315 |
if (read_lba(state, lba, (u8 *) gpt, ssz) < ssz) { |
1da177e4c 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 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 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 block: use struct... |
334 335 |
static int is_gpt_valid(struct parsed_partitions *state, u64 lba, gpt_header **gpt, gpt_entry **ptes) |
1da177e4c Linux-2.6.12-rc2 |
336 337 |
{ u32 crc, origcrc; |
c5082b70a partitions/efi: F... |
338 |
u64 lastlba, pt_size; |
1da177e4c Linux-2.6.12-rc2 |
339 |
|
1493bf217 block: use struct... |
340 |
if (!ptes) |
1da177e4c Linux-2.6.12-rc2 |
341 |
return 0; |
1493bf217 block: use struct... |
342 |
if (!(*gpt = alloc_read_gpt_header(state, lba))) |
1da177e4c 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 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 Linux-2.6.12-rc2 |
352 353 |
goto fail; } |
8b8a6e188 block/partitions/... |
354 |
/* Check the GUID Partition Table header size is too big */ |
3eb8e74ec fs/partitions/efi... |
355 356 |
if (le32_to_cpu((*gpt)->header_size) > bdev_logical_block_size(state->bdev)) { |
8b8a6e188 block/partitions/... |
357 358 |
pr_debug("GUID Partition Table Header size is too large: %u > %u ", |
3eb8e74ec fs/partitions/efi... |
359 360 361 362 |
le32_to_cpu((*gpt)->header_size), bdev_logical_block_size(state->bdev)); goto fail; } |
8b8a6e188 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 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 fs/partitions/efi... |
377 378 379 |
pr_debug("GUID Partition Table Header CRC is wrong: %x != %x ", crc, origcrc); |
1da177e4c 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 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 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 block: use struct... |
397 |
lastlba = last_lba(state->bdev); |
1da177e4c Linux-2.6.12-rc2 |
398 |
if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) { |
d99169626 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 Linux-2.6.12-rc2 |
403 404 405 |
goto fail; } if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) { |
d99169626 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 Linux-2.6.12-rc2 |
410 411 |
goto fail; } |
aa054bc93 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 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 treewide: Fix typ... |
421 422 |
pr_debug("GUID Partition Entry Size check failed. "); |
fa039d5f6 Validate size of ... |
423 424 |
goto fail; } |
c5082b70a 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 block: use struct... |
434 |
if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) |
1da177e4c Linux-2.6.12-rc2 |
435 436 437 |
goto fail; /* Check the GUID Partition Entry Array CRC */ |
c5082b70a partitions/efi: F... |
438 |
crc = efi_crc32((const unsigned char *) (*ptes), pt_size); |
1da177e4c Linux-2.6.12-rc2 |
439 440 |
if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { |
c19ca6cb4 treewide: Fix typ... |
441 442 |
pr_debug("GUID Partition Entry Array CRC check failed. "); |
1da177e4c 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 block/partitions/... |
460 461 |
* @pte:pte to check * @lastlba: last lba of the disk |
1da177e4c 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 block/partitions/... |
477 478 479 480 |
* @pgpt: primary GPT header * @agpt: alternate GPT header * @lastlba: last LBA number * |
1da177e4c 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 block/partitions/... |
492 493 494 495 |
pr_warn("GPT:Primary header LBA != Alt. header alternate_lba "); pr_warn("GPT:%lld != %lld ", |
1da177e4c 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 block/partitions/... |
501 502 503 504 |
pr_warn("GPT:Primary header alternate_lba != Alt. header my_lba "); pr_warn("GPT:%lld != %lld ", |
1da177e4c 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 block/partitions/... |
511 512 513 514 |
pr_warn("GPT:first_usable_lbas don't match. "); pr_warn("GPT:%lld != %lld ", |
1da177e4c 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 block/partitions/... |
521 522 523 524 |
pr_warn("GPT:last_usable_lbas don't match. "); pr_warn("GPT:%lld != %lld ", |
1da177e4c 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 block/partitions/... |
530 531 |
pr_warn("GPT:disk_guids don't match. "); |
1da177e4c 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 block/partitions/... |
536 |
pr_warn("GPT:num_partition_entries don't match: " |
1da177e4c 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 block/partitions/... |
545 |
pr_warn("GPT:sizeof_partition_entry values don't match: " |
1da177e4c 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 block/partitions/... |
554 |
pr_warn("GPT:partition_entry_array_crc32 values don't match: " |
1da177e4c 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 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 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 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 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 block/partitions/... |
582 583 |
pr_warn("GPT: Use GNU Parted to correct GPT errors. "); |
1da177e4c Linux-2.6.12-rc2 |
584 585 586 587 588 |
return; } /** * find_valid_gpt() - Search disk for valid GPT headers and PTEs |
16e155652 block/partitions/... |
589 590 591 592 |
* @state: disk parsed partitions * @gpt: GPT header ptr, filled on return. * @ptes: PTEs ptr, filled on return. * |
1da177e4c 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 block: use struct... |
603 604 |
static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, gpt_entry **ptes) |
1da177e4c 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 small cleanup in ... |
609 |
legacy_mbr *legacymbr; |
27a7c6421 partitions/efi: a... |
610 |
sector_t total_sectors = i_size_read(state->bdev->bd_inode) >> 9; |
1da177e4c Linux-2.6.12-rc2 |
611 |
u64 lastlba; |
1493bf217 block: use struct... |
612 613 |
if (!ptes) |
1da177e4c Linux-2.6.12-rc2 |
614 |
return 0; |
1493bf217 block: use struct... |
615 |
lastlba = last_lba(state->bdev); |
1da177e4c Linux-2.6.12-rc2 |
616 |
if (!force_gpt) { |
b05ebbbbe 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 partitions/efi: a... |
623 |
good_pmbr = is_pmbr_valid(legacymbr, total_sectors); |
b05ebbbbe 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 Linux-2.6.12-rc2 |
634 |
|
1493bf217 block: use struct... |
635 |
good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA, |
1da177e4c Linux-2.6.12-rc2 |
636 637 |
&pgpt, &pptes); if (good_pgpt) |
1493bf217 block: use struct... |
638 |
good_agpt = is_gpt_valid(state, |
1da177e4c Linux-2.6.12-rc2 |
639 640 641 |
le64_to_cpu(pgpt->alternate_lba), &agpt, &aptes); if (!good_agpt && force_gpt) |
1493bf217 block: use struct... |
642 |
good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes); |
1da177e4c 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 partitions/efi: s... |
656 |
if (!good_agpt) |
b4bc4a18a block/partitions/... |
657 658 |
pr_warn("Alternate GPT is invalid, using primary GPT. "); |
1da177e4c 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 block/partitions/... |
666 667 |
pr_warn("Primary GPT is invalid, using alternate GPT. "); |
1da177e4c 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 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 block: use struct... |
707 |
* efi_partition(struct parsed_partitions *state) |
16e155652 block/partitions/... |
708 |
* @state: disk parsed partitions |
1da177e4c 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 block: use struct... |
725 |
int efi_partition(struct parsed_partitions *state) |
1da177e4c Linux-2.6.12-rc2 |
726 727 728 729 |
{ gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; |
1493bf217 block: use struct... |
730 |
unsigned ssz = bdev_logical_block_size(state->bdev) / 512; |
1da177e4c Linux-2.6.12-rc2 |
731 |
|
1493bf217 block: use struct... |
732 |
if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { |
1da177e4c Linux-2.6.12-rc2 |
733 734 735 736 |
kfree(gpt); kfree(ptes); return 0; } |
d99169626 fs/partitions/efi... |
737 738 |
pr_debug("GUID Partition Table is valid! Yea! "); |
1da177e4c Linux-2.6.12-rc2 |
739 740 |
for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { |
eec7ecfed genhd, efi: add e... |
741 |
struct partition_meta_info *info; |
eec7ecfed genhd, efi: add e... |
742 |
unsigned label_max; |
7d13af327 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 block: use struct... |
746 |
if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) |
1da177e4c Linux-2.6.12-rc2 |
747 |
continue; |
7d13af327 partitions: use s... |
748 |
put_partition(state, i+1, start * ssz, size * ssz); |
1da177e4c Linux-2.6.12-rc2 |
749 750 |
/* If this is a RAID volume, tell md */ |
70f637e90 partitions/efi: s... |
751 |
if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) |
cc9106247 fs/partitions: us... |
752 |
state->parts[i + 1].flags = ADDPART_FLAG_RAID; |
eec7ecfed genhd, efi: add e... |
753 754 |
info = &state->parts[i + 1].info; |
26e022727 efi: Rename efi_g... |
755 |
efi_guid_to_str(&ptes[i].unique_partition_guid, info->uuid); |
eec7ecfed genhd, efi: add e... |
756 757 |
/* Naively convert UTF16-LE to 7 bits. */ |
49204c116 block/partitions/... |
758 759 |
label_max = min(ARRAY_SIZE(info->volname) - 1, ARRAY_SIZE(ptes[i].partition_name)); |
d5528d5e9 partitions/efi: F... |
760 |
utf16_le_to_7bit(ptes[i].partition_name, label_max, info->volname); |
eec7ecfed genhd, efi: add e... |
761 |
state->parts[i + 1].has_info = true; |
1da177e4c Linux-2.6.12-rc2 |
762 763 764 |
} kfree(ptes); kfree(gpt); |
9c867fbe0 partitions: fix s... |
765 766 |
strlcat(state->pp_buf, " ", PAGE_SIZE); |
1da177e4c Linux-2.6.12-rc2 |
767 768 |
return 1; } |