drv.c revision 308915
1/*-
2 * Copyright (c) 1998 Robert Nordier
3 * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms are freely
7 * permitted provided that the above copyright notice and this
8 * paragraph and the following disclaimer are duplicated in all
9 * such forms.
10 *
11 * This software is provided "AS IS" and without any express or
12 * implied warranties, including, without limitation, the implied
13 * warranties of merchantability and fitness for a particular
14 * purpose.
15 */
16
17#include <sys/cdefs.h>
18__FBSDID("$FreeBSD: stable/10/sys/boot/i386/common/drv.c 308915 2016-11-21 10:14:36Z avg $");
19
20#include <sys/param.h>
21
22#include <btxv86.h>
23
24#include "rbx.h"
25#include "util.h"
26#include "drv.h"
27#include "edd.h"
28#ifdef USE_XREAD
29#include "xreadorg.h"
30#endif
31
32#ifdef GPT
33static struct edd_params params;
34
35uint64_t
36drvsize(struct dsk *dskp)
37{
38
39	params.len = sizeof(struct edd_params);
40	v86.ctl = V86_FLAGS;
41	v86.addr = 0x13;
42	v86.eax = 0x4800;
43	v86.edx = dskp->drive;
44	v86.ds = VTOPSEG(&params);
45	v86.esi = VTOPOFF(&params);
46	v86int();
47	if (V86_CY(v86.efl)) {
48		printf("error %u\n", v86.eax >> 8 & 0xff);
49		return (0);
50	}
51	return (params.sectors);
52}
53#endif	/* GPT */
54
55#ifndef USE_XREAD
56static struct edd_packet packet;
57#endif
58
59int
60drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
61{
62	static unsigned c = 0x2d5c7c2f;
63
64	if (!OPT_CHECK(RBX_QUIET))
65		printf("%c\b", c = c << 8 | c >> 24);
66#ifndef USE_XREAD
67	packet.len = sizeof(struct edd_packet);
68	packet.count = nblk;
69	packet.off = VTOPOFF(buf);
70	packet.seg = VTOPSEG(buf);
71	packet.lba = lba;
72	v86.ctl = V86_FLAGS;
73	v86.addr = 0x13;
74	v86.eax = 0x4200;
75	v86.edx = dskp->drive;
76	v86.ds = VTOPSEG(&packet);
77	v86.esi = VTOPOFF(&packet);
78#else	/* USE_XREAD */
79	v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
80	v86.addr = XREADORG;		/* call to xread in boot1 */
81	v86.es = VTOPSEG(buf);
82	v86.eax = lba;
83	v86.ebx = VTOPOFF(buf);
84	v86.ecx = lba >> 32;
85	v86.edx = nblk << 8 | dskp->drive;
86#endif	/* USE_XREAD */
87	v86int();
88	if (V86_CY(v86.efl)) {
89		printf("%s: error %u lba %u\n",
90		    BOOTPROG, v86.eax >> 8 & 0xff, lba);
91		return (-1);
92	}
93	return (0);
94}
95
96#if defined(GPT) || defined(ZFS)
97int
98drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
99{
100
101	packet.len = sizeof(struct edd_packet);
102	packet.count = nblk;
103	packet.off = VTOPOFF(buf);
104	packet.seg = VTOPSEG(buf);
105	packet.lba = lba;
106	v86.ctl = V86_FLAGS;
107	v86.addr = 0x13;
108	v86.eax = 0x4300;
109	v86.edx = dskp->drive;
110	v86.ds = VTOPSEG(&packet);
111	v86.esi = VTOPOFF(&packet);
112	v86int();
113	if (V86_CY(v86.efl)) {
114		printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba);
115		return (-1);
116	}
117	return (0);
118}
119#endif	/* GPT || ZFS */
120