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 2/3] x86: real mode support: get EDD info

To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 2/3] x86: real mode support: get EDD info
From: "Jan Beulich" <jbeulich@xxxxxxxxxx>
Date: Fri, 02 Mar 2007 10:32:15 +0000
Delivery-date: Fri, 02 Mar 2007 02:31:22 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
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/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Obtain EDD info from BIOS and pass it up to Dom0.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Index: 2007-02-27/xen/arch/x86/Makefile
===================================================================
--- 2007-02-27.orig/xen/arch/x86/Makefile       2007-02-22 16:14:25.000000000 
+0100
+++ 2007-02-27/xen/arch/x86/Makefile    2007-02-22 15:57:24.000000000 +0100
@@ -78,7 +78,7 @@ xen.lds: $(TARGET_SUBARCH)/xen.lds.S $(H
 boot/mkelf32: boot/mkelf32.c
        $(HOSTCC) $(HOSTCFLAGS) -o $@ $<
 
-boot/$(TARGET_SUBARCH).o: boot/realmode.S
+boot/$(TARGET_SUBARCH).o: boot/realmode.S boot/edd.S
 
 .PHONY: clean
 clean::
Index: 2007-02-27/xen/arch/x86/boot/edd.S
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2007-02-27/xen/arch/x86/boot/edd.S  2007-02-21 17:45:32.000000000 +0100
@@ -0,0 +1,217 @@
+/*
+ * BIOS Enhanced Disk Drive support
+ * Copyright (C) 2002, 2003, 2004 Dell, Inc.
+ * by Matt Domsch <Matt_Domsch@xxxxxxxx> October 2002
+ * conformant to T13 Committee www.t13.org 
+ *   projects 1572D, 1484D, 1386D, 1226DT
+ * disk signature read by Matt Domsch <Matt_Domsch@xxxxxxxx>
+ *     and Andrew Wilks <Andrew_Wilks@xxxxxxxx> September 2003, June 2004
+ * legacy CHS retrieval by Patrick J. LoPresti <patl@xxxxxxxxxxxxxxxxxxxxx>
+ *      March 2004
+ * Command line option parsing, Matt Domsch, November 2004
+ * Xen adoption by Jan Beulich <jbeulich@xxxxxxxxxx>, February 2007
+ */
+
+#include <xen/edd.h>
+
+# It is assumed that %ds == INITSEG here
+
+       movb    $0, (EDD_MBR_SIG_NR_BUF)
+       movb    $0, (EDDNR)
+
+# Check the command line for options:
+# edd=of  disables EDD completely  (edd=off)
+# edd=sk  skips the MBR test    (edd=skipmbr)
+# edd=on  re-enables EDD (edd=on)
+
+       pushl   %esi
+       movw    $SYM_REAL(edd_mbr_sig_start), %di       # Default to edd=on
+
+       movl    %cs:SYM_REAL(cmd_line_ptr), %esi
+       andl    %esi, %esi
+       jz      done_cl
+
+# Convert to a real-mode pointer in fs:si
+       movl    %esi, %eax
+       shrl    $4, %eax
+       mov     %ax, %fs
+       andw    $0xf, %si
+
+# fs:si has the pointer to the command line now
+
+# Loop through kernel command line one byte at a time.  Just in
+# case the loader is buggy and failed to null-terminate the command line
+# terminate if we get close enough to the end of the segment that we
+# cannot fit "edd=XX"...
+cl_atspace:
+       cmpw    $-5, %si                # Watch for segment wraparound
+       jae     done_cl
+       movl    %fs:(%si), %eax
+       andb    %al, %al                # End of line?
+       jz      done_cl
+       cmpl    $EDD_CL_EQUALS, %eax
+       jz      found_edd_equals
+       cmpb    $0x20, %al              # <= space consider whitespace
+       ja      cl_skipword
+       incw    %si
+       jmp     cl_atspace
+
+cl_skipword:
+       cmpw    $-5, %si                # Watch for segment wraparound
+       jae     done_cl
+       movb    %fs:(%si), %al          # End of string?
+       andb    %al, %al
+       jz      done_cl
+       cmpb    $0x20, %al
+       jbe     cl_atspace
+       incw    %si
+       jmp     cl_skipword
+
+found_edd_equals:
+# only looking at first two characters after equals
+# late overrides early on the command line, so keep going after finding 
something
+       movw    %fs:4(%si), %ax
+       cmpw    $EDD_CL_OFF, %ax        # edd=of
+       je      do_edd_off
+       cmpw    $EDD_CL_SKIP, %ax       # edd=sk
+       je      do_edd_skipmbr
+       cmpw    $EDD_CL_ON, %ax         # edd=on
+       je      do_edd_on
+       jmp     cl_skipword
+do_edd_skipmbr:
+       movw    $SYM_REAL(edd_start), %di
+       jmp     cl_skipword
+do_edd_off:
+       movw    $SYM_REAL(edd_done), %di
+       jmp     cl_skipword
+do_edd_on:
+       movw    $SYM_REAL(edd_mbr_sig_start), %di
+       jmp     cl_skipword
+
+done_cl:
+       popl    %esi
+       jmpw    *%di
+
+# Read the first sector of each BIOS disk device and store the 4-byte signature
+edd_mbr_sig_start:
+       movb    $0x80, %dl                      # from device 80
+       movw    $EDD_MBR_SIG_BUF, %bx           # store buffer ptr in bx
+edd_mbr_sig_read:
+       movl    $0xFFFFFFFF, %eax
+       movl    %eax, (%bx)                     # assume failure
+       pushw   %bx
+       movb    $READ_SECTORS, %ah
+       movb    $1, %al                         # read 1 sector
+       movb    $0, %dh                         # at head 0
+       movw    $1, %cx                         # cylinder 0, sector 0
+       pushw   %es
+       pushw   %ds
+       popw    %es
+       movw    $EDDBUF, %bx                    # disk's data goes into EDDBUF
+       pushw   %dx             # work around buggy BIOSes
+       stc                     # work around buggy BIOSes
+       int     $0x13
+       sti                     # work around buggy BIOSes
+       popw    %dx
+       popw    %es
+       popw    %bx
+       jc      edd_mbr_sig_done                # on failure, we're done.
+       cmpb    $0, %ah         # some BIOSes do not set CF
+       jne     edd_mbr_sig_done                # on failure, we're done.
+       movl    (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR
+       movl    %eax, (%bx)                     # store success
+       incb    (EDD_MBR_SIG_NR_BUF)            # note that we stored something
+       incb    %dl                             # increment to next device
+       addw    $4, %bx                         # increment sig buffer ptr
+       cmpb    $EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF)  # Out of space?
+       jb      edd_mbr_sig_read                # keep looping
+edd_mbr_sig_done:
+
+# Do the BIOS Enhanced Disk Drive calls
+# This consists of two calls:
+#    int 13h ah=41h "Check Extensions Present"
+#    int 13h ah=48h "Get Device Parameters"
+#    int 13h ah=08h "Legacy Get Device Parameters"
+#
+# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use
+# in the boot_params at EDDBUF.  The first four bytes of which are
+# used to store the device number, interface support map and version
+# results from fn41.  The next four bytes are used to store the legacy
+# cylinders, heads, and sectors from fn08. The following 74 bytes are used to
+# store the results from fn48.  Starting from device 80h, fn41, then fn48
+# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE).
+# Then the pointer is incremented to store the data for the next call.
+# This repeats until either a device doesn't exist, or until EDDMAXNR
+# devices have been stored.
+# The one tricky part is that ds:si always points EDDEXTSIZE bytes into
+# the structure, and the fn41 and fn08 results are stored at offsets
+# from there.  This removes the need to increment the pointer for
+# every store, and leaves it ready for the fn48 call.
+# A second one-byte buffer, EDDNR, in the boot_params stores
+# the number of BIOS devices which exist, up to EDDMAXNR.
+# In setup.c, copy_edd() stores both boot_params buffers away
+# for later use, as they would get overwritten otherwise.
+# This code is sensitive to the size of the structs in edd.h
+edd_start:
+                                               # %ds points to the bootsector
+                                                       # result buffer for fn48
+       movw    $EDDBUF+EDDEXTSIZE, %si         # in ds:si, fn41 results
+                                               # kept just before that
+       movb    $0x80, %dl                      # BIOS device 0x80
+
+edd_check_ext:
+       movb    $CHECKEXTENSIONSPRESENT, %ah    # Function 41
+       movw    $EDDMAGIC1, %bx                 # magic
+       int     $0x13                           # make the call
+       jc      edd_done                        # no more BIOS devices
+
+       cmpw    $EDDMAGIC2, %bx                 # is magic right?
+       jne     edd_next                        # nope, next...
+
+       movb    %dl, %ds:-8(%si)                # store device number
+       movb    %ah, %ds:-7(%si)                # store version
+       movw    %cx, %ds:-6(%si)                # store extensions
+       incb    (EDDNR)                         # note that we stored something
+
+edd_get_device_params:
+       movw    $EDDPARMSIZE, %ds:(%si)         # put size
+       movw    $0x0, %ds:2(%si)                # work around buggy BIOSes
+       movb    $GETDEVICEPARAMETERS, %ah       # Function 48
+       int     $0x13                           # make the call
+                                               # Don't check for fail return
+                                               # it doesn't matter.
+edd_get_legacy_chs:
+       xorw    %ax, %ax
+       movw    %ax, %ds:-4(%si)
+       movw    %ax, %ds:-2(%si)
+        # Ralf Brown's Interrupt List says to set ES:DI to
+       # 0000h:0000h "to guard against BIOS bugs"
+       pushw   %es
+       movw    %ax, %es
+       movw    %ax, %di
+       pushw   %dx                             # legacy call clobbers %dl
+       movb    $LEGACYGETDEVICEPARAMETERS, %ah # Function 08
+       int     $0x13                           # make the call
+       jc      edd_legacy_done                 # failed
+       movb    %cl, %al                        # Low 6 bits are max
+       andb    $0x3F, %al                      #   sector number
+       movb    %al, %ds:-1(%si)                # Record max sect
+       movb    %dh, %ds:-2(%si)                # Record max head number
+       movb    %ch, %al                        # Low 8 bits of max cyl
+       shr     $6, %cl
+       movb    %cl, %ah                        # High 2 bits of max cyl
+       movw    %ax, %ds:-4(%si)
+
+edd_legacy_done:
+       popw    %dx
+       popw    %es
+       movw    %si, %ax                        # increment si
+       addw    $EDDPARMSIZE+EDDEXTSIZE, %ax
+       movw    %ax, %si
+
+edd_next:
+       incb    %dl                             # increment to next device
+       cmpb    $EDDMAXNR, (EDDNR)              # Out of space?
+       jb      edd_check_ext                   # keep looping
+
+edd_done:
Index: 2007-02-27/xen/arch/x86/boot/realmode.S
===================================================================
--- 2007-02-27.orig/xen/arch/x86/boot/realmode.S        2007-02-22 
16:14:25.000000000 +0100
+++ 2007-02-27/xen/arch/x86/boot/realmode.S     2007-02-22 15:58:16.000000000 
+0100
@@ -118,3 +118,26 @@ cmd_line_ptr: .long 0
 .Lgdt: .skip 2+4
 .Lidt: .skip 2+4
        .previous
+
+#define EDDNR                  SYM_REAL(eddnr)
+#define EDDBUF                 SYM_REAL(eddbuf)
+#define EDD_MBR_SIG_NR_BUF     SYM_REAL(edd_mbr_sig_nr_buf)
+#define EDD_MBR_SIG_BUF                SYM_REAL(edd_mbr_sig_buf)
+
+edd:
+#include "edd.S"
+       ret
+
+       .section .real.data
+       .globl eddnr, eddbuf, edd_mbr_sig_nr_buf, edd_mbr_sig_buf
+       .align 4
+eddbuf:                        .skip EDDMAXNR * (EDDEXTSIZE + EDDPARMSIZE)
+#if EDDMAXNR * (EDDEXTSIZE + EDDPARMSIZE) < 512
+/* Must have space for a full 512-byte sector */
+                       .skip 512 - EDDMAXNR * (EDDEXTSIZE + EDDPARMSIZE)
+#endif
+       .align 4
+edd_mbr_sig_buf:       .skip EDD_MBR_SIG_MAX * 4
+eddnr:                 .skip 1
+edd_mbr_sig_nr_buf:    .skip 1
+       .previous
Index: 2007-02-27/xen/arch/x86/boot/x86_32.S
===================================================================
--- 2007-02-27.orig/xen/arch/x86/boot/x86_32.S  2007-02-22 16:14:25.000000000 
+0100
+++ 2007-02-27/xen/arch/x86/boot/x86_32.S       2007-02-21 18:08:44.000000000 
+0100
@@ -90,6 +90,9 @@ __start:
         lea     __PAGE_OFFSET(%ebx),%eax
         push    %eax
 
+        pushl   $SYM_PHYS(edd)
+        call    realmode
+
 #ifdef CONFIG_X86_PAE
         /* Initialize low and high mappings of all memory with 2MB pages */
         mov     $SYM_PHYS(idle_pg_table_l2),%edi
Index: 2007-02-27/xen/arch/x86/boot/x86_64.S
===================================================================
--- 2007-02-27.orig/xen/arch/x86/boot/x86_64.S  2007-02-22 16:14:25.000000000 
+0100
+++ 2007-02-27/xen/arch/x86/boot/x86_64.S       2007-02-21 17:55:02.000000000 
+0100
@@ -73,6 +73,8 @@ __start:
         mov     %ebx,SYM_PHYS(multiboot_ptr)
 
         lss     SYM_PHYS(.Lstack_start),%esp
+        pushl   $SYM_PHYS(edd)
+        call    realmode
 
         /* We begin by interrogating the CPU for the presence of long mode. */
         mov     $0x80000000,%eax
Index: 2007-02-27/xen/arch/x86/platform_hypercall.c
===================================================================
--- 2007-02-27.orig/xen/arch/x86/platform_hypercall.c   2007-02-22 
16:14:25.000000000 +0100
+++ 2007-02-27/xen/arch/x86/platform_hypercall.c        2007-02-22 
16:14:39.000000000 +0100
@@ -17,6 +17,7 @@
 #include <xen/trace.h>
 #include <xen/console.h>
 #include <xen/iocap.h>
+#include <xen/edd.h>
 #include <xen/guest_access.h>
 #include <asm/current.h>
 #include <public/platform.h>
@@ -26,8 +27,14 @@
 #ifndef COMPAT
 typedef long ret_t;
 DEFINE_SPINLOCK(xenpf_lock);
+struct edd edd;
+# undef copy_from_compat
+# define copy_from_compat copy_from_guest
+# undef copy_to_compat
+# define copy_to_compat copy_to_guest
 #else
 extern spinlock_t xenpf_lock;
+extern struct edd edd;
 #endif
 
 ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
@@ -151,6 +158,73 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
     }
     break;
 
+    case XENPF_firmware_info:
+        switch ( op->u.firmware_info.type )
+        {
+        case XEN_FW_DISK_INFO:
+            if ( op->u.firmware_info.index < edd.edd_info_nr )
+            {
+                const struct edd_info *info = edd.edd_info + 
op->u.firmware_info.index;
+
+                op->u.firmware_info.u.disk_info.max_cylinder      = 
info->legacy_max_cylinder;
+                op->u.firmware_info.u.disk_info.max_head          = 
info->legacy_max_head;
+                op->u.firmware_info.u.disk_info.sectors_per_track = 
info->legacy_sectors_per_track;
+                if ( copy_field_to_guest(u_xenpf_op, op, 
u.firmware_info.u.disk_info) )
+                    ret = -EFAULT;
+            }
+            else
+                ret = -ESRCH;
+            break;
+        case XEN_FW_EDD_INFO:
+            if ( op->u.firmware_info.index < edd.edd_info_nr )
+            {
+                const struct edd_info *info = edd.edd_info + 
op->u.firmware_info.index;
+
+                op->u.firmware_info.u.edd_info.device    = info->device;
+                op->u.firmware_info.u.edd_info.version   = info->version;
+                op->u.firmware_info.u.edd_info.interface = 
info->interface_support;
+                if ( copy_field_to_guest(u_xenpf_op, op, 
u.firmware_info.u.edd_info) )
+                    ret = -EFAULT;
+            }
+            else
+                ret = -ESRCH;
+            break;
+        case XEN_FW_EDD_PARAMS:
+            if ( op->u.firmware_info.index < edd.edd_info_nr )
+            {
+                u16 length;
+
+                if ( copy_from_compat(&length, 
op->u.firmware_info.u.edd_params, 1) == 0 )
+                {
+                    if ( length > 
edd.edd_info[op->u.firmware_info.index].params.length )
+                        length = 
edd.edd_info[op->u.firmware_info.index].params.length;
+                    if ( copy_to_compat(op->u.firmware_info.u.edd_params,
+                                        
(u8*)&edd.edd_info[op->u.firmware_info.index].params,
+                                        length) )
+                        ret = -EFAULT;
+                }
+                else
+                    ret = -EFAULT;
+            }
+            else
+                ret = -ESRCH;
+            break;
+        case XEN_FW_MBR_SIGNATURE:
+            if ( op->u.firmware_info.index < edd.mbr_signature_nr )
+            {
+                op->u.firmware_info.u.mbr_signature = 
edd.mbr_signature[op->u.firmware_info.index];
+                if ( copy_field_to_guest(u_xenpf_op, op, 
u.firmware_info.u.mbr_signature) )
+                    ret = -EFAULT;
+            }
+            else
+                ret = -ESRCH;
+            break;
+        default:
+            ret = -EINVAL;
+            break;
+        }
+        break;
+
     default:
         ret = -ENOSYS;
         break;
@@ -161,6 +235,19 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
     return ret;
 }
 
+#ifndef COMPAT
+static int __init firmware_init(void)
+{
+    memcpy(edd.mbr_signature, edd_mbr_sig_buf, sizeof(edd.mbr_signature));
+    memcpy(edd.edd_info, eddbuf, sizeof(edd.edd_info));
+    edd.mbr_signature_nr = edd_mbr_sig_nr_buf;
+    edd.edd_info_nr = eddnr;
+
+    return 0;
+}
+__initcall(firmware_init);
+#endif
+
 /*
  * Local variables:
  * mode: C
Index: 2007-02-27/xen/include/public/platform.h
===================================================================
--- 2007-02-27.orig/xen/include/public/platform.h       2007-02-22 
16:14:25.000000000 +0100
+++ 2007-02-27/xen/include/public/platform.h    2007-02-21 14:51:00.000000000 
+0100
@@ -114,6 +114,35 @@ struct xenpf_platform_quirk {
 typedef struct xenpf_platform_quirk xenpf_platform_quirk_t;
 DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t);
 
+#define XENPF_firmware_info       50
+#define XEN_FW_DISK_INFO          1 /* from int 13 AH=08 */
+#define XEN_FW_EDD_INFO           2 /* from int 13 AH=41 */
+#define XEN_FW_EDD_PARAMS         3 /* from int 13 AH=48 */
+#define XEN_FW_MBR_SIGNATURE      4
+struct xenpf_firmware_info {
+    /* IN variables. */
+    uint32_t type;
+    uint32_t index;
+    /* OUT variables. */
+    union {
+        struct {
+            uint16_t max_cylinder;
+            uint8_t max_head;
+            uint8_t sectors_per_track;
+        } disk_info;
+        struct {
+            uint8_t device;
+            uint8_t version;
+            uint16_t interface;
+        } edd_info;
+        /* first uint16_t of buffer must be set to buffer size */
+        XEN_GUEST_HANDLE(void) edd_params;
+        uint32_t mbr_signature;
+    } u;
+};
+typedef struct xenpf_firmware_info xenpf_firmware_info_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t);
+
 struct xen_platform_op {
     uint32_t cmd;
     uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -124,6 +153,7 @@ struct xen_platform_op {
         struct xenpf_read_memtype      read_memtype;
         struct xenpf_microcode_update  microcode;
         struct xenpf_platform_quirk    platform_quirk;
+        struct xenpf_firmware_info     firmware_info;
         uint8_t                        pad[128];
     } u;
 };
Index: 2007-02-27/xen/include/xen/edd.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2007-02-27/xen/include/xen/edd.h    2007-02-21 12:19:19.000000000 +0100
@@ -0,0 +1,193 @@
+/*
+ * xen/include/linux/edd.h
+ *  Copyright (C) 2002, 2003, 2004 Dell Inc.
+ *  by Matt Domsch <Matt_Domsch@xxxxxxxx>
+ *  Adopted for Xen (C) 2007 Novell, Inc.
+ *  by Jan Beulich <jbeulich@xxxxxxxxxx>
+ *
+ * structures and definitions for the int 13h, ax={41,48}h
+ * BIOS Enhanced Disk Drive Services
+ * This is based on the T13 group document D1572 Revision 0 (August 14 2002)
+ * available at http://www.t13.org/docs2002/d1572r0.pdf.  It is
+ * very similar to D1484 Revision 3 http://www.t13.org/docs2002/d1484r3.pdf 
+ *
+ * In a nutshell, arch/{i386,x86_64}/boot/setup.S populates a scratch
+ * table in the boot_params that contains a list of BIOS-enumerated
+ * boot devices.
+ * In arch/{i386,x86_64}/kernel/setup.c, this information is
+ * transferred into the edd structure, and in drivers/firmware/edd.c, that
+ * information is used to identify BIOS boot disk.  The code in setup.S
+ * is very sensitive to the size of these structures.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation
+ *
+ * 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.
+ *
+ */
+#ifndef _XEN_EDD_H
+#define _XEN_EDD_H
+
+#define EDDMAXNR 6             /* number of edd_info structs starting at 
eddbuf */
+#define EDDEXTSIZE 8           /* change these if you muck with the structures 
*/
+#define EDDPARMSIZE 74
+#define CHECKEXTENSIONSPRESENT 0x41
+#define GETDEVICEPARAMETERS 0x48
+#define LEGACYGETDEVICEPARAMETERS 0x08
+#define EDDMAGIC1 0x55AA
+#define EDDMAGIC2 0xAA55
+
+
+#define READ_SECTORS 0x02         /* int13 AH=0x02 is READ_SECTORS command */
+#define EDD_MBR_SIG_OFFSET 0x1B8  /* offset of signature in the MBR */
+#define EDD_MBR_SIG_MAX 16        /* max number of signatures to store */
+#define EDD_CL_EQUALS   0x3d646465     /* "edd=" */
+#define EDD_CL_OFF      0x666f         /* "of" for off  */
+#define EDD_CL_SKIP     0x6b73         /* "sk" for skipmbr */
+#define EDD_CL_ON       0x6e6f        /* "on" for on */
+
+#ifndef __ASSEMBLY__
+
+#define EDD_EXT_FIXED_DISK_ACCESS           (1 << 0)
+#define EDD_EXT_DEVICE_LOCKING_AND_EJECTING (1 << 1)
+#define EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT (1 << 2)
+#define EDD_EXT_64BIT_EXTENSIONS            (1 << 3)
+
+#define EDD_INFO_DMA_BOUNDARY_ERROR_TRANSPARENT (1 << 0)
+#define EDD_INFO_GEOMETRY_VALID                (1 << 1)
+#define EDD_INFO_REMOVABLE                     (1 << 2)
+#define EDD_INFO_WRITE_VERIFY                  (1 << 3)
+#define EDD_INFO_MEDIA_CHANGE_NOTIFICATION     (1 << 4)
+#define EDD_INFO_LOCKABLE                      (1 << 5)
+#define EDD_INFO_NO_MEDIA_PRESENT              (1 << 6)
+#define EDD_INFO_USE_INT13_FN50                (1 << 7)
+
+struct edd_device_params {
+       u16 length;
+       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;     /* = 44 */
+       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));
+
+struct edd_info {
+       u8 device;
+       u8 version;
+       u16 interface_support;
+       u16 legacy_max_cylinder;
+       u8 legacy_max_head;
+       u8 legacy_sectors_per_track;
+       struct edd_device_params params;
+} __attribute__ ((packed));
+
+struct edd {
+       unsigned int mbr_signature[EDD_MBR_SIG_MAX];
+       struct edd_info edd_info[EDDMAXNR];
+       unsigned char mbr_signature_nr;
+       unsigned char edd_info_nr;
+};
+
+extern unsigned char eddnr, edd_mbr_sig_nr_buf;
+extern struct edd_info eddbuf[];
+extern unsigned int edd_mbr_sig_buf[];
+
+#endif                         /*!__ASSEMBLY__ */
+
+#endif                         /* _XEN_EDD_H */
Index: 2007-02-27/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
===================================================================
--- 2007-02-27.orig/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c   
2007-02-21 16:57:23.000000000 +0100
+++ 2007-02-27/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c        
2007-02-21 14:24:52.000000000 +0100
@@ -66,6 +66,7 @@
 #include <xen/interface/physdev.h>
 #include <xen/interface/memory.h>
 #include <xen/features.h>
+#include <xen/firmware.h>
 #include <xen/xencons.h>
 #include <setup_arch.h>
 #include <bios_ebda.h>
@@ -740,6 +741,7 @@ struct edd edd;
 #ifdef CONFIG_EDD_MODULE
 EXPORT_SYMBOL(edd);
 #endif
+#ifndef CONFIG_XEN
 /**
  * copy_edd() - Copy the BIOS EDD information
  *              from boot_params into a safe place.
@@ -752,6 +754,7 @@ static inline void copy_edd(void)
      edd.mbr_signature_nr = EDD_MBR_SIG_NR;
      edd.edd_info_nr = EDD_NR;
 }
+#endif
 #else
 static inline void copy_edd(void)
 {
Index: 2007-02-27/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c
===================================================================
--- 2007-02-27.orig/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c 
2007-02-21 16:57:23.000000000 +0100
+++ 2007-02-27/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c      
2007-02-21 14:25:07.000000000 +0100
@@ -71,6 +71,7 @@
 #include <asm/hypervisor.h>
 #include <xen/interface/nmi.h>
 #include <xen/features.h>
+#include <xen/firmware.h>
 #include <xen/xencons.h>
 #define PFN_UP(x)       (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 #define PFN_PHYS(x)     ((x) << PAGE_SHIFT)
@@ -534,6 +535,7 @@ struct edd edd;
 #ifdef CONFIG_EDD_MODULE
 EXPORT_SYMBOL(edd);
 #endif
+#ifndef CONFIG_XEN
 /**
  * copy_edd() - Copy the BIOS EDD information
  *              from boot_params into a safe place.
@@ -546,6 +548,7 @@ static inline void copy_edd(void)
      edd.mbr_signature_nr = EDD_MBR_SIG_NR;
      edd.edd_info_nr = EDD_NR;
 }
+#endif
 #else
 static inline void copy_edd(void)
 {
Index: 2007-02-27/linux-2.6-xen-sparse/drivers/firmware/Kconfig
===================================================================
--- 2007-02-27.orig/linux-2.6-xen-sparse/drivers/firmware/Kconfig       
2007-02-21 16:57:23.000000000 +0100
+++ 2007-02-27/linux-2.6-xen-sparse/drivers/firmware/Kconfig    2007-02-21 
14:19:11.000000000 +0100
@@ -8,7 +8,6 @@ menu "Firmware Drivers"
 config EDD
        tristate "BIOS Enhanced Disk Drive calls determine boot disk"
        depends on !IA64
-       depends on !XEN
        help
          Say Y or M here if you want to enable BIOS Enhanced Disk Drive
          Services real mode BIOS calls to determine which disk
Index: 2007-02-27/linux-2.6-xen-sparse/drivers/xen/core/Makefile
===================================================================
--- 2007-02-27.orig/linux-2.6-xen-sparse/drivers/xen/core/Makefile      
2007-02-21 16:57:42.000000000 +0100
+++ 2007-02-27/linux-2.6-xen-sparse/drivers/xen/core/Makefile   2007-02-21 
17:02:28.000000000 +0100
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-obj-y := evtchn.o gnttab.o features.o
+obj-y := evtchn.o gnttab.o features.o firmware.o
 
 obj-$(CONFIG_PROC_FS)          += xen_proc.o
 obj-$(CONFIG_SYSFS)            += hypervisor_sysfs.o
Index: 2007-02-27/linux-2.6-xen-sparse/drivers/xen/core/firmware.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2007-02-27/linux-2.6-xen-sparse/drivers/xen/core/firmware.c 2007-02-21 
17:09:28.000000000 +0100
@@ -0,0 +1,61 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/edd.h>
+#include <xen/interface/platform.h>
+#include <asm/hypervisor.h>
+
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+void __init copy_edd(void)
+{
+       int ret;
+       xen_platform_op_t op;
+
+       if (!is_initial_xendomain())
+               return;
+
+       op.cmd = XENPF_firmware_info;
+
+       for (op.u.firmware_info.index = 0, ret = 0;
+            ret != -ESRCH && ret != -ENOSYS && edd.edd_info_nr < EDDMAXNR;
+            ++op.u.firmware_info.index) {
+               struct edd_info *info = edd.edd_info + edd.edd_info_nr;
+
+               op.u.firmware_info.type = XEN_FW_EDD_INFO;
+               ret = HYPERVISOR_platform_op(&op);
+               if (ret)
+                       continue;
+               info->device            = op.u.firmware_info.u.edd_info.device;
+               info->version           = op.u.firmware_info.u.edd_info.version;
+               info->interface_support = 
op.u.firmware_info.u.edd_info.interface;
+
+               op.u.firmware_info.type = XEN_FW_DISK_INFO;
+               ret = HYPERVISOR_platform_op(&op);
+               if (ret)
+                       continue;
+               info->legacy_max_cylinder      = 
op.u.firmware_info.u.disk_info.max_cylinder;
+               info->legacy_max_head          = 
op.u.firmware_info.u.disk_info.max_head;
+               info->legacy_sectors_per_track = 
op.u.firmware_info.u.disk_info.sectors_per_track;
+
+               op.u.firmware_info.type = XEN_FW_EDD_PARAMS;
+               info->params.length = sizeof(info->params);
+               set_xen_guest_handle(op.u.firmware_info.u.edd_params, 
&info->params);
+               ret = HYPERVISOR_platform_op(&op);
+               if (ret)
+                       continue;
+
+               ++edd.edd_info_nr;
+       }
+
+       op.u.firmware_info.type = XEN_FW_MBR_SIGNATURE;
+       for (op.u.firmware_info.index = 0, ret = 0;
+            ret != -ESRCH && ret != -ENOSYS && edd.mbr_signature_nr < 
EDD_MBR_SIG_MAX;
+            ++op.u.firmware_info.index) {
+
+               ret = HYPERVISOR_platform_op(&op);
+               if (ret)
+                       continue;
+               edd.mbr_signature[edd.mbr_signature_nr++] = 
op.u.firmware_info.u.mbr_signature;
+       }
+}
+#endif
Index: 2007-02-27/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
===================================================================
--- 
2007-02-27.orig/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h  
    2007-02-21 16:57:23.000000000
+0100
+++ 2007-02-27/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h   
2007-02-21 14:59:20.000000000 +0100
@@ -209,6 +209,14 @@ HYPERVISOR_dom0_op(
 }
 
 static inline int
+HYPERVISOR_platform_op(
+       xen_platform_op_t *platform_op)
+{
+       platform_op->interface_version = XENPF_INTERFACE_VERSION;
+       return _hypercall1(int, platform_op, platform_op);
+}
+
+static inline int
 HYPERVISOR_set_debugreg(
        int reg, unsigned long value)
 {
Index: 
2007-02-27/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h
===================================================================
--- 
2007-02-27.orig/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h
    2007-02-21 16:57:23.000000000
+0100
+++ 2007-02-27/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h 
2007-02-21 15:01:06.000000000
+0100
@@ -212,6 +212,14 @@ HYPERVISOR_dom0_op(
 }
 
 static inline int
+HYPERVISOR_platform_op(
+       xen_platform_op_t *platform_op)
+{
+       platform_op->interface_version = XENPF_INTERFACE_VERSION;
+       return _hypercall1(int, platform_op, platform_op);
+}
+
+static inline int
 HYPERVISOR_set_debugreg(
        int reg, unsigned long value)
 {
Index: 2007-02-27/linux-2.6-xen-sparse/include/xen/firmware.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2007-02-27/linux-2.6-xen-sparse/include/xen/firmware.h      2007-02-21 
14:26:55.000000000 +0100
@@ -0,0 +1,6 @@
+#ifndef __XEN_FIRMWARE_H__
+#define __XEN_FIRMWARE_H__
+
+void copy_edd(void);
+
+#endif /* __XEN_FIRMWARE_H__ */



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel