Commit e913fd70 authored by Dave Jones's avatar Dave Jones Committed by Linus Torvalds

[PATCH] EFI GUID partition support update.

More bits from Matt Domsch. Fixes GUID printing, and updates
to what's in the IA64 tree. Other cleanups are mentioned in
the changelog in the patch.
parent 13a9b6c4
......@@ -29,6 +29,9 @@
*
* Changelog:
*
* 25 Mar 2002 - Matt Domsch <Matt_Domsch@dell.com>
* move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse()
*
* 12 Feb 2002 - Matt Domsch <Matt_Domsch@dell.com>
* use list_for_each_safe when deleting vars.
* remove ifdef CONFIG_SMP around include <linux/smp.h>
......@@ -70,7 +73,7 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
MODULE_DESCRIPTION("/proc interface to EFI Variables");
MODULE_LICENSE("GPL");
#define EFIVARS_VERSION "0.04 2002-Feb-12"
#define EFIVARS_VERSION "0.05 2002-Mar-26"
static int
efivar_read(char *page, char **start, off_t off,
......@@ -141,20 +144,6 @@ proc_calc_metrics(char *page, char **start, off_t off,
return len;
}
static void
uuid_unparse(efi_guid_t *guid, char *out)
{
sprintf(out, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
guid->data1, guid->data2, guid->data3,
guid->data4[0], guid->data4[1], guid->data4[2], guid->data4[3],
guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
}
/*
* efivar_create_proc_entry()
* Requires:
......@@ -197,7 +186,7 @@ efivar_create_proc_entry(unsigned long variable_name_size,
private variables from another's. */
*(short_name + strlen(short_name)) = '-';
uuid_unparse(vendor_guid, short_name + strlen(short_name));
efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
/* Create the entry in proc */
......
......@@ -3,6 +3,9 @@
* Purpose: Generic MCA handling layer
*
* Updated for latest kernel
* Copyright (C) 2002 Dell Computer Corporation
* Copyright (C) Matt Domsch (Matt_Domsch@dell.com)
*
* Copyright (C) 2002 Intel
* Copyright (C) Jenna Hall (jenna.s.hall@intel.com)
*
......@@ -15,6 +18,8 @@
* Copyright (C) 1999 Silicon Graphics, Inc.
* Copyright (C) Vijay Chander(vijay@engr.sgi.com)
*
* 02/03/25 M. Domsch GUID cleanups
*
* 02/01/04 J. Hall Aligned MCA stack to 16 bytes, added platform vs. CPU
* error flag, set SAL default return values, changed
* error record structure to linked list, added init call
......@@ -348,17 +353,13 @@ static int
verify_guid (efi_guid_t *test, efi_guid_t *target)
{
int rc;
char out[40];
if ((rc = memcmp((void *)test, (void *)target, sizeof(efi_guid_t)))) {
IA64_MCA_DEBUG("ia64_mca_print: invalid guid = "
"{ %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, "
"%#02x, %#02x, %#02x, %#02x, } } \n ",
test->data1, test->data2, test->data3, test->data4[0],
test->data4[1], test->data4[2], test->data4[3],
test->data4[4], test->data4[5], test->data4[6],
test->data4[7]);
if ((rc = efi_guidcmp(*test, *target))) {
IA64_MCA_DEBUG(KERN_DEBUG
"verify_guid: invalid GUID = %s\n",
efi_guid_unparse(test, out));
}
return rc;
}
......@@ -856,11 +857,8 @@ ia64_init_handler (struct pt_regs *regs)
void
ia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc)
{
printk("GUID = { %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, "
"%#02x, %#02x, %#02x, %#02x, } } \n ", p_guid->data1,
p_guid->data2, p_guid->data3, p_guid->data4[0], p_guid->data4[1],
p_guid->data4[2], p_guid->data4[3], p_guid->data4[4],
p_guid->data4[5], p_guid->data4[6], p_guid->data4[7]);
char out[40];
printk(KERN_DEBUG "GUID = %s\n", efi_guid_unparse(p_guid, out));
}
static void
......@@ -1754,7 +1752,7 @@ ia64_log_processor_info_print(sal_log_record_header_t *lh, prfunc_t prfunc)
ia64_log_prt_section_header(slsh, prfunc);
#endif // MCA_PRT_XTRA_DATA for test only @FVL
if (verify_guid((void *)&slsh->guid, (void *)&(SAL_PROC_DEV_ERR_SECT_GUID))) {
if (verify_guid(&slsh->guid, &(SAL_PROC_DEV_ERR_SECT_GUID))) {
IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n");
continue;
}
......
......@@ -23,6 +23,19 @@
* TODO:
*
* Changelog:
* 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
*
......@@ -98,10 +111,8 @@ extern void md_autodetect_dev(kdev_t dev);
/* Borrowed from /usr/include/inttypes.h */
# if BITS_PER_LONG == 64
# define __PRI64_PREFIX "l"
# define __PRIPTR_PREFIX "l"
# else
# define __PRI64_PREFIX "ll"
# define __PRIPTR_PREFIX
# endif
# define PRIx64 __PRI64_PREFIX "x"
......@@ -117,35 +128,15 @@ extern void md_autodetect_dev(kdev_t dev);
* the test for invalid PMBR. Not __initdata because reloading
* the partition tables happens after init too.
*/
static int forcegpt;
static int force_gpt;
static int __init
force_gpt(char *str)
force_gpt_fn(char *str)
{
forcegpt = 1;
force_gpt = 1;
return 1;
}
__setup("gpt", force_gpt_fn);
__setup("gpt", force_gpt);
/**
* le_efi_guid_to_cpus()
* @guid
*
* Description: modifies @guid in situ
*
* This function converts a little endian efi_guid_t to the
* native cpu representation. The EFI Spec. declares that all
* on-disk structures are stored in little endian format.
*/
static void
le_efi_guid_to_cpus(efi_guid_t *guid)
{
le32_to_cpus(guid->data1);
le16_to_cpus(guid->data2);
le16_to_cpus(guid->data3);
/* no need to change the rest. It's already an array of chars */
return;
}
/**
* efi_crc32() - EFI version of crc32 function
......@@ -165,21 +156,6 @@ efi_crc32(const void *buf, unsigned long len)
return (crc32(~0L, buf, len) ^ ~0L);
}
/**
* le_part_attributes_to_cpus(): converts LE attributes to CPU type in situ
* @attributes - ptr to partition attributes
*
* Description: modifies attributes in situ, returns nothing.
* Converts a little endian partition attributes struct to the
* native cpu representation. Good for reading attributes off of a disk.
*/
static void
le_part_attributes_to_cpus(gpt_entry_attributes * a)
{
u64 *b = (u64 *) a;
*b = le64_to_cpu(*b);
}
/**
* is_pmbr_valid(): test Protective MBR for validity
* @mbr: pointer to a legacy mbr structure
......@@ -197,7 +173,8 @@ is_pmbr_valid(legacy_mbr *mbr)
return 0;
signature = (le16_to_cpu(mbr->signature) == MSDOS_MBR_SIGNATURE);
for (i = 0; signature && i < 4; i++) {
if (mbr->partition_record[i].sys_ind == EFI_PMBR_OSTYPE_EFI_GPT) {
if (mbr->partition_record[i].sys_ind ==
EFI_PMBR_OSTYPE_EFI_GPT) {
found = 1;
break;
}
......@@ -272,37 +249,6 @@ read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba,
return totalreadcount;
}
/**
* print_gpt_header(): unparses gpt header to console
* @gpt: gpt header
*/
static void
print_gpt_header(gpt_header *gpt)
{
Dprintk("GUID Partition Table Header\n");
if (!gpt)
return;
Dprintk("signature : %" PRIx64 "\n", gpt->signature);
Dprintk("revision : %x\n", gpt->revision);
Dprintk("header_size : %x\n", gpt->header_size);
Dprintk("header_crc32 : %x\n", gpt->header_crc32);
Dprintk("my_lba : %" PRIx64 "\n", gpt->my_lba);
Dprintk("alternate_lba : %" PRIx64 "\n",
gpt->alternate_lba);
Dprintk("first_usable_lba : %" PRIx64 "\n",
gpt->first_usable_lba);
Dprintk("last_usable_lba : %" PRIx64 "\n",
gpt->last_usable_lba);
Dprintk("partition_entry_lba : %" PRIx64 "\n",
gpt->partition_entry_lba);
Dprintk("num_partition_entries : %x\n",
gpt->num_partition_entries);
Dprintk("sizeof_partition_entry : %x\n",
gpt->sizeof_partition_entry);
Dprintk("partition_entry_array_crc32 : %x\n",
gpt->partition_entry_array_crc32);
return;
}
/**
* alloc_read_gpt_entries(): reads partition entries from disk
......@@ -318,13 +264,13 @@ static gpt_entry *
alloc_read_gpt_entries(struct gendisk *hd,
struct block_device *bdev, gpt_header *gpt)
{
u32 i, j;
size_t count;
gpt_entry *pte;
if (!hd || !bdev || !gpt)
return NULL;
count = gpt->num_partition_entries * gpt->sizeof_partition_entry;
count = le32_to_cpu(gpt->num_partition_entries) *
le32_to_cpu(gpt->sizeof_partition_entry);
if (!count)
return NULL;
pte = kmalloc(count, GFP_KERNEL);
......@@ -332,23 +278,13 @@ alloc_read_gpt_entries(struct gendisk *hd,
return NULL;
memset(pte, 0, count);
if (read_lba(hd, bdev, gpt->partition_entry_lba, (u8 *) pte,
if (read_lba(hd, bdev, le64_to_cpu(gpt->partition_entry_lba),
(u8 *) pte,
count) < count) {
kfree(pte);
pte=NULL;
return NULL;
}
/* Fixup endianness */
for (i = 0; i < gpt->num_partition_entries; i++) {
le_efi_guid_to_cpus(&pte[i].partition_type_guid);
le_efi_guid_to_cpus(&pte[i].unique_partition_guid);
le64_to_cpus(pte[i].starting_lba);
le64_to_cpus(pte[i].ending_lba);
le_part_attributes_to_cpus(&pte[i].attributes);
for (j = 0; j < (72 / sizeof (efi_char16_t)); j++) {
le16_to_cpus((u16) (pte[i].partition_name[j]));
}
}
return pte;
}
......@@ -377,27 +313,10 @@ alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba)
if (read_lba(hd, bdev, lba, (u8 *) gpt,
sizeof (gpt_header)) < sizeof (gpt_header)) {
kfree(gpt);
gpt=NULL;
return NULL;
}
/* Fixup endianness */
le64_to_cpus(gpt->signature);
le32_to_cpus(gpt->revision);
le32_to_cpus(gpt->header_size);
le32_to_cpus(gpt->header_crc32);
le32_to_cpus(gpt->reserved1);
le64_to_cpus(gpt->my_lba);
le64_to_cpus(gpt->alternate_lba);
le64_to_cpus(gpt->first_usable_lba);
le64_to_cpus(gpt->last_usable_lba);
le_efi_guid_to_cpus(&gpt->disk_guid);
le64_to_cpus(gpt->partition_entry_lba);
le32_to_cpus(gpt->num_partition_entries);
le32_to_cpus(gpt->sizeof_partition_entry);
le32_to_cpus(gpt->partition_entry_array_crc32);
print_gpt_header(gpt);
return gpt;
}
......@@ -424,9 +343,9 @@ is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba,
return 0;
/* Check the GUID Partition Table signature */
if ((*gpt)->signature != GPT_HEADER_SIGNATURE) {
if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
Dprintk("GUID Partition Table Header signature is wrong: %"
PRIx64 " != %" PRIx64 "\n", (*gpt)->signature,
PRIx64 " != %" PRIx64 "\n", le64_to_cpu((*gpt)->signature),
GPT_HEADER_SIGNATURE);
kfree(*gpt);
*gpt = NULL;
......@@ -434,25 +353,25 @@ is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba,
}
/* Check the GUID Partition Table CRC */
origcrc = (*gpt)->header_crc32;
origcrc = le32_to_cpu((*gpt)->header_crc32);
(*gpt)->header_crc32 = 0;
crc = efi_crc32((const unsigned char *) (*gpt), (*gpt)->header_size);
crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size));
if (crc != origcrc) {
Dprintk
("GUID Partition Table Header CRC is wrong: %x != %x\n",
(*gpt)->header_crc32, origcrc);
crc, origcrc);
kfree(*gpt);
*gpt = NULL;
return 0;
}
(*gpt)->header_crc32 = origcrc;
(*gpt)->header_crc32 = cpu_to_le32(origcrc);
/* Check that the my_lba entry points to the LBA that contains
* the GUID Partition Table */
if ((*gpt)->my_lba != lba) {
if (le64_to_cpu((*gpt)->my_lba) != lba) {
Dprintk("GPT my_lba incorrect: %" PRIx64 " != %" PRIx64 "\n",
(*gpt)->my_lba, lba);
le64_to_cpu((*gpt)->my_lba), lba);
kfree(*gpt);
*gpt = NULL;
return 0;
......@@ -466,10 +385,10 @@ is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba,
/* Check the GUID Partition Entry Array CRC */
crc = efi_crc32((const unsigned char *) (*ptes),
(*gpt)->num_partition_entries *
(*gpt)->sizeof_partition_entry);
le32_to_cpu((*gpt)->num_partition_entries) *
le32_to_cpu((*gpt)->sizeof_partition_entry));
if (crc != (*gpt)->partition_entry_array_crc32) {
if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
Dprintk("GUID Partitition Entry Array CRC check failed.\n");
kfree(*gpt);
*gpt = NULL;
......@@ -497,71 +416,81 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
int error_found = 0;
if (!pgpt || !agpt)
return;
if (pgpt->my_lba != agpt->alternate_lba) {
if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) {
printk(KERN_WARNING
"GPT:Primary header LBA != Alt. header alternate_lba\n");
printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
pgpt->my_lba, agpt->alternate_lba);
le64_to_cpu(pgpt->my_lba),
le64_to_cpu(agpt->alternate_lba));
error_found++;
}
if (pgpt->alternate_lba != agpt->my_lba) {
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\n");
printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
pgpt->alternate_lba, agpt->my_lba);
le64_to_cpu(pgpt->alternate_lba),
le64_to_cpu(agpt->my_lba));
error_found++;
}
if (pgpt->first_usable_lba != agpt->first_usable_lba) {
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.\n");
printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
pgpt->first_usable_lba, agpt->first_usable_lba);
le64_to_cpu(pgpt->first_usable_lba),
le64_to_cpu(agpt->first_usable_lba));
error_found++;
}
if (pgpt->last_usable_lba != agpt->last_usable_lba) {
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.\n");
printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
pgpt->last_usable_lba, agpt->last_usable_lba);
le64_to_cpu(pgpt->last_usable_lba),
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.\n");
error_found++;
}
if (pgpt->num_partition_entries != agpt->num_partition_entries) {
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\n",
pgpt->num_partition_entries,
agpt->num_partition_entries);
le32_to_cpu(pgpt->num_partition_entries),
le32_to_cpu(agpt->num_partition_entries));
error_found++;
}
if (pgpt->sizeof_partition_entry != agpt->sizeof_partition_entry) {
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\n", pgpt->sizeof_partition_entry,
agpt->sizeof_partition_entry);
"0x%x != 0x%x\n",
le32_to_cpu(pgpt->sizeof_partition_entry),
le32_to_cpu(agpt->sizeof_partition_entry));
error_found++;
}
if (pgpt->partition_entry_array_crc32 !=
agpt->partition_entry_array_crc32) {
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\n", pgpt->partition_entry_array_crc32,
agpt->partition_entry_array_crc32);
"0x%x != 0x%x\n",
le32_to_cpu(pgpt->partition_entry_array_crc32),
le32_to_cpu(agpt->partition_entry_array_crc32));
error_found++;
}
if (pgpt->alternate_lba != lastlba) {
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.\n");
printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
pgpt->alternate_lba, lastlba);
le64_to_cpu(pgpt->alternate_lba), lastlba);
error_found++;
}
if (agpt->my_lba != lastlba) {
if (le64_to_cpu(agpt->my_lba) != lastlba) {
printk(KERN_WARNING
"GPT:Alternate GPT header not at the end of the disk.\n");
printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
agpt->my_lba, lastlba);
le64_to_cpu(agpt->my_lba), lastlba);
error_found++;
}
......@@ -595,98 +524,95 @@ find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
return 0;
lastlba = last_lba(hd, bdev);
/* Check the Primary GPT */
good_pgpt = is_gpt_valid(hd, bdev, GPT_PRIMARY_PARTITION_TABLE_LBA,
&pgpt, &pptes);
if (good_pgpt) {
/* Primary GPT is OK, check the alternate and warn if bad */
good_agpt = is_gpt_valid(hd, bdev, pgpt->alternate_lba,
if (good_pgpt) {
good_agpt = is_gpt_valid(hd, bdev,
le64_to_cpu(pgpt->alternate_lba),
&agpt, &aptes);
if (!good_agpt) {
printk(KERN_WARNING
"Alternate GPT is invalid, using primary GPT.\n");
}
compare_gpts(pgpt, agpt, lastlba);
*gpt = pgpt;
*ptes = pptes;
if (agpt) {
kfree(agpt);
agpt = NULL;
}
if (aptes) {
kfree(aptes);
aptes = NULL;
}
} /* if primary is valid */
else {
/* Primary GPT is bad, check the Alternate GPT */
good_agpt = is_gpt_valid(hd, bdev, lastlba, &agpt, &aptes);
if (good_agpt) {
/* 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;
}
}
if (!good_agpt) {
good_agpt = is_gpt_valid(hd, bdev, lastlba,
&agpt, &aptes);
}
}
else {
good_agpt = is_gpt_valid(hd, bdev, lastlba,
&agpt, &aptes);
}
/* The obviously unsuccessful case */
if (!good_pgpt && !good_agpt) {
goto fail;
}
/* Now test for valid PMBR */
/* This will be added to the EFI Spec. per Intel after v1.02. */
if (good_pgpt || good_agpt) {
legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL);
if (legacymbr) {
memset(legacymbr, 0, sizeof (*legacymbr));
read_lba(hd, bdev, 0, (u8 *) legacymbr,
sizeof (*legacymbr));
good_pmbr = is_pmbr_valid(legacymbr);
kfree(legacymbr);
}
if (good_pmbr)
return 1;
if (!forcegpt) {
printk
(" Warning: Disk has a valid GPT signature but invalid PMBR.\n");
printk(KERN_WARNING
" Assuming this disk is *not* a GPT disk anymore.\n");
printk(KERN_WARNING
" Use gpt kernel option to override. Use GNU Parted to correct disk.\n");
} else {
printk(KERN_WARNING
" Warning: Disk has a valid GPT signature but invalid PMBR.\n");
printk(KERN_WARNING
" Use GNU Parted to correct disk.\n");
printk(KERN_WARNING
" gpt option taken, disk treated as GPT.\n");
return 1;
}
}
/* Both primary and alternate GPTs are bad, and/or PMBR is invalid.
* This isn't our disk, return 0.
*/
if (pgpt) {
kfree(pgpt);
pgpt = NULL;
}
if (agpt) {
kfree(agpt);
agpt = NULL;
}
if (pptes) {
kfree(pptes);
pptes = NULL;
}
if (aptes) {
kfree(aptes);
aptes = NULL;
}
*gpt = NULL;
*ptes = NULL;
return 0;
legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL);
if (legacymbr) {
memset(legacymbr, 0, sizeof (*legacymbr));
read_lba(hd, bdev, 0, (u8 *) legacymbr,
sizeof (*legacymbr));
good_pmbr = is_pmbr_valid(legacymbr);
kfree(legacymbr);
legacymbr=NULL;
}
/* Failure due to bad PMBR */
if ((good_pgpt || good_agpt) && !good_pmbr && !force_gpt) {
printk(KERN_WARNING
" Warning: Disk has a valid GPT signature "
"but invalid PMBR.\n");
printk(KERN_WARNING
" Assuming this disk is *not* a GPT disk anymore.\n");
printk(KERN_WARNING
" Use gpt kernel option to override. "
"Use GNU Parted to correct disk.\n");
goto fail;
}
/* Would fail due to bad PMBR, but force GPT anyhow */
if ((good_pgpt || good_agpt) && !good_pmbr && force_gpt) {
printk(KERN_WARNING
" Warning: Disk has a valid GPT signature but "
"invalid PMBR.\n");
printk(KERN_WARNING
" Use GNU Parted to correct disk.\n");
printk(KERN_WARNING
" gpt option taken, disk treated as GPT.\n");
}
compare_gpts(pgpt, agpt, lastlba);
/* The good cases */
if (good_pgpt && (good_pmbr || force_gpt)) {
*gpt = pgpt;
*ptes = pptes;
if (agpt) { kfree(agpt); agpt = NULL; }
if (aptes) { kfree(aptes); aptes = NULL; }
if (!good_agpt) {
printk(KERN_WARNING
"Alternate GPT is invalid, "
"using primary GPT.\n");
}
return 1;
}
else if (good_agpt && (good_pmbr || force_gpt)) {
*gpt = agpt;
*ptes = aptes;
if (pgpt) { kfree(pgpt); pgpt = NULL; }
if (pptes) { kfree(pptes); pptes = NULL; }
printk(KERN_WARNING
"Primary GPT is invalid, using alternate GPT.\n");
return 1;
}
fail:
if (pgpt) { kfree(pgpt); pgpt=NULL; }
if (agpt) { kfree(agpt); agpt=NULL; }
if (pptes) { kfree(pptes); pptes=NULL; }
if (aptes) { kfree(aptes); aptes=NULL; }
*gpt = NULL;
*ptes = NULL;
return 0;
}
/**
......@@ -710,49 +636,50 @@ add_gpt_partitions(struct gendisk *hd, struct block_device *bdev, int nextminor)
{
gpt_header *gpt = NULL;
gpt_entry *ptes = NULL;
u32 i, nummade = 0;
u32 i;
int max_p;
efi_guid_t unusedGuid = UNUSED_ENTRY_GUID;
#if CONFIG_BLK_DEV_MD
efi_guid_t raidGuid = PARTITION_LINUX_RAID_GUID;
#endif
if (!hd || !bdev)
return -1;
if (!find_valid_gpt(hd, bdev, &gpt, &ptes) || !gpt || !ptes) {
if (gpt)
if (gpt) {
kfree(gpt);
if (ptes)
gpt = NULL;
}
if (ptes) {
kfree(ptes);
ptes = NULL;
}
return 0;
}
Dprintk("GUID Partition Table is valid! Yea!\n");
max_p = (1 << hd->minor_shift) - 1;
for (i = 0; i < gpt->num_partition_entries && nummade < max_p; i++) {
if (!efi_guidcmp(unusedGuid, ptes[i].partition_type_guid))
for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < max_p; i++) {
if (!efi_guidcmp(ptes[i].partition_type_guid, NULL_GUID))
continue;
add_gd_partition(hd, nextminor, ptes[i].starting_lba,
(ptes[i].ending_lba - ptes[i].starting_lba +
add_gd_partition(hd, nextminor+i,
le64_to_cpu(ptes[i].starting_lba),
(le64_to_cpu(ptes[i].ending_lba) -
le64_to_cpu(ptes[i].starting_lba) +
1));
/* If there's this is a RAID volume, tell md */
#if CONFIG_BLK_DEV_MD
if (!efi_guidcmp(raidGuid, ptes[i].partition_type_guid)) {
if (!efi_guidcmp(ptes[i].partition_type_guid,
PARTITION_LINUX_RAID_GUID)) {
md_autodetect_dev(mk_kdev(hd->major,
nextminor));
}
#endif
nummade++;
nextminor++;
}
kfree(ptes);
ptes=NULL;
kfree(gpt);
gpt=NULL;
printk("\n");
return 1;
}
......
......@@ -48,22 +48,27 @@
#define GPT_HEADER_REVISION_V1 0x00010000
#define GPT_PRIMARY_PARTITION_TABLE_LBA 1
#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 }})
EFI_GUID( 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 }})
EFI_GUID( 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 }})
EFI_GUID( 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 }})
EFI_GUID( 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 }})
EFI_GUID( 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 }})
EFI_GUID( 0x0657fd6d, 0xa4ab, 0x43c4, \
0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f)
#define PARTITION_LINUX_LVM_GUID \
((efi_guid_t) { 0xe6d6d379, 0xf507, 0x44c2, { 0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28 }})
EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \
0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
typedef struct _gpt_header {
u64 signature;
......
......@@ -32,13 +32,18 @@ typedef unsigned long efi_status_t;
typedef u8 efi_bool_t;
typedef u16 efi_char16_t; /* UNICODE character */
typedef struct {
u32 data1;
u16 data2;
u16 data3;
u8 data4[8];
u8 b[16];
} efi_guid_t;
#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
((efi_guid_t) \
{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
(b) & 0xff, ((b) >> 8) & 0xff, \
(c) & 0xff, ((c) >> 8) & 0xff, \
(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})
/*
* Generic EFI table header
*/
......@@ -165,21 +170,23 @@ typedef void efi_reset_system_t (int reset_type, efi_status_t status,
/*
* EFI Configuration Table and GUID definitions
*/
#define NULL_GUID \
EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
#define MPS_TABLE_GUID \
((efi_guid_t) { 0xeb9d2d2f, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define ACPI_TABLE_GUID \
((efi_guid_t) { 0xeb9d2d30, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define ACPI_20_TABLE_GUID \
((efi_guid_t) { 0x8868e871, 0xe4f1, 0x11d3, { 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 }})
EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 )
#define SMBIOS_TABLE_GUID \
((efi_guid_t) { 0xeb9d2d31, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define SAL_SYSTEM_TABLE_GUID \
((efi_guid_t) { 0xeb9d2d32, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
typedef struct {
efi_guid_t guid;
......@@ -233,6 +240,17 @@ efi_guidcmp (efi_guid_t left, efi_guid_t right)
return memcmp(&left, &right, sizeof (efi_guid_t));
}
static inline char *
efi_guid_unparse(efi_guid_t *guid, char *out)
{
sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
guid->b[3], guid->b[2], guid->b[1], guid->b[0],
guid->b[5], guid->b[4], guid->b[7], guid->b[6],
guid->b[8], guid->b[9], guid->b[10], guid->b[11],
guid->b[12], guid->b[13], guid->b[14], guid->b[15]);
return out;
}
extern void efi_init (void);
extern void efi_map_pal_code (void);
extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
......
......@@ -241,32 +241,32 @@ enum {
/* SAL Error Record Section GUID Definitions */
#define SAL_PROC_DEV_ERR_SECT_GUID \
((efi_guid_t) { 0xe429faf1, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 }} )
EFI_GUID ( 0xe429faf1, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 )
#define SAL_PLAT_MEM_DEV_ERR_SECT_GUID \
((efi_guid_t) { 0xe429faf2, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 }} )
EFI_GUID( 0xe429faf2, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 )
#define SAL_PLAT_SEL_DEV_ERR_SECT_GUID \
((efi_guid_t) { 0xe429faf3, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 }} )
EFI_GUID( 0xe429faf3, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 )
#define SAL_PLAT_PCI_BUS_ERR_SECT_GUID \
((efi_guid_t) { 0xe429faf4, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 }} )
EFI_GUID( 0xe429faf4, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 )
#define SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID \
((efi_guid_t) { 0xe429faf5, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 }} )
EFI_GUID( 0xe429faf5, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 )
#define SAL_PLAT_PCI_COMP_ERR_SECT_GUID \
((efi_guid_t) { 0xe429faf6, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 }} )
EFI_GUID( 0xe429faf6, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 )
#define SAL_PLAT_SPECIFIC_ERR_SECT_GUID \
((efi_guid_t) { 0xe429faf7, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 }} )
EFI_GUID( 0xe429faf7, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 )
#define SAL_PLAT_HOST_CTLR_ERR_SECT_GUID \
((efi_guid_t) { 0xe429faf8, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 }} )
EFI_GUID( 0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 )
#define SAL_PLAT_BUS_ERR_SECT_GUID \
((efi_guid_t) { 0xe429faf9, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 }} )
EFI_GUID( 0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
0xc7, 0x3c, 0x88, 0x81 )
#define MAX_CACHE_ERRORS 6
#define MAX_TLB_ERRORS 6
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment