* [Linux-ia64] [PATCH] EFI GUID Partition Table support
@ 2000-10-25 17:34 Matt_Domsch
0 siblings, 0 replies; only message in thread
From: Matt_Domsch @ 2000-10-25 17:34 UTC (permalink / raw)
To: linux-ia64
[-- Attachment #1: Type: text/plain, Size: 529 bytes --]
Attached is my patch (against 2.4.0-test9) to add EFI GUID Partition Table
support to the Linux kernel, specifically for IA-64. This code is licensed
under the GPL.
To enable support, add CONFIG_EFI_PARTITION=y to your config files.
Special thanks to Andries Brouwer for his assistance in helping me to
understand the kernel block device layer.
Please direct any feedback you have with about code to me.
Thanks,
Matt Domsch
Dell Enterprise Systems Group
Linux Development Team
<<linux-2.4.0-test9-efigpt-001025.patch>>
[-- Attachment #2: linux-2.4.0-test9-efigpt-001025.patch --]
[-- Type: application/octet-stream, Size: 30887 bytes --]
diff -burN linux-2.4.0-test9.orig/Documentation/Configure.help linux-2.4.0-test9-efigpt/Documentation/Configure.help
--- linux-2.4.0-test9.orig/Documentation/Configure.help Fri Sep 22 19:11:37 2000
+++ linux-2.4.0-test9-efigpt/Documentation/Configure.help Wed Oct 25 10:49:21 2000
@@ -11279,6 +11279,12 @@
Say Y here if you would like to be able to read the hard disk
partition table format used by SGI machines.
+Intel EFI GUID partition support
+CONFIG_EFI_PARTITION
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned using EFI GPT. Presently only useful on the
+ IA-64 platform.
+
ADFS file system support (EXPERIMENTAL)
CONFIG_ADFS_FS
The Acorn Disc Filing System is the standard file system of the
diff -burN linux-2.4.0-test9.orig/fs/partitions/Config.in linux-2.4.0-test9-efigpt/fs/partitions/Config.in
--- linux-2.4.0-test9.orig/fs/partitions/Config.in Mon Jul 10 00:21:41 2000
+++ linux-2.4.0-test9-efigpt/fs/partitions/Config.in Wed Oct 25 10:49:21 2000
@@ -23,6 +23,7 @@
bool ' BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
bool ' Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
bool ' Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
+ bool ' EFI GUID Partition support' CONFIG_EFI_PARTITION
fi
bool ' SGI partition support' CONFIG_SGI_PARTITION
bool ' Ultrix partition table support' CONFIG_ULTRIX_PARTITION
diff -burN linux-2.4.0-test9.orig/fs/partitions/Makefile linux-2.4.0-test9-efigpt/fs/partitions/Makefile
--- linux-2.4.0-test9.orig/fs/partitions/Makefile Wed Jul 19 00:49:47 2000
+++ linux-2.4.0-test9-efigpt/fs/partitions/Makefile Wed Oct 25 10:49:21 2000
@@ -20,6 +20,7 @@
obj-$(CONFIG_SUN_PARTITION) += sun.o
obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
obj-$(CONFIG_IBM_PARTITION) += ibm.o
+obj-$(CONFIG_EFI_PARTITION) += efi.o
O_OBJS += $(obj-y)
M_OBJS += $(obj-m)
diff -burN linux-2.4.0-test9.orig/fs/partitions/check.c linux-2.4.0-test9-efigpt/fs/partitions/check.c
--- linux-2.4.0-test9.orig/fs/partitions/check.c Wed Sep 27 15:39:23 2000
+++ linux-2.4.0-test9-efigpt/fs/partitions/check.c Wed Oct 25 10:49:21 2000
@@ -32,6 +32,7 @@
#include "sun.h"
#include "ibm.h"
#include "ultrix.h"
+#include "efi.h"
extern void device_init(void);
extern int *blk_size[];
@@ -71,6 +72,9 @@
#endif
#ifdef CONFIG_IBM_PARTITION
ibm_partition,
+#endif
+#ifdef CONFIG_EFI_PARTITION
+ efi_partition,
#endif
NULL
};
diff -burN linux-2.4.0-test9.orig/fs/partitions/efi.c linux-2.4.0-test9-efigpt/fs/partitions/efi.c
--- linux-2.4.0-test9.orig/fs/partitions/efi.c Wed Dec 31 18:00:00 1969
+++ linux-2.4.0-test9-efigpt/fs/partitions/efi.c Wed Oct 25 11:26:28 2000
@@ -0,0 +1,646 @@
+/************************************************************
+ * EFI GUID Partition Table handling
+ * Per Intel EFI Specification v0.99
+ * http://developer.intel.com/technology/efi/efi.htm
+ * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com>
+ * Copyright 2000 Dell Computer Corporation
+ * CRC routines taken from the EFI Sample Implementation,
+ * 1999.12.31, lib/crc.c
+ *
+ * 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:
+ * Wed Oct 25 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * - Fixed the LastLBA() 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.
+ *
+ ************************************************************/
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/malloc.h>
+#include <linux/smp_lock.h>
+#include <asm/system.h>
+#include <asm/efi.h>
+
+#include "check.h"
+#include "efi.h"
+
+#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
+extern void md_autodetect_dev(kdev_t dev);
+#endif
+
+
+#undef EFI_DEBUG
+#ifdef EFI_DEBUG
+static char *efi_printk_level = KERN_DEBUG;
+#define debug_printk printk
+#else
+#define debug_printk(...)
+#endif
+
+/* CRC routines taken from the EFI Sample Implementation,
+ * 1999.12.31, lib/crc.c
+ *
+ * Note, the EFI Specification, v0.99, has a reference to
+ * Dr. Dobbs Journal, May 1994 (actually it's in May 1992)
+ * but that isn't the CRC function being used by EFI.
+ */
+
+static u32 CRCTable[256] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
+ 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
+ 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
+ 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
+ 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
+ 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
+ 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
+ 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
+ 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
+ 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
+ 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
+ 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
+ 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
+ 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
+ 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
+ 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
+ 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
+ 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
+ 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
+ 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
+ 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
+ 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+static u32
+CalculateCrc (void *_pt, u32 Size)
+{
+ u8 *pt = (u8 *)_pt;
+ register u32 Crc;
+
+ /* compute crc */
+ Crc = 0xffffffff;
+ while (Size) {
+ Crc = (Crc >> 8) ^ CRCTable[(__u8) Crc ^ *pt];
+ pt += 1;
+ Size -= 1;
+ }
+ Crc = Crc ^ 0xffffffff;
+ return Crc;
+}
+
+
+
+/************************************************************
+ * IsLegacyMBRValid()
+ * Requires:
+ * - mbr is a pointer to a legacy mbr structure
+ * Modifies: nothing
+ * Returns:
+ * 1 on true
+ * 0 on false
+ ************************************************************/
+static inline int
+IsLegacyMBRValid(LegacyMBR_t *mbr)
+{
+ return (mbr ? (mbr->Signature == MSDOS_MBR_SIGNATURE) : 0);
+}
+
+
+
+/************************************************************
+ * LastLBA()
+ * Requires:
+ * - struct gendisk hd
+ * - kdev_t dev
+ * Modifies: nothing
+ * Returns:
+ * Last LBA value on success. 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.
+ * 0 on error
+ ************************************************************/
+u64
+LastLBA(struct gendisk *hd, kdev_t dev)
+{
+ if (!hd || !hd->part) return 0;
+ return hd->part[MINOR(dev)].nr_sects - 1;
+}
+
+
+/************************************************************
+ * ReadLBA()
+ * Requires:
+ * - hd is our disk device.
+ * - dev is our device major number
+ * - lba is the logical block address desired (disk hardsector number)
+ * - buffer is a buffer of size size into which data copied
+ * - size_t count is size of the read (in bytes)
+ * Modifies:
+ * - buffer
+ * Returns:
+ * - count of bytes read
+ * - 0 on error
+ * Bugs:
+ * - bread() takes second argument as a signed int, not a u64.
+ * This is because getblk() takes the block number as a signed int.
+ * This overflow is known on l-k. We overflow at about 1TB.
+ *
+ ************************************************************/
+
+static size_t
+ReadLBA(struct gendisk *hd, kdev_t dev, u64 _lba, u8 *buffer, size_t count)
+{
+ struct buffer_head *bh;
+ size_t totalreadcount = 0, bytesread;
+ int lba = (_lba & 0x7FFFFFFF), i, blockstoread, blocksize;
+ debug_printk(efi_printk_level "ReadLBA(%p,%s,%x,%p,%x)\n",
+ hd, kdevname(dev), lba, buffer, count);
+
+ if (!hd || !buffer || !count) return 0;
+
+
+ blocksize = get_hardblocksize(dev);
+ if (!blocksize) blocksize = 512;
+ blockstoread = count / blocksize;
+ if (count % blocksize) blockstoread += 1;
+ debug_printk(efi_printk_level "about to read %d blocks\n",
+ blockstoread);
+
+
+ for (i=0; i<blockstoread; i++) {
+ bh = bread(dev, lba+i, blocksize);
+ if (!bh) {
+ /* We hit the end of the disk */
+ debug_printk(efi_printk_level
+ "bread returned NULL.\n");
+ return totalreadcount;
+ }
+
+ bytesread = (count > bh->b_size ? bh->b_size : count);
+ memcpy(buffer, bh->b_data, bytesread);
+
+ buffer += bytesread; /* Advance the buffer pointer */
+ totalreadcount += bytesread; /* Advance the total read count */
+ count -= bytesread; /* Subtract bytesread from count */
+
+ brelse(bh);
+ }
+
+ return totalreadcount;
+}
+
+void
+PrintGuidPartitionTableHeader(GuidPartitionTableHeader_t *gpt)
+{
+ debug_printk(efi_printk_level "GUID Partition Table Header\n");
+ if (!gpt) return;
+ debug_printk(efi_printk_level "Signature : %lx\n",
+ gpt->Signature);
+ debug_printk(efi_printk_level "Revision : %x\n",
+ gpt->Revision);
+ debug_printk(efi_printk_level "HeaderSize : %x\n",
+ gpt->HeaderSize);
+ debug_printk(efi_printk_level "HeaderCRC32 : %x\n",
+ gpt->HeaderCRC32);
+ debug_printk(efi_printk_level "MyLBA : %lx\n",
+ gpt->MyLBA);
+ debug_printk(efi_printk_level "AlternateLBA : %lx\n",
+ gpt->AlternateLBA);
+ debug_printk(efi_printk_level "FirstUsableLBA : %lx\n",
+ gpt->FirstUsableLBA);
+ debug_printk(efi_printk_level "LastUsableLBA : %lx\n",
+ gpt->LastUsableLBA);
+
+ debug_printk(efi_printk_level "PartitionEntryLBA : %lx\n",
+ gpt->PartitionEntryLBA);
+ debug_printk(efi_printk_level "NumberOfPartitionEntries : %x\n",
+ gpt->NumberOfPartitionEntries);
+ debug_printk(efi_printk_level "SizeOfPartitionEntry : %x\n",
+ gpt->SizeOfPartitionEntry);
+ debug_printk(efi_printk_level "PartitionEntryArrayCRC32 : %x\n",
+ gpt->PartitionEntryArrayCRC32);
+
+ return;
+}
+
+
+
+/************************************************************
+ * ReadGuidPartitionEntries()
+ * Requires:
+ * - filedes is an open file descriptor, suitable for reading
+ * - lba is the Logical Block Address of the partition table
+ * - gpt is a buffer into which the GPT will be put
+ * Modifies:
+ * - filedes file and pointer
+ * - gpt
+ * Returns:
+ * pte on success
+ * NULL on error
+ * Notes: remember to free pte when you're done!
+ ************************************************************/
+GuidPartitionEntry_t *
+ReadGuidPartitionEntries(struct gendisk *hd, kdev_t dev,
+ GuidPartitionTableHeader_t *gpt)
+{
+ size_t count;
+ GuidPartitionEntry_t *pte;
+ if (!hd || !gpt) return NULL;
+
+ count = gpt->NumberOfPartitionEntries * gpt->SizeOfPartitionEntry;
+ debug_printk(efi_printk_level "ReadGPTEs() kmallocing %x bytes\n",
+ count);
+ if (!count) return NULL;
+ pte = kmalloc(count, GFP_KERNEL);
+ if (!pte) return NULL;
+ memset(pte, 0, count);
+
+ if (ReadLBA(hd, dev, gpt->PartitionEntryLBA, (u8 *)pte,
+ count) < count) {
+ kfree(pte);
+ return NULL;
+ }
+ return pte;
+}
+
+
+
+/************************************************************
+ * ReadGuidPartitionTableHeader()
+ * Requires:
+ * - hd is our struct gendisk
+ * - dev is our device major number
+ * - lba is the Logical Block Address of the partition table
+ * - gpt is a buffer into which the GPT will be put
+ * - pte is a buffer into which the PTEs will be put
+ * Modifies:
+ * - gpt and pte
+ * Returns:
+ * 1 on success
+ * 0 on error
+ ************************************************************/
+
+GuidPartitionTableHeader_t *
+ReadGuidPartitionTableHeader(struct gendisk *hd, kdev_t dev, u64 lba)
+
+{
+ GuidPartitionTableHeader_t *gpt;
+ if (!hd) return NULL;
+
+ gpt = kmalloc(sizeof(GuidPartitionTableHeader_t), GFP_KERNEL);
+ if (!gpt) return NULL;
+ memset(gpt, 0, sizeof(GuidPartitionTableHeader_t));
+
+ debug_printk(efi_printk_level "GPTH() calling ReadLBA().\n");
+ if (ReadLBA(hd, dev, lba, (u8 *)gpt,
+ sizeof(GuidPartitionTableHeader_t)) <
+ sizeof(GuidPartitionTableHeader_t)) {
+ debug_printk(efi_printk_level "ReadGPTH(%lx) read failed.\n",
+ lba);
+ kfree(gpt);
+ return NULL;
+ }
+ PrintGuidPartitionTableHeader(gpt);
+
+ return gpt;
+}
+
+
+
+/************************************************************
+ * IsGuidPartitionTableValid()
+ * Requires:
+ * - gd points to our struct gendisk
+ * - dev is our device major number
+ * - lba is the logical block address of the GPTH to test
+ * - gpt is a GPTH if it's valid
+ * - ptes is a PTEs if it's valid
+ * Modifies:
+ * - gpt and ptes
+ * Returns:
+ * 1 if valid
+ * 0 on error
+ ************************************************************/
+static int
+IsGuidPartitionTableValid(struct gendisk *hd, kdev_t dev, u64 lba,
+ GuidPartitionTableHeader_t **gpt,
+ GuidPartitionEntry_t **ptes)
+{
+ u32 crc, origcrc;
+
+ if (!hd || !gpt || !ptes) return 0;
+ if (!(*gpt = ReadGuidPartitionTableHeader(hd, dev, lba))) return 0;
+
+ /* Check the GUID Partition Table Signature */
+ if ((*gpt)->Signature != GUID_PT_HEADER_SIGNATURE) {
+ debug_printk(efi_printk_level "GUID Partition Table Header Signature is wrong: %x != %x\n", (*gpt)->Signature, GUID_PT_HEADER_SIGNATURE);
+ kfree(*gpt);
+ *gpt = NULL;
+ return 0;
+ }
+
+ /* Check the GUID Partition Table CRC */
+ origcrc = (*gpt)->HeaderCRC32;
+ (*gpt)->HeaderCRC32 = 0;
+ crc = CalculateCrc(*gpt, (*gpt)->HeaderSize);
+
+
+ if (crc != origcrc) {
+ debug_printk(efi_printk_level "GUID Partition Table Header CRC is wrong: %x != %x\n", (*gpt)->HeaderCRC32, origcrc);
+ kfree(*gpt);
+ *gpt = NULL;
+ return 0;
+ }
+ (*gpt)->HeaderCRC32 = origcrc;
+
+ /* Check that the MyLBA entry points to the LBA that contains
+ * the GUID Partition Table */
+ if ((*gpt)->MyLBA != lba) {
+ debug_printk(efi_printk_level "GPT MyLBA incorrect: %lx != %lx\n", (*gpt)->MyLBA, lba);
+ kfree(*gpt);
+ *gpt = NULL;
+ return 0;
+ }
+
+ if (!(*ptes = ReadGuidPartitionEntries(hd, dev, *gpt))) {
+ debug_printk(efi_printk_level "read PTEs failed.\n");
+ kfree(*gpt);
+ *gpt = NULL;
+ return 0;
+ }
+
+ /* Check the GUID Partition Entry Array CRC */
+ crc = CalculateCrc(*ptes, (*gpt)->NumberOfPartitionEntries *
+ (*gpt)->SizeOfPartitionEntry);
+
+ if (crc != (*gpt)->PartitionEntryArrayCRC32) {
+ debug_printk(efi_printk_level "GUID Partitition Entry Array CRC check failed.\n");
+ kfree(*gpt);
+ *gpt = NULL;
+ kfree(*ptes);
+ *ptes = NULL;
+ return 0;
+ }
+
+
+ /* We're done, all's well */
+ return 1;
+}
+
+
+
+/************************************************************
+ * FindValidGPT()
+ * Requires:
+ * - gd points to our struct gendisk
+ * - dev is our device major number
+ * - gpt is a GPTH if it's valid
+ * - ptes is a PTE
+ * Modifies:
+ * - gpt & ptes
+ * Returns:
+ * 1 if valid
+ * 0 on error
+ ************************************************************/
+static int
+FindValidGPT(struct gendisk *hd, kdev_t dev,
+ GuidPartitionTableHeader_t **gpt,
+ GuidPartitionEntry_t **ptes)
+{
+ int rc = 0;
+ GuidPartitionTableHeader_t *pgpt = NULL, *agpt = NULL;
+ GuidPartitionEntry_t *pptes = NULL, *aptes = NULL;
+ u64 lastlba;
+ if (!hd || !gpt || !ptes) return 0;
+
+ lastlba = LastLBA(hd, dev);
+ /* Check the Primary GPT */
+ rc = IsGuidPartitionTableValid(hd, dev, 1, &pgpt, &pptes);
+ if (rc) {
+ /* Primary GPT is OK, check the alternate and warn if bad */
+ rc = IsGuidPartitionTableValid(hd, dev, pgpt->AlternateLBA,
+ &agpt, &aptes);
+ if (!rc){
+ printk(KERN_WARNING "Alternate GPT is invalid, using primary GPT.\n");
+ }
+
+ *gpt = pgpt;
+ *ptes = pptes;
+ if (agpt) kfree(agpt);
+ if (aptes) kfree(aptes);
+ return 1;
+ } /* if primary is valid */
+ else {
+ /* Primary GPT is bad, check the Alternate GPT */
+ rc = IsGuidPartitionTableValid(hd, dev, lastlba,
+ &agpt, &aptes);
+ if (rc) {
+ /* Primary is bad, alternate is good.
+ Return values from the alternate and warn.
+ */
+ printk(KERN_WARNING "Primary GPT is invalid, using alternate GPT.\n");
+ *gpt = agpt;
+ *ptes = aptes;
+ return 1;
+ }
+ else {
+ /* Primary is bad, alternate is bad, try "other"
+ * alternate. This is necessary because if we
+ * have an odd-sized disk, user-space might
+ * have put the alternate in block lastlba-1.
+ */
+ if (!(lastlba & 1)) {
+ lastlba--;
+ rc = IsGuidPartitionTableValid(hd, dev,
+ lastlba,
+ &agpt, &aptes);
+ if (rc) {
+ /* Primary is bad, alternate is good.
+ * Return values from the alternate
+ * and warn.
+ */
+ printk("Primary GPT is invalid, using alternate GPT.\n");
+ *gpt = agpt;
+ *ptes = aptes;
+ return 1;
+ }
+ }
+ }
+ }
+ /* Both primary and alternate GPTs are bad.
+ * This isn't our disk, return 0.
+ */
+ return 0;
+}
+
+
+
+/*
+ * Create devices for each entry in the GUID Partition Table Entries.
+ * The first block of each partition is a Legacy MBR.
+ *
+ * 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
+ *
+ */
+
+static int
+add_gpt_partitions(struct gendisk *hd, kdev_t dev, int nextminor)
+{
+ GuidPartitionTableHeader_t *gpt = NULL;
+ GuidPartitionEntry_t *ptes = NULL;
+ u32 i, nummade=0;
+
+ efi_guid_t unusedGuid = UNUSED_ENTRY_GUID;
+#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
+ efi_guid_t raidGuid = PARTITION_LINUX_RAID_GUID;
+#endif
+
+ if (!hd) return -1;
+
+ if (!FindValidGPT(hd, dev, &gpt, &ptes) ||
+ !gpt || !ptes) {
+ if (gpt) kfree(gpt);
+ if (ptes) kfree(ptes);
+ return 0;
+ }
+
+ debug_printk(efi_printk_level "GUID Partition Table is valid! Yea!\n");
+ for (i = 0; i < gpt->NumberOfPartitionEntries &&
+ nummade < (hd->max_p - 1); i++) {
+ if (!efi_guidcmp(unusedGuid, ptes[i].PartitionTypeGuid))
+ continue;
+
+ add_gd_partition(hd, nextminor, ptes[i].StartingLBA,
+ (ptes[i].EndingLBA-ptes[i].StartingLBA + 1));
+
+ /* If there's this is a RAID volume, tell md */
+#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
+ if (!efi_guidcmp(raidGuid, ptes[i].PartitionTypeGuid)) {
+ md_autodetect_dev(MKDEV(MAJOR(dev),nextminor));
+ }
+#endif
+ nummade++;
+ nextminor++;
+
+ }
+ kfree(ptes);
+ kfree(gpt);
+ printk("\n");
+ return 1;
+
+}
+
+
+/*
+ * efi_partition()
+ *
+ * If the first block on the disk is a legacy MBR,
+ * it got handled already by msdos_partition().
+ * If it's a Protective MBR, we'll handle it here.
+ *
+ * Returns:
+ * -1 if unable to read the partition table
+ * 0 if this isn't our partitoin table
+ * 1 if successful
+ *
+ */
+
+int
+efi_partition(struct gendisk *hd, kdev_t dev,
+ unsigned long first_sector, int first_part_minor) {
+ int hardblocksize = get_hardblocksize(dev);
+ int orig_blksize_size = BLOCK_SIZE;
+ int rc = 0;
+
+ /* not good, but choose something! */
+ if (!hardblocksize) hardblocksize = 512;
+
+ /* Need to change the block size that the block layer uses */
+ if (blksize_size[MAJOR(dev)]){
+ orig_blksize_size = blksize_size[MAJOR(dev)][MINOR(dev)];
+ }
+
+ if (orig_blksize_size != hardblocksize)
+ set_blocksize(dev, hardblocksize);
+
+ rc = add_gpt_partitions(hd, dev, first_part_minor);
+
+ /* change back */
+ if (orig_blksize_size != hardblocksize)
+ set_blocksize(dev, orig_blksize_size);
+
+ return rc;
+}
+
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
+
+
+
diff -burN linux-2.4.0-test9.orig/fs/partitions/efi.h linux-2.4.0-test9-efigpt/fs/partitions/efi.h
--- linux-2.4.0-test9.orig/fs/partitions/efi.h Wed Dec 31 18:00:00 1969
+++ linux-2.4.0-test9-efigpt/fs/partitions/efi.h Wed Oct 25 10:59:37 2000
@@ -0,0 +1,154 @@
+/************************************************************
+ * EFI GUID Partition Table
+ * Per Intel EFI Specification v0.99
+ * http://developer.intel.com/technology/efi/efi.htm
+ *
+ * By Matt Domsch <Matt_Domsch@dell.com> Fri Sep 22 22:15:56 CDT 2000
+ * Copyright 2000 Dell Computer Corporation
+ *
+ * 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
+ *
+ ************************************************************/
+
+#ifndef FS_PART_EFI_H_INCLUDED
+#define FS_PART_EFI_H_INCLUDED
+
+#include <linux/types.h>
+#include <asm/efi.h>
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+
+#define MSDOS_MBR_SIGNATURE 0xaa55
+#define EFI_PMBR_OSTYPE_EFI 0xEF
+#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
+
+#define GUID_PT_BLOCK_SIZE 512
+
+#define GUID_PT_HEADER_SIGNATURE 0x5452415020494645L
+#define GUID_PT_HEADER_REVISION_V1 0x00010000
+#define GUID_PT_HEADER_REVISION_V0_99 0x00000099
+#define UNUSED_ENTRY_GUID \
+ ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
+#define PARTITION_SYSTEM_GUID \
+((efi_guid_t) { 0xC12A7328, 0xF81F, 0x11d2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }})
+#define LEGACY_MBR_PARTITION_GUID \
+ ((efi_guid_t) { 0x024DEE41, 0x33E7, 0x11d3, { 0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }})
+#define PARTITION_MSFT_RESERVED_GUID \
+ ((efi_guid_t) { 0xE3C9E316, 0x0B5C, 0x4DB8, { 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }})
+#define PARTITION_BASIC_DATA_GUID \
+ ((efi_guid_t) { 0xEBD0A0A2, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }})
+#define PARTITION_LINUX_RAID_GUID \
+ ((efi_guid_t) { 0xa19d880f, 0x05fc, 0x4d3b, { 0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e }})
+#define PARTITION_LINUX_SWAP_GUID \
+ ((efi_guid_t) { 0x0657fd6d, 0xa4ab, 0x43c4, { 0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f }})
+
+typedef struct _GuidPartitionTableHeader_t {
+ u64 Signature;
+ u32 Revision;
+ u32 HeaderSize;
+ u32 HeaderCRC32;
+ u32 Reserved1;
+ u64 MyLBA;
+ u64 AlternateLBA;
+ u64 FirstUsableLBA;
+ u64 LastUsableLBA;
+ efi_guid_t DiskGUID;
+ u64 PartitionEntryLBA;
+ u32 NumberOfPartitionEntries;
+ u32 SizeOfPartitionEntry;
+ u32 PartitionEntryArrayCRC32;
+ u8 Reserved2[GUID_PT_BLOCK_SIZE - 92];
+} GuidPartitionTableHeader_t;
+
+typedef struct _GuidPartitionEntryAttributes_t {
+ __u64 RequiredToFunction:1;
+ __u64 Reserved:63;
+} GuidPartitionEntryAttributes_t;
+
+typedef struct _GuidPartitionEntry_t {
+ efi_guid_t PartitionTypeGuid;
+ efi_guid_t UniquePartitionGuid;
+ u64 StartingLBA;
+ u64 EndingLBA;
+ GuidPartitionEntryAttributes_t Attributes;
+ efi_char16_t PartitionName[72/sizeof(efi_char16_t)];
+} GuidPartitionEntry_t;
+
+
+
+typedef struct _PartitionRecord_t {
+ u8 BootIndicator; /* Not used by EFI firmware. Set to 0x80 to indicate that this
+ is the bootable legacy partition. */
+ u8 StartHead; /* Start of partition in CHS address, not used by EFI firmware. */
+ u8 StartSector; /* Start of partition in CHS address, not used by EFI firmware. */
+ u8 StartTrack; /* Start of partition in CHS address, not used by EFI firmware. */
+ u8 OSType; /* OS type. A value of 0xEF defines an EFI system partition.
+ Other values are reserved for legacy operating systems, and
+ allocated independently of the EFI specification. */
+ u8 EndHead; /* End of partition in CHS address, not used by EFI firmware. */
+ u8 EndSector; /* End of partition in CHS address, not used by EFI firmware. */
+ u8 EndTrack; /* End of partition in CHS address, not used by EFI firmware. */
+ u32 StartingLBA; /* Starting LBA address of the partition on the disk. Used by
+ EFI firmware to define the start of the partition. */
+ u32 SizeInLBA; /* Size of partition in LBA. Used by EFI firmware to determine
+ the size of the partition. */
+} PartitionRecord_t;
+
+typedef struct _LegacyMBR_t {
+ u8 BootCode[440];
+ u32 UniqueMBRSignature;
+ u16 Unknown;
+ PartitionRecord_t PartitionRecord[4];
+ u16 Signature;
+} __attribute__ ((packed)) LegacyMBR_t;
+
+
+
+#define EFI_GPT_PRIMARY_PARTITION_TABLE_LBA 1
+
+/* Functions */
+extern int
+efi_partition(struct gendisk *hd, kdev_t dev,
+ unsigned long first_sector, int first_part_minor);
+
+
+
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * --------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -burN linux-2.4.0-test9.orig/fs/partitions/msdos.c linux-2.4.0-test9-efigpt/fs/partitions/msdos.c
--- linux-2.4.0-test9.orig/fs/partitions/msdos.c Wed Jul 19 01:29:16 2000
+++ linux-2.4.0-test9-efigpt/fs/partitions/msdos.c Wed Oct 25 10:49:21 2000
@@ -36,6 +36,10 @@
#include "check.h"
#include "msdos.h"
+#ifdef CONFIG_EFI_PARTITION
+#include "efi.h"
+#endif
+
#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
extern void md_autodetect_dev(kdev_t dev);
#endif
@@ -378,6 +382,16 @@
bforget(bh);
return 0;
}
+#ifdef CONFIG_EFI_PARTITION
+ p = (struct partition *) (0x1be + data);
+ for (i=1 ; i<=4 ; i++,p++) {
+ /* If this is an EFI GPT disk, msdos should ignore it. */
+ if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) {
+ bforget(bh);
+ return 0;
+ }
+ }
+#endif
p = (struct partition *) (0x1be + data);
#ifdef CONFIG_BLK_DEV_IDE
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2000-10-25 17:34 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2000-10-25 17:34 [Linux-ia64] [PATCH] EFI GUID Partition Table support Matt_Domsch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox