drv.c revision 221177
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: head/sys/boot/i386/common/drv.c 221177 2011-04-28 17:44:24Z jhb $");
19
20#include <sys/param.h>
21
22#include <machine/psl.h>
23
24#include <btxv86.h>
25
26#include "rbx.h"
27#include "util.h"
28#include "drv.h"
29#ifdef USE_XREAD
30#include "xreadorg.h"
31#endif
32
33#define	V86_CY(x)	((x) & PSL_C)
34#define	V86_ZR(x)	((x) & PSL_Z)
35
36#ifdef GPT
37uint64_t
38drvsize(struct dsk *dskp)
39{
40	unsigned char params[0x42];
41	uint64_t sectors;
42
43	*(uint32_t *)params = sizeof(params);
44
45	v86.ctl = V86_FLAGS;
46	v86.addr = 0x13;
47	v86.eax = 0x4800;
48	v86.edx = dskp->drive;
49	v86.ds = VTOPSEG(params);
50	v86.esi = VTOPOFF(params);
51	v86int();
52	if (V86_CY(v86.efl)) {
53		printf("error %u\n", v86.eax >> 8 & 0xff);
54		return (0);
55	}
56	memcpy(&sectors, params + 0x10, sizeof(sectors));
57	return (sectors);
58}
59#endif	/* GPT */
60
61#ifndef USE_XREAD
62static struct {
63	uint16_t	len;
64	uint16_t	count;
65	uint16_t	off;
66	uint16_t	seg;
67	uint64_t	lba;
68} packet;
69#endif
70
71int
72drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
73{
74	static unsigned c = 0x2d5c7c2f;
75
76	if (!OPT_CHECK(RBX_QUIET))
77		printf("%c\b", c = c << 8 | c >> 24);
78#ifndef USE_XREAD
79	packet.len = 0x10;
80	packet.count = nblk;
81	packet.off = VTOPOFF(buf);
82	packet.seg = VTOPSEG(buf);
83	packet.lba = lba;
84	v86.ctl = V86_FLAGS;
85	v86.addr = 0x13;
86	v86.eax = 0x4200;
87	v86.edx = dskp->drive;
88	v86.ds = VTOPSEG(&packet);
89	v86.esi = VTOPOFF(&packet);
90#else	/* USE_XREAD */
91	v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
92	v86.addr = XREADORG;		/* call to xread in boot1 */
93	v86.es = VTOPSEG(buf);
94	v86.eax = lba;
95	v86.ebx = VTOPOFF(buf);
96	v86.ecx = lba >> 32;
97	v86.edx = nblk << 8 | dskp->drive;
98#endif	/* USE_XREAD */
99	v86int();
100	if (V86_CY(v86.efl)) {
101		printf("%s: error %u lba %u\n",
102		    BOOTPROG, v86.eax >> 8 & 0xff, lba);
103		return (-1);
104	}
105	return (0);
106}
107
108#ifdef GPT
109int
110drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
111{
112
113	packet.len = 0x10;
114	packet.count = nblk;
115	packet.off = VTOPOFF(buf);
116	packet.seg = VTOPSEG(buf);
117	packet.lba = lba;
118	v86.ctl = V86_FLAGS;
119	v86.addr = 0x13;
120	v86.eax = 0x4300;
121	v86.edx = dskp->drive;
122	v86.ds = VTOPSEG(&packet);
123	v86.esi = VTOPOFF(&packet);
124	v86int();
125	if (V86_CY(v86.efl)) {
126		printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba);
127		return (-1);
128	}
129	return (0);
130}
131#endif	/* GPT */
132