1*529c1f20SDavid du Colombier #include <u.h>
2*529c1f20SDavid du Colombier #include "fns.h"
3*529c1f20SDavid du Colombier #include "efi.h"
4*529c1f20SDavid du Colombier
5*529c1f20SDavid du Colombier enum {
6*529c1f20SDavid du Colombier Sectsz = 0x800,
7*529c1f20SDavid du Colombier Dirsz = 33,
8*529c1f20SDavid du Colombier };
9*529c1f20SDavid du Colombier
10*529c1f20SDavid du Colombier typedef struct Extend Extend;
11*529c1f20SDavid du Colombier typedef struct Dir Dir;
12*529c1f20SDavid du Colombier
13*529c1f20SDavid du Colombier struct Extend
14*529c1f20SDavid du Colombier {
15*529c1f20SDavid du Colombier ulong lba;
16*529c1f20SDavid du Colombier ulong len;
17*529c1f20SDavid du Colombier uchar *rp;
18*529c1f20SDavid du Colombier uchar *ep;
19*529c1f20SDavid du Colombier uchar buf[Sectsz];
20*529c1f20SDavid du Colombier };
21*529c1f20SDavid du Colombier
22*529c1f20SDavid du Colombier struct Dir
23*529c1f20SDavid du Colombier {
24*529c1f20SDavid du Colombier uchar dirlen;
25*529c1f20SDavid du Colombier uchar extlen;
26*529c1f20SDavid du Colombier
27*529c1f20SDavid du Colombier uchar lba[8];
28*529c1f20SDavid du Colombier uchar len[8];
29*529c1f20SDavid du Colombier
30*529c1f20SDavid du Colombier uchar date[7];
31*529c1f20SDavid du Colombier
32*529c1f20SDavid du Colombier uchar flags[3];
33*529c1f20SDavid du Colombier
34*529c1f20SDavid du Colombier uchar seq[4];
35*529c1f20SDavid du Colombier
36*529c1f20SDavid du Colombier uchar namelen;
37*529c1f20SDavid du Colombier };
38*529c1f20SDavid du Colombier
39*529c1f20SDavid du Colombier typedef struct {
40*529c1f20SDavid du Colombier UINT32 MediaId;
41*529c1f20SDavid du Colombier
42*529c1f20SDavid du Colombier BOOLEAN RemovableMedia;
43*529c1f20SDavid du Colombier BOOLEAN MediaPresent;
44*529c1f20SDavid du Colombier BOOLEAN LogicalPartition;
45*529c1f20SDavid du Colombier BOOLEAN ReadOnly;
46*529c1f20SDavid du Colombier
47*529c1f20SDavid du Colombier BOOLEAN WriteCaching;
48*529c1f20SDavid du Colombier BOOLEAN Pad[3];
49*529c1f20SDavid du Colombier
50*529c1f20SDavid du Colombier UINT32 BlockSize;
51*529c1f20SDavid du Colombier UINT32 IoAlign;
52*529c1f20SDavid du Colombier UINT64 LastBlock;
53*529c1f20SDavid du Colombier } EFI_BLOCK_IO_MEDIA;
54*529c1f20SDavid du Colombier
55*529c1f20SDavid du Colombier typedef struct {
56*529c1f20SDavid du Colombier UINT64 Revision;
57*529c1f20SDavid du Colombier EFI_BLOCK_IO_MEDIA *Media;
58*529c1f20SDavid du Colombier void *Reset;
59*529c1f20SDavid du Colombier void *ReadBlocks;
60*529c1f20SDavid du Colombier void *WriteBlocks;
61*529c1f20SDavid du Colombier void *FlushBlocks;
62*529c1f20SDavid du Colombier } EFI_BLOCK_IO_PROTOCOL;
63*529c1f20SDavid du Colombier
64*529c1f20SDavid du Colombier static EFI_GUID
65*529c1f20SDavid du Colombier EFI_BLOCK_IO_PROTOCOL_GUID = {
66*529c1f20SDavid du Colombier 0x964e5b21, 0x6459, 0x11d2,
67*529c1f20SDavid du Colombier 0x8e, 0x39, 0x00, 0xa0,
68*529c1f20SDavid du Colombier 0xc9, 0x69, 0x72, 0x3b,
69*529c1f20SDavid du Colombier };
70*529c1f20SDavid du Colombier
71*529c1f20SDavid du Colombier static EFI_BLOCK_IO_PROTOCOL *bio;
72*529c1f20SDavid du Colombier
73*529c1f20SDavid du Colombier static int
readsect(ulong lba,void * buf)74*529c1f20SDavid du Colombier readsect(ulong lba, void *buf)
75*529c1f20SDavid du Colombier {
76*529c1f20SDavid du Colombier lba *= Sectsz/bio->Media->BlockSize;
77*529c1f20SDavid du Colombier return eficall(bio->ReadBlocks, bio, (UINTN)bio->Media->MediaId, (UINT64)lba, (UINTN)Sectsz, buf);
78*529c1f20SDavid du Colombier }
79*529c1f20SDavid du Colombier
80*529c1f20SDavid du Colombier static int
isoread(void * f,void * data,int len)81*529c1f20SDavid du Colombier isoread(void *f, void *data, int len)
82*529c1f20SDavid du Colombier {
83*529c1f20SDavid du Colombier Extend *ex = f;
84*529c1f20SDavid du Colombier
85*529c1f20SDavid du Colombier if(ex->len > 0 && ex->rp >= ex->ep)
86*529c1f20SDavid du Colombier if(readsect(ex->lba++, ex->rp = ex->buf))
87*529c1f20SDavid du Colombier return -1;
88*529c1f20SDavid du Colombier if(ex->len < len)
89*529c1f20SDavid du Colombier len = ex->len;
90*529c1f20SDavid du Colombier if(len > (ex->ep - ex->rp))
91*529c1f20SDavid du Colombier len = ex->ep - ex->rp;
92*529c1f20SDavid du Colombier memmove(data, ex->rp, len);
93*529c1f20SDavid du Colombier ex->rp += len;
94*529c1f20SDavid du Colombier ex->len -= len;
95*529c1f20SDavid du Colombier return len;
96*529c1f20SDavid du Colombier }
97*529c1f20SDavid du Colombier
98*529c1f20SDavid du Colombier void
isoclose(void * f)99*529c1f20SDavid du Colombier isoclose(void *f)
100*529c1f20SDavid du Colombier {
101*529c1f20SDavid du Colombier Extend *ex = f;
102*529c1f20SDavid du Colombier
103*529c1f20SDavid du Colombier ex->lba = 0;
104*529c1f20SDavid du Colombier ex->len = 0;
105*529c1f20SDavid du Colombier ex->rp = ex->ep = ex->buf + Sectsz;
106*529c1f20SDavid du Colombier }
107*529c1f20SDavid du Colombier
108*529c1f20SDavid du Colombier static int
isowalk(Extend * ex,char * path)109*529c1f20SDavid du Colombier isowalk(Extend *ex, char *path)
110*529c1f20SDavid du Colombier {
111*529c1f20SDavid du Colombier char name[MAXPATH], c, *end;
112*529c1f20SDavid du Colombier int i;
113*529c1f20SDavid du Colombier Dir d;
114*529c1f20SDavid du Colombier
115*529c1f20SDavid du Colombier isoclose(ex);
116*529c1f20SDavid du Colombier
117*529c1f20SDavid du Colombier /* find pvd */
118*529c1f20SDavid du Colombier for(i=0x10; i<0x1000; i++){
119*529c1f20SDavid du Colombier if(readsect(i, ex->buf))
120*529c1f20SDavid du Colombier return -1;
121*529c1f20SDavid du Colombier if(memcmp(ex->buf, "\001CD001\001", 7) == 0)
122*529c1f20SDavid du Colombier goto Foundpvd;
123*529c1f20SDavid du Colombier }
124*529c1f20SDavid du Colombier return -1;
125*529c1f20SDavid du Colombier Foundpvd:
126*529c1f20SDavid du Colombier ex->lba = *((ulong*)(ex->buf + 156 + 2));
127*529c1f20SDavid du Colombier ex->len = *((ulong*)(ex->buf + 156 + 10));
128*529c1f20SDavid du Colombier if(*path == 0)
129*529c1f20SDavid du Colombier return 0;
130*529c1f20SDavid du Colombier
131*529c1f20SDavid du Colombier for(;;){
132*529c1f20SDavid du Colombier if(read(ex, &d.dirlen, 1) != 1)
133*529c1f20SDavid du Colombier break;
134*529c1f20SDavid du Colombier if(d.dirlen == 0)
135*529c1f20SDavid du Colombier continue; /* zero padding to next sector */
136*529c1f20SDavid du Colombier if(read(ex, &d.dirlen + 1, Dirsz-1) != Dirsz-1)
137*529c1f20SDavid du Colombier break;
138*529c1f20SDavid du Colombier if(read(ex, name, d.namelen) != d.namelen)
139*529c1f20SDavid du Colombier break;
140*529c1f20SDavid du Colombier i = d.dirlen - (Dirsz + d.namelen);
141*529c1f20SDavid du Colombier while(i-- > 0){
142*529c1f20SDavid du Colombier if(read(ex, &c, 1) != 1)
143*529c1f20SDavid du Colombier break;
144*529c1f20SDavid du Colombier }
145*529c1f20SDavid du Colombier for(i=0; i<d.namelen; i++){
146*529c1f20SDavid du Colombier c = name[i];
147*529c1f20SDavid du Colombier if(c >= 'A' && c <= 'Z'){
148*529c1f20SDavid du Colombier c -= 'A';
149*529c1f20SDavid du Colombier c += 'a';
150*529c1f20SDavid du Colombier }
151*529c1f20SDavid du Colombier name[i] = c;
152*529c1f20SDavid du Colombier }
153*529c1f20SDavid du Colombier name[i] = 0;
154*529c1f20SDavid du Colombier while(*path == '/')
155*529c1f20SDavid du Colombier path++;
156*529c1f20SDavid du Colombier if((end = strchr(path, '/')) == 0)
157*529c1f20SDavid du Colombier end = path + strlen(path);
158*529c1f20SDavid du Colombier i = end - path;
159*529c1f20SDavid du Colombier if(d.namelen == i && memcmp(name, path, i) == 0){
160*529c1f20SDavid du Colombier ex->rp = ex->ep;
161*529c1f20SDavid du Colombier ex->lba = *((ulong*)d.lba);
162*529c1f20SDavid du Colombier ex->len = *((ulong*)d.len);
163*529c1f20SDavid du Colombier if(*end == 0)
164*529c1f20SDavid du Colombier return 0;
165*529c1f20SDavid du Colombier else if(d.flags[0] & 2){
166*529c1f20SDavid du Colombier path = end;
167*529c1f20SDavid du Colombier continue;
168*529c1f20SDavid du Colombier }
169*529c1f20SDavid du Colombier break;
170*529c1f20SDavid du Colombier }
171*529c1f20SDavid du Colombier }
172*529c1f20SDavid du Colombier return -1;
173*529c1f20SDavid du Colombier }
174*529c1f20SDavid du Colombier
175*529c1f20SDavid du Colombier static void*
isoopen(char * path)176*529c1f20SDavid du Colombier isoopen(char *path)
177*529c1f20SDavid du Colombier {
178*529c1f20SDavid du Colombier static uchar buf[sizeof(Extend)+8];
179*529c1f20SDavid du Colombier Extend *ex = (Extend*)((uintptr)(buf+7)&~7);
180*529c1f20SDavid du Colombier
181*529c1f20SDavid du Colombier if(isowalk(ex, path))
182*529c1f20SDavid du Colombier return nil;
183*529c1f20SDavid du Colombier return ex;
184*529c1f20SDavid du Colombier }
185*529c1f20SDavid du Colombier
186*529c1f20SDavid du Colombier int
isoinit(void ** fp)187*529c1f20SDavid du Colombier isoinit(void **fp)
188*529c1f20SDavid du Colombier {
189*529c1f20SDavid du Colombier EFI_BLOCK_IO_MEDIA *media;
190*529c1f20SDavid du Colombier EFI_HANDLE *Handles;
191*529c1f20SDavid du Colombier UINTN Count;
192*529c1f20SDavid du Colombier int i;
193*529c1f20SDavid du Colombier
194*529c1f20SDavid du Colombier bio = nil;
195*529c1f20SDavid du Colombier Count = 0;
196*529c1f20SDavid du Colombier Handles = nil;
197*529c1f20SDavid du Colombier if(eficall(ST->BootServices->LocateHandleBuffer,
198*529c1f20SDavid du Colombier ByProtocol, &EFI_BLOCK_IO_PROTOCOL_GUID, nil, &Count, &Handles))
199*529c1f20SDavid du Colombier return -1;
200*529c1f20SDavid du Colombier
201*529c1f20SDavid du Colombier for(i=0; i<Count; i++){
202*529c1f20SDavid du Colombier bio = nil;
203*529c1f20SDavid du Colombier if(eficall(ST->BootServices->HandleProtocol,
204*529c1f20SDavid du Colombier Handles[i], &EFI_BLOCK_IO_PROTOCOL_GUID, &bio))
205*529c1f20SDavid du Colombier continue;
206*529c1f20SDavid du Colombier
207*529c1f20SDavid du Colombier media = bio->Media;
208*529c1f20SDavid du Colombier if(media != nil
209*529c1f20SDavid du Colombier && media->MediaPresent
210*529c1f20SDavid du Colombier && media->LogicalPartition == 0
211*529c1f20SDavid du Colombier && media->BlockSize != 0
212*529c1f20SDavid du Colombier && isoopen("") != nil)
213*529c1f20SDavid du Colombier goto Found;
214*529c1f20SDavid du Colombier }
215*529c1f20SDavid du Colombier return -1;
216*529c1f20SDavid du Colombier
217*529c1f20SDavid du Colombier Found:
218*529c1f20SDavid du Colombier open = isoopen;
219*529c1f20SDavid du Colombier read = isoread;
220*529c1f20SDavid du Colombier close = isoclose;
221*529c1f20SDavid du Colombier
222*529c1f20SDavid du Colombier if(fp != nil)
223*529c1f20SDavid du Colombier *fp = isoopen("/cfg/plan9.ini");
224*529c1f20SDavid du Colombier
225*529c1f20SDavid du Colombier return 0;
226*529c1f20SDavid du Colombier }
227