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