1 /*
2 * boot driver for BIOS devices with partitions
3 * devbios must be called first
4 */
5 #include "u.h"
6 #include "lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 #include "ureg.h"
12 #include "error.h"
13
14 #include "sd.h"
15 #include "fs.h"
16
17 long biosread(Fs *, void *, long);
18 vlong biosseek(Fs *fs, vlong off);
19
20 extern SDifc sdbiosifc;
21 extern int onlybios0, biosinited;
22
23 int
biosverify(SDunit *)24 biosverify(SDunit* )
25 {
26 if (onlybios0 || !biosinited)
27 return 0;
28 return 1;
29 }
30
31 int
biosonline(SDunit * unit)32 biosonline(SDunit* unit)
33 {
34 if (onlybios0 || !biosinited || !unit)
35 return 0;
36 unit->sectors = 1UL << 30; /* a bunch */
37 unit->secsize = 512; /* conventional */
38 return 1;
39 }
40
41 static int
biosrio(SDreq * r)42 biosrio(SDreq* r)
43 {
44 int nb;
45 long got;
46 vlong len, off;
47 uchar *p;
48 Fs fs; /* just for fs->dev, which is zero */
49
50 if (onlybios0 || !biosinited)
51 return SDeio;
52 /*
53 * Most SCSI commands can be passed unchanged except for
54 * the padding on the end. The few which require munging
55 * are not used internally. Mode select/sense(6) could be
56 * converted to the 10-byte form but it's not worth the
57 * effort. Read/write(6) are easy.
58 */
59 r->rlen = 0;
60 r->status = SDok;
61 switch(r->cmd[0]){
62 case 0x08: /* read */
63 case 0x28: /* read */
64 if (r->cmd[0] == 0x08)
65 panic("biosrio: 0x08 read op\n");
66 off = r->cmd[2]<<24 | r->cmd[3]<<16 | r->cmd[4]<<8 | r->cmd[5];
67 nb = r->cmd[7]<<8 | r->cmd[8]; /* often 4 */
68 USED(nb); /* is nb*512 == r->dlen? */
69 memset(&fs, 0, sizeof fs);
70 biosseek(&fs, off*512);
71 got = biosread(&fs, r->data, r->dlen);
72 if (got < 0)
73 r->status = SDeio;
74 else
75 r->rlen = got;
76 break;
77 case 0x0A: /* write */
78 case 0x2A: /* write */
79 r->status = SDeio; /* boot programs don't write */
80 break;
81 case 0x25: /* read capacity */
82 /*
83 * Read capacity returns the LBA of the last sector.
84 */
85 len = r->unit->sectors - 1;
86 p = r->data;
87 *p++ = len>>24;
88 *p++ = len>>16;
89 *p++ = len>>8;
90 *p++ = len;
91 len = r->unit->secsize;
92 *p++ = len>>24;
93 *p++ = len>>16;
94 *p++ = len>>8;
95 *p = len;
96 r->data = (char *)r->data + 8;
97 return SDok;
98 case 0x9E: /* long read capacity */
99 /*
100 * Read capacity returns the LBA of the last sector.
101 */
102 len = r->unit->sectors - 1;
103 p = r->data;
104 *p++ = len>>56;
105 *p++ = len>>48;
106 *p++ = len>>40;
107 *p++ = len>>32;
108 *p++ = len>>24;
109 *p++ = len>>16;
110 *p++ = len>>8;
111 *p++ = len;
112 len = r->unit->secsize;
113 *p++ = len>>24;
114 *p++ = len>>16;
115 *p++ = len>>8;
116 *p = len;
117 r->data = (char *)r->data + 8;
118 return SDok;
119 /* ignore others */
120 }
121 return r->status;
122 }
123
124 SDev*
biosid(SDev * sdev)125 biosid(SDev* sdev)
126 {
127 for (; sdev; sdev = sdev->next)
128 if (sdev->ifc == &sdbiosifc)
129 sdev->idno = 'B';
130 return sdev;
131 }
132
133 static SDev*
biospnp(void)134 biospnp(void)
135 {
136 SDev *sdev;
137
138 /* 9pxeload can't use bios int 13 calls; they wedge the machine */
139 if (pxe || getconf("*nobiosload") != nil || onlybios0 || !biosinited)
140 return nil;
141 if((sdev = malloc(sizeof(SDev))) != nil) {
142 sdev->ifc = &sdbiosifc;
143 sdev->index = -1;
144 sdev->nunit = 1;
145 }
146 return sdev;
147 }
148
149 SDifc sdbiosifc = {
150 "bios", /* name */
151
152 biospnp, /* pnp */
153 nil, /* legacy */
154 biosid, /* id */
155 nil, /* enable */
156 nil, /* disable */
157
158 biosverify, /* verify */
159 biosonline, /* online */
160 biosrio, /* rio */
161 nil, /* rctl */
162 nil, /* wctl */
163
164 scsibio, /* bio */
165 };
166