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(&section);
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