1 #include <u.h>
2 #include "fns.h"
3 #include "efi.h"
4
5 UINTN MK;
6 EFI_HANDLE IH;
7 EFI_SYSTEM_TABLE *ST;
8
9 void* (*open)(char *name);
10 int (*read)(void *f, void *data, int len);
11 void (*close)(void *f);
12
13 void
putc(int c)14 putc(int c)
15 {
16 CHAR16 w[2];
17
18 w[0] = c;
19 w[1] = 0;
20 eficall(ST->ConOut->OutputString, ST->ConOut, w);
21 }
22
23 int
getc(void)24 getc(void)
25 {
26 EFI_INPUT_KEY k;
27
28 if(eficall(ST->ConIn->ReadKeyStroke, ST->ConIn, &k))
29 return 0;
30 return k.UnicodeChar;
31 }
32
33 void
usleep(int us)34 usleep(int us)
35 {
36 eficall(ST->BootServices->Stall, (UINTN)us);
37 }
38
39 void
unload(void)40 unload(void)
41 {
42 eficall(ST->BootServices->ExitBootServices, IH, MK);
43 }
44
45 static void
memconf(char ** cfg)46 memconf(char **cfg)
47 {
48 static uchar memtype[EfiMaxMemoryType] = {
49 [EfiReservedMemoryType] 2,
50 [EfiLoaderCode] 1,
51 [EfiLoaderData] 1,
52 [EfiBootServicesCode] 2,
53 [EfiBootServicesData] 2,
54 [EfiRuntimeServicesCode] 2,
55 [EfiRuntimeServicesData] 2,
56 [EfiConventionalMemory] 1,
57 [EfiUnusableMemory] 2,
58 [EfiACPIReclaimMemory] 3,
59 [EfiACPIMemoryNVS] 4,
60 [EfiMemoryMappedIO] 2,
61 [EfiMemoryMappedIOPortSpace] 2,
62 [EfiPalCode] 2,
63 };
64 UINTN mapsize, entsize;
65 EFI_MEMORY_DESCRIPTOR *t;
66 uchar mapbuf[96*1024], *p, m;
67 UINT32 entvers;
68 char *s;
69
70 mapsize = sizeof(mapbuf);
71 entsize = sizeof(EFI_MEMORY_DESCRIPTOR);
72 entvers = 1;
73 if(eficall(ST->BootServices->GetMemoryMap, &mapsize, mapbuf, &MK, &entsize, &entvers))
74 return;
75
76 s = *cfg;
77 for(p = mapbuf; mapsize >= entsize; p += entsize, mapsize -= entsize){
78 t = (EFI_MEMORY_DESCRIPTOR*)p;
79
80 m = 0;
81 if(t->Type < EfiMaxMemoryType)
82 m = memtype[t->Type];
83
84 if(m == 0)
85 continue;
86
87 if(s == *cfg)
88 memmove(s, "*e820=", 6), s += 6;
89 s = hexfmt(s, 1, m), *s++ = ' ';
90 s = hexfmt(s, 16, t->PhysicalStart), *s++ = ' ';
91 s = hexfmt(s, 16, t->PhysicalStart + t->NumberOfPages * 4096ULL), *s++ = ' ';
92 }
93 *s = '\0';
94 if(s > *cfg){
95 s[-1] = '\n';
96 print(*cfg);
97 *cfg = s;
98 }
99 }
100
101 static void
acpiconf(char ** cfg)102 acpiconf(char **cfg)
103 {
104 static EFI_GUID ACPI_20_TABLE_GUID = {
105 0x8868e871, 0xe4f1, 0x11d3,
106 0xbc, 0x22, 0x00, 0x80,
107 0xc7, 0x3c, 0x88, 0x81,
108 };
109 static EFI_GUID ACPI_10_TABLE_GUID = {
110 0xeb9d2d30, 0x2d88, 0x11d3,
111 0x9a, 0x16, 0x00, 0x90,
112 0x27, 0x3f, 0xc1, 0x4d,
113 };
114 EFI_CONFIGURATION_TABLE *t;
115 uintptr pa;
116 char *s;
117 int n;
118
119 pa = 0;
120 t = ST->ConfigurationTable;
121 n = ST->NumberOfTableEntries;
122 while(--n >= 0){
123 if(memcmp(&t->VendorGuid, &ACPI_10_TABLE_GUID, sizeof(EFI_GUID)) == 0){
124 if(pa == 0)
125 pa = (uintptr)t->VendorTable;
126 } else if(memcmp(&t->VendorGuid, &ACPI_20_TABLE_GUID, sizeof(EFI_GUID)) == 0)
127 pa = (uintptr)t->VendorTable;
128 t++;
129 }
130
131 if(pa){
132 s = *cfg;
133 memmove(s, "*acpi=0x", 8), s += 8;
134 s = hexfmt(s, 0, pa), *s++ = '\n';
135 *s = '\0';
136 print(*cfg);
137 *cfg = s;
138 }
139 }
140
141
142 static int
topbit(ulong mask)143 topbit(ulong mask)
144 {
145 int bit = 0;
146
147 while(mask != 0){
148 mask >>= 1;
149 bit++;
150 }
151 return bit;
152 }
153
154 static int
lowbit(ulong mask)155 lowbit(ulong mask)
156 {
157 int bit = 0;
158
159 while((mask & 1) == 0){
160 mask >>= 1;
161 bit++;
162 }
163 return bit;
164 }
165
166 static void
screenconf(char ** cfg)167 screenconf(char **cfg)
168 {
169 static EFI_GUID EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID = {
170 0x9042a9de, 0x23dc, 0x4a38,
171 0x96, 0xfb, 0x7a, 0xde,
172 0xd0, 0x80, 0x51, 0x6a,
173 };
174 EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
175 EFI_HANDLE *Handles;
176 UINTN Count;
177
178 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
179 ulong mr, mg, mb, mx, mc;
180 int i, bits, depth;
181 char *s;
182
183 Count = 0;
184 Handles = nil;
185 if(eficall(ST->BootServices->LocateHandleBuffer,
186 ByProtocol, &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, nil, &Count, &Handles))
187 return;
188
189 for(i=0; i<Count; i++){
190 gop = nil;
191 if(eficall(ST->BootServices->HandleProtocol,
192 Handles[i], &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, &gop))
193 continue;
194
195 if(gop == nil)
196 continue;
197 if((info = gop->Mode->Info) == nil)
198 continue;
199
200 switch(info->PixelFormat){
201 default:
202 continue; /* unsupported */
203
204 case PixelRedGreenBlueReserved8BitPerColor:
205 mr = 0x000000ff;
206 mg = 0x0000ff00;
207 mb = 0x00ff0000;
208 mx = 0xff000000;
209 break;
210
211 case PixelBlueGreenRedReserved8BitPerColor:
212 mb = 0x000000ff;
213 mg = 0x0000ff00;
214 mr = 0x00ff0000;
215 mx = 0xff000000;
216 break;
217
218 case PixelBitMask:
219 mr = info->PixelInformation.RedMask;
220 mg = info->PixelInformation.GreenMask;
221 mb = info->PixelInformation.BlueMask;
222 mx = info->PixelInformation.ReservedMask;
223 break;
224 }
225
226 if((depth = topbit(mr | mg | mb | mx)) == 0)
227 continue;
228
229 /* make sure we have linear framebuffer */
230 if(gop->Mode->FrameBufferBase == 0)
231 continue;
232 if(gop->Mode->FrameBufferSize == 0)
233 continue;
234
235 goto Found;
236 }
237 return;
238
239 Found:
240 s = *cfg;
241 memmove(s, "*bootscreen=", 12), s += 12;
242 s = decfmt(s, 0, info->PixelsPerScanLine), *s++ = 'x';
243 s = decfmt(s, 0, info->VerticalResolution), *s++ = 'x';
244 s = decfmt(s, 0, depth), *s++ = ' ';
245
246 while(depth > 0){
247 if(depth == topbit(mr)){
248 mc = mr;
249 *s++ = 'r';
250 } else if(depth == topbit(mg)){
251 mc = mg;
252 *s++ = 'g';
253 } else if(depth == topbit(mb)){
254 mc = mb;
255 *s++ = 'b';
256 } else if(depth == topbit(mx)){
257 mc = mx;
258 *s++ = 'x';
259 } else {
260 break;
261 }
262 bits = depth - lowbit(mc);
263 s = decfmt(s, 0, bits);
264 depth -= bits;
265 }
266 *s++ = ' ';
267
268 *s++ = '0', *s++ = 'x';
269 s = hexfmt(s, 0, gop->Mode->FrameBufferBase), *s++ = '\n';
270 *s = '\0';
271
272 print(*cfg);
273 *cfg = s;
274 }
275
276 void
eficonfig(char ** cfg)277 eficonfig(char **cfg)
278 {
279 memconf(cfg);
280 acpiconf(cfg);
281 screenconf(cfg);
282 }
283
284 EFI_STATUS
efimain(EFI_HANDLE ih,EFI_SYSTEM_TABLE * st)285 efimain(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st)
286 {
287 char path[MAXPATH], *kern;
288 void *f;
289
290 IH = ih;
291 ST = st;
292
293 f = nil;
294 if(pxeinit(&f) && isoinit(&f) && fsinit(&f))
295 print("no boot devices\n");
296
297 for(;;){
298 kern = configure(f, path);
299 f = open(kern);
300 if(f == nil){
301 print("not found\n");
302 continue;
303 }
304 print(bootkern(f));
305 print("\n");
306 f = nil;
307 }
308 }
309