6ba84c2a51
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
120 lines
2.5 KiB
C
120 lines
2.5 KiB
C
/*-
|
|
* Copyright (c) 1998 Robert Nordier
|
|
* Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms are freely
|
|
* permitted provided that the above copyright notice and this
|
|
* paragraph and the following disclaimer are duplicated in all
|
|
* such forms.
|
|
*
|
|
* This software is provided "AS IS" and without any express or
|
|
* implied warranties, including, without limitation, the implied
|
|
* warranties of merchantability and fitness for a particular
|
|
* purpose.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <btxv86.h>
|
|
|
|
#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)
|
|
{
|
|
|
|
params.len = sizeof(struct edd_params);
|
|
v86.ctl = V86_FLAGS;
|
|
v86.addr = 0x13;
|
|
v86.eax = 0x4800;
|
|
v86.edx = dskp->drive;
|
|
v86.ds = VTOPSEG(¶ms);
|
|
v86.esi = VTOPOFF(¶ms);
|
|
v86int();
|
|
if (V86_CY(v86.efl)) {
|
|
printf("error %u\n", v86.eax >> 8 & 0xff);
|
|
return (0);
|
|
}
|
|
return (params.sectors);
|
|
}
|
|
#endif /* GPT */
|
|
|
|
#ifndef USE_XREAD
|
|
static struct edd_packet packet;
|
|
#endif
|
|
|
|
int
|
|
drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
|
|
{
|
|
static unsigned c = 0x2d5c7c2f;
|
|
|
|
if (!OPT_CHECK(RBX_QUIET))
|
|
printf("%c\b", c = c << 8 | c >> 24);
|
|
#ifndef USE_XREAD
|
|
packet.len = sizeof(struct edd_packet);
|
|
packet.count = nblk;
|
|
packet.off = VTOPOFF(buf);
|
|
packet.seg = VTOPSEG(buf);
|
|
packet.lba = lba;
|
|
v86.ctl = V86_FLAGS;
|
|
v86.addr = 0x13;
|
|
v86.eax = 0x4200;
|
|
v86.edx = dskp->drive;
|
|
v86.ds = VTOPSEG(&packet);
|
|
v86.esi = VTOPOFF(&packet);
|
|
#else /* USE_XREAD */
|
|
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
|
|
v86.addr = XREADORG; /* call to xread in boot1 */
|
|
v86.es = VTOPSEG(buf);
|
|
v86.eax = lba;
|
|
v86.ebx = VTOPOFF(buf);
|
|
v86.ecx = lba >> 32;
|
|
v86.edx = nblk << 8 | dskp->drive;
|
|
#endif /* USE_XREAD */
|
|
v86int();
|
|
if (V86_CY(v86.efl)) {
|
|
printf("%s: error %u lba %u\n",
|
|
BOOTPROG, v86.eax >> 8 & 0xff, lba);
|
|
return (-1);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
#ifdef GPT
|
|
int
|
|
drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
|
|
{
|
|
|
|
packet.len = sizeof(struct edd_packet);
|
|
packet.count = nblk;
|
|
packet.off = VTOPOFF(buf);
|
|
packet.seg = VTOPSEG(buf);
|
|
packet.lba = lba;
|
|
v86.ctl = V86_FLAGS;
|
|
v86.addr = 0x13;
|
|
v86.eax = 0x4300;
|
|
v86.edx = dskp->drive;
|
|
v86.ds = VTOPSEG(&packet);
|
|
v86.esi = VTOPOFF(&packet);
|
|
v86int();
|
|
if (V86_CY(v86.efl)) {
|
|
printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba);
|
|
return (-1);
|
|
}
|
|
return (0);
|
|
}
|
|
#endif /* GPT */
|