xref: /plan9-contrib/sys/src/nboot/efi/efi.c (revision 529c1f209803c78c4f2cda11b13818a57f01c872)
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