Blame view
fs/partitions/efi.c
20.7 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 |
/************************************************************ * EFI GUID Partition Table handling |
7d13af327 partitions: use s... |
3 4 5 6 |
* * http://www.uefi.org/specs/ * http://www.intel.com/technology/efi/ * |
1da177e4c Linux-2.6.12-rc2 |
7 8 9 10 11 12 13 14 15 16 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 85 86 87 88 89 90 91 92 93 94 95 |
* 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: * 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. * ************************************************************/ |
1da177e4c Linux-2.6.12-rc2 |
96 |
#include <linux/crc32.h> |
eec7ecfed genhd, efi: add e... |
97 |
#include <linux/ctype.h> |
7d13af327 partitions: use s... |
98 |
#include <linux/math64.h> |
5a0e3ad6a include cleanup: ... |
99 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
100 101 |
#include "check.h" #include "efi.h" |
1da177e4c Linux-2.6.12-rc2 |
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
/* 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 * @len - length of buf * * 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... |
143 |
static u64 last_lba(struct block_device *bdev) |
1da177e4c Linux-2.6.12-rc2 |
144 145 146 |
{ if (!bdev || !bdev->bd_inode) return 0; |
7d13af327 partitions: use s... |
147 148 |
return div_u64(bdev->bd_inode->i_size, bdev_logical_block_size(bdev)) - 1ULL; |
1da177e4c Linux-2.6.12-rc2 |
149 150 151 |
} static inline int |
4c64c30a5 small cleanup in ... |
152 |
pmbr_part_valid(struct partition *part) |
1da177e4c Linux-2.6.12-rc2 |
153 154 155 156 157 158 159 160 161 162 |
{ if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT && le32_to_cpu(part->start_sect) == 1UL) return 1; return 0; } /** * is_pmbr_valid(): test Protective MBR for validity * @mbr: pointer to a legacy mbr structure |
1da177e4c Linux-2.6.12-rc2 |
163 164 165 166 167 168 169 |
* * Description: Returns 1 if PMBR is valid, 0 otherwise. * Validity depends on two things: * 1) MSDOS signature is in the last two bytes of the MBR * 2) One partition of type 0xEE is found */ static int |
4c64c30a5 small cleanup in ... |
170 |
is_pmbr_valid(legacy_mbr *mbr) |
1da177e4c Linux-2.6.12-rc2 |
171 172 173 174 175 |
{ int i; if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) return 0; for (i = 0; i < 4; i++) |
4c64c30a5 small cleanup in ... |
176 |
if (pmbr_part_valid(&mbr->partition_record[i])) |
1da177e4c Linux-2.6.12-rc2 |
177 178 179 180 181 182 |
return 1; return 0; } /** * read_lba(): Read bytes from disk, starting at given LBA |
1493bf217 block: use struct... |
183 |
* @state |
1da177e4c Linux-2.6.12-rc2 |
184 185 186 187 |
* @lba * @buffer * @size_t * |
1493bf217 block: use struct... |
188 |
* Description: Reads @count bytes from @state->bdev into @buffer. |
1da177e4c Linux-2.6.12-rc2 |
189 190 |
* Returns number of bytes read on success, 0 on error. */ |
1493bf217 block: use struct... |
191 192 |
static size_t read_lba(struct parsed_partitions *state, u64 lba, u8 *buffer, size_t count) |
1da177e4c Linux-2.6.12-rc2 |
193 194 |
{ size_t totalreadcount = 0; |
1493bf217 block: use struct... |
195 |
struct block_device *bdev = state->bdev; |
7d13af327 partitions: use s... |
196 |
sector_t n = lba * (bdev_logical_block_size(bdev) / 512); |
1da177e4c Linux-2.6.12-rc2 |
197 |
|
1493bf217 block: use struct... |
198 |
if (!buffer || lba > last_lba(bdev)) |
1da177e4c Linux-2.6.12-rc2 |
199 200 201 202 203 |
return 0; while (count) { int copied = 512; Sector sect; |
1493bf217 block: use struct... |
204 |
unsigned char *data = read_part_sector(state, n++, §); |
1da177e4c Linux-2.6.12-rc2 |
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
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 |
1493bf217 block: use struct... |
220 |
* @state |
1da177e4c Linux-2.6.12-rc2 |
221 222 223 224 225 226 |
* @gpt - GPT header * * 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... |
227 228 |
static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state, gpt_header *gpt) |
1da177e4c Linux-2.6.12-rc2 |
229 230 231 |
{ size_t count; gpt_entry *pte; |
1493bf217 block: use struct... |
232 233 |
if (!gpt) |
1da177e4c Linux-2.6.12-rc2 |
234 235 236 237 238 239 |
return NULL; count = le32_to_cpu(gpt->num_partition_entries) * le32_to_cpu(gpt->sizeof_partition_entry); if (!count) return NULL; |
f8314dc60 [PATCH] fs: Conve... |
240 |
pte = kzalloc(count, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
241 242 |
if (!pte) return NULL; |
1da177e4c Linux-2.6.12-rc2 |
243 |
|
1493bf217 block: use struct... |
244 |
if (read_lba(state, le64_to_cpu(gpt->partition_entry_lba), |
1da177e4c Linux-2.6.12-rc2 |
245 246 247 248 249 250 251 252 253 254 255 |
(u8 *) pte, count) < count) { kfree(pte); pte=NULL; return NULL; } return pte; } /** * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk |
1493bf217 block: use struct... |
256 |
* @state |
1da177e4c Linux-2.6.12-rc2 |
257 258 259 |
* @lba is the Logical Block Address of the partition table * * Description: returns GPT header on success, NULL on error. Allocates |
1493bf217 block: use struct... |
260 |
* and fills a GPT header starting at @ from @state->bdev. |
1da177e4c Linux-2.6.12-rc2 |
261 262 |
* Note: remember to free gpt when finished with it. */ |
1493bf217 block: use struct... |
263 264 |
static gpt_header *alloc_read_gpt_header(struct parsed_partitions *state, u64 lba) |
1da177e4c Linux-2.6.12-rc2 |
265 266 |
{ gpt_header *gpt; |
1493bf217 block: use struct... |
267 |
unsigned ssz = bdev_logical_block_size(state->bdev); |
1da177e4c Linux-2.6.12-rc2 |
268 |
|
87038c2d5 partitions: read ... |
269 |
gpt = kzalloc(ssz, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
270 271 |
if (!gpt) return NULL; |
1da177e4c Linux-2.6.12-rc2 |
272 |
|
1493bf217 block: use struct... |
273 |
if (read_lba(state, lba, (u8 *) gpt, ssz) < ssz) { |
1da177e4c Linux-2.6.12-rc2 |
274 275 276 277 278 279 280 281 282 283 |
kfree(gpt); gpt=NULL; return NULL; } return gpt; } /** * is_gpt_valid() - tests one GPT header and PTEs for validity |
1493bf217 block: use struct... |
284 |
* @state |
1da177e4c Linux-2.6.12-rc2 |
285 286 287 288 289 290 291 |
* @lba is the logical block address of the GPT header to test * @gpt is a GPT header ptr, filled on return. * @ptes is a PTEs ptr, filled on return. * * Description: returns 1 if valid, 0 on error. * If valid, returns pointers to newly allocated GPT header and PTEs. */ |
1493bf217 block: use struct... |
292 293 |
static int is_gpt_valid(struct parsed_partitions *state, u64 lba, gpt_header **gpt, gpt_entry **ptes) |
1da177e4c Linux-2.6.12-rc2 |
294 295 296 |
{ u32 crc, origcrc; u64 lastlba; |
1493bf217 block: use struct... |
297 |
if (!ptes) |
1da177e4c Linux-2.6.12-rc2 |
298 |
return 0; |
1493bf217 block: use struct... |
299 |
if (!(*gpt = alloc_read_gpt_header(state, lba))) |
1da177e4c Linux-2.6.12-rc2 |
300 301 302 303 |
return 0; /* Check the GUID Partition Table signature */ if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) { |
d99169626 fs/partitions/efi... |
304 305 306 307 308 |
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 |
309 310 |
goto fail; } |
3eb8e74ec fs/partitions/efi... |
311 312 313 314 315 316 317 318 319 |
/* Check the GUID Partition Table header size */ if (le32_to_cpu((*gpt)->header_size) > bdev_logical_block_size(state->bdev)) { pr_debug("GUID Partition Table Header size is wrong: %u > %u ", le32_to_cpu((*gpt)->header_size), bdev_logical_block_size(state->bdev)); goto fail; } |
1da177e4c Linux-2.6.12-rc2 |
320 321 322 323 324 325 |
/* 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... |
326 327 328 |
pr_debug("GUID Partition Table Header CRC is wrong: %x != %x ", crc, origcrc); |
1da177e4c Linux-2.6.12-rc2 |
329 330 331 332 333 334 335 |
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... |
336 337 338 339 |
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 |
340 341 342 343 344 345 |
goto fail; } /* Check the first_usable_lba and last_usable_lba are * within the disk. */ |
1493bf217 block: use struct... |
346 |
lastlba = last_lba(state->bdev); |
1da177e4c Linux-2.6.12-rc2 |
347 |
if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) { |
d99169626 fs/partitions/efi... |
348 349 350 351 |
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 |
352 353 354 |
goto fail; } if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) { |
d99169626 fs/partitions/efi... |
355 356 357 358 |
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 |
359 360 |
goto fail; } |
fa039d5f6 Validate size of ... |
361 362 363 364 365 366 |
/* Check that sizeof_partition_entry has the correct value */ if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { pr_debug("GUID Partitition Entry Size check failed. "); goto fail; } |
1493bf217 block: use struct... |
367 |
if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) |
1da177e4c Linux-2.6.12-rc2 |
368 369 370 371 372 373 374 375 |
goto fail; /* Check the GUID Partition Entry Array CRC */ crc = efi_crc32((const unsigned char *) (*ptes), le32_to_cpu((*gpt)->num_partition_entries) * le32_to_cpu((*gpt)->sizeof_partition_entry)); if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { |
d99169626 fs/partitions/efi... |
376 377 |
pr_debug("GUID Partitition Entry Array CRC check failed. "); |
1da177e4c Linux-2.6.12-rc2 |
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 |
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 * @pte is the pte to check * @lastlba is last lba of the disk * * 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 * @pgpt is the primary GPT header * @agpt is the alternate GPT header * @lastlba is the last LBA number * 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)) { printk(KERN_WARNING "GPT:Primary header LBA != Alt. header alternate_lba "); printk(KERN_WARNING "GPT:%lld != %lld ", (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)) { printk(KERN_WARNING "GPT:Primary header alternate_lba != Alt. header my_lba "); printk(KERN_WARNING "GPT:%lld != %lld ", (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)) { printk(KERN_WARNING "GPT:first_usable_lbas don't match. "); printk(KERN_WARNING "GPT:%lld != %lld ", (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)) { printk(KERN_WARNING "GPT:last_usable_lbas don't match. "); printk(KERN_WARNING "GPT:%lld != %lld ", (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)) { printk(KERN_WARNING "GPT:disk_guids don't match. "); error_found++; } if (le32_to_cpu(pgpt->num_partition_entries) != le32_to_cpu(agpt->num_partition_entries)) { printk(KERN_WARNING "GPT:num_partition_entries don't match: " "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)) { printk(KERN_WARNING "GPT:sizeof_partition_entry values don't match: " "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)) { printk(KERN_WARNING "GPT:partition_entry_array_crc32 values don't match: " "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) { printk(KERN_WARNING "GPT:Primary header thinks Alt. header is not at the end of the disk. "); printk(KERN_WARNING "GPT:%lld != %lld ", (unsigned long long)le64_to_cpu(pgpt->alternate_lba), (unsigned long long)lastlba); error_found++; } if (le64_to_cpu(agpt->my_lba) != lastlba) { printk(KERN_WARNING "GPT:Alternate GPT header not at the end of the disk. "); printk(KERN_WARNING "GPT:%lld != %lld ", (unsigned long long)le64_to_cpu(agpt->my_lba), (unsigned long long)lastlba); error_found++; } if (error_found) printk(KERN_WARNING "GPT: Use GNU Parted to correct GPT errors. "); return; } /** * find_valid_gpt() - Search disk for valid GPT headers and PTEs |
1493bf217 block: use struct... |
530 |
* @state |
1da177e4c Linux-2.6.12-rc2 |
531 532 533 534 535 536 537 538 539 540 541 542 |
* @gpt is a GPT header ptr, filled on return. * @ptes is a PTEs ptr, filled on return. * 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... |
543 544 |
static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, gpt_entry **ptes) |
1da177e4c Linux-2.6.12-rc2 |
545 546 547 548 |
{ 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 ... |
549 |
legacy_mbr *legacymbr; |
1da177e4c Linux-2.6.12-rc2 |
550 |
u64 lastlba; |
1493bf217 block: use struct... |
551 552 |
if (!ptes) |
1da177e4c Linux-2.6.12-rc2 |
553 |
return 0; |
1493bf217 block: use struct... |
554 |
lastlba = last_lba(state->bdev); |
1da177e4c Linux-2.6.12-rc2 |
555 556 |
if (!force_gpt) { /* This will be added to the EFI Spec. per Intel after v1.02. */ |
f8314dc60 [PATCH] fs: Conve... |
557 |
legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
558 |
if (legacymbr) { |
1493bf217 block: use struct... |
559 560 |
read_lba(state, 0, (u8 *) legacymbr, sizeof (*legacymbr)); |
4c64c30a5 small cleanup in ... |
561 |
good_pmbr = is_pmbr_valid(legacymbr); |
1da177e4c Linux-2.6.12-rc2 |
562 |
kfree(legacymbr); |
1da177e4c Linux-2.6.12-rc2 |
563 564 565 566 |
} if (!good_pmbr) goto fail; } |
1493bf217 block: use struct... |
567 |
good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA, |
1da177e4c Linux-2.6.12-rc2 |
568 569 |
&pgpt, &pptes); if (good_pgpt) |
1493bf217 block: use struct... |
570 |
good_agpt = is_gpt_valid(state, |
1da177e4c Linux-2.6.12-rc2 |
571 572 573 |
le64_to_cpu(pgpt->alternate_lba), &agpt, &aptes); if (!good_agpt && force_gpt) |
1493bf217 block: use struct... |
574 |
good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes); |
1da177e4c Linux-2.6.12-rc2 |
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 |
/* 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); if (!good_agpt) { printk(KERN_WARNING "Alternate GPT is invalid, " "using primary GPT. "); } return 1; } else if (good_agpt) { *gpt = agpt; *ptes = aptes; kfree(pgpt); kfree(pptes); printk(KERN_WARNING "Primary GPT is invalid, using alternate GPT. "); return 1; } fail: kfree(pgpt); kfree(agpt); kfree(pptes); kfree(aptes); *gpt = NULL; *ptes = NULL; return 0; } /** |
1493bf217 block: use struct... |
618 |
* efi_partition(struct parsed_partitions *state) |
1da177e4c Linux-2.6.12-rc2 |
619 |
* @state |
1da177e4c Linux-2.6.12-rc2 |
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 |
* * 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... |
636 |
int efi_partition(struct parsed_partitions *state) |
1da177e4c Linux-2.6.12-rc2 |
637 638 639 640 |
{ gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; |
1493bf217 block: use struct... |
641 |
unsigned ssz = bdev_logical_block_size(state->bdev) / 512; |
eec7ecfed genhd, efi: add e... |
642 |
u8 unparsed_guid[37]; |
1da177e4c Linux-2.6.12-rc2 |
643 |
|
1493bf217 block: use struct... |
644 |
if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { |
1da177e4c Linux-2.6.12-rc2 |
645 646 647 648 |
kfree(gpt); kfree(ptes); return 0; } |
d99169626 fs/partitions/efi... |
649 650 |
pr_debug("GUID Partition Table is valid! Yea! "); |
1da177e4c Linux-2.6.12-rc2 |
651 652 |
for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { |
eec7ecfed genhd, efi: add e... |
653 654 655 |
struct partition_meta_info *info; unsigned label_count = 0; unsigned label_max; |
7d13af327 partitions: use s... |
656 657 658 |
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... |
659 |
if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) |
1da177e4c Linux-2.6.12-rc2 |
660 |
continue; |
7d13af327 partitions: use s... |
661 |
put_partition(state, i+1, start * ssz, size * ssz); |
1da177e4c Linux-2.6.12-rc2 |
662 663 664 665 |
/* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) |
cc9106247 fs/partitions: us... |
666 |
state->parts[i + 1].flags = ADDPART_FLAG_RAID; |
eec7ecfed genhd, efi: add e... |
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 |
info = &state->parts[i + 1].info; /* Instead of doing a manual swap to big endian, reuse the * common ASCII hex format as the interim. */ efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid); part_pack_uuid(unparsed_guid, info->uuid); /* Naively convert UTF16-LE to 7 bits. */ label_max = min(sizeof(info->volname) - 1, sizeof(ptes[i].partition_name)); 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; |
1da177e4c Linux-2.6.12-rc2 |
687 688 689 |
} kfree(ptes); kfree(gpt); |
9c867fbe0 partitions: fix s... |
690 691 |
strlcat(state->pp_buf, " ", PAGE_SIZE); |
1da177e4c Linux-2.6.12-rc2 |
692 693 |
return 1; } |