summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2011-10-25 19:54:06 +0000
committerjhb <jhb@FreeBSD.org>2011-10-25 19:54:06 +0000
commit6ba84c2a5198e1c20d36490ee71f17efabc13995 (patch)
tree06cf6965e6209f7b27624f4d32c4fb74e6480b75 /sys/boot
parent465469fc74999a15659ae97644b7fcd86a664cd5 (diff)
downloadFreeBSD-src-6ba84c2a5198e1c20d36490ee71f17efabc13995.zip
FreeBSD-src-6ba84c2a5198e1c20d36490ee71f17efabc13995.tar.gz
- 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
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/i386/common/drv.c27
-rw-r--r--sys/boot/i386/common/edd.h110
-rw-r--r--sys/boot/i386/libi386/Makefile3
-rw-r--r--sys/boot/i386/libi386/bioscd.c4
-rw-r--r--sys/boot/i386/libi386/biosdisk.c7
-rw-r--r--sys/boot/i386/libi386/libi386.h8
6 files changed, 128 insertions, 31 deletions
diff --git a/sys/boot/i386/common/drv.c b/sys/boot/i386/common/drv.c
index 661047c..52933d5 100644
--- a/sys/boot/i386/common/drv.c
+++ b/sys/boot/i386/common/drv.c
@@ -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, daddr_t lba, unsigned nblk)
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);
diff --git a/sys/boot/i386/common/edd.h b/sys/boot/i386/common/edd.h
new file mode 100644
index 0000000..a33ce8f
--- /dev/null
+++ b/sys/boot/i386/common/edd.h
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 2011 Advanced Computing Technologies LLC
+ * Written by: John H. Baldwin <jhb@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_ */
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile
index 7940471..de32c91 100644
--- a/sys/boot/i386/libi386/Makefile
+++ b/sys/boot/i386/libi386/Makefile
@@ -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
diff --git a/sys/boot/i386/libi386/bioscd.c b/sys/boot/i386/libi386/bioscd.c
index 3c2c211..dd50f7d 100644
--- a/sys/boot/i386/libi386/bioscd.c
+++ b/sys/boot/i386/libi386/bioscd.c
@@ -325,9 +325,9 @@ bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
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;
diff --git a/sys/boot/i386/libi386/biosdisk.c b/sys/boot/i386/libi386/biosdisk.c
index 340dd6f..533ce44 100644
--- a/sys/boot/i386/libi386/biosdisk.c
+++ b/sys/boot/i386/libi386/biosdisk.c
@@ -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 dblk, int blks, caddr_t dest, int write)
{
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;
diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h
index ebf1b4c..8cfe922 100644
--- a/sys/boot/i386/libi386/libi386.h
+++ b/sys/boot/i386/libi386/libi386.h
@@ -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);
OpenPOWER on IntegriCloud