[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86: Gather BIOS EDD info during boot.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1181653389 -3600
# Node ID 699f0c4296204557dee30c399ed304e677b8f6f4
# Parent  be33028fcda596d6ebdca89bbb0331a1e3b417ae
x86: Gather BIOS EDD info during boot.
Still needs plumbing to dom0.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/boot/Makefile     |    2 
 xen/arch/x86/boot/cmdline.S    |   20 +++++
 xen/arch/x86/boot/edd.S        |  161 +++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/boot/trampoline.S |    9 +-
 xen/arch/x86/boot/video.S      |    2 
 xen/arch/x86/setup.c           |    7 +
 xen/include/asm-x86/edd.h      |   44 +++++++++++
 7 files changed, 240 insertions(+), 5 deletions(-)

diff -r be33028fcda5 -r 699f0c429620 xen/arch/x86/boot/Makefile
--- a/xen/arch/x86/boot/Makefile        Tue Jun 12 11:39:51 2007 +0100
+++ b/xen/arch/x86/boot/Makefile        Tue Jun 12 14:03:09 2007 +0100
@@ -1,3 +1,3 @@ obj-y += head.o
 obj-y += head.o
 
-head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S video.S cmdline.S
+head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S video.S cmdline.S edd.S
diff -r be33028fcda5 -r 699f0c429620 xen/arch/x86/boot/cmdline.S
--- a/xen/arch/x86/boot/cmdline.S       Tue Jun 12 11:39:51 2007 +0100
+++ b/xen/arch/x86/boot/cmdline.S       Tue Jun 12 14:03:09 2007 +0100
@@ -169,6 +169,24 @@ cmdline_parse_early:
         test    %eax,%eax
         setnz   bootsym_phys(skip_realmode)
 
+.Lparse_edd:
+        /* Check for 'edd=' command-line option. */
+        movl    $sym_phys(.Ledd_opt),4(%esp)
+        call    .Lfind_option
+        test    %eax,%eax
+        jz      .Lparse_edid
+        cmpb    $'=',3(%eax)
+        jne     .Lparse_edid
+        add     $4,%eax
+        movb    $2,bootsym_phys(opt_edd)  /* opt_edd=2: edd=off */
+        cmpw    $0x666f,(%eax)            /* 0x666f == "of" */
+        je      .Lparse_edid
+        decb    bootsym_phys(opt_edd)     /* opt_edd=1: edd=skipmbr */
+        cmpw    $0x6b73,(%eax)            /* 0x6b73 == "sk" */
+        je      .Lparse_edid
+        decb    bootsym_phys(opt_edid)    /* opt_edd=0: edd=on (default) */
+
+.Lparse_edid:
         /* Check for 'edid=' command-line option. */
         movl    $sym_phys(.Ledid_opt),4(%esp)
         call    .Lfind_option
@@ -318,3 +336,5 @@ 1:      lodsw
         .asciz  "force"
 .Ledid_no:
         .asciz  "no"
+.Ledd_opt:
+        .asciz  "edd"
diff -r be33028fcda5 -r 699f0c429620 xen/arch/x86/boot/edd.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/boot/edd.S   Tue Jun 12 14:03:09 2007 +0100
@@ -0,0 +1,161 @@
+/******************************************************************************
+ * edd.S
+ *
+ * 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
+ *
+ * Updated and ported for Xen by Keir Fraser <keir@xxxxxxxxxxxxx> June 2007
+ */
+
+        .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_edd_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
+        cmpb    $1, bootsym(opt_edd)            # edd=skipmbr ?
+        je      edd_start
+
+# 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    $bootsym(boot_edd_signature),%bx # store buffer ptr in bx
+edd_mbr_sig_read:
+        movl    $0xFFFFFFFF, %eax
+        movl    %eax, (%bx)                     # assume failure
+        pushw   %bx
+        movb    $0x02, %ah                      # 0x02 Read Sectors
+        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    $bootsym(boot_edd_info), %bx    # disk's data goes into info
+        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    bootsym(boot_edd_info)+EDD_MBR_SIG_OFFSET,%eax
+        movl    %eax, (%bx)                     # store signature from MBR
+        incb    bootsym(boot_edd_signature_nr)  # note that we stored something
+        incb    %dl                             # increment to next device
+        addw    $4, %bx                         # increment sig buffer ptr
+        cmpb    $EDD_MBR_SIG_MAX,bootsym(boot_edd_signature_nr)
+        jb      edd_mbr_sig_read
+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 EDD_INFO_MAX*(EDDEXTSIZE+EDDPARMSIZE) is reserved at
+# boot_edd_info, 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.
+# This code is sensitive to the size of the structs in edd.h
+edd_start:
+        /* ds:si points at fn48 results. Fn41 results go immediately before. */
+        movw    $bootsym(boot_edd_info)+EDDEXTSIZE, %si
+        movb    $0x80, %dl                      # BIOS device 0x80
+
+edd_check_ext:
+        movb    $0x41, %ah                      # 0x41 Check Extensions Present
+        movw    $0x55AA, %bx                    # magic
+        int     $0x13                           # make the call
+        jc      edd_done                        # no more BIOS devices
+
+        cmpw    $0xAA55, %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    bootsym(boot_edd_info_nr)       # 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    $0x48, %ah                      # 0x48 Get Device Parameters
+        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    $0x08, %ah                      # 0x08 Legacy Get Device Params
+        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    $EDD_INFO_MAX,bootsym(boot_edd_info_nr)
+        jb      edd_check_ext
+
+edd_done:
+        ret
+
+opt_edd:
+        .byte   0                               # edd=on/off/skipmbr
+
+.globl  boot_edd_info_nr, boot_edd_signature_nr
+boot_edd_info_nr:
+        .byte   0
+boot_edd_signature_nr:
+        .byte   0
+boot_edd_signature:
+        .fill   EDD_MBR_SIG_MAX*4,1,0
+boot_edd_info:
+        .fill   512,1,0                         # big enough for a disc sector
diff -r be33028fcda5 -r 699f0c429620 xen/arch/x86/boot/trampoline.S
--- a/xen/arch/x86/boot/trampoline.S    Tue Jun 12 11:39:51 2007 +0100
+++ b/xen/arch/x86/boot/trampoline.S    Tue Jun 12 14:03:09 2007 +0100
@@ -142,17 +142,19 @@ 1:      mov     $(BOOT_TRAMPOLINE>>4),%a
         mov     %ax,%es
         mov     %ax,%ss
 
-        /* Stack grows down from 0x9200. Initialise IDT and enable irqs. */
-        mov     $0x2000,%sp
+        /* Stack grows down from 0x93000. Initialise IDT and enable irqs. */
+        mov     $0x3000,%sp
         lidt    bootsym(rm_idt)
         sti
 
         /*
          * Do real-mode work:
          *  1. Get memory map.
-         *  2. Set video mode.
+         *  2. Get Enhanced Disk Drive (EDD) information.
+         *  3. Set video mode.
          */
         call    get_memory_map
+        call    get_edd
         call    video
 
         /* Disable irqs before returning to protected mode. */
@@ -187,4 +189,5 @@ rm_idt: .word   256*4-1, 0, 0
 rm_idt: .word   256*4-1, 0, 0
 
 #include "mem.S"
+#include "edd.S"
 #include "video.S"
diff -r be33028fcda5 -r 699f0c429620 xen/arch/x86/boot/video.S
--- a/xen/arch/x86/boot/video.S Tue Jun 12 11:39:51 2007 +0100
+++ b/xen/arch/x86/boot/video.S Tue Jun 12 14:03:09 2007 +0100
@@ -15,7 +15,7 @@
 
 #include "video.h"
 
-#define modelist (0x2000)
+#define modelist (0x3000)
 
 /* Retrieve Extended Display Identification Data. */
 #define CONFIG_FIRMWARE_EDID
diff -r be33028fcda5 -r 699f0c429620 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Tue Jun 12 11:39:51 2007 +0100
+++ b/xen/arch/x86/setup.c      Tue Jun 12 14:03:09 2007 +0100
@@ -34,6 +34,7 @@
 #include <asm/e820.h>
 #include <acm/acm_hooks.h>
 #include <xen/kexec.h>
+#include <asm/edd.h>
 
 #if defined(CONFIG_X86_64)
 #define BOOTSTRAP_DIRECTMAP_END (1UL << 32)
@@ -490,6 +491,12 @@ void __init __start_xen(multiboot_info_t
         }
     }
 
+    printk("Disc information:\n");
+    printk(" Found %d MBR signatures\n",
+           bootsym(boot_edd_signature_nr));
+    printk(" Found %d EDD information structures\n",
+           bootsym(boot_edd_info_nr));
+
     /* Check that we have at least one Multiboot module. */
     if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
         EARLY_FAIL("dom0 kernel not specified. "
diff -r be33028fcda5 -r 699f0c429620 xen/include/asm-x86/edd.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/edd.h Tue Jun 12 14:03:09 2007 +0100
@@ -0,0 +1,44 @@
+/******************************************************************************
+ * edd.h
+ * 
+ * Copyright (C) 2002, 2003, 2004 Dell Inc.
+ * by Matt Domsch <Matt_Domsch@xxxxxxxx>
+ *
+ * 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
+ *
+ * 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__
+
+struct edd_info {
+    /* Int13, Fn48: Check Extensions Present. */
+    u8 device;                   /* %dl: device */
+    u8 version;                  /* %ah: major version */
+    u16 interface_support;       /* %cx: interface support bitmap */
+    /* Int13, Fn08: Legacy Get Device Parameters. */
+    u16 legacy_max_cylinder;     /* %cl[7:6]:%ch: maximum cylinder number */
+    u8 legacy_max_head;          /* %dh: maximum head number */
+    u8 legacy_sectors_per_track; /* %cl[5:0]: maximum sector number */
+    /* Int13, Fn41: Get Device Parameters */
+    u8 edd_device_params[74];    /* as filled into %ds:%si */
+} __attribute__ ((packed));
+
+extern u32 boot_edd_signature[];
+extern u8 boot_edd_signature_nr;
+extern struct edd_info boot_edd_info[];
+extern u8 boot_edd_info_nr;
+
+#endif /* __XEN_EDD_H__ */

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.