1 #include "efi.h"
2 #include <efi/efiprot.h>
3 #include <efi/efipciio.h>
4 #include <public/xen.h>
5 #include <xen/bitops.h>
6 #include <xen/compile.h>
7 #include <xen/ctype.h>
8 #include <xen/dmi.h>
9 #include <xen/init.h>
10 #include <xen/keyhandler.h>
11 #include <xen/lib.h>
12 #include <xen/mm.h>
13 #include <xen/multiboot.h>
14 #include <xen/pci_regs.h>
15 #include <xen/pfn.h>
16 #if EFI_PAGE_SIZE != PAGE_SIZE
17 # error Cannot use xen/pfn.h here!
18 #endif
19 #include <xen/string.h>
20 #include <xen/stringify.h>
21 #ifdef CONFIG_X86
22 /*
23 * Keep this arch-specific modified include in the common file, as moving
24 * it to the arch specific include file would obscure that special care is
25 * taken to include it with __ASSEMBLY__ defined.
26 */
27 #define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
28 #include <asm/fixmap.h>
29 #undef __ASSEMBLY__
30 #endif
31
32 /* Using SetVirtualAddressMap() is incompatible with kexec: */
33 #undef USE_SET_VIRTUAL_ADDRESS_MAP
34
35 #define EFI_REVISION(major, minor) (((major) << 16) | (minor))
36
37 #define SMBIOS3_TABLE_GUID \
38 { 0xf2fd1544, 0x9794, 0x4a2c, {0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94} }
39 #define SHIM_LOCK_PROTOCOL_GUID \
40 { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
41 #define APPLE_PROPERTIES_PROTOCOL_GUID \
42 { 0x91bd12fe, 0xf6c3, 0x44fb, { 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0} }
43
44 typedef EFI_STATUS
45 (/* _not_ EFIAPI */ *EFI_SHIM_LOCK_VERIFY) (
46 IN VOID *Buffer,
47 IN UINT32 Size);
48
49 typedef struct {
50 EFI_SHIM_LOCK_VERIFY Verify;
51 } EFI_SHIM_LOCK_PROTOCOL;
52
53 struct _EFI_APPLE_PROPERTIES;
54
55 typedef EFI_STATUS
56 (EFIAPI *EFI_APPLE_PROPERTIES_GET) (
57 IN struct _EFI_APPLE_PROPERTIES *This,
58 IN const EFI_DEVICE_PATH *Device,
59 IN const CHAR16 *PropertyName,
60 OUT VOID *Buffer,
61 IN OUT UINT32 *BufferSize);
62
63 typedef EFI_STATUS
64 (EFIAPI *EFI_APPLE_PROPERTIES_SET) (
65 IN struct _EFI_APPLE_PROPERTIES *This,
66 IN const EFI_DEVICE_PATH *Device,
67 IN const CHAR16 *PropertyName,
68 IN const VOID *Value,
69 IN UINT32 ValueLen);
70
71 typedef EFI_STATUS
72 (EFIAPI *EFI_APPLE_PROPERTIES_DELETE) (
73 IN struct _EFI_APPLE_PROPERTIES *This,
74 IN const EFI_DEVICE_PATH *Device,
75 IN const CHAR16 *PropertyName);
76
77 typedef EFI_STATUS
78 (EFIAPI *EFI_APPLE_PROPERTIES_GETALL) (
79 IN struct _EFI_APPLE_PROPERTIES *This,
80 OUT VOID *Buffer,
81 IN OUT UINT32 *BufferSize);
82
83 typedef struct _EFI_APPLE_PROPERTIES {
84 UINTN Version; /* 0x10000 */
85 EFI_APPLE_PROPERTIES_GET Get;
86 EFI_APPLE_PROPERTIES_SET Set;
87 EFI_APPLE_PROPERTIES_DELETE Delete;
88 EFI_APPLE_PROPERTIES_GETALL GetAll;
89 } EFI_APPLE_PROPERTIES;
90
91 union string {
92 CHAR16 *w;
93 char *s;
94 const char *cs;
95 };
96
97 struct file {
98 UINTN size;
99 union {
100 EFI_PHYSICAL_ADDRESS addr;
101 void *ptr;
102 };
103 };
104
105 static CHAR16 *FormatDec(UINT64 Val, CHAR16 *Buffer);
106 static CHAR16 *FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer);
107 static void DisplayUint(UINT64 Val, INTN Width);
108 static CHAR16 *wstrcpy(CHAR16 *d, const CHAR16 *s);
109 static void noreturn blexit(const CHAR16 *str);
110 static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
111 static char *get_value(const struct file *cfg, const char *section,
112 const char *item);
113 static char *split_string(char *s);
114 static CHAR16 *s2w(union string *str);
115 static char *w2s(const union string *str);
116 static bool read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
117 struct file *file, char *options);
118 static size_t wstrlen(const CHAR16 * s);
119 static int set_color(u32 mask, int bpp, u8 *pos, u8 *sz);
120 static bool match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2);
121
122 static void efi_init(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable);
123 static void efi_console_set_mode(void);
124 static EFI_GRAPHICS_OUTPUT_PROTOCOL *efi_get_gop(void);
125 static UINTN efi_find_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
126 UINTN cols, UINTN rows, UINTN depth);
127 static void efi_tables(void);
128 static void setup_efi_pci(void);
129 static void efi_variables(void);
130 static void efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop_mode);
131 static void efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable);
132
133 static const EFI_BOOT_SERVICES *__initdata efi_bs;
134 static UINT32 __initdata efi_bs_revision;
135 static EFI_HANDLE __initdata efi_ih;
136
137 static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdOut;
138 static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdErr;
139
140 static UINT32 __initdata mdesc_ver;
141 static bool __initdata map_bs;
142
143 static struct file __initdata cfg;
144 static struct file __initdata kernel;
145 static struct file __initdata ramdisk;
146 static struct file __initdata xsm;
147 static CHAR16 __initdata newline[] = L"\r\n";
148
149 #define PrintStr(s) StdOut->OutputString(StdOut, s)
150 #define PrintErr(s) StdErr->OutputString(StdErr, s)
151
152 #ifdef CONFIG_ARM
153 /*
154 * TODO: Enable EFI boot allocator on ARM.
155 * This code can be common for x86 and ARM.
156 * Things TODO on ARM before enabling ebmalloc:
157 * - estimate required EBMALLOC_SIZE value,
158 * - where (in which section) ebmalloc_mem[] should live; if in
159 * .bss.page_aligned, as it is right now, then whole BSS zeroing
160 * have to be disabled in xen/arch/arm/arm64/head.S; though BSS
161 * should be initialized somehow before use of variables living there,
162 * - use ebmalloc() in ARM/common EFI boot code,
163 * - call free_ebmalloc_unused_mem() somewhere in init code.
164 */
165 #define EBMALLOC_SIZE MB(0)
166 #else
167 #define EBMALLOC_SIZE MB(1)
168 #endif
169
170 static char __section(".bss.page_aligned") __aligned(PAGE_SIZE)
171 ebmalloc_mem[EBMALLOC_SIZE];
172 static unsigned long __initdata ebmalloc_allocated;
173
174 /* EFI boot allocator. */
ebmalloc(size_t size)175 static void __init __maybe_unused *ebmalloc(size_t size)
176 {
177 void *ptr = ebmalloc_mem + ebmalloc_allocated;
178
179 ebmalloc_allocated += (size + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
180
181 if ( ebmalloc_allocated > sizeof(ebmalloc_mem) )
182 blexit(L"Out of static memory\r\n");
183
184 return ptr;
185 }
186
free_ebmalloc_unused_mem(void)187 static void __init __maybe_unused free_ebmalloc_unused_mem(void)
188 {
189 #if 0 /* FIXME: Putting a hole in the BSS breaks the IOMMU mappings for dom0. */
190 unsigned long start, end;
191
192 start = (unsigned long)ebmalloc_mem + PAGE_ALIGN(ebmalloc_allocated);
193 end = (unsigned long)ebmalloc_mem + sizeof(ebmalloc_mem);
194
195 destroy_xen_mappings(start, end);
196 init_xenheap_pages(__pa(start), __pa(end));
197
198 printk(XENLOG_INFO "Freed %lukB unused BSS memory\n", (end - start) >> 10);
199 #endif
200 }
201
202 /*
203 * Include architecture specific implementation here, which references the
204 * static globals defined above.
205 */
206 #include "efi-boot.h"
207
FormatDec(UINT64 Val,CHAR16 * Buffer)208 static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer)
209 {
210 if ( Val >= 10 )
211 Buffer = FormatDec(Val / 10, Buffer);
212 *Buffer = (CHAR16)(L'0' + Val % 10);
213 return Buffer + 1;
214 }
215
FormatHex(UINT64 Val,UINTN Width,CHAR16 * Buffer)216 static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer)
217 {
218 if ( Width > 1 || Val >= 0x10 )
219 Buffer = FormatHex(Val >> 4, Width ? Width - 1 : 0, Buffer);
220 *Buffer = (CHAR16)((Val &= 0xf) < 10 ? L'0' + Val : L'a' + Val - 10);
221 return Buffer + 1;
222 }
223
DisplayUint(UINT64 Val,INTN Width)224 static void __init DisplayUint(UINT64 Val, INTN Width)
225 {
226 CHAR16 PrintString[32], *end;
227
228 if (Width < 0)
229 end = FormatDec(Val, PrintString);
230 else
231 {
232 PrintStr(L"0x");
233 end = FormatHex(Val, Width, PrintString);
234 }
235 *end = 0;
236 PrintStr(PrintString);
237 }
238
wstrlen(const CHAR16 * s)239 static size_t __init __maybe_unused wstrlen(const CHAR16 *s)
240 {
241 const CHAR16 *sc;
242
243 for ( sc = s; *sc != L'\0'; ++sc )
244 /* nothing */;
245 return sc - s;
246 }
247
wstrcpy(CHAR16 * d,const CHAR16 * s)248 static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s)
249 {
250 CHAR16 *r = d;
251
252 while ( (*d++ = *s++) != 0 )
253 ;
254 return r;
255 }
256
wstrcmp(const CHAR16 * s1,const CHAR16 * s2)257 static int __init wstrcmp(const CHAR16 *s1, const CHAR16 *s2)
258 {
259 while ( *s1 && *s1 == *s2 )
260 {
261 ++s1;
262 ++s2;
263 }
264 return *s1 - *s2;
265 }
266
wstrncmp(const CHAR16 * s1,const CHAR16 * s2,UINTN n)267 static int __init wstrncmp(const CHAR16 *s1, const CHAR16 *s2, UINTN n)
268 {
269 while ( n && *s1 && *s1 == *s2 )
270 {
271 --n;
272 ++s1;
273 ++s2;
274 }
275 return n ? *s1 - *s2 : 0;
276 }
277
s2w(union string * str)278 static CHAR16 *__init s2w(union string *str)
279 {
280 const char *s = str->s;
281 CHAR16 *w;
282 void *ptr;
283
284 if ( efi_bs->AllocatePool(EfiLoaderData, (strlen(s) + 1) * sizeof(*w),
285 &ptr) != EFI_SUCCESS )
286 return NULL;
287
288 w = str->w = ptr;
289 do {
290 *w = *s++;
291 } while ( *w++ );
292
293 return str->w;
294 }
295
w2s(const union string * str)296 static char *__init w2s(const union string *str)
297 {
298 const CHAR16 *w = str->w;
299 char *s = str->s;
300
301 do {
302 if ( *w > 0x007f )
303 return NULL;
304 *s = *w++;
305 } while ( *s++ );
306
307 return str->s;
308 }
309
match_guid(const EFI_GUID * guid1,const EFI_GUID * guid2)310 static bool __init match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2)
311 {
312 return guid1->Data1 == guid2->Data1 &&
313 guid1->Data2 == guid2->Data2 &&
314 guid1->Data3 == guid2->Data3 &&
315 !memcmp(guid1->Data4, guid2->Data4, sizeof(guid1->Data4));
316 }
317
blexit(const CHAR16 * str)318 static void __init noreturn blexit(const CHAR16 *str)
319 {
320 if ( str )
321 PrintStr((CHAR16 *)str);
322 PrintStr(newline);
323
324 if ( !efi_bs )
325 efi_arch_halt();
326
327 if ( cfg.addr )
328 efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
329 if ( kernel.addr )
330 efi_bs->FreePages(kernel.addr, PFN_UP(kernel.size));
331 if ( ramdisk.addr )
332 efi_bs->FreePages(ramdisk.addr, PFN_UP(ramdisk.size));
333 if ( xsm.addr )
334 efi_bs->FreePages(xsm.addr, PFN_UP(xsm.size));
335
336 efi_arch_blexit();
337
338 efi_bs->Exit(efi_ih, EFI_SUCCESS, 0, NULL);
339 unreachable(); /* not reached */
340 }
341
342 /* generic routine for printing error messages */
PrintErrMesg(const CHAR16 * mesg,EFI_STATUS ErrCode)343 static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode)
344 {
345 static const CHAR16* const ErrCodeToStr[] __initconstrel = {
346 [~EFI_ERROR_MASK & EFI_NOT_FOUND] = L"Not found",
347 [~EFI_ERROR_MASK & EFI_NO_MEDIA] = L"The device has no media",
348 [~EFI_ERROR_MASK & EFI_MEDIA_CHANGED] = L"Media changed",
349 [~EFI_ERROR_MASK & EFI_DEVICE_ERROR] = L"Device error",
350 [~EFI_ERROR_MASK & EFI_VOLUME_CORRUPTED] = L"Volume corrupted",
351 [~EFI_ERROR_MASK & EFI_ACCESS_DENIED] = L"Access denied",
352 [~EFI_ERROR_MASK & EFI_OUT_OF_RESOURCES] = L"Out of resources",
353 [~EFI_ERROR_MASK & EFI_VOLUME_FULL] = L"Volume is full",
354 [~EFI_ERROR_MASK & EFI_SECURITY_VIOLATION] = L"Security violation",
355 [~EFI_ERROR_MASK & EFI_CRC_ERROR] = L"CRC error",
356 [~EFI_ERROR_MASK & EFI_COMPROMISED_DATA] = L"Compromised data",
357 [~EFI_ERROR_MASK & EFI_BUFFER_TOO_SMALL] = L"Buffer too small",
358 };
359 EFI_STATUS ErrIdx = ErrCode & ~EFI_ERROR_MASK;
360
361 StdOut = StdErr;
362 PrintErr((CHAR16 *)mesg);
363 PrintErr(L": ");
364
365 if( (ErrIdx < ARRAY_SIZE(ErrCodeToStr)) && ErrCodeToStr[ErrIdx] )
366 mesg = ErrCodeToStr[ErrIdx];
367 else
368 {
369 PrintErr(L"ErrCode: ");
370 DisplayUint(ErrCode, 0);
371 mesg = NULL;
372 }
373 blexit(mesg);
374 }
375
get_argv(unsigned int argc,CHAR16 ** argv,CHAR16 * cmdline,UINTN cmdsize,CHAR16 ** options)376 static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
377 CHAR16 *cmdline, UINTN cmdsize,
378 CHAR16 **options)
379 {
380 CHAR16 *ptr = (CHAR16 *)(argv + argc + 1), *prev = NULL;
381 bool prev_sep = true;
382
383 for ( ; cmdsize > sizeof(*cmdline) && *cmdline;
384 cmdsize -= sizeof(*cmdline), ++cmdline )
385 {
386 bool cur_sep = *cmdline == L' ' || *cmdline == L'\t';
387
388 if ( !prev_sep )
389 {
390 if ( cur_sep )
391 ++ptr;
392 else if ( argv )
393 {
394 *ptr = *cmdline;
395 *++ptr = 0;
396 }
397 }
398 else if ( !cur_sep )
399 {
400 if ( !argv )
401 ++argc;
402 else if ( prev && wstrcmp(prev, L"--") == 0 )
403 {
404 --argv;
405 if ( options )
406 *options = cmdline;
407 break;
408 }
409 else
410 {
411 *argv++ = prev = ptr;
412 *ptr = *cmdline;
413 *++ptr = 0;
414 }
415 }
416 prev_sep = cur_sep;
417 }
418 if ( argv )
419 *argv = NULL;
420 return argc;
421 }
422
get_parent_handle(EFI_LOADED_IMAGE * loaded_image,CHAR16 ** leaf)423 static EFI_FILE_HANDLE __init get_parent_handle(EFI_LOADED_IMAGE *loaded_image,
424 CHAR16 **leaf)
425 {
426 static EFI_GUID __initdata fs_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
427 EFI_FILE_HANDLE dir_handle;
428 EFI_DEVICE_PATH *dp;
429 CHAR16 *pathend, *ptr;
430 EFI_STATUS ret;
431
432 do {
433 EFI_FILE_IO_INTERFACE *fio;
434
435 /* Get the file system interface. */
436 ret = efi_bs->HandleProtocol(loaded_image->DeviceHandle,
437 &fs_protocol, (void **)&fio);
438 if ( EFI_ERROR(ret) )
439 PrintErrMesg(L"Couldn't obtain the File System Protocol Interface",
440 ret);
441 ret = fio->OpenVolume(fio, &dir_handle);
442 } while ( ret == EFI_MEDIA_CHANGED );
443 if ( ret != EFI_SUCCESS )
444 PrintErrMesg(L"OpenVolume failure", ret);
445
446 #define buffer ((CHAR16 *)keyhandler_scratch)
447 #define BUFFERSIZE sizeof(keyhandler_scratch)
448 for ( dp = loaded_image->FilePath, *buffer = 0;
449 DevicePathType(dp) != END_DEVICE_PATH_TYPE;
450 dp = (void *)dp + DevicePathNodeLength(dp) )
451 {
452 FILEPATH_DEVICE_PATH *fp;
453
454 if ( DevicePathType(dp) != MEDIA_DEVICE_PATH ||
455 DevicePathSubType(dp) != MEDIA_FILEPATH_DP )
456 blexit(L"Unsupported device path component");
457
458 if ( *buffer )
459 {
460 EFI_FILE_HANDLE new_handle;
461
462 ret = dir_handle->Open(dir_handle, &new_handle, buffer,
463 EFI_FILE_MODE_READ, 0);
464 if ( ret != EFI_SUCCESS )
465 {
466 PrintErr(L"Open failed for ");
467 PrintErrMesg(buffer, ret);
468 }
469 dir_handle->Close(dir_handle);
470 dir_handle = new_handle;
471 }
472 fp = (void *)dp;
473 if ( BUFFERSIZE < DevicePathNodeLength(dp) -
474 sizeof(*dp) + sizeof(*buffer) )
475 blexit(L"Increase BUFFERSIZE");
476 memcpy(buffer, fp->PathName, DevicePathNodeLength(dp) - sizeof(*dp));
477 buffer[(DevicePathNodeLength(dp) - sizeof(*dp)) / sizeof(*buffer)] = 0;
478 }
479 for ( ptr = buffer, pathend = NULL; *ptr; ++ptr )
480 if ( *ptr == L'\\' )
481 pathend = ptr;
482 if ( pathend )
483 {
484 *pathend = 0;
485 *leaf = pathend + 1;
486 if ( *buffer )
487 {
488 EFI_FILE_HANDLE new_handle;
489
490 ret = dir_handle->Open(dir_handle, &new_handle, buffer,
491 EFI_FILE_MODE_READ, 0);
492 if ( ret != EFI_SUCCESS ) {
493 PrintErr(L"Open failed for ");
494 PrintErrMesg(buffer, ret);
495 }
496 dir_handle->Close(dir_handle);
497 dir_handle = new_handle;
498 }
499 }
500 else
501 *leaf = buffer;
502 #undef BUFFERSIZE
503 #undef buffer
504
505 return dir_handle;
506 }
507
point_tail(CHAR16 * fn)508 static CHAR16 *__init point_tail(CHAR16 *fn)
509 {
510 CHAR16 *tail = NULL;
511
512 for ( ; ; ++fn )
513 switch ( *fn )
514 {
515 case 0:
516 return tail;
517 case L'.':
518 case L'-':
519 case L'_':
520 tail = fn;
521 break;
522 }
523 }
524 /*
525 * Truncate string at first space, and return pointer
526 * to remainder of string, if any/ NULL returned if
527 * no remainder after space.
528 */
split_string(char * s)529 static char * __init split_string(char *s)
530 {
531 while ( *s && !isspace(*s) )
532 ++s;
533 if ( *s )
534 {
535 *s = 0;
536 return s + 1;
537 }
538 return NULL;
539 }
540
read_file(EFI_FILE_HANDLE dir_handle,CHAR16 * name,struct file * file,char * options)541 static bool __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
542 struct file *file, char *options)
543 {
544 EFI_FILE_HANDLE FileHandle = NULL;
545 UINT64 size;
546 EFI_STATUS ret;
547 CHAR16 *what = NULL;
548
549 if ( !name )
550 PrintErrMesg(L"No filename", EFI_OUT_OF_RESOURCES);
551 ret = dir_handle->Open(dir_handle, &FileHandle, name,
552 EFI_FILE_MODE_READ, 0);
553 if ( file == &cfg && ret == EFI_NOT_FOUND )
554 return false;
555 if ( EFI_ERROR(ret) )
556 what = L"Open";
557 else
558 ret = FileHandle->SetPosition(FileHandle, -1);
559 if ( EFI_ERROR(ret) )
560 what = what ?: L"Seek";
561 else
562 ret = FileHandle->GetPosition(FileHandle, &size);
563 if ( EFI_ERROR(ret) )
564 what = what ?: L"Get size";
565 else
566 ret = FileHandle->SetPosition(FileHandle, 0);
567 if ( EFI_ERROR(ret) )
568 what = what ?: L"Seek";
569 else
570 {
571 file->addr = min(1UL << (32 + PAGE_SHIFT),
572 HYPERVISOR_VIRT_END - DIRECTMAP_VIRT_START);
573 ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
574 PFN_UP(size), &file->addr);
575 }
576 if ( EFI_ERROR(ret) )
577 {
578 file->addr = 0;
579 what = what ?: L"Allocation";
580 }
581 else
582 {
583 file->size = size;
584 if ( file != &cfg )
585 {
586 PrintStr(name);
587 PrintStr(L": ");
588 DisplayUint(file->addr, 2 * sizeof(file->addr));
589 PrintStr(L"-");
590 DisplayUint(file->addr + size, 2 * sizeof(file->addr));
591 PrintStr(newline);
592 efi_arch_handle_module(file, name, options);
593 }
594
595 ret = FileHandle->Read(FileHandle, &file->size, file->ptr);
596 if ( !EFI_ERROR(ret) && file->size != size )
597 ret = EFI_ABORTED;
598 if ( EFI_ERROR(ret) )
599 what = L"Read";
600 }
601
602 if ( FileHandle )
603 FileHandle->Close(FileHandle);
604
605 if ( what )
606 {
607 PrintErr(what);
608 PrintErr(L" failed for ");
609 PrintErrMesg(name, ret);
610 }
611
612 efi_arch_flush_dcache_area(file->ptr, file->size);
613
614 return true;
615 }
616
pre_parse(const struct file * cfg)617 static void __init pre_parse(const struct file *cfg)
618 {
619 char *ptr = cfg->ptr, *end = ptr + cfg->size;
620 bool start = true, comment = false;
621
622 for ( ; ptr < end; ++ptr )
623 {
624 if ( iscntrl(*ptr) )
625 {
626 comment = false;
627 start = true;
628 *ptr = 0;
629 }
630 else if ( comment || (start && isspace(*ptr)) )
631 *ptr = 0;
632 else if ( *ptr == '#' || (start && *ptr == ';') )
633 {
634 comment = true;
635 *ptr = 0;
636 }
637 else
638 start = 0;
639 }
640 if ( cfg->size && end[-1] )
641 PrintStr(L"No newline at end of config file,"
642 " last line will be ignored.\r\n");
643 }
644
get_value(const struct file * cfg,const char * section,const char * item)645 static char *__init get_value(const struct file *cfg, const char *section,
646 const char *item)
647 {
648 char *ptr = cfg->ptr, *end = ptr + cfg->size;
649 size_t slen = section ? strlen(section) : 0, ilen = strlen(item);
650 bool match = !slen;
651
652 for ( ; ptr < end; ++ptr )
653 {
654 switch ( *ptr )
655 {
656 case 0:
657 continue;
658 case '[':
659 if ( !slen )
660 break;
661 if ( match )
662 return NULL;
663 match = strncmp(++ptr, section, slen) == 0 && ptr[slen] == ']';
664 break;
665 default:
666 if ( match && strncmp(ptr, item, ilen) == 0 && ptr[ilen] == '=' )
667 {
668 ptr += ilen + 1;
669 /* strip off any leading spaces */
670 while ( *ptr && isspace(*ptr) )
671 ptr++;
672 return ptr;
673 }
674 break;
675 }
676 ptr += strlen(ptr);
677 }
678 return NULL;
679 }
680
efi_init(EFI_HANDLE ImageHandle,EFI_SYSTEM_TABLE * SystemTable)681 static void __init efi_init(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
682 {
683 efi_ih = ImageHandle;
684 efi_bs = SystemTable->BootServices;
685 efi_bs_revision = efi_bs->Hdr.Revision;
686 efi_rs = SystemTable->RuntimeServices;
687 efi_ct = SystemTable->ConfigurationTable;
688 efi_num_ct = SystemTable->NumberOfTableEntries;
689 efi_version = SystemTable->Hdr.Revision;
690 efi_fw_vendor = SystemTable->FirmwareVendor;
691 efi_fw_revision = SystemTable->FirmwareRevision;
692
693 StdOut = SystemTable->ConOut;
694 StdErr = SystemTable->StdErr ?: StdOut;
695 }
696
efi_console_set_mode(void)697 static void __init efi_console_set_mode(void)
698 {
699 UINTN cols, rows, size;
700 unsigned int best, i;
701
702 for ( i = 0, size = 0, best = StdOut->Mode->Mode;
703 i < StdOut->Mode->MaxMode; ++i )
704 {
705 if ( StdOut->QueryMode(StdOut, i, &cols, &rows) == EFI_SUCCESS &&
706 cols * rows > size )
707 {
708 size = cols * rows;
709 best = i;
710 }
711 }
712 if ( best != StdOut->Mode->Mode )
713 StdOut->SetMode(StdOut, best);
714 }
715
efi_get_gop(void)716 static EFI_GRAPHICS_OUTPUT_PROTOCOL __init *efi_get_gop(void)
717 {
718 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
719 EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
720 EFI_HANDLE *handles = NULL;
721 EFI_STATUS status;
722 UINTN info_size, size = 0;
723 static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
724 unsigned int i;
725
726 status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size, NULL);
727 if ( status == EFI_BUFFER_TOO_SMALL )
728 status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
729 if ( !EFI_ERROR(status) )
730 status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size,
731 handles);
732 if ( EFI_ERROR(status) )
733 size = 0;
734 for ( i = 0; i < size / sizeof(*handles); ++i )
735 {
736 status = efi_bs->HandleProtocol(handles[i], &gop_guid, (void **)&gop);
737 if ( EFI_ERROR(status) )
738 continue;
739 status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
740 if ( !EFI_ERROR(status) )
741 break;
742 }
743 if ( handles )
744 efi_bs->FreePool(handles);
745 if ( EFI_ERROR(status) )
746 gop = NULL;
747
748 return gop;
749 }
750
efi_find_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL * gop,UINTN cols,UINTN rows,UINTN depth)751 static UINTN __init efi_find_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
752 UINTN cols, UINTN rows, UINTN depth)
753 {
754 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
755 EFI_STATUS status;
756 UINTN gop_mode = ~0, info_size, size;
757 unsigned int i;
758
759 for ( i = size = 0; i < gop->Mode->MaxMode; ++i )
760 {
761 unsigned int bpp = 0;
762
763 status = gop->QueryMode(gop, i, &info_size, &mode_info);
764 if ( EFI_ERROR(status) )
765 continue;
766 switch ( mode_info->PixelFormat )
767 {
768 case PixelBitMask:
769 bpp = hweight32(mode_info->PixelInformation.RedMask |
770 mode_info->PixelInformation.GreenMask |
771 mode_info->PixelInformation.BlueMask);
772 break;
773 case PixelRedGreenBlueReserved8BitPerColor:
774 case PixelBlueGreenRedReserved8BitPerColor:
775 bpp = 24;
776 break;
777 default:
778 continue;
779 }
780 if ( cols == mode_info->HorizontalResolution &&
781 rows == mode_info->VerticalResolution &&
782 (!depth || bpp == depth) )
783 {
784 gop_mode = i;
785 break;
786 }
787 if ( !cols && !rows &&
788 (UINTN)mode_info->HorizontalResolution *
789 mode_info->VerticalResolution > size )
790 {
791 size = (UINTN)mode_info->HorizontalResolution *
792 mode_info->VerticalResolution;
793 gop_mode = i;
794 }
795 }
796
797 return gop_mode;
798 }
799
efi_tables(void)800 static void __init efi_tables(void)
801 {
802 unsigned int i;
803
804 /* Obtain basic table pointers. */
805 for ( i = 0; i < efi_num_ct; ++i )
806 {
807 static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
808 static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
809 static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
810 static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
811 static EFI_GUID __initdata smbios3_guid = SMBIOS3_TABLE_GUID;
812
813 if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
814 efi.acpi20 = (long)efi_ct[i].VendorTable;
815 if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
816 efi.acpi = (long)efi_ct[i].VendorTable;
817 if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
818 efi.mps = (long)efi_ct[i].VendorTable;
819 if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
820 efi.smbios = (long)efi_ct[i].VendorTable;
821 if ( match_guid(&smbios3_guid, &efi_ct[i].VendorGuid) )
822 efi.smbios3 = (long)efi_ct[i].VendorTable;
823 }
824
825 #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
826 dmi_efi_get_table(efi.smbios != EFI_INVALID_TABLE_ADDR
827 ? (void *)(long)efi.smbios : NULL,
828 efi.smbios3 != EFI_INVALID_TABLE_ADDR
829 ? (void *)(long)efi.smbios3 : NULL);
830 #endif
831 }
832
setup_efi_pci(void)833 static void __init setup_efi_pci(void)
834 {
835 EFI_STATUS status;
836 EFI_HANDLE *handles;
837 static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL;
838 UINTN i, nr_pci, size = 0;
839 struct efi_pci_rom *last = NULL;
840
841 status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL);
842 if ( status != EFI_BUFFER_TOO_SMALL )
843 return;
844 status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
845 if ( EFI_ERROR(status) )
846 return;
847 status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, handles);
848 if ( EFI_ERROR(status) )
849 size = 0;
850
851 nr_pci = size / sizeof(*handles);
852 for ( i = 0; i < nr_pci; ++i )
853 {
854 EFI_PCI_IO *pci = NULL;
855 u64 attributes;
856 struct efi_pci_rom *rom, *va;
857 UINTN segment, bus, device, function;
858
859 status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci);
860 if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize )
861 continue;
862
863 status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0,
864 &attributes);
865 if ( EFI_ERROR(status) ||
866 !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) ||
867 EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device,
868 &function)) )
869 continue;
870
871 DisplayUint(segment, 4);
872 PrintStr(L":");
873 DisplayUint(bus, 2);
874 PrintStr(L":");
875 DisplayUint(device, 2);
876 PrintStr(L".");
877 DisplayUint(function, 1);
878 PrintStr(L": ROM: ");
879 DisplayUint(pci->RomSize, 0);
880 PrintStr(L" bytes at ");
881 DisplayUint((UINTN)pci->RomImage, 0);
882 PrintStr(newline);
883
884 size = pci->RomSize + sizeof(*rom);
885 status = efi_bs->AllocatePool(EfiRuntimeServicesData, size,
886 (void **)&rom);
887 if ( EFI_ERROR(status) )
888 continue;
889
890 rom->next = NULL;
891 rom->size = pci->RomSize;
892
893 status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
894 &rom->vendor);
895 if ( !EFI_ERROR(status) )
896 status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
897 &rom->devid);
898 if ( EFI_ERROR(status) )
899 {
900 efi_bs->FreePool(rom);
901 continue;
902 }
903
904 rom->segment = segment;
905 rom->bus = bus;
906 rom->devfn = (device << 3) | function;
907 memcpy(rom->data, pci->RomImage, pci->RomSize);
908
909 va = (void *)rom + DIRECTMAP_VIRT_START;
910 if ( last )
911 last->next = va;
912 else
913 efi_pci_roms = va;
914 last = rom;
915 }
916
917 efi_bs->FreePool(handles);
918 }
919
efi_variables(void)920 static void __init efi_variables(void)
921 {
922 EFI_STATUS status;
923
924 status = (efi_rs->Hdr.Revision >> 16) >= 2 ?
925 efi_rs->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE |
926 EFI_VARIABLE_BOOTSERVICE_ACCESS |
927 EFI_VARIABLE_RUNTIME_ACCESS,
928 &efi_boot_max_var_store_size,
929 &efi_boot_remain_var_store_size,
930 &efi_boot_max_var_size) :
931 EFI_INCOMPATIBLE_VERSION;
932 if ( EFI_ERROR(status) )
933 {
934 efi_boot_max_var_store_size = 0;
935 efi_boot_remain_var_store_size = 0;
936 efi_boot_max_var_size = status;
937 PrintStr(L"Warning: Could not query variable store: ");
938 DisplayUint(status, 0);
939 PrintStr(newline);
940 }
941 }
942
efi_get_apple_properties(void)943 static void __init efi_get_apple_properties(void)
944 {
945 static EFI_GUID __initdata props_guid = APPLE_PROPERTIES_PROTOCOL_GUID;
946 EFI_APPLE_PROPERTIES *props;
947 UINT32 size = 0;
948 VOID *data;
949 EFI_STATUS status;
950
951 if ( efi_bs->LocateProtocol(&props_guid, NULL,
952 (void **)&props) != EFI_SUCCESS )
953 return;
954 if ( props->Version != 0x10000 )
955 {
956 PrintStr(L"Warning: Unsupported Apple device properties version: ");
957 DisplayUint(props->Version, 0);
958 PrintStr(newline);
959 return;
960 }
961
962 props->GetAll(props, NULL, &size);
963 if ( !size ||
964 efi_bs->AllocatePool(EfiRuntimeServicesData, size,
965 &data) != EFI_SUCCESS )
966 return;
967
968 status = props->GetAll(props, data, &size);
969 if ( status == EFI_SUCCESS )
970 {
971 efi_apple_properties_addr = (UINTN)data;
972 efi_apple_properties_len = size;
973 }
974 else
975 {
976 efi_bs->FreePool(data);
977 PrintStr(L"Warning: Could not query Apple device properties: ");
978 DisplayUint(status, 0);
979 PrintStr(newline);
980 }
981 }
982
efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL * gop,UINTN gop_mode)983 static void __init efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop_mode)
984 {
985 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
986 EFI_STATUS status;
987 UINTN info_size;
988
989 /* Set graphics mode. */
990 if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode )
991 gop->SetMode(gop, gop_mode);
992
993 /* Get graphics and frame buffer info. */
994 status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
995 if ( !EFI_ERROR(status) )
996 efi_arch_video_init(gop, info_size, mode_info);
997 }
998
efi_exit_boot(EFI_HANDLE ImageHandle,EFI_SYSTEM_TABLE * SystemTable)999 static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
1000 {
1001 EFI_STATUS status;
1002 UINTN info_size = 0, map_key;
1003 bool retry;
1004
1005 efi_bs->GetMemoryMap(&info_size, NULL, &map_key,
1006 &efi_mdesc_size, &mdesc_ver);
1007 info_size += 8 * efi_mdesc_size;
1008 efi_memmap = efi_arch_allocate_mmap_buffer(info_size);
1009 if ( !efi_memmap )
1010 blexit(L"Unable to allocate memory for EFI memory map");
1011
1012 for ( retry = false; ; retry = true )
1013 {
1014 efi_memmap_size = info_size;
1015 status = SystemTable->BootServices->GetMemoryMap(&efi_memmap_size,
1016 efi_memmap, &map_key,
1017 &efi_mdesc_size,
1018 &mdesc_ver);
1019 if ( EFI_ERROR(status) )
1020 PrintErrMesg(L"Cannot obtain memory map", status);
1021
1022 efi_arch_process_memory_map(SystemTable, efi_memmap, efi_memmap_size,
1023 efi_mdesc_size, mdesc_ver);
1024
1025 efi_arch_pre_exit_boot();
1026
1027 status = SystemTable->BootServices->ExitBootServices(ImageHandle,
1028 map_key);
1029 efi_bs = NULL;
1030 if ( status != EFI_INVALID_PARAMETER || retry )
1031 break;
1032 }
1033
1034 if ( EFI_ERROR(status) )
1035 PrintErrMesg(L"Cannot exit boot services", status);
1036
1037 /* Adjust pointers into EFI. */
1038 efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
1039 #ifdef USE_SET_VIRTUAL_ADDRESS_MAP
1040 efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
1041 #endif
1042 efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
1043 efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
1044 }
1045
set_color(u32 mask,int bpp,u8 * pos,u8 * sz)1046 static int __init __maybe_unused set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
1047 {
1048 if ( bpp < 0 )
1049 return bpp;
1050 if ( !mask )
1051 return -EINVAL;
1052 for ( *pos = 0; !(mask & 1); ++*pos )
1053 mask >>= 1;
1054 for ( *sz = 0; mask & 1; ++sz)
1055 mask >>= 1;
1056 if ( mask )
1057 return -EINVAL;
1058 return max(*pos + *sz, bpp);
1059 }
1060
1061 void EFIAPI __init noreturn
efi_start(EFI_HANDLE ImageHandle,EFI_SYSTEM_TABLE * SystemTable)1062 efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
1063 {
1064 static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL;
1065 static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID;
1066 EFI_LOADED_IMAGE *loaded_image;
1067 EFI_STATUS status;
1068 unsigned int i, argc;
1069 CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL;
1070 UINTN gop_mode = ~0;
1071 EFI_SHIM_LOCK_PROTOCOL *shim_lock;
1072 EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
1073 union string section = { NULL }, name;
1074 bool base_video = false;
1075 char *option_str;
1076 bool use_cfg_file;
1077
1078 __set_bit(EFI_BOOT, &efi_flags);
1079 __set_bit(EFI_LOADER, &efi_flags);
1080
1081 #ifndef CONFIG_ARM /* Disabled until runtime services implemented. */
1082 __set_bit(EFI_RS, &efi_flags);
1083 #endif
1084
1085 efi_init(ImageHandle, SystemTable);
1086
1087 use_cfg_file = efi_arch_use_config_file(SystemTable);
1088
1089 status = efi_bs->HandleProtocol(ImageHandle, &loaded_image_guid,
1090 (void **)&loaded_image);
1091 if ( status != EFI_SUCCESS )
1092 PrintErrMesg(L"No Loaded Image Protocol", status);
1093
1094 efi_arch_load_addr_check(loaded_image);
1095
1096 if ( use_cfg_file )
1097 {
1098 argc = get_argv(0, NULL, loaded_image->LoadOptions,
1099 loaded_image->LoadOptionsSize, NULL);
1100 if ( argc > 0 &&
1101 efi_bs->AllocatePool(EfiLoaderData,
1102 (argc + 1) * sizeof(*argv) +
1103 loaded_image->LoadOptionsSize,
1104 (void **)&argv) == EFI_SUCCESS )
1105 get_argv(argc, argv, loaded_image->LoadOptions,
1106 loaded_image->LoadOptionsSize, &options);
1107 else
1108 argc = 0;
1109 for ( i = 1; i < argc; ++i )
1110 {
1111 CHAR16 *ptr = argv[i];
1112
1113 if ( !ptr )
1114 break;
1115 if ( *ptr == L'/' || *ptr == L'-' )
1116 {
1117 if ( wstrcmp(ptr + 1, L"basevideo") == 0 )
1118 base_video = true;
1119 else if ( wstrcmp(ptr + 1, L"mapbs") == 0 )
1120 map_bs = true;
1121 else if ( wstrncmp(ptr + 1, L"cfg=", 4) == 0 )
1122 cfg_file_name = ptr + 5;
1123 else if ( i + 1 < argc && wstrcmp(ptr + 1, L"cfg") == 0 )
1124 cfg_file_name = argv[++i];
1125 else if ( wstrcmp(ptr + 1, L"help") == 0 ||
1126 (ptr[1] == L'?' && !ptr[2]) )
1127 {
1128 PrintStr(L"Xen EFI Loader options:\r\n");
1129 PrintStr(L"-basevideo retain current video mode\r\n");
1130 PrintStr(L"-mapbs map EfiBootServices{Code,Data}\r\n");
1131 PrintStr(L"-cfg=<file> specify configuration file\r\n");
1132 PrintStr(L"-help, -? display this help\r\n");
1133 blexit(NULL);
1134 }
1135 else
1136 {
1137 PrintStr(L"WARNING: Unknown command line option '");
1138 PrintStr(ptr);
1139 PrintStr(L"' ignored\r\n");
1140 }
1141 }
1142 else
1143 section.w = ptr;
1144 }
1145
1146 if ( !base_video )
1147 efi_console_set_mode();
1148 }
1149
1150 PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION)
1151 XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n");
1152
1153 efi_arch_relocate_image(0);
1154
1155 if ( use_cfg_file )
1156 {
1157 EFI_FILE_HANDLE dir_handle;
1158 UINTN depth, cols, rows, size;
1159
1160 size = cols = rows = depth = 0;
1161
1162 if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
1163 &cols, &rows) == EFI_SUCCESS )
1164 efi_arch_console_init(cols, rows);
1165
1166 gop = efi_get_gop();
1167
1168 /* Get the file system interface. */
1169 dir_handle = get_parent_handle(loaded_image, &file_name);
1170
1171 /* Read and parse the config file. */
1172 if ( !cfg_file_name )
1173 {
1174 CHAR16 *tail;
1175
1176 while ( (tail = point_tail(file_name)) != NULL )
1177 {
1178 wstrcpy(tail, L".cfg");
1179 if ( read_file(dir_handle, file_name, &cfg, NULL) )
1180 break;
1181 *tail = 0;
1182 }
1183 if ( !tail )
1184 blexit(L"No configuration file found.");
1185 PrintStr(L"Using configuration file '");
1186 PrintStr(file_name);
1187 PrintStr(L"'\r\n");
1188 }
1189 else if ( !read_file(dir_handle, cfg_file_name, &cfg, NULL) )
1190 blexit(L"Configuration file not found.");
1191 pre_parse(&cfg);
1192
1193 if ( section.w )
1194 w2s(§ion);
1195 else
1196 section.s = get_value(&cfg, "global", "default");
1197
1198 for ( ; ; )
1199 {
1200 name.s = get_value(&cfg, section.s, "kernel");
1201 if ( name.s )
1202 break;
1203 name.s = get_value(&cfg, "global", "chain");
1204 if ( !name.s )
1205 break;
1206 efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
1207 cfg.addr = 0;
1208 if ( !read_file(dir_handle, s2w(&name), &cfg, NULL) )
1209 {
1210 PrintStr(L"Chained configuration file '");
1211 PrintStr(name.w);
1212 efi_bs->FreePool(name.w);
1213 blexit(L"'not found.");
1214 }
1215 pre_parse(&cfg);
1216 efi_bs->FreePool(name.w);
1217 }
1218
1219 if ( !name.s )
1220 blexit(L"No Dom0 kernel image specified.");
1221
1222 efi_arch_cfg_file_early(dir_handle, section.s);
1223
1224 option_str = split_string(name.s);
1225 read_file(dir_handle, s2w(&name), &kernel, option_str);
1226 efi_bs->FreePool(name.w);
1227
1228 if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
1229 (void **)&shim_lock)) &&
1230 (status = shim_lock->Verify(kernel.ptr, kernel.size)) != EFI_SUCCESS )
1231 PrintErrMesg(L"Dom0 kernel image could not be verified", status);
1232
1233 name.s = get_value(&cfg, section.s, "ramdisk");
1234 if ( name.s )
1235 {
1236 read_file(dir_handle, s2w(&name), &ramdisk, NULL);
1237 efi_bs->FreePool(name.w);
1238 }
1239
1240 name.s = get_value(&cfg, section.s, "xsm");
1241 if ( name.s )
1242 {
1243 read_file(dir_handle, s2w(&name), &xsm, NULL);
1244 efi_bs->FreePool(name.w);
1245 }
1246
1247 name.s = get_value(&cfg, section.s, "options");
1248 efi_arch_handle_cmdline(argc ? *argv : NULL, options, name.s);
1249
1250 if ( !base_video )
1251 {
1252 name.cs = get_value(&cfg, section.s, "video");
1253 if ( !name.cs )
1254 name.cs = get_value(&cfg, "global", "video");
1255 if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
1256 {
1257 cols = simple_strtoul(name.cs + 4, &name.cs, 10);
1258 if ( *name.cs == 'x' )
1259 rows = simple_strtoul(name.cs + 1, &name.cs, 10);
1260 if ( *name.cs == 'x' )
1261 depth = simple_strtoul(name.cs + 1, &name.cs, 10);
1262 if ( *name.cs )
1263 cols = rows = depth = 0;
1264 }
1265 }
1266
1267 efi_arch_cfg_file_late(dir_handle, section.s);
1268
1269 efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
1270 cfg.addr = 0;
1271
1272 dir_handle->Close(dir_handle);
1273
1274 if ( gop && !base_video )
1275 gop_mode = efi_find_gop_mode(gop, cols, rows, depth);
1276 }
1277
1278 efi_arch_edd();
1279
1280 /* XXX Collect EDID info. */
1281 efi_arch_cpu();
1282
1283 efi_tables();
1284
1285 /* Collect PCI ROM contents. */
1286 setup_efi_pci();
1287
1288 /* Get snapshot of variable store parameters. */
1289 efi_variables();
1290
1291 /* Collect Apple device properties, if any. */
1292 efi_get_apple_properties();
1293
1294 efi_arch_memory_setup();
1295
1296 if ( gop )
1297 efi_set_gop_mode(gop, gop_mode);
1298
1299 efi_exit_boot(ImageHandle, SystemTable);
1300
1301 efi_arch_post_exit_boot();
1302 for( ; ; ); /* not reached */
1303 }
1304
1305 #ifndef CONFIG_ARM /* TODO - runtime service support */
1306
1307 static bool __initdata efi_map_uc;
1308
parse_efi_param(const char * s)1309 static int __init parse_efi_param(const char *s)
1310 {
1311 const char *ss;
1312 int rc = 0;
1313
1314 do {
1315 bool val = strncmp(s, "no-", 3);
1316
1317 if ( !val )
1318 s += 3;
1319
1320 ss = strchr(s, ',');
1321 if ( !ss )
1322 ss = strchr(s, '\0');
1323
1324 if ( !strncmp(s, "rs", ss - s) )
1325 {
1326 if ( val )
1327 __set_bit(EFI_RS, &efi_flags);
1328 else
1329 __clear_bit(EFI_RS, &efi_flags);
1330 }
1331 else if ( !strncmp(s, "attr=uc", ss - s) )
1332 efi_map_uc = val;
1333 else
1334 rc = -EINVAL;
1335
1336 s = ss + 1;
1337 } while ( *ss );
1338
1339 return rc;
1340 }
1341 custom_param("efi", parse_efi_param);
1342
1343 #ifndef USE_SET_VIRTUAL_ADDRESS_MAP
copy_mapping(unsigned long mfn,unsigned long end,bool (* is_valid)(unsigned long smfn,unsigned long emfn))1344 static __init void copy_mapping(unsigned long mfn, unsigned long end,
1345 bool (*is_valid)(unsigned long smfn,
1346 unsigned long emfn))
1347 {
1348 unsigned long next;
1349
1350 for ( ; mfn < end; mfn = next )
1351 {
1352 l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
1353 l3_pgentry_t *l3src, *l3dst;
1354 unsigned long va = (unsigned long)mfn_to_virt(mfn);
1355
1356 next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
1357 if ( !is_valid(mfn, min(next, end)) )
1358 continue;
1359 if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
1360 {
1361 l3dst = alloc_xen_pagetable();
1362 BUG_ON(!l3dst);
1363 clear_page(l3dst);
1364 efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] =
1365 l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR);
1366 }
1367 else
1368 l3dst = l4e_to_l3e(l4e);
1369 l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]);
1370 l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)];
1371 }
1372 }
1373
ram_range_valid(unsigned long smfn,unsigned long emfn)1374 static bool __init ram_range_valid(unsigned long smfn, unsigned long emfn)
1375 {
1376 unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1;
1377
1378 return !(smfn & pfn_hole_mask) &&
1379 find_next_bit(pdx_group_valid, sz,
1380 pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz;
1381 }
1382
rt_range_valid(unsigned long smfn,unsigned long emfn)1383 static bool __init rt_range_valid(unsigned long smfn, unsigned long emfn)
1384 {
1385 return true;
1386 }
1387 #endif
1388
1389 #define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
1390 (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
1391
efi_init_memory(void)1392 void __init efi_init_memory(void)
1393 {
1394 unsigned int i;
1395 #ifndef USE_SET_VIRTUAL_ADDRESS_MAP
1396 struct rt_extra {
1397 struct rt_extra *next;
1398 unsigned long smfn, emfn;
1399 unsigned int prot;
1400 } *extra, *extra_head = NULL;
1401 #endif
1402
1403 free_ebmalloc_unused_mem();
1404
1405 if ( !efi_enabled(EFI_BOOT) )
1406 return;
1407
1408 printk(XENLOG_INFO "EFI memory map:%s\n",
1409 map_bs ? " (mapping BootServices)" : "");
1410 for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
1411 {
1412 EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
1413 u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
1414 unsigned long smfn, emfn;
1415 unsigned int prot = PAGE_HYPERVISOR_RWX;
1416
1417 printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
1418 " type=%u attr=%016" PRIx64 "\n",
1419 desc->PhysicalStart, desc->PhysicalStart + len - 1,
1420 desc->Type, desc->Attribute);
1421
1422 if ( !efi_enabled(EFI_RS) ||
1423 (!(desc->Attribute & EFI_MEMORY_RUNTIME) &&
1424 (!map_bs ||
1425 (desc->Type != EfiBootServicesCode &&
1426 desc->Type != EfiBootServicesData))) )
1427 continue;
1428
1429 desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
1430
1431 smfn = PFN_DOWN(desc->PhysicalStart);
1432 emfn = PFN_UP(desc->PhysicalStart + len);
1433
1434 if ( desc->Attribute & EFI_MEMORY_WB )
1435 /* nothing */;
1436 else if ( desc->Attribute & EFI_MEMORY_WT )
1437 prot |= _PAGE_PWT | MAP_SMALL_PAGES;
1438 else if ( desc->Attribute & EFI_MEMORY_WC )
1439 prot |= _PAGE_PAT | MAP_SMALL_PAGES;
1440 else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) )
1441 prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
1442 else if ( efi_bs_revision >= EFI_REVISION(2, 5) &&
1443 (desc->Attribute & EFI_MEMORY_WP) )
1444 prot |= _PAGE_PAT | _PAGE_PWT | MAP_SMALL_PAGES;
1445 else
1446 {
1447 printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx%s\n",
1448 smfn, emfn - 1, efi_map_uc ? ", assuming UC" : "");
1449 if ( !efi_map_uc )
1450 continue;
1451 prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
1452 }
1453
1454 if ( desc->Attribute & (efi_bs_revision < EFI_REVISION(2, 5)
1455 ? EFI_MEMORY_WP : EFI_MEMORY_RO) )
1456 prot &= ~_PAGE_RW;
1457 if ( desc->Attribute & EFI_MEMORY_XP )
1458 prot |= _PAGE_NX;
1459
1460 if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) &&
1461 !(smfn & pfn_hole_mask) &&
1462 !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
1463 {
1464 if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
1465 prot &= ~_PAGE_GLOBAL;
1466 if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
1467 smfn, emfn - smfn, prot) == 0 )
1468 desc->VirtualStart =
1469 (unsigned long)maddr_to_virt(desc->PhysicalStart);
1470 else
1471 printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n",
1472 smfn, emfn - 1);
1473 }
1474 #ifndef USE_SET_VIRTUAL_ADDRESS_MAP
1475 else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) &&
1476 (extra = xmalloc(struct rt_extra)) != NULL )
1477 {
1478 extra->smfn = smfn;
1479 extra->emfn = emfn;
1480 extra->prot = prot & ~_PAGE_GLOBAL;
1481 extra->next = extra_head;
1482 extra_head = extra;
1483 desc->VirtualStart = desc->PhysicalStart;
1484 }
1485 #endif
1486 else
1487 {
1488 #ifdef USE_SET_VIRTUAL_ADDRESS_MAP
1489 /* XXX allocate e.g. down from FIXADDR_START */
1490 #endif
1491 printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n",
1492 smfn, emfn - 1);
1493 }
1494 }
1495
1496 if ( !efi_enabled(EFI_RS) )
1497 {
1498 efi_fw_vendor = NULL;
1499 return;
1500 }
1501
1502 #ifdef USE_SET_VIRTUAL_ADDRESS_MAP
1503 efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
1504 mdesc_ver, efi_memmap);
1505 #else
1506 /* Set up 1:1 page tables to do runtime calls in "physical" mode. */
1507 efi_l4_pgtable = alloc_xen_pagetable();
1508 BUG_ON(!efi_l4_pgtable);
1509 clear_page(efi_l4_pgtable);
1510
1511 copy_mapping(0, max_page, ram_range_valid);
1512
1513 /* Insert non-RAM runtime mappings inside the direct map. */
1514 for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
1515 {
1516 const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
1517
1518 if ( ((desc->Attribute & EFI_MEMORY_RUNTIME) ||
1519 (map_bs &&
1520 (desc->Type == EfiBootServicesCode ||
1521 desc->Type == EfiBootServicesData))) &&
1522 desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
1523 desc->VirtualStart != desc->PhysicalStart )
1524 copy_mapping(PFN_DOWN(desc->PhysicalStart),
1525 PFN_UP(desc->PhysicalStart +
1526 (desc->NumberOfPages << EFI_PAGE_SHIFT)),
1527 rt_range_valid);
1528 }
1529
1530 /* Insert non-RAM runtime mappings outside of the direct map. */
1531 while ( (extra = extra_head) != NULL )
1532 {
1533 unsigned long addr = extra->smfn << PAGE_SHIFT;
1534 l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)];
1535 l3_pgentry_t *pl3e;
1536 l2_pgentry_t *pl2e;
1537 l1_pgentry_t *l1t;
1538
1539 if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
1540 {
1541 pl3e = alloc_xen_pagetable();
1542 BUG_ON(!pl3e);
1543 clear_page(pl3e);
1544 efi_l4_pgtable[l4_table_offset(addr)] =
1545 l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR);
1546 }
1547 else
1548 pl3e = l4e_to_l3e(l4e);
1549 pl3e += l3_table_offset(addr);
1550 if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
1551 {
1552 pl2e = alloc_xen_pagetable();
1553 BUG_ON(!pl2e);
1554 clear_page(pl2e);
1555 *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR);
1556 }
1557 else
1558 {
1559 BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
1560 pl2e = l3e_to_l2e(*pl3e);
1561 }
1562 pl2e += l2_table_offset(addr);
1563 if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
1564 {
1565 l1t = alloc_xen_pagetable();
1566 BUG_ON(!l1t);
1567 clear_page(l1t);
1568 *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR);
1569 }
1570 else
1571 {
1572 BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
1573 l1t = l2e_to_l1e(*pl2e);
1574 }
1575 for ( i = l1_table_offset(addr);
1576 i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn;
1577 ++i, ++extra->smfn )
1578 l1t[i] = l1e_from_pfn(extra->smfn, extra->prot);
1579
1580 if ( extra->smfn == extra->emfn )
1581 {
1582 extra_head = extra->next;
1583 xfree(extra);
1584 }
1585 }
1586
1587 /* Insert Xen mappings. */
1588 for ( i = l4_table_offset(HYPERVISOR_VIRT_START);
1589 i < l4_table_offset(DIRECTMAP_VIRT_END); ++i )
1590 efi_l4_pgtable[i] = idle_pg_table[i];
1591 #endif
1592 }
1593 #endif
1594