"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(&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 
 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