ia64/xen-unstable

changeset 15336:699f0c429620

x86: Gather BIOS EDD info during boot.
Still needs plumbing to dom0.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Jun 12 14:03:09 2007 +0100 (2007-06-12)
parents be33028fcda5
children c56ebab69b84
files xen/arch/x86/boot/Makefile xen/arch/x86/boot/cmdline.S xen/arch/x86/boot/edd.S xen/arch/x86/boot/trampoline.S xen/arch/x86/boot/video.S xen/arch/x86/setup.c xen/include/asm-x86/edd.h
line diff
     1.1 --- a/xen/arch/x86/boot/Makefile	Tue Jun 12 11:39:51 2007 +0100
     1.2 +++ b/xen/arch/x86/boot/Makefile	Tue Jun 12 14:03:09 2007 +0100
     1.3 @@ -1,3 +1,3 @@
     1.4  obj-y += head.o
     1.5  
     1.6 -head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S video.S cmdline.S
     1.7 +head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S video.S cmdline.S edd.S
     2.1 --- a/xen/arch/x86/boot/cmdline.S	Tue Jun 12 11:39:51 2007 +0100
     2.2 +++ b/xen/arch/x86/boot/cmdline.S	Tue Jun 12 14:03:09 2007 +0100
     2.3 @@ -169,6 +169,24 @@ cmdline_parse_early:
     2.4          test    %eax,%eax
     2.5          setnz   bootsym_phys(skip_realmode)
     2.6  
     2.7 +.Lparse_edd:
     2.8 +        /* Check for 'edd=' command-line option. */
     2.9 +        movl    $sym_phys(.Ledd_opt),4(%esp)
    2.10 +        call    .Lfind_option
    2.11 +        test    %eax,%eax
    2.12 +        jz      .Lparse_edid
    2.13 +        cmpb    $'=',3(%eax)
    2.14 +        jne     .Lparse_edid
    2.15 +        add     $4,%eax
    2.16 +        movb    $2,bootsym_phys(opt_edd)  /* opt_edd=2: edd=off */
    2.17 +        cmpw    $0x666f,(%eax)            /* 0x666f == "of" */
    2.18 +        je      .Lparse_edid
    2.19 +        decb    bootsym_phys(opt_edd)     /* opt_edd=1: edd=skipmbr */
    2.20 +        cmpw    $0x6b73,(%eax)            /* 0x6b73 == "sk" */
    2.21 +        je      .Lparse_edid
    2.22 +        decb    bootsym_phys(opt_edid)    /* opt_edd=0: edd=on (default) */
    2.23 +
    2.24 +.Lparse_edid:
    2.25          /* Check for 'edid=' command-line option. */
    2.26          movl    $sym_phys(.Ledid_opt),4(%esp)
    2.27          call    .Lfind_option
    2.28 @@ -318,3 +336,5 @@ 1:      lodsw
    2.29          .asciz  "force"
    2.30  .Ledid_no:
    2.31          .asciz  "no"
    2.32 +.Ledd_opt:
    2.33 +        .asciz  "edd"
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/arch/x86/boot/edd.S	Tue Jun 12 14:03:09 2007 +0100
     3.3 @@ -0,0 +1,161 @@
     3.4 +/******************************************************************************
     3.5 + * edd.S
     3.6 + *
     3.7 + * BIOS Enhanced Disk Drive support
     3.8 + * 
     3.9 + * Copyright (C) 2002, 2003, 2004 Dell, Inc.
    3.10 + * by Matt Domsch <Matt_Domsch@dell.com> October 2002
    3.11 + * conformant to T13 Committee www.t13.org
    3.12 + *   projects 1572D, 1484D, 1386D, 1226DT
    3.13 + * disk signature read by Matt Domsch <Matt_Domsch@dell.com>
    3.14 + *      and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004
    3.15 + * legacy CHS retrieval by Patrick J. LoPresti <patl@users.sourceforge.net>
    3.16 + *      March 2004
    3.17 + * Command line option parsing, Matt Domsch, November 2004
    3.18 + *
    3.19 + * Updated and ported for Xen by Keir Fraser <keir@xensource.com> June 2007
    3.20 + */
    3.21 +
    3.22 +        .code16
    3.23 +
    3.24 +/* Offset of disc signature in the MBR. */
    3.25 +#define EDD_MBR_SIG_OFFSET      0x1B8
    3.26 +
    3.27 +/* Maximum number of EDD information structures at boot_edd_info. */
    3.28 +#define EDD_INFO_MAX            6
    3.29 +
    3.30 +/* Maximum number of MBR signatures at boot_edd_signature. */
    3.31 +#define EDD_MBR_SIG_MAX         16
    3.32 +
    3.33 +/* Size of components of EDD information structure. */
    3.34 +#define EDDEXTSIZE              8
    3.35 +#define EDDPARMSIZE             74
    3.36 +
    3.37 +get_edd:
    3.38 +        cmpb    $2, bootsym(opt_edd)            # edd=off ?
    3.39 +        je      edd_done
    3.40 +        cmpb    $1, bootsym(opt_edd)            # edd=skipmbr ?
    3.41 +        je      edd_start
    3.42 +
    3.43 +# Read the first sector of each BIOS disk device and store the 4-byte signature
    3.44 +edd_mbr_sig_start:
    3.45 +        movb    $0x80, %dl                      # from device 80
    3.46 +        movw    $bootsym(boot_edd_signature),%bx # store buffer ptr in bx
    3.47 +edd_mbr_sig_read:
    3.48 +        movl    $0xFFFFFFFF, %eax
    3.49 +        movl    %eax, (%bx)                     # assume failure
    3.50 +        pushw   %bx
    3.51 +        movb    $0x02, %ah                      # 0x02 Read Sectors
    3.52 +        movb    $1, %al                         # read 1 sector
    3.53 +        movb    $0, %dh                         # at head 0
    3.54 +        movw    $1, %cx                         # cylinder 0, sector 0
    3.55 +        pushw   %es
    3.56 +        pushw   %ds
    3.57 +        popw    %es
    3.58 +        movw    $bootsym(boot_edd_info), %bx    # disk's data goes into info
    3.59 +        pushw   %dx             # work around buggy BIOSes
    3.60 +        stc                     # work around buggy BIOSes
    3.61 +        int     $0x13
    3.62 +        sti                     # work around buggy BIOSes
    3.63 +        popw    %dx
    3.64 +        popw    %es
    3.65 +        popw    %bx
    3.66 +        jc      edd_mbr_sig_done                # on failure, we're done.
    3.67 +        cmpb    $0, %ah                         # some BIOSes do not set CF
    3.68 +        jne     edd_mbr_sig_done                # on failure, we're done.
    3.69 +        movl    bootsym(boot_edd_info)+EDD_MBR_SIG_OFFSET,%eax
    3.70 +        movl    %eax, (%bx)                     # store signature from MBR
    3.71 +        incb    bootsym(boot_edd_signature_nr)  # note that we stored something
    3.72 +        incb    %dl                             # increment to next device
    3.73 +        addw    $4, %bx                         # increment sig buffer ptr
    3.74 +        cmpb    $EDD_MBR_SIG_MAX,bootsym(boot_edd_signature_nr)
    3.75 +        jb      edd_mbr_sig_read
    3.76 +edd_mbr_sig_done:
    3.77 +
    3.78 +# Do the BIOS Enhanced Disk Drive calls
    3.79 +# This consists of two calls:
    3.80 +#    int 13h ah=41h "Check Extensions Present"
    3.81 +#    int 13h ah=48h "Get Device Parameters"
    3.82 +#    int 13h ah=08h "Legacy Get Device Parameters"
    3.83 +#
    3.84 +# A buffer of size EDD_INFO_MAX*(EDDEXTSIZE+EDDPARMSIZE) is reserved at
    3.85 +# boot_edd_info, the first four bytes of which are used to store the device
    3.86 +# number, interface support map and version results from fn41. The next four
    3.87 +# bytes are used to store the legacy cylinders, heads, and sectors from fn08.
    3.88 +# The following 74 bytes are used to store the results from fn48.
    3.89 +# This code is sensitive to the size of the structs in edd.h
    3.90 +edd_start:
    3.91 +        /* ds:si points at fn48 results. Fn41 results go immediately before. */
    3.92 +        movw    $bootsym(boot_edd_info)+EDDEXTSIZE, %si
    3.93 +        movb    $0x80, %dl                      # BIOS device 0x80
    3.94 +
    3.95 +edd_check_ext:
    3.96 +        movb    $0x41, %ah                      # 0x41 Check Extensions Present
    3.97 +        movw    $0x55AA, %bx                    # magic
    3.98 +        int     $0x13                           # make the call
    3.99 +        jc      edd_done                        # no more BIOS devices
   3.100 +
   3.101 +        cmpw    $0xAA55, %bx                    # is magic right?
   3.102 +        jne     edd_next                        # nope, next...
   3.103 +
   3.104 +        movb    %dl, %ds:-8(%si)                # store device number
   3.105 +        movb    %ah, %ds:-7(%si)                # store version
   3.106 +        movw    %cx, %ds:-6(%si)                # store extensions
   3.107 +        incb    bootsym(boot_edd_info_nr)       # note that we stored something
   3.108 +
   3.109 +edd_get_device_params:
   3.110 +        movw    $EDDPARMSIZE, %ds:(%si)         # put size
   3.111 +        movw    $0x0, %ds:2(%si)                # work around buggy BIOSes
   3.112 +        movb    $0x48, %ah                      # 0x48 Get Device Parameters
   3.113 +        int     $0x13                           # make the call
   3.114 +                                                # Don't check for fail return
   3.115 +                                                # it doesn't matter.
   3.116 +edd_get_legacy_chs:
   3.117 +        xorw    %ax, %ax
   3.118 +        movw    %ax, %ds:-4(%si)
   3.119 +        movw    %ax, %ds:-2(%si)
   3.120 +        # Ralf Brown's Interrupt List says to set ES:DI to
   3.121 +        # 0000h:0000h "to guard against BIOS bugs"
   3.122 +        pushw   %es
   3.123 +        movw    %ax, %es
   3.124 +        movw    %ax, %di
   3.125 +        pushw   %dx                             # legacy call clobbers %dl
   3.126 +        movb    $0x08, %ah                      # 0x08 Legacy Get Device Params
   3.127 +        int     $0x13                           # make the call
   3.128 +        jc      edd_legacy_done                 # failed
   3.129 +        movb    %cl, %al                        # Low 6 bits are max
   3.130 +        andb    $0x3F, %al                      #   sector number
   3.131 +        movb    %al, %ds:-1(%si)                # Record max sect
   3.132 +        movb    %dh, %ds:-2(%si)                # Record max head number
   3.133 +        movb    %ch, %al                        # Low 8 bits of max cyl
   3.134 +        shr     $6, %cl
   3.135 +        movb    %cl, %ah                        # High 2 bits of max cyl
   3.136 +        movw    %ax, %ds:-4(%si)
   3.137 +
   3.138 +edd_legacy_done:
   3.139 +        popw    %dx
   3.140 +        popw    %es
   3.141 +        movw    %si, %ax                        # increment si
   3.142 +        addw    $EDDPARMSIZE+EDDEXTSIZE, %ax
   3.143 +        movw    %ax, %si
   3.144 +
   3.145 +edd_next:
   3.146 +        incb    %dl                             # increment to next device
   3.147 +        cmpb    $EDD_INFO_MAX,bootsym(boot_edd_info_nr)
   3.148 +        jb      edd_check_ext
   3.149 +
   3.150 +edd_done:
   3.151 +        ret
   3.152 +
   3.153 +opt_edd:
   3.154 +        .byte   0                               # edd=on/off/skipmbr
   3.155 +
   3.156 +.globl  boot_edd_info_nr, boot_edd_signature_nr
   3.157 +boot_edd_info_nr:
   3.158 +        .byte   0
   3.159 +boot_edd_signature_nr:
   3.160 +        .byte   0
   3.161 +boot_edd_signature:
   3.162 +        .fill   EDD_MBR_SIG_MAX*4,1,0
   3.163 +boot_edd_info:
   3.164 +        .fill   512,1,0                         # big enough for a disc sector
     4.1 --- a/xen/arch/x86/boot/trampoline.S	Tue Jun 12 11:39:51 2007 +0100
     4.2 +++ b/xen/arch/x86/boot/trampoline.S	Tue Jun 12 14:03:09 2007 +0100
     4.3 @@ -142,17 +142,19 @@ 1:      mov     $(BOOT_TRAMPOLINE>>4),%a
     4.4          mov     %ax,%es
     4.5          mov     %ax,%ss
     4.6  
     4.7 -        /* Stack grows down from 0x9200. Initialise IDT and enable irqs. */
     4.8 -        mov     $0x2000,%sp
     4.9 +        /* Stack grows down from 0x93000. Initialise IDT and enable irqs. */
    4.10 +        mov     $0x3000,%sp
    4.11          lidt    bootsym(rm_idt)
    4.12          sti
    4.13  
    4.14          /*
    4.15           * Do real-mode work:
    4.16           *  1. Get memory map.
    4.17 -         *  2. Set video mode.
    4.18 +         *  2. Get Enhanced Disk Drive (EDD) information.
    4.19 +         *  3. Set video mode.
    4.20           */
    4.21          call    get_memory_map
    4.22 +        call    get_edd
    4.23          call    video
    4.24  
    4.25          /* Disable irqs before returning to protected mode. */
    4.26 @@ -187,4 +189,5 @@ skip_realmode:
    4.27  rm_idt: .word   256*4-1, 0, 0
    4.28  
    4.29  #include "mem.S"
    4.30 +#include "edd.S"
    4.31  #include "video.S"
     5.1 --- a/xen/arch/x86/boot/video.S	Tue Jun 12 11:39:51 2007 +0100
     5.2 +++ b/xen/arch/x86/boot/video.S	Tue Jun 12 14:03:09 2007 +0100
     5.3 @@ -15,7 +15,7 @@
     5.4  
     5.5  #include "video.h"
     5.6  
     5.7 -#define modelist (0x2000)
     5.8 +#define modelist (0x3000)
     5.9  
    5.10  /* Retrieve Extended Display Identification Data. */
    5.11  #define CONFIG_FIRMWARE_EDID
     6.1 --- a/xen/arch/x86/setup.c	Tue Jun 12 11:39:51 2007 +0100
     6.2 +++ b/xen/arch/x86/setup.c	Tue Jun 12 14:03:09 2007 +0100
     6.3 @@ -34,6 +34,7 @@
     6.4  #include <asm/e820.h>
     6.5  #include <acm/acm_hooks.h>
     6.6  #include <xen/kexec.h>
     6.7 +#include <asm/edd.h>
     6.8  
     6.9  #if defined(CONFIG_X86_64)
    6.10  #define BOOTSTRAP_DIRECTMAP_END (1UL << 32)
    6.11 @@ -490,6 +491,12 @@ void __init __start_xen(multiboot_info_t
    6.12          }
    6.13      }
    6.14  
    6.15 +    printk("Disc information:\n");
    6.16 +    printk(" Found %d MBR signatures\n",
    6.17 +           bootsym(boot_edd_signature_nr));
    6.18 +    printk(" Found %d EDD information structures\n",
    6.19 +           bootsym(boot_edd_info_nr));
    6.20 +
    6.21      /* Check that we have at least one Multiboot module. */
    6.22      if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
    6.23          EARLY_FAIL("dom0 kernel not specified. "
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen/include/asm-x86/edd.h	Tue Jun 12 14:03:09 2007 +0100
     7.3 @@ -0,0 +1,44 @@
     7.4 +/******************************************************************************
     7.5 + * edd.h
     7.6 + * 
     7.7 + * Copyright (C) 2002, 2003, 2004 Dell Inc.
     7.8 + * by Matt Domsch <Matt_Domsch@dell.com>
     7.9 + *
    7.10 + * structures and definitions for the int 13h, ax={41,48}h
    7.11 + * BIOS Enhanced Disk Drive Services
    7.12 + * This is based on the T13 group document D1572 Revision 0 (August 14 2002)
    7.13 + * available at http://www.t13.org/docs2002/d1572r0.pdf.  It is
    7.14 + * very similar to D1484 Revision 3 http://www.t13.org/docs2002/d1484r3.pdf
    7.15 + *
    7.16 + * This program is free software; you can redistribute it and/or modify
    7.17 + * it under the terms of the GNU General Public License v2.0 as published by
    7.18 + * the Free Software Foundation
    7.19 + *
    7.20 + * This program is distributed in the hope that it will be useful,
    7.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.23 + * GNU General Public License for more details.
    7.24 + */
    7.25 +
    7.26 +#ifndef __XEN_EDD_H__
    7.27 +#define __XEN_EDD_H__
    7.28 +
    7.29 +struct edd_info {
    7.30 +    /* Int13, Fn48: Check Extensions Present. */
    7.31 +    u8 device;                   /* %dl: device */
    7.32 +    u8 version;                  /* %ah: major version */
    7.33 +    u16 interface_support;       /* %cx: interface support bitmap */
    7.34 +    /* Int13, Fn08: Legacy Get Device Parameters. */
    7.35 +    u16 legacy_max_cylinder;     /* %cl[7:6]:%ch: maximum cylinder number */
    7.36 +    u8 legacy_max_head;          /* %dh: maximum head number */
    7.37 +    u8 legacy_sectors_per_track; /* %cl[5:0]: maximum sector number */
    7.38 +    /* Int13, Fn41: Get Device Parameters */
    7.39 +    u8 edd_device_params[74];    /* as filled into %ds:%si */
    7.40 +} __attribute__ ((packed));
    7.41 +
    7.42 +extern u32 boot_edd_signature[];
    7.43 +extern u8 boot_edd_signature_nr;
    7.44 +extern struct edd_info boot_edd_info[];
    7.45 +extern u8 boot_edd_info_nr;
    7.46 +
    7.47 +#endif /* __XEN_EDD_H__ */