The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/partitions/efi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 Dell Computer Corporation
    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  * Wed  Mar 27 2002 Matt Domsch <Matt_Domsch@dell.com>
   27  * - Ported to 2.5.7-pre1 and 2.4.18
   28  * - Applied patch to avoid fault in alternate header handling
   29  * - cleaned up find_valid_gpt
   30  * - On-disk structure and copy in memory is *always* LE now - 
   31  *   swab fields as needed
   32  * - remove print_gpt_header()
   33  * - only use first max_p partition entries, to keep the kernel minor number
   34  *   and partition numbers tied.
   35  * - 2.4.18 patch needs own crc32() function - there's no official
   36  *   lib/crc32.c in 2.4.x.
   37  *
   38  * Mon  Feb 04 2002 Matt Domsch <Matt_Domsch@dell.com>
   39  * - Removed __PRIPTR_PREFIX - not being used
   40  *
   41  * Mon  Jan 14 2002 Matt Domsch <Matt_Domsch@dell.com>
   42  * - Ported to 2.5.2-pre11 + library crc32 patch Linus applied
   43  *
   44  * Thu Dec 6 2001 Matt Domsch <Matt_Domsch@dell.com>
   45  * - Added compare_gpts().
   46  * - moved le_efi_guid_to_cpus() back into this file.  GPT is the only
   47  *   thing that keeps EFI GUIDs on disk.
   48  * - Changed gpt structure names and members to be simpler and more Linux-like.
   49  * 
   50  * Wed Oct 17 2001 Matt Domsch <Matt_Domsch@dell.com>
   51  * - Removed CONFIG_DEVFS_VOLUMES_UUID code entirely per Martin Wilck
   52  *
   53  * Wed Oct 10 2001 Matt Domsch <Matt_Domsch@dell.com>
   54  * - Changed function comments to DocBook style per Andreas Dilger suggestion.
   55  *
   56  * Mon Oct 08 2001 Matt Domsch <Matt_Domsch@dell.com>
   57  * - Change read_lba() to use the page cache per Al Viro's work.
   58  * - print u64s properly on all architectures
   59  * - fixed debug_printk(), now Dprintk()
   60  *
   61  * Mon Oct 01 2001 Matt Domsch <Matt_Domsch@dell.com>
   62  * - Style cleanups
   63  * - made most functions static
   64  * - Endianness addition
   65  * - remove test for second alternate header, as it's not per spec,
   66  *   and is unnecessary.  There's now a method to read/write the last
   67  *   sector of an odd-sized disk from user space.  No tools have ever
   68  *   been released which used this code, so it's effectively dead.
   69  * - Per Asit Mallick of Intel, added a test for a valid PMBR.
   70  * - Added kernel command line option 'gpt' to override valid PMBR test.
   71  *
   72  * Wed Jun  6 2001 Martin Wilck <Martin.Wilck@Fujitsu-Siemens.com>
   73  * - added devfs volume UUID support (/dev/volumes/uuids) for
   74  *   mounting file systems by the partition GUID. 
   75  *
   76  * Tue Dec  5 2000 Matt Domsch <Matt_Domsch@dell.com>
   77  * - Moved crc32() to linux/lib, added efi_crc32().
   78  *
   79  * Thu Nov 30 2000 Matt Domsch <Matt_Domsch@dell.com>
   80  * - Replaced Intel's CRC32 function with an equivalent
   81  *   non-license-restricted version.
   82  *
   83  * Wed Oct 25 2000 Matt Domsch <Matt_Domsch@dell.com>
   84  * - Fixed the last_lba() call to return the proper last block
   85  *
   86  * Thu Oct 12 2000 Matt Domsch <Matt_Domsch@dell.com>
   87  * - Thanks to Andries Brouwer for his debugging assistance.
   88  * - Code works, detects all the partitions.
   89  *
   90  ************************************************************/
   91 #include <linux/config.h>
   92 #include <linux/fs.h>
   93 #include <linux/genhd.h>
   94 #include <linux/kernel.h>
   95 #include <linux/major.h>
   96 #include <linux/string.h>
   97 #include <linux/blk.h>
   98 #include <linux/blkpg.h>
   99 #include <linux/slab.h>
  100 #include <linux/smp_lock.h>
  101 #include <linux/init.h>
  102 #include <linux/crc32.h>
  103 #include <asm/system.h>
  104 #include <asm/byteorder.h>
  105 #include "check.h"
  106 #include "efi.h"
  107 
  108 #if CONFIG_BLK_DEV_MD
  109 extern void md_autodetect_dev(kdev_t dev);
  110 #endif
  111 
  112 /* Handle printing of 64-bit values */
  113 /* Borrowed from /usr/include/inttypes.h */
  114 # if BITS_PER_LONG == 64 
  115 #  define __PRI64_PREFIX        "l"
  116 # else
  117 #  define __PRI64_PREFIX        "ll"
  118 # endif
  119 # define PRIx64         __PRI64_PREFIX "x"
  120 
  121 
  122 #undef EFI_DEBUG
  123 #ifdef EFI_DEBUG
  124 #define Dprintk(x...) printk(KERN_DEBUG x)
  125 #else
  126 #define Dprintk(x...)
  127 #endif
  128 
  129 /* This allows a kernel command line option 'gpt' to override
  130  * the test for invalid PMBR.  Not __initdata because reloading
  131  * the partition tables happens after init too.
  132  */
  133 static int force_gpt;
  134 static int __init
  135 force_gpt_fn(char *str)
  136 {
  137         force_gpt = 1;
  138         return 1;
  139 }
  140 __setup("gpt", force_gpt_fn);
  141 
  142 /**
  143  * efi_crc32() - EFI version of crc32 function
  144  * @buf: buffer to calculate crc32 of
  145  * @len - length of buf
  146  *
  147  * Description: Returns EFI-style CRC32 value for @buf
  148  * 
  149  * This function uses the little endian Ethernet polynomial
  150  * but seeds the function with ~0, and xor's with ~0 at the end.
  151  * Note, the EFI Specification, v1.02, has a reference to
  152  * Dr. Dobbs Journal, May 1994 (actually it's in May 1992).
  153  */
  154 static inline u32
  155 efi_crc32(const void *buf, unsigned long len)
  156 {
  157         return (crc32(~0L, buf, len) ^ ~0L);
  158 }
  159 
  160 /**
  161  * is_pmbr_valid(): test Protective MBR for validity
  162  * @mbr: pointer to a legacy mbr structure
  163  *
  164  * Description: Returns 1 if PMBR is valid, 0 otherwise.
  165  * Validity depends on two things:
  166  *  1) MSDOS signature is in the last two bytes of the MBR
  167  *  2) One partition of type 0xEE is found
  168  */
  169 static int
  170 is_pmbr_valid(legacy_mbr *mbr)
  171 {
  172         int i, found = 0, signature = 0;
  173         if (!mbr)
  174                 return 0;
  175         signature = (le16_to_cpu(mbr->signature) == MSDOS_MBR_SIGNATURE);
  176         for (i = 0; signature && i < 4; i++) {
  177                 if (mbr->partition_record[i].sys_ind ==
  178                     EFI_PMBR_OSTYPE_EFI_GPT) {
  179                         found = 1;
  180                         break;
  181                 }
  182         }
  183         return (signature && found);
  184 }
  185 
  186 /**
  187  * last_lba(): return number of last logical block of device
  188  * @hd: gendisk with partition list
  189  * @bdev: block device
  190  * 
  191  * Description: Returns last LBA value on success, 0 on error.
  192  * This is stored (by sd and ide-geometry) in
  193  *  the part[0] entry for this disk, and is the number of
  194  *  physical sectors available on the disk.
  195  */
  196 static u64
  197 last_lba(struct gendisk *hd, struct block_device *bdev)
  198 {
  199         if (!hd || !hd->part || !bdev)
  200                 return 0;
  201         return hd->part[MINOR(to_kdev_t(bdev->bd_dev))].nr_sects - 1;
  202 }
  203 
  204 /**
  205  * read_lba(): Read bytes from disk, starting at given LBA
  206  * @hd
  207  * @bdev
  208  * @lba
  209  * @buffer
  210  * @size_t
  211  *
  212  * Description:  Reads @count bytes from @bdev into @buffer.
  213  * Returns number of bytes read on success, 0 on error.
  214  */
  215 static size_t
  216 read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba,
  217          u8 * buffer, size_t count)
  218 {
  219 
  220         size_t totalreadcount = 0, bytesread = 0;
  221         unsigned long blocksize;
  222         int i;
  223         Sector sect;
  224         unsigned char *data = NULL;
  225 
  226         if (!hd || !bdev || !buffer || !count)
  227                 return 0;
  228 
  229         blocksize = get_hardsect_size(to_kdev_t(bdev->bd_dev));
  230         if (!blocksize)
  231                 blocksize = 512;
  232 
  233         for (i = 0; count > 0; i++) {
  234                 data = read_dev_sector(bdev, lba, &sect);
  235                 if (!data)
  236                         return totalreadcount;
  237 
  238                 bytesread =
  239                     PAGE_CACHE_SIZE - (data -
  240                                        (unsigned char *) page_address(sect.v));
  241                 bytesread = min(bytesread, count);
  242                 memcpy(buffer, data, bytesread);
  243                 put_dev_sector(sect);
  244 
  245                 buffer += bytesread;
  246                 totalreadcount += bytesread;
  247                 count -= bytesread;
  248                 lba += (bytesread / blocksize);
  249         }
  250         return totalreadcount;
  251 }
  252 
  253 
  254 /**
  255  * alloc_read_gpt_entries(): reads partition entries from disk
  256  * @hd
  257  * @bdev
  258  * @gpt - GPT header
  259  * 
  260  * Description: Returns ptes on success,  NULL on error.
  261  * Allocates space for PTEs based on information found in @gpt.
  262  * Notes: remember to free pte when you're done!
  263  */
  264 static gpt_entry *
  265 alloc_read_gpt_entries(struct gendisk *hd,
  266                        struct block_device *bdev, gpt_header *gpt)
  267 {
  268         size_t count;
  269         gpt_entry *pte;
  270         if (!hd || !bdev || !gpt)
  271                 return NULL;
  272 
  273         count = le32_to_cpu(gpt->num_partition_entries) *
  274                 le32_to_cpu(gpt->sizeof_partition_entry);
  275         if (!count)
  276                 return NULL;
  277         pte = kmalloc(count, GFP_KERNEL);
  278         if (!pte)
  279                 return NULL;
  280         memset(pte, 0, count);
  281 
  282         if (read_lba(hd, bdev, le64_to_cpu(gpt->partition_entry_lba),
  283                      (u8 *) pte,
  284                      count) < count) {
  285                 kfree(pte);
  286                 pte=NULL;
  287                 return NULL;
  288         }
  289         return pte;
  290 }
  291 
  292 /**
  293  * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
  294  * @hd
  295  * @bdev
  296  * @lba is the Logical Block Address of the partition table
  297  * 
  298  * Description: returns GPT header on success, NULL on error.   Allocates
  299  * and fills a GPT header starting at @ from @bdev.
  300  * Note: remember to free gpt when finished with it.
  301  */
  302 static gpt_header *
  303 alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba)
  304 {
  305         gpt_header *gpt;
  306         if (!hd || !bdev)
  307                 return NULL;
  308 
  309         gpt = kmalloc(sizeof (gpt_header), GFP_KERNEL);
  310         if (!gpt)
  311                 return NULL;
  312         memset(gpt, 0, sizeof (gpt_header));
  313 
  314         if (read_lba(hd, bdev, lba, (u8 *) gpt,
  315                      sizeof (gpt_header)) < sizeof (gpt_header)) {
  316                 kfree(gpt);
  317                 gpt=NULL;
  318                 return NULL;
  319         }
  320 
  321         return gpt;
  322 }
  323 
  324 /**
  325  * is_gpt_valid() - tests one GPT header and PTEs for validity
  326  * @hd
  327  * @bdev
  328  * @lba is the logical block address of the GPT header to test
  329  * @gpt is a GPT header ptr, filled on return.
  330  * @ptes is a PTEs ptr, filled on return.
  331  *
  332  * Description: returns 1 if valid,  0 on error.
  333  * If valid, returns pointers to newly allocated GPT header and PTEs.
  334  */
  335 static int
  336 is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba,
  337              gpt_header **gpt, gpt_entry **ptes)
  338 {
  339         u32 crc, origcrc;
  340 
  341         if (!hd || !bdev || !gpt || !ptes)
  342                 return 0;
  343         if (!(*gpt = alloc_read_gpt_header(hd, bdev, lba)))
  344                 return 0;
  345 
  346         /* Check the GUID Partition Table signature */
  347         if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
  348                 Dprintk("GUID Partition Table Header signature is wrong: %"
  349                         PRIx64 " != %" PRIx64 "\n", le64_to_cpu((*gpt)->signature),
  350                         GPT_HEADER_SIGNATURE);
  351                 kfree(*gpt);
  352                 *gpt = NULL;
  353                 return 0;
  354         }
  355 
  356         /* Check the GUID Partition Table CRC */
  357         origcrc = le32_to_cpu((*gpt)->header_crc32);
  358         (*gpt)->header_crc32 = 0;
  359         crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size));
  360 
  361         if (crc != origcrc) {
  362                 Dprintk
  363                     ("GUID Partition Table Header CRC is wrong: %x != %x\n",
  364                      crc, origcrc);
  365                 kfree(*gpt);
  366                 *gpt = NULL;
  367                 return 0;
  368         }
  369         (*gpt)->header_crc32 = cpu_to_le32(origcrc);
  370 
  371         /* Check that the my_lba entry points to the LBA that contains
  372          * the GUID Partition Table */
  373         if (le64_to_cpu((*gpt)->my_lba) != lba) {
  374                 Dprintk("GPT my_lba incorrect: %" PRIx64 " != %" PRIx64 "\n",
  375                         le64_to_cpu((*gpt)->my_lba), lba);
  376                 kfree(*gpt);
  377                 *gpt = NULL;
  378                 return 0;
  379         }
  380 
  381         if (!(*ptes = alloc_read_gpt_entries(hd, bdev, *gpt))) {
  382                 kfree(*gpt);
  383                 *gpt = NULL;
  384                 return 0;
  385         }
  386 
  387         /* Check the GUID Partition Entry Array CRC */
  388         crc = efi_crc32((const unsigned char *) (*ptes),
  389                         le32_to_cpu((*gpt)->num_partition_entries) *
  390                         le32_to_cpu((*gpt)->sizeof_partition_entry));
  391 
  392         if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
  393                 Dprintk("GUID Partitition Entry Array CRC check failed.\n");
  394                 kfree(*gpt);
  395                 *gpt = NULL;
  396                 kfree(*ptes);
  397                 *ptes = NULL;
  398                 return 0;
  399         }
  400 
  401         /* We're done, all's well */
  402         return 1;
  403 }
  404 
  405 /**
  406  * compare_gpts() - Search disk for valid GPT headers and PTEs
  407  * @pgpt is the primary GPT header
  408  * @agpt is the alternate GPT header
  409  * @lastlba is the last LBA number
  410  * Description: Returns nothing.  Sanity checks pgpt and agpt fields
  411  * and prints warnings on discrepancies.
  412  * 
  413  */
  414 static void
  415 compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
  416 {
  417         int error_found = 0;
  418         if (!pgpt || !agpt)
  419                 return;
  420         if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) {
  421                 printk(KERN_WARNING
  422                        "GPT:Primary header LBA != Alt. header alternate_lba\n");
  423                 printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
  424                        le64_to_cpu(pgpt->my_lba),
  425                        le64_to_cpu(agpt->alternate_lba));
  426                 error_found++;
  427         }
  428         if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) {
  429                 printk(KERN_WARNING
  430                        "GPT:Primary header alternate_lba != Alt. header my_lba\n");
  431                 printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
  432                        le64_to_cpu(pgpt->alternate_lba),
  433                        le64_to_cpu(agpt->my_lba));
  434                 error_found++;
  435         }
  436         if (le64_to_cpu(pgpt->first_usable_lba) !=
  437             le64_to_cpu(agpt->first_usable_lba)) {
  438                 printk(KERN_WARNING "GPT:first_usable_lbas don't match.\n");
  439                 printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
  440                        le64_to_cpu(pgpt->first_usable_lba),
  441                        le64_to_cpu(agpt->first_usable_lba));
  442                 error_found++;
  443         }
  444         if (le64_to_cpu(pgpt->last_usable_lba) !=
  445             le64_to_cpu(agpt->last_usable_lba)) {
  446                 printk(KERN_WARNING "GPT:last_usable_lbas don't match.\n");
  447                 printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
  448                        le64_to_cpu(pgpt->last_usable_lba),
  449                        le64_to_cpu(agpt->last_usable_lba));
  450                 error_found++;
  451         }
  452         if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
  453                 printk(KERN_WARNING "GPT:disk_guids don't match.\n");
  454                 error_found++;
  455         }
  456         if (le32_to_cpu(pgpt->num_partition_entries) !=
  457             le32_to_cpu(agpt->num_partition_entries)) {
  458                 printk(KERN_WARNING "GPT:num_partition_entries don't match: "
  459                        "0x%x != 0x%x\n",
  460                        le32_to_cpu(pgpt->num_partition_entries),
  461                        le32_to_cpu(agpt->num_partition_entries));
  462                 error_found++;
  463         }
  464         if (le32_to_cpu(pgpt->sizeof_partition_entry) !=
  465             le32_to_cpu(agpt->sizeof_partition_entry)) {
  466                 printk(KERN_WARNING
  467                        "GPT:sizeof_partition_entry values don't match: "
  468                        "0x%x != 0x%x\n",
  469                        le32_to_cpu(pgpt->sizeof_partition_entry),
  470                        le32_to_cpu(agpt->sizeof_partition_entry));
  471                 error_found++;
  472         }
  473         if (le32_to_cpu(pgpt->partition_entry_array_crc32) !=
  474             le32_to_cpu(agpt->partition_entry_array_crc32)) {
  475                 printk(KERN_WARNING
  476                        "GPT:partition_entry_array_crc32 values don't match: "
  477                        "0x%x != 0x%x\n",
  478                        le32_to_cpu(pgpt->partition_entry_array_crc32),
  479                        le32_to_cpu(agpt->partition_entry_array_crc32));
  480                 error_found++;
  481         }
  482         if (le64_to_cpu(pgpt->alternate_lba) != lastlba) {
  483                 printk(KERN_WARNING
  484                        "GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
  485                 printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
  486                        le64_to_cpu(pgpt->alternate_lba), lastlba);
  487                 error_found++;
  488         }
  489 
  490         if (le64_to_cpu(agpt->my_lba) != lastlba) {
  491                 printk(KERN_WARNING
  492                        "GPT:Alternate GPT header not at the end of the disk.\n");
  493                 printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
  494                        le64_to_cpu(agpt->my_lba), lastlba);
  495                 error_found++;
  496         }
  497 
  498         if (error_found)
  499                 printk(KERN_WARNING
  500                        "GPT: Use GNU Parted to correct GPT errors.\n");
  501         return;
  502 }
  503 
  504 /**
  505  * find_valid_gpt() - Search disk for valid GPT headers and PTEs
  506  * @hd
  507  * @bdev
  508  * @gpt is a GPT header ptr, filled on return.
  509  * @ptes is a PTEs ptr, filled on return.
  510  * Description: Returns 1 if valid, 0 on error.
  511  * If valid, returns pointers to newly allocated GPT header and PTEs.
  512  * Validity depends on finding either the Primary GPT header and PTEs valid,
  513  * or the Alternate GPT header and PTEs valid, and the PMBR valid.
  514  */
  515 static int
  516 find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
  517                gpt_header **gpt, gpt_entry **ptes)
  518 {
  519         int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
  520         gpt_header *pgpt = NULL, *agpt = NULL;
  521         gpt_entry *pptes = NULL, *aptes = NULL;
  522         legacy_mbr *legacymbr = NULL;
  523         u64 lastlba;
  524         if (!hd || !bdev || !gpt || !ptes)
  525                 return 0;
  526 
  527         lastlba = last_lba(hd, bdev);
  528         good_pgpt = is_gpt_valid(hd, bdev, GPT_PRIMARY_PARTITION_TABLE_LBA,
  529                                  &pgpt, &pptes);
  530         if (good_pgpt) {
  531                 good_agpt = is_gpt_valid(hd, bdev,
  532                                          le64_to_cpu(pgpt->alternate_lba),
  533                                          &agpt, &aptes);
  534                 if (!good_agpt) {
  535                         good_agpt = is_gpt_valid(hd, bdev, lastlba,
  536                                                  &agpt, &aptes);
  537                 }
  538         }
  539         else {
  540                 good_agpt = is_gpt_valid(hd, bdev, lastlba,
  541                                          &agpt, &aptes);
  542         }
  543 
  544         /* The obviously unsuccessful case */
  545         if (!good_pgpt && !good_agpt) {
  546                 goto fail;
  547         }
  548 
  549         /* This will be added to the EFI Spec. per Intel after v1.02. */
  550         legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL);
  551         if (legacymbr) {
  552                 memset(legacymbr, 0, sizeof (*legacymbr));
  553                 read_lba(hd, bdev, 0, (u8 *) legacymbr,
  554                          sizeof (*legacymbr));
  555                 good_pmbr = is_pmbr_valid(legacymbr);
  556                 kfree(legacymbr);
  557                 legacymbr=NULL;
  558         }
  559 
  560         /* Failure due to bad PMBR */
  561         if ((good_pgpt || good_agpt) && !good_pmbr && !force_gpt) {
  562                 printk(KERN_WARNING 
  563                        "  Warning: Disk has a valid GPT signature "
  564                        "but invalid PMBR.\n");
  565                 printk(KERN_WARNING
  566                        "  Assuming this disk is *not* a GPT disk anymore.\n");
  567                 printk(KERN_WARNING
  568                        "  Use gpt kernel option to override.  "
  569                        "Use GNU Parted to correct disk.\n");
  570                 goto fail;
  571         }
  572 
  573         /* Would fail due to bad PMBR, but force GPT anyhow */
  574         if ((good_pgpt || good_agpt) && !good_pmbr && force_gpt) {
  575                 printk(KERN_WARNING
  576                        "  Warning: Disk has a valid GPT signature but "
  577                        "invalid PMBR.\n");
  578                 printk(KERN_WARNING
  579                        "  Use GNU Parted to correct disk.\n");
  580                 printk(KERN_WARNING
  581                        "  gpt option taken, disk treated as GPT.\n");
  582         }
  583 
  584         compare_gpts(pgpt, agpt, lastlba);
  585 
  586         /* The good cases */
  587         if (good_pgpt && (good_pmbr || force_gpt)) {
  588                 *gpt  = pgpt;
  589                 *ptes = pptes;
  590                 if (agpt)  { kfree(agpt);   agpt = NULL; }
  591                 if (aptes) { kfree(aptes); aptes = NULL; }
  592                 if (!good_agpt) {
  593                         printk(KERN_WARNING 
  594                                "Alternate GPT is invalid, "
  595                                "using primary GPT.\n");
  596                 }
  597                 return 1;
  598         }
  599         else if (good_agpt && (good_pmbr || force_gpt)) {
  600                 *gpt  = agpt;
  601                 *ptes = aptes;
  602                 if (pgpt)  { kfree(pgpt);   pgpt = NULL; }
  603                 if (pptes) { kfree(pptes); pptes = NULL; }
  604                 printk(KERN_WARNING 
  605                        "Primary GPT is invalid, using alternate GPT.\n");
  606                 return 1;
  607         }
  608 
  609  fail:
  610         if (pgpt)  { kfree(pgpt);   pgpt=NULL; }
  611         if (agpt)  { kfree(agpt);   agpt=NULL; }
  612         if (pptes) { kfree(pptes); pptes=NULL; }
  613         if (aptes) { kfree(aptes); aptes=NULL; }
  614         *gpt = NULL;
  615         *ptes = NULL;
  616         return 0;
  617 }
  618 
  619 /**
  620  * add_gpt_partitions(struct gendisk *hd, struct block_device *bdev,
  621  * @hd
  622  * @bdev
  623  *
  624  * Description: Create devices for each entry in the GUID Partition Table
  625  * Entries.
  626  *
  627  * We do not create a Linux partition for GPT, but
  628  * only for the actual data partitions.
  629  * Returns:
  630  * -1 if unable to read the partition table
  631  *  0 if this isn't our partition table
  632  *  1 if successful
  633  *
  634  */
  635 static int
  636 add_gpt_partitions(struct gendisk *hd, struct block_device *bdev, int nextminor)
  637 {
  638         gpt_header *gpt = NULL;
  639         gpt_entry *ptes = NULL;
  640         u32 i;
  641         int max_p; 
  642 
  643         if (!hd || !bdev)
  644                 return -1;
  645 
  646         if (!find_valid_gpt(hd, bdev, &gpt, &ptes) || !gpt || !ptes) {
  647                 if (gpt) {
  648                         kfree(gpt);
  649                         gpt = NULL;
  650                 }
  651                 if (ptes) {
  652                         kfree(ptes);
  653                         ptes = NULL;
  654                 }
  655                 return 0;
  656         }
  657 
  658         Dprintk("GUID Partition Table is valid!  Yea!\n");
  659 
  660         max_p = (1 << hd->minor_shift) - 1;
  661         for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < max_p; i++) {
  662                 if (!efi_guidcmp(ptes[i].partition_type_guid, NULL_GUID))
  663                         continue;
  664 
  665                 add_gd_partition(hd, nextminor+i,
  666                                  le64_to_cpu(ptes[i].starting_lba),
  667                                  (le64_to_cpu(ptes[i].ending_lba) -
  668                                   le64_to_cpu(ptes[i].starting_lba) +
  669                                   1));
  670 
  671                 /* If there's this is a RAID volume, tell md */
  672 #if CONFIG_BLK_DEV_MD
  673                 if (!efi_guidcmp(ptes[i].partition_type_guid,
  674                                  PARTITION_LINUX_RAID_GUID)) {
  675                         md_autodetect_dev(MKDEV
  676                                           (MAJOR(to_kdev_t(bdev->bd_dev)),
  677                                            nextminor+i));
  678                 }
  679 #endif
  680         }
  681         kfree(ptes);
  682         ptes=NULL;
  683         kfree(gpt);
  684         gpt=NULL;
  685         printk("\n");
  686         return 1;
  687 }
  688 
  689 /**
  690  * efi_partition(): EFI GPT partition handling entry function
  691  * @hd
  692  * @bdev
  693  * @first_sector: unused
  694  * @first_part_minor: minor number assigned to first GPT partition found
  695  *
  696  * Description: called from check.c, if the disk contains GPT
  697  * partitions, sets up partition entries in the kernel.
  698  *
  699  * If the first block on the disk is a legacy MBR,
  700  * it will get handled by msdos_partition().
  701  * If it's a Protective MBR, we'll handle it here.
  702  *
  703  * set_blocksize() calls are necessary to be able to read
  704  * a disk with an odd number of 512-byte sectors, as the
  705  * default BLOCK_SIZE of 1024 bytes won't let that last
  706  * sector be read otherwise.
  707  *
  708  * Returns:
  709  * -1 if unable to read the partition table
  710  *  0 if this isn't our partitoin table
  711  *  1 if successful
  712  */
  713 int
  714 efi_partition(struct gendisk *hd, struct block_device *bdev,
  715               unsigned long first_sector, int first_part_minor)
  716 {
  717 
  718         kdev_t dev = to_kdev_t(bdev->bd_dev);
  719         int hardblocksize = get_hardsect_size(dev);
  720         int orig_blksize_size = BLOCK_SIZE;
  721         int rc = 0;
  722 
  723         /* Need to change the block size that the block layer uses */
  724         if (blksize_size[MAJOR(dev)]) {
  725                 orig_blksize_size = blksize_size[MAJOR(dev)][MINOR(dev)];
  726         }
  727 
  728         if (orig_blksize_size != hardblocksize)
  729                 set_blocksize(dev, hardblocksize);
  730 
  731         rc = add_gpt_partitions(hd, bdev, first_part_minor);
  732 
  733         /* change back */
  734         if (orig_blksize_size != hardblocksize)
  735                 set_blocksize(dev, orig_blksize_size);
  736 
  737         return rc;
  738 }

Cache object: 504eb30d9ce77de05db06175b157ad3f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.