"Fossies" - the Fresh Open Source Software Archive 
Member "xen-4.11.0/xen/common/efi/boot.c" (9 Jul 2018, 49403 Bytes) of package /linux/misc/xen-4.11.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "boot.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
4.10.1_vs_4.11.0.
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. */
175 static void __init __maybe_unused *ebmalloc(size_t size)
176 {
177 void *ptr = ebmalloc_mem + ebmalloc_allocated;
178
179 ebmalloc_allocated += ROUNDUP(size, sizeof(void *));
180
181 if ( ebmalloc_allocated > sizeof(ebmalloc_mem) )
182 blexit(L"Out of static memory\r\n");
183
184 return ptr;
185 }
186
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
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
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
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
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
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
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
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
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
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
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
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 */
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
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
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
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 */
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1062 efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
1063 {
1064 static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL;
1065 static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID;
1066 EFI_LOADED_IMAGE *loaded_image;
1067 EFI_STATUS status;
1068 unsigned int i, argc;
1069 CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL;
1070 UINTN gop_mode = ~0;
1071 EFI_SHIM_LOCK_PROTOCOL *shim_lock;
1072 EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
1073 union string section = { NULL }, name;
1074 bool base_video = false;
1075 char *option_str;
1076 bool use_cfg_file;
1077
1078 __set_bit(EFI_BOOT, &efi_flags);
1079 __set_bit(EFI_LOADER, &efi_flags);
1080
1081 #ifndef CONFIG_ARM /* Disabled until runtime services implemented. */
1082 __set_bit(EFI_RS, &efi_flags);
1083 #endif
1084
1085 efi_init(ImageHandle, SystemTable);
1086
1087 use_cfg_file = efi_arch_use_config_file(SystemTable);
1088
1089 status = efi_bs->HandleProtocol(ImageHandle, &loaded_image_guid,
1090 (void **)&loaded_image);
1091 if ( status != EFI_SUCCESS )
1092 PrintErrMesg(L"No Loaded Image Protocol", status);
1093
1094 efi_arch_load_addr_check(loaded_image);
1095
1096 if ( use_cfg_file )
1097 {
1098 argc = get_argv(0, NULL, loaded_image->LoadOptions,
1099 loaded_image->LoadOptionsSize, NULL);
1100 if ( argc > 0 &&
1101 efi_bs->AllocatePool(EfiLoaderData,
1102 (argc + 1) * sizeof(*argv) +
1103 loaded_image->LoadOptionsSize,
1104 (void **)&argv) == EFI_SUCCESS )
1105 get_argv(argc, argv, loaded_image->LoadOptions,
1106 loaded_image->LoadOptionsSize, &options);
1107 else
1108 argc = 0;
1109 for ( i = 1; i < argc; ++i )
1110 {
1111 CHAR16 *ptr = argv[i];
1112
1113 if ( !ptr )
1114 break;
1115 if ( *ptr == L'/' || *ptr == L'-' )
1116 {
1117 if ( wstrcmp(ptr + 1, L"basevideo") == 0 )
1118 base_video = true;
1119 else if ( wstrcmp(ptr + 1, L"mapbs") == 0 )
1120 map_bs = true;
1121 else if ( wstrncmp(ptr + 1, L"cfg=", 4) == 0 )
1122 cfg_file_name = ptr + 5;
1123 else if ( i + 1 < argc && wstrcmp(ptr + 1, L"cfg") == 0 )
1124 cfg_file_name = argv[++i];
1125 else if ( wstrcmp(ptr + 1, L"help") == 0 ||
1126 (ptr[1] == L'?' && !ptr[2]) )
1127 {
1128 PrintStr(L"Xen EFI Loader options:\r\n");
1129 PrintStr(L"-basevideo retain current video mode\r\n");
1130 PrintStr(L"-mapbs map EfiBootServices{Code,Data}\r\n");
1131 PrintStr(L"-cfg=<file> specify configuration file\r\n");
1132 PrintStr(L"-help, -? display this help\r\n");
1133 blexit(NULL);
1134 }
1135 else
1136 {
1137 PrintStr(L"WARNING: Unknown command line option '");
1138 PrintStr(ptr);
1139 PrintStr(L"' ignored\r\n");
1140 }
1141 }
1142 else
1143 section.w = ptr;
1144 }
1145
1146 if ( !base_video )
1147 efi_console_set_mode();
1148 }
1149
1150 PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION)
1151 XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n");
1152
1153 efi_arch_relocate_image(0);
1154
1155 if ( use_cfg_file )
1156 {
1157 EFI_FILE_HANDLE dir_handle;
1158 UINTN depth, cols, rows, size;
1159
1160 size = cols = rows = depth = 0;
1161
1162 if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
1163 &cols, &rows) == EFI_SUCCESS )
1164 efi_arch_console_init(cols, rows);
1165
1166 gop = efi_get_gop();
1167
1168 /* Get the file system interface. */
1169 dir_handle = get_parent_handle(loaded_image, &file_name);
1170
1171 /* Read and parse the config file. */
1172 if ( !cfg_file_name )
1173 {
1174 CHAR16 *tail;
1175
1176 while ( (tail = point_tail(file_name)) != NULL )
1177 {
1178 wstrcpy(tail, L".cfg");
1179 if ( read_file(dir_handle, file_name, &cfg, NULL) )
1180 break;
1181 *tail = 0;
1182 }
1183 if ( !tail )
1184 blexit(L"No configuration file found.");
1185 PrintStr(L"Using configuration file '");
1186 PrintStr(file_name);
1187 PrintStr(L"'\r\n");
1188 }
1189 else if ( !read_file(dir_handle, cfg_file_name, &cfg, NULL) )
1190 blexit(L"Configuration file not found.");
1191 pre_parse(&cfg);
1192
1193 if ( section.w )
1194 w2s(§ion);
1195 else
1196 section.s = get_value(&cfg, "global", "default");
1197
1198 for ( ; ; )
1199 {
1200 name.s = get_value(&cfg, section.s, "kernel");
1201 if ( name.s )
1202 break;
1203 name.s = get_value(&cfg, "global", "chain");
1204 if ( !name.s )
1205 break;
1206 efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
1207 cfg.addr = 0;
1208 if ( !read_file(dir_handle, s2w(&name), &cfg, NULL) )
1209 {
1210 PrintStr(L"Chained configuration file '");
1211 PrintStr(name.w);
1212 efi_bs->FreePool(name.w);
1213 blexit(L"'not found.");
1214 }
1215 pre_parse(&cfg);
1216 efi_bs->FreePool(name.w);
1217 }
1218
1219 if ( !name.s )
1220 blexit(L"No Dom0 kernel image specified.");
1221
1222 efi_arch_cfg_file_early(dir_handle, section.s);
1223
1224 option_str = split_string(name.s);
1225 read_file(dir_handle, s2w(&name), &kernel, option_str);
1226 efi_bs->FreePool(name.w);
1227
1228 if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
1229 (void **)&shim_lock)) &&
1230 (status = shim_lock->Verify(kernel.ptr, kernel.size)) != EFI_SUCCESS )
1231 PrintErrMesg(L"Dom0 kernel image could not be verified", status);
1232
1233 name.s = get_value(&cfg, section.s, "ramdisk");
1234 if ( name.s )
1235 {
1236 read_file(dir_handle, s2w(&name), &ramdisk, NULL);
1237 efi_bs->FreePool(name.w);
1238 }
1239
1240 name.s = get_value(&cfg, section.s, "xsm");
1241 if ( name.s )
1242 {
1243 read_file(dir_handle, s2w(&name), &xsm, NULL);
1244 efi_bs->FreePool(name.w);
1245 }
1246
1247 name.s = get_value(&cfg, section.s, "options");
1248 efi_arch_handle_cmdline(argc ? *argv : NULL, options, name.s);
1249
1250 if ( !base_video )
1251 {
1252 name.cs = get_value(&cfg, section.s, "video");
1253 if ( !name.cs )
1254 name.cs = get_value(&cfg, "global", "video");
1255 if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
1256 {
1257 cols = simple_strtoul(name.cs + 4, &name.cs, 10);
1258 if ( *name.cs == 'x' )
1259 rows = simple_strtoul(name.cs + 1, &name.cs, 10);
1260 if ( *name.cs == 'x' )
1261 depth = simple_strtoul(name.cs + 1, &name.cs, 10);
1262 if ( *name.cs )
1263 cols = rows = depth = 0;
1264 }
1265 }
1266
1267 efi_arch_cfg_file_late(dir_handle, section.s);
1268
1269 efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
1270 cfg.addr = 0;
1271
1272 dir_handle->Close(dir_handle);
1273
1274 if ( gop && !base_video )
1275 gop_mode = efi_find_gop_mode(gop, cols, rows, depth);
1276 }
1277
1278 efi_arch_edd();
1279
1280 /* XXX Collect EDID info. */
1281 efi_arch_cpu();
1282
1283 efi_tables();
1284
1285 /* Collect PCI ROM contents. */
1286 setup_efi_pci();
1287
1288 /* Get snapshot of variable store parameters. */
1289 efi_variables();
1290
1291 /* Collect Apple device properties, if any. */
1292 efi_get_apple_properties();
1293
1294 efi_arch_memory_setup();
1295
1296 if ( gop )
1297 efi_set_gop_mode(gop, gop_mode);
1298
1299 efi_exit_boot(ImageHandle, SystemTable);
1300
1301 efi_arch_post_exit_boot();
1302 for( ; ; ); /* not reached */
1303 }
1304
1305 #ifndef CONFIG_ARM /* TODO - runtime service support */
1306
1307 static bool __initdata efi_map_uc;
1308
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
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
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
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
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 _mfn(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