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