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 typedef struct {
6*529c1f20SDavid du Colombier UINT64 Revision;
7*529c1f20SDavid du Colombier void *Open;
8*529c1f20SDavid du Colombier void *Close;
9*529c1f20SDavid du Colombier void *Delete;
10*529c1f20SDavid du Colombier void *Read;
11*529c1f20SDavid du Colombier void *Write;
12*529c1f20SDavid du Colombier void *GetPosition;
13*529c1f20SDavid du Colombier void *SetPosition;
14*529c1f20SDavid du Colombier void *GetInfo;
15*529c1f20SDavid du Colombier void *SetInfo;
16*529c1f20SDavid du Colombier void *Flush;
17*529c1f20SDavid du Colombier void *OpenEx;
18*529c1f20SDavid du Colombier void *ReadEx;
19*529c1f20SDavid du Colombier void *WriteEx;
20*529c1f20SDavid du Colombier void *FlushEx;
21*529c1f20SDavid du Colombier } EFI_FILE_PROTOCOL;
22*529c1f20SDavid du Colombier
23*529c1f20SDavid du Colombier typedef struct {
24*529c1f20SDavid du Colombier UINT64 Revision;
25*529c1f20SDavid du Colombier void *OpenVolume;
26*529c1f20SDavid du Colombier } EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
27*529c1f20SDavid du Colombier
28*529c1f20SDavid du Colombier static
29*529c1f20SDavid du Colombier EFI_GUID EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID = {
30*529c1f20SDavid du Colombier 0x0964e5b22, 0x6459, 0x11d2,
31*529c1f20SDavid du Colombier 0x8e, 0x39, 0x00, 0xa0,
32*529c1f20SDavid du Colombier 0xc9, 0x69, 0x72, 0x3b,
33*529c1f20SDavid du Colombier };
34*529c1f20SDavid du Colombier
35*529c1f20SDavid du Colombier static EFI_GUID EFI_LOADED_IMAGE_PROTOCOL_GUID = {
36*529c1f20SDavid du Colombier 0x5b1b31a1, 0x9562, 0x11d2,
37*529c1f20SDavid du Colombier 0x8e, 0x3f, 0x00, 0xa0,
38*529c1f20SDavid du Colombier 0xc9, 0x69, 0x72, 0x3b,
39*529c1f20SDavid du Colombier };
40*529c1f20SDavid du Colombier
41*529c1f20SDavid du Colombier static
42*529c1f20SDavid du Colombier EFI_FILE_PROTOCOL *fsroot;
43*529c1f20SDavid du Colombier
44*529c1f20SDavid du Colombier static void
towpath(CHAR16 * w,int nw,char * s)45*529c1f20SDavid du Colombier towpath(CHAR16 *w, int nw, char *s)
46*529c1f20SDavid du Colombier {
47*529c1f20SDavid du Colombier int i;
48*529c1f20SDavid du Colombier
49*529c1f20SDavid du Colombier for(i=0; *s && i<nw-1; i++){
50*529c1f20SDavid du Colombier *w = *s++;
51*529c1f20SDavid du Colombier if(*w == '/')
52*529c1f20SDavid du Colombier *w = '\\';
53*529c1f20SDavid du Colombier w++;
54*529c1f20SDavid du Colombier }
55*529c1f20SDavid du Colombier *w = 0;
56*529c1f20SDavid du Colombier }
57*529c1f20SDavid du Colombier
58*529c1f20SDavid du Colombier static void*
fsopen(char * name)59*529c1f20SDavid du Colombier fsopen(char *name)
60*529c1f20SDavid du Colombier {
61*529c1f20SDavid du Colombier CHAR16 wname[MAXPATH];
62*529c1f20SDavid du Colombier EFI_FILE_PROTOCOL *fp;
63*529c1f20SDavid du Colombier
64*529c1f20SDavid du Colombier if(fsroot == nil)
65*529c1f20SDavid du Colombier return nil;
66*529c1f20SDavid du Colombier
67*529c1f20SDavid du Colombier towpath(wname, MAXPATH, name);
68*529c1f20SDavid du Colombier
69*529c1f20SDavid du Colombier fp = nil;
70*529c1f20SDavid du Colombier if(eficall(fsroot->Open, fsroot, &fp, wname, (UINT64)1, (UINT64)1))
71*529c1f20SDavid du Colombier return nil;
72*529c1f20SDavid du Colombier return fp;
73*529c1f20SDavid du Colombier }
74*529c1f20SDavid du Colombier
75*529c1f20SDavid du Colombier static int
fsread(void * f,void * data,int len)76*529c1f20SDavid du Colombier fsread(void *f, void *data, int len)
77*529c1f20SDavid du Colombier {
78*529c1f20SDavid du Colombier UINTN size;
79*529c1f20SDavid du Colombier
80*529c1f20SDavid du Colombier size = len > 4096 ? 4096 : len;
81*529c1f20SDavid du Colombier if(eficall(((EFI_FILE_PROTOCOL*)f)->Read, f, &size, data))
82*529c1f20SDavid du Colombier return 0;
83*529c1f20SDavid du Colombier return (int)size;
84*529c1f20SDavid du Colombier }
85*529c1f20SDavid du Colombier
86*529c1f20SDavid du Colombier static void
fsclose(void * f)87*529c1f20SDavid du Colombier fsclose(void *f)
88*529c1f20SDavid du Colombier {
89*529c1f20SDavid du Colombier eficall(((EFI_FILE_PROTOCOL*)f)->Close, f);
90*529c1f20SDavid du Colombier }
91*529c1f20SDavid du Colombier
92*529c1f20SDavid du Colombier int
fsinit(void ** pf)93*529c1f20SDavid du Colombier fsinit(void **pf)
94*529c1f20SDavid du Colombier {
95*529c1f20SDavid du Colombier EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs;
96*529c1f20SDavid du Colombier EFI_LOADED_IMAGE_PROTOCOL *image;
97*529c1f20SDavid du Colombier EFI_FILE_PROTOCOL *root;
98*529c1f20SDavid du Colombier EFI_HANDLE *Handles;
99*529c1f20SDavid du Colombier void *f;
100*529c1f20SDavid du Colombier UINTN Count;
101*529c1f20SDavid du Colombier int i;
102*529c1f20SDavid du Colombier
103*529c1f20SDavid du Colombier image = nil;
104*529c1f20SDavid du Colombier
105*529c1f20SDavid du Colombier /* locate kernel and plan9.ini by deriving a fs protocol
106*529c1f20SDavid du Colombier * from the device the loader was read from.
107*529c1f20SDavid du Colombier * if that fails, fall back to old method.
108*529c1f20SDavid du Colombier */
109*529c1f20SDavid du Colombier if(eficall(ST->BootServices->HandleProtocol, IH,
110*529c1f20SDavid du Colombier &EFI_LOADED_IMAGE_PROTOCOL_GUID, &image) == 0 &&
111*529c1f20SDavid du Colombier eficall(ST->BootServices->HandleProtocol, image->DeviceHandle,
112*529c1f20SDavid du Colombier &EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, &fs) == 0 &&
113*529c1f20SDavid du Colombier eficall(fs->OpenVolume, fs, &root) == 0){
114*529c1f20SDavid du Colombier
115*529c1f20SDavid du Colombier fsroot = root;
116*529c1f20SDavid du Colombier f = fsopen("/plan9.ini");
117*529c1f20SDavid du Colombier if(f != nil){
118*529c1f20SDavid du Colombier if(pf != nil)
119*529c1f20SDavid du Colombier *pf = f;
120*529c1f20SDavid du Colombier else
121*529c1f20SDavid du Colombier fsclose(f);
122*529c1f20SDavid du Colombier
123*529c1f20SDavid du Colombier goto gotit;
124*529c1f20SDavid du Colombier }
125*529c1f20SDavid du Colombier }
126*529c1f20SDavid du Colombier
127*529c1f20SDavid du Colombier Count = 0;
128*529c1f20SDavid du Colombier Handles = nil;
129*529c1f20SDavid du Colombier if(eficall(ST->BootServices->LocateHandleBuffer,
130*529c1f20SDavid du Colombier ByProtocol, &EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, nil, &Count, &Handles))
131*529c1f20SDavid du Colombier return -1;
132*529c1f20SDavid du Colombier
133*529c1f20SDavid du Colombier /*
134*529c1f20SDavid du Colombier * assuming the ESP is the first entry in the handle buffer, so go backwards
135*529c1f20SDavid du Colombier * to scan for plan9.ini in other (9fat) filesystems first. if nothing is found
136*529c1f20SDavid du Colombier * we'll be defaulting to the ESP.
137*529c1f20SDavid du Colombier */
138*529c1f20SDavid du Colombier fsroot = nil;
139*529c1f20SDavid du Colombier for(i=Count-1; i>=0; i--){
140*529c1f20SDavid du Colombier root = nil;
141*529c1f20SDavid du Colombier fs = nil;
142*529c1f20SDavid du Colombier if(eficall(ST->BootServices->HandleProtocol,
143*529c1f20SDavid du Colombier Handles[i], &EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, &fs))
144*529c1f20SDavid du Colombier continue;
145*529c1f20SDavid du Colombier if(eficall(fs->OpenVolume, fs, &root))
146*529c1f20SDavid du Colombier continue;
147*529c1f20SDavid du Colombier fsroot = root;
148*529c1f20SDavid du Colombier f = fsopen("/plan9.ini");
149*529c1f20SDavid du Colombier if(f != nil){
150*529c1f20SDavid du Colombier if(pf != nil)
151*529c1f20SDavid du Colombier *pf = f;
152*529c1f20SDavid du Colombier else
153*529c1f20SDavid du Colombier fsclose(f);
154*529c1f20SDavid du Colombier break;
155*529c1f20SDavid du Colombier }
156*529c1f20SDavid du Colombier }
157*529c1f20SDavid du Colombier if(fsroot == nil)
158*529c1f20SDavid du Colombier return -1;
159*529c1f20SDavid du Colombier
160*529c1f20SDavid du Colombier gotit:
161*529c1f20SDavid du Colombier read = fsread;
162*529c1f20SDavid du Colombier close = fsclose;
163*529c1f20SDavid du Colombier open = fsopen;
164*529c1f20SDavid du Colombier
165*529c1f20SDavid du Colombier return 0;
166*529c1f20SDavid du Colombier }
167