]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - sys/boot/i386/common/drv.c
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / sys / boot / i386 / common / drv.c
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$");
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
37 uint64_t
38 drvsize(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
62 static 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
71 int
72 drvread(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
109 int
110 drvwrite(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 */