Author: jhb
Date: Tue Oct 25 19:54:06 2011
New Revision: 226748
URL: http://svn.freebsd.org/changeset/base/226748

Log:
  - Add a new header for the x86 boot code that defines various structures
    and constants related to the BIOS Enhanced Disk Drive Specification.
  - Use this header instead of magic numbers and various duplicate structure
    definitions for doing I/O.
  - Use an actual structure for the request to fetch drive parameters in
    drvsize() rather than a gross hack of a char array with some magic
    size.  While here, change drvsize() to only pass the 1.1 version of
    the structure and not request device path information.  If we want
    device path information you have to set the length of the device
    path information as an input (along with probably checking the actual
    EDD version to see which size one should use as the device path
    information is variable-length).  This fixes data smashing problems
    from passing an EDD 3 structure to BIOSes supporting EDD 4.
  
  Reviewed by:  avg
  Tested by:    Dennis Koegel  dk neveragain.de
  MFC after:    1 week

Added:
  head/sys/boot/i386/common/edd.h   (contents, props changed)
Modified:
  head/sys/boot/i386/common/drv.c
  head/sys/boot/i386/libi386/Makefile
  head/sys/boot/i386/libi386/bioscd.c
  head/sys/boot/i386/libi386/biosdisk.c
  head/sys/boot/i386/libi386/libi386.h

Modified: head/sys/boot/i386/common/drv.c
==============================================================================
--- head/sys/boot/i386/common/drv.c     Tue Oct 25 19:47:28 2011        
(r226747)
+++ head/sys/boot/i386/common/drv.c     Tue Oct 25 19:54:06 2011        
(r226748)
@@ -24,43 +24,36 @@ __FBSDID("$FreeBSD$");
 #include "rbx.h"
 #include "util.h"
 #include "drv.h"
+#include "edd.h"
 #ifdef USE_XREAD
 #include "xreadorg.h"
 #endif
 
 #ifdef GPT
+static struct edd_params params;
+
 uint64_t
 drvsize(struct dsk *dskp)
 {
-       unsigned char params[0x42];
-       uint64_t sectors;
-
-       *(uint32_t *)params = sizeof(params);
 
+       params.len = sizeof(struct edd_params);
        v86.ctl = V86_FLAGS;
        v86.addr = 0x13;
        v86.eax = 0x4800;
        v86.edx = dskp->drive;
-       v86.ds = VTOPSEG(params);
-       v86.esi = VTOPOFF(params);
+       v86.ds = VTOPSEG(&params);
+       v86.esi = VTOPOFF(&params);
        v86int();
        if (V86_CY(v86.efl)) {
                printf("error %u\n", v86.eax >> 8 & 0xff);
                return (0);
        }
-       memcpy(&sectors, params + 0x10, sizeof(sectors));
-       return (sectors);
+       return (params.sectors);
 }
 #endif /* GPT */
 
 #ifndef USE_XREAD
-static struct {
-       uint16_t        len;
-       uint16_t        count;
-       uint16_t        off;
-       uint16_t        seg;
-       uint64_t        lba;
-} packet;
+static struct edd_packet packet;
 #endif
 
 int
@@ -71,7 +64,7 @@ drvread(struct dsk *dskp, void *buf, dad
        if (!OPT_CHECK(RBX_QUIET))
                printf("%c\b", c = c << 8 | c >> 24);
 #ifndef USE_XREAD
-       packet.len = 0x10;
+       packet.len = sizeof(struct edd_packet);
        packet.count = nblk;
        packet.off = VTOPOFF(buf);
        packet.seg = VTOPSEG(buf);
@@ -105,7 +98,7 @@ int
 drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
 {
 
-       packet.len = 0x10;
+       packet.len = sizeof(struct edd_packet);
        packet.count = nblk;
        packet.off = VTOPOFF(buf);
        packet.seg = VTOPSEG(buf);

Added: head/sys/boot/i386/common/edd.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/boot/i386/common/edd.h     Tue Oct 25 19:54:06 2011        
(r226748)
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 2011 Advanced Computing Technologies LLC
+ * Written by: John H. Baldwin <j...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef        _EDD_H_
+#define        _EDD_H_
+
+/* Supported interfaces for "Check Extensions Present". */
+#define        EDD_INTERFACE_FIXED_DISK        0x01
+#define        EDD_INTERFACE_EJECT             0x02
+#define        EDD_INTERFACE_EDD               0x04
+
+struct edd_packet {
+       uint16_t        len;
+       uint16_t        count;
+       uint16_t        off;
+       uint16_t        seg;
+       uint64_t        lba;
+};
+
+struct edd_packet_v3 {
+       uint16_t        len;
+       uint16_t        count;
+       uint16_t        off;
+       uint16_t        seg;
+       uint64_t        lba;
+       uint64_t        phys_addr;
+};
+
+struct edd_params {
+       uint16_t        len;
+       uint16_t        flags;
+       uint32_t        cylinders;
+       uint32_t        heads;
+       uint32_t        sectors_per_track;
+       uint64_t        sectors;
+       uint16_t        sector_size;
+       uint16_t        edd_params_seg;
+       uint16_t        edd_params_off;
+};
+
+struct edd_device_path_v3 {
+       uint16_t        key;
+       uint8_t         len;
+       uint8_t         reserved[3];
+       char            host_bus[4];
+       char            interface[8];
+       uint64_t        interface_path;
+       uint64_t        device_path;
+       uint8_t         reserved2[1];
+       uint8_t         checksum;
+};
+
+struct edd_params_v3 {
+       struct edd_params params;
+       struct edd_device_path_v3 device_path;
+};
+
+struct edd_device_path_v4 {
+       uint16_t        key;
+       uint8_t         len;
+       uint8_t         reserved[3];
+       char            host_bus[4];
+       char            interface[8];
+       uint64_t        interface_path;
+       uint64_t        device_path[2];
+       uint8_t         reserved2[1];
+       uint8_t         checksum;
+};
+
+struct edd_params_v4 {
+       struct edd_params params;
+       struct edd_device_path_v4 device_path;
+};
+
+#define        EDD_FLAGS_DMA_BOUNDARY_HANDLING         0x0001
+#define        EDD_FLAGS_REMOVABLE_MEDIA               0x0002
+#define        EDD_FLAGS_WRITE_VERIFY                  0x0004
+#define        EDD_FLAGS_MEDIA_CHANGE_NOTIFICATION     0x0008
+#define        EDD_FLAGS_LOCKABLE_MEDIA                0x0010
+#define        EDD_FLAGS_NO_MEDIA_PRESENT              0x0020
+
+#define        EDD_DEVICE_PATH_KEY     0xbedd
+
+#endif /* !_EDD_H_ */

Modified: head/sys/boot/i386/libi386/Makefile
==============================================================================
--- head/sys/boot/i386/libi386/Makefile Tue Oct 25 19:47:28 2011        
(r226747)
+++ head/sys/boot/i386/libi386/Makefile Tue Oct 25 19:54:06 2011        
(r226748)
@@ -47,7 +47,8 @@ CFLAGS+= -DTERM_EMU
 # XXX: make alloca() useable
 CFLAGS+= -Dalloca=__builtin_alloca
 
-CFLAGS+=       -I${.CURDIR}/../../common -I${.CURDIR}/../btx/lib \
+CFLAGS+=       -I${.CURDIR}/../../common -I${.CURDIR}/../common \
+               -I${.CURDIR}/../btx/lib \
                -I${.CURDIR}/../../../contrib/dev/acpica/include \
                -I${.CURDIR}/../../.. -I.
 # the location of libstand

Modified: head/sys/boot/i386/libi386/bioscd.c
==============================================================================
--- head/sys/boot/i386/libi386/bioscd.c Tue Oct 25 19:47:28 2011        
(r226747)
+++ head/sys/boot/i386/libi386/bioscd.c Tue Oct 25 19:54:06 2011        
(r226748)
@@ -325,9 +325,9 @@ bc_read(int unit, daddr_t dblk, int blks
                                v86int();
                        }
 
-                       packet.len = 0x10;
+                       packet.len = sizeof(struct edd_packet);
                        packet.count = x;
-                       packet.offset = VTOPOFF(xp);
+                       packet.off = VTOPOFF(xp);
                        packet.seg = VTOPSEG(xp);
                        packet.lba = dblk;
                        v86.ctl = V86_FLAGS;

Modified: head/sys/boot/i386/libi386/biosdisk.c
==============================================================================
--- head/sys/boot/i386/libi386/biosdisk.c       Tue Oct 25 19:47:28 2011        
(r226747)
+++ head/sys/boot/i386/libi386/biosdisk.c       Tue Oct 25 19:54:06 2011        
(r226748)
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
 
 #include <bootstrap.h>
 #include <btxv86.h>
+#include <edd.h>
 #include "libi386.h"
 
 #define BIOS_NUMDRIVES         0x475
@@ -266,7 +267,7 @@ bd_int13probe(struct bdinfo *bd)
        v86int();
        if (!(V86_CY(v86.efl)) &&                       /* carry clear */
            ((v86.ebx & 0xffff) == 0xaa55) &&           /* signature */
-           (v86.ecx & 0x1)) {                          /* packets mode ok */
+           (v86.ecx & EDD_INTERFACE_FIXED_DISK)) {     /* packets mode ok */
            bd->bd_flags |= BD_MODEEDD1;
            if ((v86.eax & 0xff00) >= 0x3000)
                bd->bd_flags |= BD_MODEEDD3;
@@ -1134,9 +1135,9 @@ bd_edd_io(struct open_disk *od, daddr_t 
 {
     static struct edd_packet packet;
 
-    packet.len = 0x10;
+    packet.len = sizeof(struct edd_packet);
     packet.count = blks;
-    packet.offset = VTOPOFF(dest);
+    packet.off = VTOPOFF(dest);
     packet.seg = VTOPSEG(dest);
     packet.lba = dblk;
     v86.ctl = V86_FLAGS;

Modified: head/sys/boot/i386/libi386/libi386.h
==============================================================================
--- head/sys/boot/i386/libi386/libi386.h        Tue Oct 25 19:47:28 2011        
(r226747)
+++ head/sys/boot/i386/libi386/libi386.h        Tue Oct 25 19:54:06 2011        
(r226748)
@@ -52,14 +52,6 @@ struct i386_devdesc
     } d_kind;
 };
 
-struct edd_packet {
-    uint16_t   len;
-    uint16_t   count;
-    uint16_t   offset;
-    uint16_t   seg;
-    uint64_t   lba;
-};
-                 
 int    i386_getdev(void **vdev, const char *devspec, const char **path);
 char   *i386_fmtdev(void *vdev);
 int    i386_setcurrdev(struct env_var *ev, int flags, const void *value);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to