WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] x86-64/EFI: construct EDD data from device path prot

To: "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH] x86-64/EFI: construct EDD data from device path protocol information
From: "Jan Beulich" <JBeulich@xxxxxxxxxx>
Date: Wed, 17 Aug 2011 15:48:31 +0100
Delivery-date: Wed, 17 Aug 2011 07:48:15 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
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@xxxxxxxxxx>

--- a/xen/arch/x86/boot/edd.S
+++ b/xen/arch/x86/boot/edd.S
@@ -16,21 +16,13 @@
  * Updated and ported for Xen by Keir Fraser <keir@xxxxxxxxxxxxx> 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
--- a/xen/arch/x86/efi/boot.c
+++ b/xen/arch/x86/efi/boot.c
@@ -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 )
@@ -604,6 +617,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;
@@ -883,7 +898,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 *)&params->key; p < &params->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 )
--- a/xen/include/asm-x86/edd.h
+++ b/xen/include/asm-x86/edd.h
@@ -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__ */


Attachment: x86-EFI-EDD.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] x86-64/EFI: construct EDD data from device path protocol information, Jan Beulich <=