Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.21 641 lines 20 kB view raw
1/************************************************************ 2 * EFI GUID Partition Table handling 3 * Per Intel EFI Specification v1.02 4 * http://developer.intel.com/technology/efi/efi.htm 5 * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com> 6 * Copyright 2000,2001,2002,2004 Dell Inc. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 * 23 * TODO: 24 * 25 * Changelog: 26 * Mon Nov 09 2004 Matt Domsch <Matt_Domsch@dell.com> 27 * - test for valid PMBR and valid PGPT before ever reading 28 * AGPT, allow override with 'gpt' kernel command line option. 29 * - check for first/last_usable_lba outside of size of disk 30 * 31 * Tue Mar 26 2002 Matt Domsch <Matt_Domsch@dell.com> 32 * - Ported to 2.5.7-pre1 and 2.5.7-dj2 33 * - Applied patch to avoid fault in alternate header handling 34 * - cleaned up find_valid_gpt 35 * - On-disk structure and copy in memory is *always* LE now - 36 * swab fields as needed 37 * - remove print_gpt_header() 38 * - only use first max_p partition entries, to keep the kernel minor number 39 * and partition numbers tied. 40 * 41 * Mon Feb 04 2002 Matt Domsch <Matt_Domsch@dell.com> 42 * - Removed __PRIPTR_PREFIX - not being used 43 * 44 * Mon Jan 14 2002 Matt Domsch <Matt_Domsch@dell.com> 45 * - Ported to 2.5.2-pre11 + library crc32 patch Linus applied 46 * 47 * Thu Dec 6 2001 Matt Domsch <Matt_Domsch@dell.com> 48 * - Added compare_gpts(). 49 * - moved le_efi_guid_to_cpus() back into this file. GPT is the only 50 * thing that keeps EFI GUIDs on disk. 51 * - Changed gpt structure names and members to be simpler and more Linux-like. 52 * 53 * Wed Oct 17 2001 Matt Domsch <Matt_Domsch@dell.com> 54 * - Removed CONFIG_DEVFS_VOLUMES_UUID code entirely per Martin Wilck 55 * 56 * Wed Oct 10 2001 Matt Domsch <Matt_Domsch@dell.com> 57 * - Changed function comments to DocBook style per Andreas Dilger suggestion. 58 * 59 * Mon Oct 08 2001 Matt Domsch <Matt_Domsch@dell.com> 60 * - Change read_lba() to use the page cache per Al Viro's work. 61 * - print u64s properly on all architectures 62 * - fixed debug_printk(), now Dprintk() 63 * 64 * Mon Oct 01 2001 Matt Domsch <Matt_Domsch@dell.com> 65 * - Style cleanups 66 * - made most functions static 67 * - Endianness addition 68 * - remove test for second alternate header, as it's not per spec, 69 * and is unnecessary. There's now a method to read/write the last 70 * sector of an odd-sized disk from user space. No tools have ever 71 * been released which used this code, so it's effectively dead. 72 * - Per Asit Mallick of Intel, added a test for a valid PMBR. 73 * - Added kernel command line option 'gpt' to override valid PMBR test. 74 * 75 * Wed Jun 6 2001 Martin Wilck <Martin.Wilck@Fujitsu-Siemens.com> 76 * - added devfs volume UUID support (/dev/volumes/uuids) for 77 * mounting file systems by the partition GUID. 78 * 79 * Tue Dec 5 2000 Matt Domsch <Matt_Domsch@dell.com> 80 * - Moved crc32() to linux/lib, added efi_crc32(). 81 * 82 * Thu Nov 30 2000 Matt Domsch <Matt_Domsch@dell.com> 83 * - Replaced Intel's CRC32 function with an equivalent 84 * non-license-restricted version. 85 * 86 * Wed Oct 25 2000 Matt Domsch <Matt_Domsch@dell.com> 87 * - Fixed the last_lba() call to return the proper last block 88 * 89 * Thu Oct 12 2000 Matt Domsch <Matt_Domsch@dell.com> 90 * - Thanks to Andries Brouwer for his debugging assistance. 91 * - Code works, detects all the partitions. 92 * 93 ************************************************************/ 94#include <linux/crc32.h> 95#include "check.h" 96#include "efi.h" 97 98#undef EFI_DEBUG 99#ifdef EFI_DEBUG 100#define Dprintk(x...) printk(KERN_DEBUG x) 101#else 102#define Dprintk(x...) 103#endif 104 105/* This allows a kernel command line option 'gpt' to override 106 * the test for invalid PMBR. Not __initdata because reloading 107 * the partition tables happens after init too. 108 */ 109static int force_gpt; 110static int __init 111force_gpt_fn(char *str) 112{ 113 force_gpt = 1; 114 return 1; 115} 116__setup("gpt", force_gpt_fn); 117 118 119/** 120 * efi_crc32() - EFI version of crc32 function 121 * @buf: buffer to calculate crc32 of 122 * @len - length of buf 123 * 124 * Description: Returns EFI-style CRC32 value for @buf 125 * 126 * This function uses the little endian Ethernet polynomial 127 * but seeds the function with ~0, and xor's with ~0 at the end. 128 * Note, the EFI Specification, v1.02, has a reference to 129 * Dr. Dobbs Journal, May 1994 (actually it's in May 1992). 130 */ 131static inline u32 132efi_crc32(const void *buf, unsigned long len) 133{ 134 return (crc32(~0L, buf, len) ^ ~0L); 135} 136 137/** 138 * last_lba(): return number of last logical block of device 139 * @bdev: block device 140 * 141 * Description: Returns last LBA value on success, 0 on error. 142 * This is stored (by sd and ide-geometry) in 143 * the part[0] entry for this disk, and is the number of 144 * physical sectors available on the disk. 145 */ 146static u64 147last_lba(struct block_device *bdev) 148{ 149 if (!bdev || !bdev->bd_inode) 150 return 0; 151 return (bdev->bd_inode->i_size >> 9) - 1ULL; 152} 153 154static inline int 155pmbr_part_valid(struct partition *part, u64 lastlba) 156{ 157 if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT && 158 le32_to_cpu(part->start_sect) == 1UL) 159 return 1; 160 return 0; 161} 162 163/** 164 * is_pmbr_valid(): test Protective MBR for validity 165 * @mbr: pointer to a legacy mbr structure 166 * @lastlba: last_lba for the whole device 167 * 168 * Description: Returns 1 if PMBR is valid, 0 otherwise. 169 * Validity depends on two things: 170 * 1) MSDOS signature is in the last two bytes of the MBR 171 * 2) One partition of type 0xEE is found 172 */ 173static int 174is_pmbr_valid(legacy_mbr *mbr, u64 lastlba) 175{ 176 int i; 177 if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) 178 return 0; 179 for (i = 0; i < 4; i++) 180 if (pmbr_part_valid(&mbr->partition_record[i], lastlba)) 181 return 1; 182 return 0; 183} 184 185/** 186 * read_lba(): Read bytes from disk, starting at given LBA 187 * @bdev 188 * @lba 189 * @buffer 190 * @size_t 191 * 192 * Description: Reads @count bytes from @bdev into @buffer. 193 * Returns number of bytes read on success, 0 on error. 194 */ 195static size_t 196read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count) 197{ 198 size_t totalreadcount = 0; 199 200 if (!bdev || !buffer || lba > last_lba(bdev)) 201 return 0; 202 203 while (count) { 204 int copied = 512; 205 Sector sect; 206 unsigned char *data = read_dev_sector(bdev, lba++, &sect); 207 if (!data) 208 break; 209 if (copied > count) 210 copied = count; 211 memcpy(buffer, data, copied); 212 put_dev_sector(sect); 213 buffer += copied; 214 totalreadcount +=copied; 215 count -= copied; 216 } 217 return totalreadcount; 218} 219 220/** 221 * alloc_read_gpt_entries(): reads partition entries from disk 222 * @bdev 223 * @gpt - GPT header 224 * 225 * Description: Returns ptes on success, NULL on error. 226 * Allocates space for PTEs based on information found in @gpt. 227 * Notes: remember to free pte when you're done! 228 */ 229static gpt_entry * 230alloc_read_gpt_entries(struct block_device *bdev, gpt_header *gpt) 231{ 232 size_t count; 233 gpt_entry *pte; 234 if (!bdev || !gpt) 235 return NULL; 236 237 count = le32_to_cpu(gpt->num_partition_entries) * 238 le32_to_cpu(gpt->sizeof_partition_entry); 239 if (!count) 240 return NULL; 241 pte = kzalloc(count, GFP_KERNEL); 242 if (!pte) 243 return NULL; 244 245 if (read_lba(bdev, le64_to_cpu(gpt->partition_entry_lba), 246 (u8 *) pte, 247 count) < count) { 248 kfree(pte); 249 pte=NULL; 250 return NULL; 251 } 252 return pte; 253} 254 255/** 256 * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk 257 * @bdev 258 * @lba is the Logical Block Address of the partition table 259 * 260 * Description: returns GPT header on success, NULL on error. Allocates 261 * and fills a GPT header starting at @ from @bdev. 262 * Note: remember to free gpt when finished with it. 263 */ 264static gpt_header * 265alloc_read_gpt_header(struct block_device *bdev, u64 lba) 266{ 267 gpt_header *gpt; 268 if (!bdev) 269 return NULL; 270 271 gpt = kzalloc(sizeof (gpt_header), GFP_KERNEL); 272 if (!gpt) 273 return NULL; 274 275 if (read_lba(bdev, lba, (u8 *) gpt, 276 sizeof (gpt_header)) < sizeof (gpt_header)) { 277 kfree(gpt); 278 gpt=NULL; 279 return NULL; 280 } 281 282 return gpt; 283} 284 285/** 286 * is_gpt_valid() - tests one GPT header and PTEs for validity 287 * @bdev 288 * @lba is the logical block address of the GPT header to test 289 * @gpt is a GPT header ptr, filled on return. 290 * @ptes is a PTEs ptr, filled on return. 291 * 292 * Description: returns 1 if valid, 0 on error. 293 * If valid, returns pointers to newly allocated GPT header and PTEs. 294 */ 295static int 296is_gpt_valid(struct block_device *bdev, u64 lba, 297 gpt_header **gpt, gpt_entry **ptes) 298{ 299 u32 crc, origcrc; 300 u64 lastlba; 301 302 if (!bdev || !gpt || !ptes) 303 return 0; 304 if (!(*gpt = alloc_read_gpt_header(bdev, lba))) 305 return 0; 306 307 /* Check the GUID Partition Table signature */ 308 if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) { 309 Dprintk("GUID Partition Table Header signature is wrong:" 310 "%lld != %lld\n", 311 (unsigned long long)le64_to_cpu((*gpt)->signature), 312 (unsigned long long)GPT_HEADER_SIGNATURE); 313 goto fail; 314 } 315 316 /* Check the GUID Partition Table CRC */ 317 origcrc = le32_to_cpu((*gpt)->header_crc32); 318 (*gpt)->header_crc32 = 0; 319 crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size)); 320 321 if (crc != origcrc) { 322 Dprintk 323 ("GUID Partition Table Header CRC is wrong: %x != %x\n", 324 crc, origcrc); 325 goto fail; 326 } 327 (*gpt)->header_crc32 = cpu_to_le32(origcrc); 328 329 /* Check that the my_lba entry points to the LBA that contains 330 * the GUID Partition Table */ 331 if (le64_to_cpu((*gpt)->my_lba) != lba) { 332 Dprintk("GPT my_lba incorrect: %lld != %lld\n", 333 (unsigned long long)le64_to_cpu((*gpt)->my_lba), 334 (unsigned long long)lba); 335 goto fail; 336 } 337 338 /* Check the first_usable_lba and last_usable_lba are 339 * within the disk. 340 */ 341 lastlba = last_lba(bdev); 342 if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) { 343 Dprintk("GPT: first_usable_lba incorrect: %lld > %lld\n", 344 (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba), 345 (unsigned long long)lastlba); 346 goto fail; 347 } 348 if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) { 349 Dprintk("GPT: last_usable_lba incorrect: %lld > %lld\n", 350 (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba), 351 (unsigned long long)lastlba); 352 goto fail; 353 } 354 355 if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt))) 356 goto fail; 357 358 /* Check the GUID Partition Entry Array CRC */ 359 crc = efi_crc32((const unsigned char *) (*ptes), 360 le32_to_cpu((*gpt)->num_partition_entries) * 361 le32_to_cpu((*gpt)->sizeof_partition_entry)); 362 363 if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { 364 Dprintk("GUID Partitition Entry Array CRC check failed.\n"); 365 goto fail_ptes; 366 } 367 368 /* We're done, all's well */ 369 return 1; 370 371 fail_ptes: 372 kfree(*ptes); 373 *ptes = NULL; 374 fail: 375 kfree(*gpt); 376 *gpt = NULL; 377 return 0; 378} 379 380/** 381 * is_pte_valid() - tests one PTE for validity 382 * @pte is the pte to check 383 * @lastlba is last lba of the disk 384 * 385 * Description: returns 1 if valid, 0 on error. 386 */ 387static inline int 388is_pte_valid(const gpt_entry *pte, const u64 lastlba) 389{ 390 if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) || 391 le64_to_cpu(pte->starting_lba) > lastlba || 392 le64_to_cpu(pte->ending_lba) > lastlba) 393 return 0; 394 return 1; 395} 396 397/** 398 * compare_gpts() - Search disk for valid GPT headers and PTEs 399 * @pgpt is the primary GPT header 400 * @agpt is the alternate GPT header 401 * @lastlba is the last LBA number 402 * Description: Returns nothing. Sanity checks pgpt and agpt fields 403 * and prints warnings on discrepancies. 404 * 405 */ 406static void 407compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba) 408{ 409 int error_found = 0; 410 if (!pgpt || !agpt) 411 return; 412 if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) { 413 printk(KERN_WARNING 414 "GPT:Primary header LBA != Alt. header alternate_lba\n"); 415 printk(KERN_WARNING "GPT:%lld != %lld\n", 416 (unsigned long long)le64_to_cpu(pgpt->my_lba), 417 (unsigned long long)le64_to_cpu(agpt->alternate_lba)); 418 error_found++; 419 } 420 if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) { 421 printk(KERN_WARNING 422 "GPT:Primary header alternate_lba != Alt. header my_lba\n"); 423 printk(KERN_WARNING "GPT:%lld != %lld\n", 424 (unsigned long long)le64_to_cpu(pgpt->alternate_lba), 425 (unsigned long long)le64_to_cpu(agpt->my_lba)); 426 error_found++; 427 } 428 if (le64_to_cpu(pgpt->first_usable_lba) != 429 le64_to_cpu(agpt->first_usable_lba)) { 430 printk(KERN_WARNING "GPT:first_usable_lbas don't match.\n"); 431 printk(KERN_WARNING "GPT:%lld != %lld\n", 432 (unsigned long long)le64_to_cpu(pgpt->first_usable_lba), 433 (unsigned long long)le64_to_cpu(agpt->first_usable_lba)); 434 error_found++; 435 } 436 if (le64_to_cpu(pgpt->last_usable_lba) != 437 le64_to_cpu(agpt->last_usable_lba)) { 438 printk(KERN_WARNING "GPT:last_usable_lbas don't match.\n"); 439 printk(KERN_WARNING "GPT:%lld != %lld\n", 440 (unsigned long long)le64_to_cpu(pgpt->last_usable_lba), 441 (unsigned long long)le64_to_cpu(agpt->last_usable_lba)); 442 error_found++; 443 } 444 if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) { 445 printk(KERN_WARNING "GPT:disk_guids don't match.\n"); 446 error_found++; 447 } 448 if (le32_to_cpu(pgpt->num_partition_entries) != 449 le32_to_cpu(agpt->num_partition_entries)) { 450 printk(KERN_WARNING "GPT:num_partition_entries don't match: " 451 "0x%x != 0x%x\n", 452 le32_to_cpu(pgpt->num_partition_entries), 453 le32_to_cpu(agpt->num_partition_entries)); 454 error_found++; 455 } 456 if (le32_to_cpu(pgpt->sizeof_partition_entry) != 457 le32_to_cpu(agpt->sizeof_partition_entry)) { 458 printk(KERN_WARNING 459 "GPT:sizeof_partition_entry values don't match: " 460 "0x%x != 0x%x\n", 461 le32_to_cpu(pgpt->sizeof_partition_entry), 462 le32_to_cpu(agpt->sizeof_partition_entry)); 463 error_found++; 464 } 465 if (le32_to_cpu(pgpt->partition_entry_array_crc32) != 466 le32_to_cpu(agpt->partition_entry_array_crc32)) { 467 printk(KERN_WARNING 468 "GPT:partition_entry_array_crc32 values don't match: " 469 "0x%x != 0x%x\n", 470 le32_to_cpu(pgpt->partition_entry_array_crc32), 471 le32_to_cpu(agpt->partition_entry_array_crc32)); 472 error_found++; 473 } 474 if (le64_to_cpu(pgpt->alternate_lba) != lastlba) { 475 printk(KERN_WARNING 476 "GPT:Primary header thinks Alt. header is not at the end of the disk.\n"); 477 printk(KERN_WARNING "GPT:%lld != %lld\n", 478 (unsigned long long)le64_to_cpu(pgpt->alternate_lba), 479 (unsigned long long)lastlba); 480 error_found++; 481 } 482 483 if (le64_to_cpu(agpt->my_lba) != lastlba) { 484 printk(KERN_WARNING 485 "GPT:Alternate GPT header not at the end of the disk.\n"); 486 printk(KERN_WARNING "GPT:%lld != %lld\n", 487 (unsigned long long)le64_to_cpu(agpt->my_lba), 488 (unsigned long long)lastlba); 489 error_found++; 490 } 491 492 if (error_found) 493 printk(KERN_WARNING 494 "GPT: Use GNU Parted to correct GPT errors.\n"); 495 return; 496} 497 498/** 499 * find_valid_gpt() - Search disk for valid GPT headers and PTEs 500 * @bdev 501 * @gpt is a GPT header ptr, filled on return. 502 * @ptes is a PTEs ptr, filled on return. 503 * Description: Returns 1 if valid, 0 on error. 504 * If valid, returns pointers to newly allocated GPT header and PTEs. 505 * Validity depends on PMBR being valid (or being overridden by the 506 * 'gpt' kernel command line option) and finding either the Primary 507 * GPT header and PTEs valid, or the Alternate GPT header and PTEs 508 * valid. If the Primary GPT header is not valid, the Alternate GPT header 509 * is not checked unless the 'gpt' kernel command line option is passed. 510 * This protects against devices which misreport their size, and forces 511 * the user to decide to use the Alternate GPT. 512 */ 513static int 514find_valid_gpt(struct block_device *bdev, gpt_header **gpt, gpt_entry **ptes) 515{ 516 int good_pgpt = 0, good_agpt = 0, good_pmbr = 0; 517 gpt_header *pgpt = NULL, *agpt = NULL; 518 gpt_entry *pptes = NULL, *aptes = NULL; 519 legacy_mbr *legacymbr = NULL; 520 u64 lastlba; 521 if (!bdev || !gpt || !ptes) 522 return 0; 523 524 lastlba = last_lba(bdev); 525 if (!force_gpt) { 526 /* This will be added to the EFI Spec. per Intel after v1.02. */ 527 legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL); 528 if (legacymbr) { 529 read_lba(bdev, 0, (u8 *) legacymbr, 530 sizeof (*legacymbr)); 531 good_pmbr = is_pmbr_valid(legacymbr, lastlba); 532 kfree(legacymbr); 533 legacymbr=NULL; 534 } 535 if (!good_pmbr) 536 goto fail; 537 } 538 539 good_pgpt = is_gpt_valid(bdev, GPT_PRIMARY_PARTITION_TABLE_LBA, 540 &pgpt, &pptes); 541 if (good_pgpt) 542 good_agpt = is_gpt_valid(bdev, 543 le64_to_cpu(pgpt->alternate_lba), 544 &agpt, &aptes); 545 if (!good_agpt && force_gpt) 546 good_agpt = is_gpt_valid(bdev, lastlba, 547 &agpt, &aptes); 548 549 /* The obviously unsuccessful case */ 550 if (!good_pgpt && !good_agpt) 551 goto fail; 552 553 compare_gpts(pgpt, agpt, lastlba); 554 555 /* The good cases */ 556 if (good_pgpt) { 557 *gpt = pgpt; 558 *ptes = pptes; 559 kfree(agpt); 560 kfree(aptes); 561 if (!good_agpt) { 562 printk(KERN_WARNING 563 "Alternate GPT is invalid, " 564 "using primary GPT.\n"); 565 } 566 return 1; 567 } 568 else if (good_agpt) { 569 *gpt = agpt; 570 *ptes = aptes; 571 kfree(pgpt); 572 kfree(pptes); 573 printk(KERN_WARNING 574 "Primary GPT is invalid, using alternate GPT.\n"); 575 return 1; 576 } 577 578 fail: 579 kfree(pgpt); 580 kfree(agpt); 581 kfree(pptes); 582 kfree(aptes); 583 *gpt = NULL; 584 *ptes = NULL; 585 return 0; 586} 587 588/** 589 * efi_partition(struct parsed_partitions *state, struct block_device *bdev) 590 * @state 591 * @bdev 592 * 593 * Description: called from check.c, if the disk contains GPT 594 * partitions, sets up partition entries in the kernel. 595 * 596 * If the first block on the disk is a legacy MBR, 597 * it will get handled by msdos_partition(). 598 * If it's a Protective MBR, we'll handle it here. 599 * 600 * We do not create a Linux partition for GPT, but 601 * only for the actual data partitions. 602 * Returns: 603 * -1 if unable to read the partition table 604 * 0 if this isn't our partition table 605 * 1 if successful 606 * 607 */ 608int 609efi_partition(struct parsed_partitions *state, struct block_device *bdev) 610{ 611 gpt_header *gpt = NULL; 612 gpt_entry *ptes = NULL; 613 u32 i; 614 615 if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { 616 kfree(gpt); 617 kfree(ptes); 618 return 0; 619 } 620 621 Dprintk("GUID Partition Table is valid! Yea!\n"); 622 623 for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { 624 if (!is_pte_valid(&ptes[i], last_lba(bdev))) 625 continue; 626 627 put_partition(state, i+1, le64_to_cpu(ptes[i].starting_lba), 628 (le64_to_cpu(ptes[i].ending_lba) - 629 le64_to_cpu(ptes[i].starting_lba) + 630 1ULL)); 631 632 /* If this is a RAID volume, tell md */ 633 if (!efi_guidcmp(ptes[i].partition_type_guid, 634 PARTITION_LINUX_RAID_GUID)) 635 state->parts[i+1].flags = 1; 636 } 637 kfree(ptes); 638 kfree(gpt); 639 printk("\n"); 640 return 1; 641}