2011-08-26 18:49:33 +02:00
|
|
|
# HG changeset patch
|
|
|
|
# User Jan Beulich <jbeulich@novell.com>
|
|
|
|
# Date 1313744120 -3600
|
|
|
|
# Node ID e35c5202625ef5534561f84352833ad9467d986c
|
|
|
|
# Parent dd90b59cb11c60c48e174c899190e2967341fe32
|
|
|
|
x86-64/EFI: construct EDD data from device path protocol information
|
|
|
|
|
|
|
|
In the absence of a BIOS to handle INT13 requests, this information
|
|
|
|
must be constructed artificially instead when booted from EFI.
|
|
|
|
|
|
|
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
|
|
|
|
2011-09-15 23:43:21 +02:00
|
|
|
Index: xen-4.1.2-testing/xen/arch/x86/boot/edd.S
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.1.2-testing.orig/xen/arch/x86/boot/edd.S
|
|
|
|
+++ xen-4.1.2-testing/xen/arch/x86/boot/edd.S
|
2011-08-26 18:49:33 +02:00
|
|
|
@@ -16,21 +16,13 @@
|
|
|
|
* Updated and ported for Xen by Keir Fraser <keir@xensource.com> June 2007
|
|
|
|
*/
|
|
|
|
|
|
|
|
+#include <asm/edd.h>
|
|
|
|
+
|
|
|
|
.code16
|
|
|
|
|
|
|
|
/* Offset of disc signature in the MBR. */
|
|
|
|
#define EDD_MBR_SIG_OFFSET 0x1B8
|
|
|
|
|
|
|
|
-/* Maximum number of EDD information structures at boot_edd_info. */
|
|
|
|
-#define EDD_INFO_MAX 6
|
|
|
|
-
|
|
|
|
-/* Maximum number of MBR signatures at boot_mbr_signature. */
|
|
|
|
-#define EDD_MBR_SIG_MAX 16
|
|
|
|
-
|
|
|
|
-/* Size of components of EDD information structure. */
|
|
|
|
-#define EDDEXTSIZE 8
|
|
|
|
-#define EDDPARMSIZE 74
|
|
|
|
-
|
|
|
|
get_edd:
|
|
|
|
cmpb $2, bootsym(opt_edd) # edd=off ?
|
|
|
|
je edd_done
|
2011-09-15 23:43:21 +02:00
|
|
|
Index: xen-4.1.2-testing/xen/arch/x86/efi/boot.c
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.1.2-testing.orig/xen/arch/x86/efi/boot.c
|
|
|
|
+++ xen-4.1.2-testing/xen/arch/x86/efi/boot.c
|
2011-08-26 18:49:33 +02:00
|
|
|
@@ -16,6 +16,7 @@
|
|
|
|
#include <xen/stringify.h>
|
|
|
|
#include <xen/vga.h>
|
|
|
|
#include <asm/e820.h>
|
|
|
|
+#include <asm/edd.h>
|
|
|
|
#include <asm/mm.h>
|
|
|
|
#include <asm/msr.h>
|
|
|
|
#include <asm/processor.h>
|
|
|
|
@@ -539,6 +540,18 @@ static void __init split_value(char *s)
|
|
|
|
*s = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
+static void __init edd_put_string(u8 *dst, size_t n, const char *src)
|
|
|
|
+{
|
|
|
|
+ while ( n-- && *src )
|
|
|
|
+ *dst++ = *src++;
|
|
|
|
+ if ( *src )
|
|
|
|
+ PrintErrMesg(L"Internal error populating EDD info",
|
|
|
|
+ EFI_BUFFER_TOO_SMALL);
|
|
|
|
+ while ( n-- )
|
|
|
|
+ *dst++ = ' ';
|
|
|
|
+}
|
|
|
|
+#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s)
|
|
|
|
+
|
|
|
|
static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
|
|
|
|
{
|
|
|
|
if ( bpp < 0 )
|
|
|
|
@@ -607,6 +620,8 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
|
|
|
{
|
|
|
|
static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL;
|
|
|
|
static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
|
|
|
+ static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL;
|
|
|
|
+ static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL;
|
|
|
|
EFI_LOADED_IMAGE *loaded_image;
|
|
|
|
EFI_STATUS status;
|
|
|
|
unsigned int i, argc;
|
|
|
|
@@ -887,7 +902,148 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
|
|
|
|
|
|
|
place_string(&mbi.mem_upper, NULL);
|
|
|
|
|
|
|
|
- /* XXX Collect EDD info. */
|
|
|
|
+ /* Collect EDD info. */
|
|
|
|
+ BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE);
|
|
|
|
+ BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE);
|
|
|
|
+ size = 0;
|
|
|
|
+ status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, NULL);
|
|
|
|
+ if ( status == EFI_BUFFER_TOO_SMALL )
|
|
|
|
+ status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
|
|
|
|
+ if ( !EFI_ERROR(status) )
|
|
|
|
+ status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size,
|
|
|
|
+ handles);
|
|
|
|
+ if ( EFI_ERROR(status) )
|
|
|
|
+ size = 0;
|
|
|
|
+ for ( i = 0; i < size / sizeof(*handles); ++i )
|
|
|
|
+ {
|
|
|
|
+ EFI_BLOCK_IO *bio;
|
|
|
|
+ EFI_DEV_PATH_PTR devp;
|
|
|
|
+ struct edd_info *info = boot_edd_info + boot_edd_info_nr;
|
|
|
|
+ struct edd_device_params *params = &info->edd_device_params;
|
|
|
|
+ enum { root, acpi, pci, ctrlr } state = root;
|
|
|
|
+
|
|
|
|
+ status = efi_bs->HandleProtocol(handles[i], &bio_guid, (void **)&bio);
|
|
|
|
+ if ( EFI_ERROR(status) ||
|
|
|
|
+ bio->Media->RemovableMedia ||
|
|
|
|
+ bio->Media->LogicalPartition )
|
|
|
|
+ continue;
|
|
|
|
+ if ( boot_edd_info_nr < EDD_INFO_MAX )
|
|
|
|
+ {
|
|
|
|
+ info->device = 0x80 + boot_edd_info_nr; /* fake */
|
|
|
|
+ info->version = 0x11;
|
|
|
|
+ params->length = offsetof(struct edd_device_params, dpte_ptr);
|
|
|
|
+ params->number_of_sectors = bio->Media->LastBlock + 1;
|
|
|
|
+ params->bytes_per_sector = bio->Media->BlockSize;
|
|
|
|
+ params->dpte_ptr = ~0;
|
|
|
|
+ }
|
|
|
|
+ ++boot_edd_info_nr;
|
|
|
|
+ status = efi_bs->HandleProtocol(handles[i], &devp_guid,
|
|
|
|
+ (void **)&devp);
|
|
|
|
+ if ( EFI_ERROR(status) )
|
|
|
|
+ continue;
|
|
|
|
+ for ( ; !IsDevicePathEnd(devp.DevPath);
|
|
|
|
+ devp.DevPath = NextDevicePathNode(devp.DevPath) )
|
|
|
|
+ {
|
|
|
|
+ switch ( DevicePathType(devp.DevPath) )
|
|
|
|
+ {
|
|
|
|
+ const u8 *p;
|
|
|
|
+
|
|
|
|
+ case ACPI_DEVICE_PATH:
|
|
|
|
+ if ( state != root || boot_edd_info_nr > EDD_INFO_MAX )
|
|
|
|
+ break;
|
|
|
|
+ switch ( DevicePathSubType(devp.DevPath) )
|
|
|
|
+ {
|
|
|
|
+ case ACPI_DP:
|
|
|
|
+ if ( devp.Acpi->HID != EISA_PNP_ID(0xA03) &&
|
|
|
|
+ devp.Acpi->HID != EISA_PNP_ID(0xA08) )
|
|
|
|
+ break;
|
|
|
|
+ params->interface_path.pci.bus = devp.Acpi->UID;
|
|
|
|
+ state = acpi;
|
|
|
|
+ break;
|
|
|
|
+ case EXPANDED_ACPI_DP:
|
|
|
|
+ /* XXX */
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case HARDWARE_DEVICE_PATH:
|
|
|
|
+ if ( state != acpi ||
|
|
|
|
+ DevicePathSubType(devp.DevPath) != HW_PCI_DP ||
|
|
|
|
+ boot_edd_info_nr > EDD_INFO_MAX )
|
|
|
|
+ break;
|
|
|
|
+ state = pci;
|
|
|
|
+ edd_put_string(params->host_bus_type, "PCI");
|
|
|
|
+ params->interface_path.pci.slot = devp.Pci->Device;
|
|
|
|
+ params->interface_path.pci.function = devp.Pci->Function;
|
|
|
|
+ break;
|
|
|
|
+ case MESSAGING_DEVICE_PATH:
|
|
|
|
+ if ( state != pci || boot_edd_info_nr > EDD_INFO_MAX )
|
|
|
|
+ break;
|
|
|
|
+ state = ctrlr;
|
|
|
|
+ switch ( DevicePathSubType(devp.DevPath) )
|
|
|
|
+ {
|
|
|
|
+ case MSG_ATAPI_DP:
|
|
|
|
+ edd_put_string(params->interface_type, "ATAPI");
|
|
|
|
+ params->interface_path.pci.channel =
|
|
|
|
+ devp.Atapi->PrimarySecondary;
|
|
|
|
+ params->device_path.atapi.device = devp.Atapi->SlaveMaster;
|
|
|
|
+ params->device_path.atapi.lun = devp.Atapi->Lun;
|
|
|
|
+ break;
|
|
|
|
+ case MSG_SCSI_DP:
|
|
|
|
+ edd_put_string(params->interface_type, "SCSI");
|
|
|
|
+ params->device_path.scsi.id = devp.Scsi->Pun;
|
|
|
|
+ params->device_path.scsi.lun = devp.Scsi->Lun;
|
|
|
|
+ break;
|
|
|
|
+ case MSG_FIBRECHANNEL_DP:
|
|
|
|
+ edd_put_string(params->interface_type, "FIBRE");
|
|
|
|
+ params->device_path.fibre.wwid = devp.FibreChannel->WWN;
|
|
|
|
+ params->device_path.fibre.lun = devp.FibreChannel->Lun;
|
|
|
|
+ break;
|
|
|
|
+ case MSG_1394_DP:
|
|
|
|
+ edd_put_string(params->interface_type, "1394");
|
|
|
|
+ params->device_path.i1394.eui = devp.F1394->Guid;
|
|
|
|
+ break;
|
|
|
|
+ case MSG_USB_DP:
|
|
|
|
+ case MSG_USB_CLASS_DP:
|
|
|
|
+ edd_put_string(params->interface_type, "USB");
|
|
|
|
+ break;
|
|
|
|
+ case MSG_I2O_DP:
|
|
|
|
+ edd_put_string(params->interface_type, "I2O");
|
|
|
|
+ params->device_path.i2o.identity_tag = devp.I2O->Tid;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ info->version = 0x30;
|
|
|
|
+ params->length = sizeof(struct edd_device_params);
|
|
|
|
+ params->key = 0xbedd;
|
|
|
|
+ params->device_path_info_length =
|
|
|
|
+ sizeof(struct edd_device_params) -
|
|
|
|
+ offsetof(struct edd_device_params, key);
|
|
|
|
+ for ( p = (const u8 *)¶ms->key; p < ¶ms->checksum; ++p )
|
|
|
|
+ params->checksum -= *p;
|
|
|
|
+ break;
|
|
|
|
+ case MEDIA_DEVICE_PATH:
|
|
|
|
+ if ( DevicePathSubType(devp.DevPath) == MEDIA_HARDDRIVE_DP &&
|
|
|
|
+ devp.HardDrive->MBRType == MBR_TYPE_PCAT &&
|
|
|
|
+ boot_mbr_signature_nr < EDD_MBR_SIG_MAX )
|
|
|
|
+ {
|
|
|
|
+ struct mbr_signature *sig = boot_mbr_signature +
|
|
|
|
+ boot_mbr_signature_nr;
|
|
|
|
+
|
|
|
|
+ sig->device = 0x80 + boot_edd_info_nr; /* fake */
|
|
|
|
+ memcpy(&sig->signature, devp.HardDrive->Signature,
|
|
|
|
+ sizeof(sig->signature));
|
|
|
|
+ ++boot_mbr_signature_nr;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if ( handles )
|
|
|
|
+ efi_bs->FreePool(handles);
|
|
|
|
+ if ( boot_edd_info_nr > EDD_INFO_MAX )
|
|
|
|
+ boot_edd_info_nr = EDD_INFO_MAX;
|
|
|
|
+
|
|
|
|
/* XXX Collect EDID info. */
|
|
|
|
|
|
|
|
if ( cpuid_eax(0x80000000) > 0x80000000 )
|
2011-09-15 23:43:21 +02:00
|
|
|
Index: xen-4.1.2-testing/xen/include/asm-x86/edd.h
|
|
|
|
===================================================================
|
|
|
|
--- xen-4.1.2-testing.orig/xen/include/asm-x86/edd.h
|
|
|
|
+++ xen-4.1.2-testing/xen/include/asm-x86/edd.h
|
2011-08-26 18:49:33 +02:00
|
|
|
@@ -23,6 +23,8 @@
|
|
|
|
#ifndef __XEN_EDD_H__
|
|
|
|
#define __XEN_EDD_H__
|
|
|
|
|
|
|
|
+#ifndef __ASSEMBLY__
|
|
|
|
+
|
|
|
|
struct edd_info {
|
|
|
|
/* Int13, Fn48: Check Extensions Present. */
|
|
|
|
u8 device; /* %dl: device */
|
|
|
|
@@ -33,10 +35,106 @@ struct edd_info {
|
|
|
|
u8 legacy_max_head; /* %dh: maximum head number */
|
|
|
|
u8 legacy_sectors_per_track; /* %cl[5:0]: maximum sector number */
|
|
|
|
/* Int13, Fn41: Get Device Parameters (as filled into %ds:%esi). */
|
|
|
|
- struct {
|
|
|
|
+ struct edd_device_params {
|
|
|
|
u16 length;
|
|
|
|
- u8 data[72];
|
|
|
|
- } edd_device_params;
|
|
|
|
+ u16 info_flags;
|
|
|
|
+ u32 num_default_cylinders;
|
|
|
|
+ u32 num_default_heads;
|
|
|
|
+ u32 sectors_per_track;
|
|
|
|
+ u64 number_of_sectors;
|
|
|
|
+ u16 bytes_per_sector;
|
|
|
|
+ u32 dpte_ptr; /* 0xFFFFFFFF for our purposes */
|
|
|
|
+ u16 key; /* = 0xBEDD */
|
|
|
|
+ u8 device_path_info_length;
|
|
|
|
+ u8 reserved2;
|
|
|
|
+ u16 reserved3;
|
|
|
|
+ u8 host_bus_type[4];
|
|
|
|
+ u8 interface_type[8];
|
|
|
|
+ union {
|
|
|
|
+ struct {
|
|
|
|
+ u16 base_address;
|
|
|
|
+ u16 reserved1;
|
|
|
|
+ u32 reserved2;
|
|
|
|
+ } __attribute__ ((packed)) isa;
|
|
|
|
+ struct {
|
|
|
|
+ u8 bus;
|
|
|
|
+ u8 slot;
|
|
|
|
+ u8 function;
|
|
|
|
+ u8 channel;
|
|
|
|
+ u32 reserved;
|
|
|
|
+ } __attribute__ ((packed)) pci;
|
|
|
|
+ /* pcix is same as pci */
|
|
|
|
+ struct {
|
|
|
|
+ u64 reserved;
|
|
|
|
+ } __attribute__ ((packed)) ibnd;
|
|
|
|
+ struct {
|
|
|
|
+ u64 reserved;
|
|
|
|
+ } __attribute__ ((packed)) xprs;
|
|
|
|
+ struct {
|
|
|
|
+ u64 reserved;
|
|
|
|
+ } __attribute__ ((packed)) htpt;
|
|
|
|
+ struct {
|
|
|
|
+ u64 reserved;
|
|
|
|
+ } __attribute__ ((packed)) unknown;
|
|
|
|
+ } interface_path;
|
|
|
|
+ union {
|
|
|
|
+ struct {
|
|
|
|
+ u8 device;
|
|
|
|
+ u8 reserved1;
|
|
|
|
+ u16 reserved2;
|
|
|
|
+ u32 reserved3;
|
|
|
|
+ u64 reserved4;
|
|
|
|
+ } __attribute__ ((packed)) ata;
|
|
|
|
+ struct {
|
|
|
|
+ u8 device;
|
|
|
|
+ u8 lun;
|
|
|
|
+ u8 reserved1;
|
|
|
|
+ u8 reserved2;
|
|
|
|
+ u32 reserved3;
|
|
|
|
+ u64 reserved4;
|
|
|
|
+ } __attribute__ ((packed)) atapi;
|
|
|
|
+ struct {
|
|
|
|
+ u16 id;
|
|
|
|
+ u64 lun;
|
|
|
|
+ u16 reserved1;
|
|
|
|
+ u32 reserved2;
|
|
|
|
+ } __attribute__ ((packed)) scsi;
|
|
|
|
+ struct {
|
|
|
|
+ u64 serial_number;
|
|
|
|
+ u64 reserved;
|
|
|
|
+ } __attribute__ ((packed)) usb;
|
|
|
|
+ struct {
|
|
|
|
+ u64 eui;
|
|
|
|
+ u64 reserved;
|
|
|
|
+ } __attribute__ ((packed)) i1394;
|
|
|
|
+ struct {
|
|
|
|
+ u64 wwid;
|
|
|
|
+ u64 lun;
|
|
|
|
+ } __attribute__ ((packed)) fibre;
|
|
|
|
+ struct {
|
|
|
|
+ u64 identity_tag;
|
|
|
|
+ u64 reserved;
|
|
|
|
+ } __attribute__ ((packed)) i2o;
|
|
|
|
+ struct {
|
|
|
|
+ u32 array_number;
|
|
|
|
+ u32 reserved1;
|
|
|
|
+ u64 reserved2;
|
|
|
|
+ } __attribute__ ((packed)) raid;
|
|
|
|
+ struct {
|
|
|
|
+ u8 device;
|
|
|
|
+ u8 reserved1;
|
|
|
|
+ u16 reserved2;
|
|
|
|
+ u32 reserved3;
|
|
|
|
+ u64 reserved4;
|
|
|
|
+ } __attribute__ ((packed)) sata;
|
|
|
|
+ struct {
|
|
|
|
+ u64 reserved1;
|
|
|
|
+ u64 reserved2;
|
|
|
|
+ } __attribute__ ((packed)) unknown;
|
|
|
|
+ } device_path;
|
|
|
|
+ u8 reserved4;
|
|
|
|
+ u8 checksum;
|
|
|
|
+ } __attribute__ ((packed)) edd_device_params;
|
|
|
|
} __attribute__ ((packed));
|
|
|
|
|
|
|
|
struct mbr_signature {
|
|
|
|
@@ -51,4 +149,16 @@ extern u8 boot_mbr_signature_nr;
|
|
|
|
extern struct edd_info boot_edd_info[];
|
|
|
|
extern u8 boot_edd_info_nr;
|
|
|
|
|
|
|
|
+#endif /* __ASSEMBLY__ */
|
|
|
|
+
|
|
|
|
+/* Maximum number of EDD information structures at boot_edd_info. */
|
|
|
|
+#define EDD_INFO_MAX 6
|
|
|
|
+
|
|
|
|
+/* Maximum number of MBR signatures at boot_mbr_signature. */
|
|
|
|
+#define EDD_MBR_SIG_MAX 16
|
|
|
|
+
|
|
|
|
+/* Size of components of EDD information structure. */
|
|
|
|
+#define EDDEXTSIZE 8
|
|
|
|
+#define EDDPARMSIZE 74
|
|
|
|
+
|
|
|
|
#endif /* __XEN_EDD_H__ */
|