All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V4 00/15] arm64 EFI stub
@ 2014-09-10  0:51 Roy Franz
  2014-09-10  0:51 ` [PATCH V4 01/15] move x86 EFI boot code to common/efi Roy Franz
                   ` (14 more replies)
  0 siblings, 15 replies; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:51 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

This patch series adds EFI boot support for arm64.  A PE/COFF header is created
in head.S, as there is no toolchain support for PE/COFF on arm64.  This also
has the advantage that the file is both an "Image" file and a PE/COFF
executable - the same binary can be loaded and run either way.  The EFI 'stub'
code is a shim layer that serves as the loader for the XEN kernel in the EFI
environment.  The stub loads the dom0 kernel and initrd if required, and adds
entries for them as well as for the EFI data structures into the device tree
passed to XEN.  Once the device tree is constructed, EFI boot services are
exited, and the stub transfers control to the normal XEN entry point.  The only
indication XEN has that it was loaded via the stub is that the device tree
contains EFI properties.  This is all very similar to the arm/arm64 Linux
kernel EFI stubs.

Changes since v3:
* Add symbolic link from common/efi/boot.c to arch/x86/efi/boot.c.  This
  simplifies the build system changes and resolves the parallel build issues
  in v3.  x86 EFI code build is unchanged, and ARM EFI code uses the normal
  common build structure. (This symlink seems to have confused git's moved file
  detection for boot.c)
* Fix XEN to be Xen throughout
* Fix spacing and missing blank lines between functions
* Add pseudo-prototype of efi_xen_start is head.S, change prototype to take
  pointer instead of integer to avoid cast, add comment explaining saving of x0
* Use uintptr_t in casts from uint to pointer for device tree.
* Change alignment requirements to 4k in PE/COFF header and alignment check
  in code.
* Rebased to latest master branch.

Changes since v2:
* Major refactor to use common EFI entry point and factor out arch specific
  code, rather than factoring out the common code.
* Update entire libfdt to v1.4.0 to provide fdt_create_empty_tree()

Changes since v1:
* Added common/efi directory for shared EFI code, and arch/arm/efi for 
  arm-specfic code.  Global build hacking of -fshort-wchar removed.
  arm32, arm64, and x86 with/without EFI enabled toolchain all build.
  The x86 build previously autodetected whether the EFI version should
  be built or not based on toolchain support.  I couldn't get this working
  nicely with the common code, so for x86 I have the common code always
  build, and the EFI autodection works as normal for building the EFI
  version.
* Basic use of the EFI memory map instead of FDT based memory description.
  More work needed to resolve differences between FDT description of 
  a small number of large memory banks with reserved regions, and EFI's
  potentially long list of available regions, which can be long.
* More refactoring of common EFI code to not directly exit using blexit(),
  as this broke the pre-linking targets.  All shared code returns status,
  and it is up to the caller to exit and clean up.
* Reduced the number of patches.  Refactoring of x86 code first, then moving
  all code to efi-shared.c in one patch.
* Fixed formatting/tab issues in new files, added Emacs footer.
* Fixed efi_get_memory_map to return NULL map pointer on error in addition
  to failed status.
* Added comments in head.S regarding PE/COFF specification, and 1:1 
  mapping used by EFI code.
* Updated device tree bindings to use new multiboot bindings.  Since the stub
  is always built into XEN, we don't have to support older bindings.

Roy Franz (15):
  move x86 EFI boot code to common/efi
  Move x86 specific funtions/variables to arch header
  create arch functions to get and process EFI memory map.
  Add architecture functions for pre/post ExitBootServices
  Add efi_arch_cfg_file() to handle arch specific cfg file fields
  Add efi_arch_handle_cmdline() for processing commandline
  Move x86 specific video and disk probing code
  Add efi_arch_memory() for arch specific memory setup
  Add arch specific module handling to read_file()
  Add SMBIOS and runtime services setup arch functions.
  Add several misc. arch functions for EFI boot code.
  Add efi_arch_use_config_file() function to control use of config file
  add arm64 cache flushing code from linux v3.16
  Update libfdt to v1.4.0
  Add ARM EFI boot support

 config/arm64.mk                             |    1 +
 xen/arch/arm/arm64/Makefile                 |    1 +
 xen/arch/arm/arm64/cache.S                  |  100 ++
 xen/arch/arm/arm64/head.S                   |  150 ++-
 xen/arch/arm/xen.lds.S                      |    1 +
 xen/arch/x86/efi/boot.c                     | 1724 +--------------------------
 xen/arch/x86/efi/runtime.c                  |    2 +-
 xen/common/Makefile                         |    1 +
 xen/common/efi/Makefile                     |    3 +
 xen/common/efi/boot.c                       |  831 +++++++++++++
 xen/common/libfdt/Makefile.libfdt           |    4 +-
 xen/common/libfdt/fdt.c                     |   30 +-
 xen/common/libfdt/fdt_empty_tree.c          |   84 ++
 xen/common/libfdt/fdt_ro.c                  |    7 +-
 xen/common/libfdt/fdt_rw.c                  |   31 +-
 xen/common/libfdt/fdt_sw.c                  |    4 +-
 xen/common/libfdt/fdt_wip.c                 |    2 +-
 xen/common/libfdt/version.lds               |    6 +
 xen/include/asm-arm/arm64/efibind.h         |  216 ++++
 xen/include/asm-arm/efi-boot.h              |  630 ++++++++++
 xen/include/asm-arm/efi.h                   |   29 +
 xen/include/asm-arm/efibind.h               |    2 +
 xen/include/asm-arm/setup.h                 |    2 +-
 xen/include/asm-x86/efi-boot.h              | 1079 +++++++++++++++++
 xen/{arch/x86/efi => include/asm-x86}/efi.h |    0
 xen/include/xen/libfdt/fdt.h                |   93 +-
 xen/include/xen/libfdt/libfdt.h             |  315 ++++-
 xen/include/xen/libfdt/libfdt_env.h         |    4 +
 28 files changed, 3573 insertions(+), 1779 deletions(-)
 create mode 100644 xen/arch/arm/arm64/cache.S
 mode change 100644 => 120000 xen/arch/x86/efi/boot.c
 create mode 100644 xen/common/efi/Makefile
 create mode 100644 xen/common/efi/boot.c
 create mode 100644 xen/common/libfdt/fdt_empty_tree.c
 create mode 100644 xen/include/asm-arm/arm64/efibind.h
 create mode 100644 xen/include/asm-arm/efi-boot.h
 create mode 100644 xen/include/asm-arm/efi.h
 create mode 100644 xen/include/asm-arm/efibind.h
 create mode 100644 xen/include/asm-x86/efi-boot.h
 rename xen/{arch/x86/efi => include/asm-x86}/efi.h (100%)

-- 
2.1.0.rc1

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH V4 01/15] move x86 EFI boot code to common/efi
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
@ 2014-09-10  0:51 ` Roy Franz
  2014-09-11 13:50   ` Jan Beulich
  2014-09-10  0:51 ` [PATCH V4 02/15] Move x86 specific funtions/variables to arch header Roy Franz
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:51 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

This moves the boot.c,the file that implements the EFI entry point
to efi/common, and builds with both EFI/non-EFI toolchains.  No code
changes, just file movement and make updates.
Note that since both the EFI and non-EFI versions are built at the
same time, the EFI boot code cannot be included in the common/build_in.o.
In the ARM case, it will always be built in, so the normal common
build infrastructure can be used.
The EFI runtime code is left alone as this patch series just
implements the boot code.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/arch/x86/efi/boot.c                     | 1724 +--------------------------
 xen/arch/x86/efi/runtime.c                  |    2 +-
 xen/common/efi/boot.c                       | 1723 ++++++++++++++++++++++++++
 xen/{arch/x86/efi => include/asm-x86}/efi.h |    0
 4 files changed, 1725 insertions(+), 1724 deletions(-)
 mode change 100644 => 120000 xen/arch/x86/efi/boot.c
 create mode 100644 xen/common/efi/boot.c
 rename xen/{arch/x86/efi => include/asm-x86}/efi.h (100%)

diff --git a/xen/arch/x86/efi/boot.c b/xen/arch/x86/efi/boot.c
deleted file mode 100644
index 3bdc158..0000000
--- a/xen/arch/x86/efi/boot.c
+++ /dev/null
@@ -1,1723 +0,0 @@
-#include "efi.h"
-#include <efi/efiprot.h>
-#include <efi/efipciio.h>
-#include <public/xen.h>
-#include <xen/compile.h>
-#include <xen/ctype.h>
-#include <xen/dmi.h>
-#include <xen/init.h>
-#include <xen/keyhandler.h>
-#include <xen/lib.h>
-#include <xen/mm.h>
-#include <xen/multiboot.h>
-#include <xen/pci_regs.h>
-#include <xen/pfn.h>
-#if EFI_PAGE_SIZE != PAGE_SIZE
-# error Cannot use xen/pfn.h here!
-#endif
-#include <xen/string.h>
-#include <xen/stringify.h>
-#include <xen/vga.h>
-#include <asm/e820.h>
-#include <asm/edd.h>
-#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
-#include <asm/fixmap.h>
-#undef __ASSEMBLY__
-#include <asm/msr.h>
-#include <asm/processor.h>
-
-/* Using SetVirtualAddressMap() is incompatible with kexec: */
-#undef USE_SET_VIRTUAL_ADDRESS_MAP
-
-#define SHIM_LOCK_PROTOCOL_GUID \
-  { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
-
-typedef EFI_STATUS
-(/* _not_ EFIAPI */ *EFI_SHIM_LOCK_VERIFY) (
-    IN VOID *Buffer,
-    IN UINT32 Size);
-
-typedef struct {
-    EFI_SHIM_LOCK_VERIFY Verify;
-} EFI_SHIM_LOCK_PROTOCOL;
-
-extern char start[];
-extern u32 cpuid_ext_features;
-
-union string {
-    CHAR16 *w;
-    char *s;
-    const char *cs;
-};
-
-struct file {
-    UINTN size;
-    union {
-        EFI_PHYSICAL_ADDRESS addr;
-        void *ptr;
-    };
-};
-
-static EFI_BOOT_SERVICES *__initdata efi_bs;
-static EFI_HANDLE __initdata efi_ih;
-
-static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdOut;
-static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdErr;
-
-static UINT32 __initdata mdesc_ver;
-
-static struct file __initdata cfg;
-static struct file __initdata kernel;
-static struct file __initdata ramdisk;
-static struct file __initdata ucode;
-static struct file __initdata xsm;
-
-static multiboot_info_t __initdata mbi = {
-    .flags = MBI_MODULES | MBI_LOADERNAME
-};
-static module_t __initdata mb_modules[3];
-
-static CHAR16 __initdata newline[] = L"\r\n";
-
-#define PrintStr(s) StdOut->OutputString(StdOut, s)
-#define PrintErr(s) StdErr->OutputString(StdErr, s)
-
-static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer)
-{
-    if ( Val >= 10 )
-        Buffer = FormatDec(Val / 10, Buffer);
-    *Buffer = (CHAR16)(L'0' + Val % 10);
-    return Buffer + 1;
-}
-
-static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer)
-{
-    if ( Width > 1 || Val >= 0x10 )
-        Buffer = FormatHex(Val >> 4, Width ? Width - 1 : 0, Buffer);
-    *Buffer = (CHAR16)((Val &= 0xf) < 10 ? L'0' + Val : L'a' + Val - 10);
-    return Buffer + 1;
-}
-
-static void __init DisplayUint(UINT64 Val, INTN Width)
-{
-    CHAR16 PrintString[32], *end;
-
-    if (Width < 0)
-        end = FormatDec(Val, PrintString);
-    else
-    {
-        PrintStr(L"0x");
-        end = FormatHex(Val, Width, PrintString);
-    }
-    *end = 0;
-    PrintStr(PrintString);
-}
-
-static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s)
-{
-    CHAR16 *r = d;
-
-    while ( (*d++ = *s++) != 0 )
-        ;
-    return r;
-}
-
-static int __init wstrcmp(const CHAR16 *s1, const CHAR16 *s2)
-{
-    while ( *s1 && *s1 == *s2 )
-    {
-        ++s1;
-        ++s2;
-    }
-    return *s1 - *s2;
-}
-
-static int __init wstrncmp(const CHAR16 *s1, const CHAR16 *s2, UINTN n)
-{
-    while ( n && *s1 && *s1 == *s2 )
-    {
-        --n;
-        ++s1;
-        ++s2;
-    }
-    return n ? *s1 - *s2 : 0;
-}
-
-static CHAR16 *__init s2w(union string *str)
-{
-    const char *s = str->s;
-    CHAR16 *w;
-    void *ptr;
-
-    if ( efi_bs->AllocatePool(EfiLoaderData, (strlen(s) + 1) * sizeof(*w),
-                              &ptr) != EFI_SUCCESS )
-        return NULL;
-
-    w = str->w = ptr;
-    do {
-        *w = *s++;
-    } while ( *w++ );
-
-    return str->w;
-}
-
-static char *__init w2s(const union string *str)
-{
-    const CHAR16 *w = str->w;
-    char *s = str->s;
-
-    do {
-        if ( *w > 0x007f )
-            return NULL;
-        *s = *w++;
-    } while ( *s++ );
-
-    return str->s;
-}
-
-static bool_t __init match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2)
-{
-    return guid1->Data1 == guid2->Data1 &&
-           guid1->Data2 == guid2->Data2 &&
-           guid1->Data3 == guid2->Data3 &&
-           !memcmp(guid1->Data4, guid2->Data4, sizeof(guid1->Data4));
-}
-
-static void __init noreturn blexit(const CHAR16 *str)
-{
-    if ( str )
-        PrintStr((CHAR16 *)str);
-    PrintStr(newline);
-
-    if ( cfg.addr )
-        efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
-    if ( kernel.addr )
-        efi_bs->FreePages(kernel.addr, PFN_UP(kernel.size));
-    if ( ramdisk.addr )
-        efi_bs->FreePages(ramdisk.addr, PFN_UP(ramdisk.size));
-    if ( ucode.addr )
-        efi_bs->FreePages(ucode.addr, PFN_UP(ucode.size));
-    if ( xsm.addr )
-        efi_bs->FreePages(xsm.addr, PFN_UP(xsm.size));
-
-    efi_bs->Exit(efi_ih, EFI_SUCCESS, 0, NULL);
-    unreachable(); /* not reached */
-}
-
-/* generic routine for printing error messages */
-static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode)
-{
-    StdOut = StdErr;
-    PrintErr((CHAR16 *)mesg);
-    PrintErr(L": ");
-
-    switch (ErrCode)
-    {
-    case EFI_NOT_FOUND:
-        mesg = L"Not found";
-        break;
-    case EFI_NO_MEDIA:
-        mesg = L"The device has no media";
-        break;
-    case EFI_MEDIA_CHANGED:
-        mesg = L"Media changed";
-        break;
-    case EFI_DEVICE_ERROR:
-        mesg = L"Device error";
-        break;
-    case EFI_VOLUME_CORRUPTED:
-        mesg = L"Volume corrupted";
-        break;
-    case EFI_ACCESS_DENIED:
-        mesg = L"Access denied";
-        break;
-    case EFI_OUT_OF_RESOURCES:
-        mesg = L"Out of resources";
-        break;
-    case EFI_VOLUME_FULL:
-        mesg = L"Volume is full";
-        break;
-    case EFI_SECURITY_VIOLATION:
-        mesg = L"Security violation";
-        break;
-    case EFI_CRC_ERROR:
-        mesg = L"CRC error";
-        break;
-    case EFI_COMPROMISED_DATA:
-        mesg = L"Compromised data";
-        break;
-    default:
-        PrintErr(L"ErrCode: ");
-        DisplayUint(ErrCode, 0);
-        mesg = NULL;
-        break;
-    }
-    blexit(mesg);
-}
-
-static void __init place_string(u32 *addr, const char *s)
-{
-    static char *__initdata alloc = start;
-
-    if ( s && *s )
-    {
-        size_t len1 = strlen(s) + 1;
-        const char *old = (char *)(long)*addr;
-        size_t len2 = *addr ? strlen(old) + 1 : 0;
-
-        alloc -= len1 + len2;
-        /*
-         * Insert new string before already existing one. This is needed
-         * for options passed on the command line to override options from
-         * the configuration file.
-         */
-        memcpy(alloc, s, len1);
-        if ( *addr )
-        {
-            alloc[len1 - 1] = ' ';
-            memcpy(alloc + len1, old, len2);
-        }
-    }
-    *addr = (long)alloc;
-}
-
-static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
-                                    CHAR16 *cmdline, UINTN cmdsize)
-{
-    CHAR16 *ptr = (CHAR16 *)(argv + argc + 1), *prev = NULL;
-    bool_t prev_sep = TRUE;
-
-    for ( ; cmdsize > sizeof(*cmdline) && *cmdline;
-            cmdsize -= sizeof(*cmdline), ++cmdline )
-    {
-        bool_t cur_sep = *cmdline == L' ' || *cmdline == L'\t';
-
-        if ( !prev_sep )
-        {
-            if ( cur_sep )
-                ++ptr;
-            else if ( argv )
-            {
-                *ptr = *cmdline;
-                *++ptr = 0;
-            }
-        }
-        else if ( !cur_sep )
-        {
-            if ( !argv )
-                ++argc;
-            else if ( prev && wstrcmp(prev, L"--") == 0 )
-            {
-                union string rest = { .w = cmdline };
-
-                --argv;
-                place_string(&mbi.cmdline, w2s(&rest));
-                break;
-            }
-            else
-            {
-                *argv++ = prev = ptr;
-                *ptr = *cmdline;
-                *++ptr = 0;
-            }
-        }
-        prev_sep = cur_sep;
-    }
-    if ( argv )
-        *argv = NULL;
-    return argc;
-}
-
-static EFI_FILE_HANDLE __init get_parent_handle(EFI_LOADED_IMAGE *loaded_image,
-                                                CHAR16 **leaf)
-{
-    static EFI_GUID __initdata fs_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
-    EFI_FILE_HANDLE dir_handle;
-    EFI_DEVICE_PATH *dp;
-    CHAR16 *pathend, *ptr;
-    EFI_STATUS ret;
-
-    do {
-        EFI_FILE_IO_INTERFACE *fio;
-
-        /* Get the file system interface. */
-        ret = efi_bs->HandleProtocol(loaded_image->DeviceHandle,
-                                     &fs_protocol, (void **)&fio);
-        if ( EFI_ERROR(ret) )
-            PrintErrMesg(L"Couldn't obtain the File System Protocol Interface",
-                         ret);
-        ret = fio->OpenVolume(fio, &dir_handle);
-    } while ( ret == EFI_MEDIA_CHANGED );
-    if ( ret != EFI_SUCCESS )
-        PrintErrMesg(L"OpenVolume failure", ret);
-
-#define buffer ((CHAR16 *)keyhandler_scratch)
-#define BUFFERSIZE sizeof(keyhandler_scratch)
-    for ( dp = loaded_image->FilePath, *buffer = 0;
-          DevicePathType(dp) != END_DEVICE_PATH_TYPE;
-          dp = (void *)dp + DevicePathNodeLength(dp) )
-    {
-        FILEPATH_DEVICE_PATH *fp;
-
-        if ( DevicePathType(dp) != MEDIA_DEVICE_PATH ||
-             DevicePathSubType(dp) != MEDIA_FILEPATH_DP )
-            blexit(L"Unsupported device path component");
-
-        if ( *buffer )
-        {
-            EFI_FILE_HANDLE new_handle;
-
-            ret = dir_handle->Open(dir_handle, &new_handle, buffer,
-                                   EFI_FILE_MODE_READ, 0);
-            if ( ret != EFI_SUCCESS )
-            {
-                PrintErr(L"Open failed for ");
-                PrintErrMesg(buffer, ret);
-            }
-            dir_handle->Close(dir_handle);
-            dir_handle = new_handle;
-        }
-        fp = (void *)dp;
-        if ( BUFFERSIZE < DevicePathNodeLength(dp) -
-                          sizeof(*dp) + sizeof(*buffer) )
-            blexit(L"Increase BUFFERSIZE");
-        memcpy(buffer, fp->PathName, DevicePathNodeLength(dp) - sizeof(*dp));
-        buffer[(DevicePathNodeLength(dp) - sizeof(*dp)) / sizeof(*buffer)] = 0;
-    }
-    for ( ptr = buffer, pathend = NULL; *ptr; ++ptr )
-        if ( *ptr == L'\\' )
-            pathend = ptr;
-    if ( pathend )
-    {
-        *pathend = 0;
-        *leaf = pathend + 1;
-        if ( *buffer )
-        {
-            EFI_FILE_HANDLE new_handle;
-
-            ret = dir_handle->Open(dir_handle, &new_handle, buffer,
-                                   EFI_FILE_MODE_READ, 0);
-            if ( ret != EFI_SUCCESS ) {
-                PrintErr(L"Open failed for ");
-                PrintErrMesg(buffer, ret);
-            }
-            dir_handle->Close(dir_handle);
-            dir_handle = new_handle;
-        }
-    }
-    else
-        *leaf = buffer;
-#undef BUFFERSIZE
-#undef buffer
-
-    return dir_handle;
-}
-
-static CHAR16 *__init point_tail(CHAR16 *fn)
-{
-    CHAR16 *tail = NULL;
-
-    for ( ; ; ++fn )
-        switch ( *fn )
-        {
-        case 0:
-            return tail;
-        case L'.':
-        case L'-':
-        case L'_':
-            tail = fn;
-            break;
-        }
-}
-
-static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
-                               struct file *file)
-{
-    EFI_FILE_HANDLE FileHandle = NULL;
-    UINT64 size;
-    EFI_STATUS ret;
-    CHAR16 *what = NULL;
-
-    if ( !name )
-        PrintErrMesg(L"No filename", EFI_OUT_OF_RESOURCES);
-    ret = dir_handle->Open(dir_handle, &FileHandle, name,
-                           EFI_FILE_MODE_READ, 0);
-    if ( file == &cfg && ret == EFI_NOT_FOUND )
-        return 0;
-    if ( EFI_ERROR(ret) )
-        what = L"Open";
-    else
-        ret = FileHandle->SetPosition(FileHandle, -1);
-    if ( EFI_ERROR(ret) )
-        what = what ?: L"Seek";
-    else
-        ret = FileHandle->GetPosition(FileHandle, &size);
-    if ( EFI_ERROR(ret) )
-        what = what ?: L"Get size";
-    else
-        ret = FileHandle->SetPosition(FileHandle, 0);
-    if ( EFI_ERROR(ret) )
-        what = what ?: L"Seek";
-    else
-    {
-        file->addr = min(1UL << (32 + PAGE_SHIFT),
-                         HYPERVISOR_VIRT_END - DIRECTMAP_VIRT_START);
-        ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
-                                    PFN_UP(size), &file->addr);
-    }
-    if ( EFI_ERROR(ret) )
-    {
-        file->addr = 0;
-        what = what ?: L"Allocation";
-    }
-    else
-    {
-        if ( file != &cfg )
-        {
-            PrintStr(name);
-            PrintStr(L": ");
-            DisplayUint(file->addr, 2 * sizeof(file->addr));
-            PrintStr(L"-");
-            DisplayUint(file->addr + size, 2 * sizeof(file->addr));
-            PrintStr(newline);
-            mb_modules[mbi.mods_count].mod_start = file->addr >> PAGE_SHIFT;
-            mb_modules[mbi.mods_count].mod_end = size;
-            ++mbi.mods_count;
-        }
-
-        file->size = size;
-        ret = FileHandle->Read(FileHandle, &file->size, file->ptr);
-        if ( !EFI_ERROR(ret) && file->size != size )
-            ret = EFI_ABORTED;
-        if ( EFI_ERROR(ret) )
-            what = L"Read";
-    }
-
-    if ( FileHandle )
-        FileHandle->Close(FileHandle);
-
-    if ( what )
-    {
-        PrintErr(what);
-        PrintErr(L" failed for ");
-        PrintErrMesg(name, ret);
-    }
-
-    return 1;
-}
-
-static void __init pre_parse(const struct file *cfg)
-{
-    char *ptr = cfg->ptr, *end = ptr + cfg->size;
-    bool_t start = 1, comment = 0;
-
-    for ( ; ptr < end; ++ptr )
-    {
-        if ( iscntrl(*ptr) )
-        {
-            comment = 0;
-            start = 1;
-            *ptr = 0;
-        }
-        else if ( comment || (start && isspace(*ptr)) )
-            *ptr = 0;
-        else if ( *ptr == '#' || (start && *ptr == ';') )
-        {
-            comment = 1;
-            *ptr = 0;
-        }
-        else
-            start = 0;
-    }
-    if ( cfg->size && end[-1] )
-         PrintStr(L"No newline at end of config file,"
-                   " last line will be ignored.\r\n");
-}
-
-static char *__init get_value(const struct file *cfg, const char *section,
-                              const char *item)
-{
-    char *ptr = cfg->ptr, *end = ptr + cfg->size;
-    size_t slen = section ? strlen(section) : 0, ilen = strlen(item);
-    bool_t match = !slen;
-
-    for ( ; ptr < end; ++ptr )
-    {
-        switch ( *ptr )
-        {
-        case 0:
-            continue;
-        case '[':
-            if ( !slen )
-                break;
-            if ( match )
-                return NULL;
-            match = strncmp(++ptr, section, slen) == 0 && ptr[slen] == ']';
-            break;
-        default:
-            if ( match && strncmp(ptr, item, ilen) == 0 && ptr[ilen] == '=' )
-                return ptr + ilen + 1;
-            break;
-        }
-        ptr += strlen(ptr);
-    }
-    return NULL;
-}
-
-static void __init split_value(char *s)
-{
-    while ( *s && isspace(*s) )
-        ++s;
-    place_string(&mb_modules[mbi.mods_count].string, s);
-    while ( *s && !isspace(*s) )
-        ++s;
-    *s = 0;
-}
-
-static void __init edd_put_string(u8 *dst, size_t n, const char *src)
-{
-    while ( n-- && *src )
-       *dst++ = *src++;
-    if ( *src )
-       PrintErrMesg(L"Internal error populating EDD info",
-                    EFI_BUFFER_TOO_SMALL);
-    while ( n-- )
-       *dst++ = ' ';
-}
-#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s)
-
-static void __init setup_efi_pci(void)
-{
-    EFI_STATUS status;
-    EFI_HANDLE *handles;
-    static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL;
-    UINTN i, nr_pci, size = 0;
-    struct efi_pci_rom *last = NULL;
-
-    status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL);
-    if ( status == EFI_BUFFER_TOO_SMALL )
-        status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
-    if ( !EFI_ERROR(status) )
-        status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size,
-                                      handles);
-    if ( EFI_ERROR(status) )
-        size = 0;
-
-    nr_pci = size / sizeof(*handles);
-    for ( i = 0; i < nr_pci; ++i )
-    {
-        EFI_PCI_IO *pci = NULL;
-        u64 attributes;
-        struct efi_pci_rom *rom, *va;
-        UINTN segment, bus, device, function;
-
-        status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci);
-        if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize )
-            continue;
-
-        status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0,
-                                 &attributes);
-        if ( EFI_ERROR(status) ||
-             !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) ||
-             EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device,
-                       &function)) )
-            continue;
-
-        DisplayUint(segment, 4);
-        PrintStr(L":");
-        DisplayUint(bus, 2);
-        PrintStr(L":");
-        DisplayUint(device, 2);
-        PrintStr(L".");
-        DisplayUint(function, 1);
-        PrintStr(L": ROM: ");
-        DisplayUint(pci->RomSize, 0);
-        PrintStr(L" bytes at ");
-        DisplayUint((UINTN)pci->RomImage, 0);
-        PrintStr(newline);
-
-        size = pci->RomSize + sizeof(*rom);
-        status = efi_bs->AllocatePool(EfiRuntimeServicesData, size,
-                                      (void **)&rom);
-        if ( EFI_ERROR(status) )
-            continue;
-
-        rom->next = NULL;
-        rom->size = pci->RomSize;
-
-        status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
-                               &rom->vendor);
-        if ( !EFI_ERROR(status) )
-            status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
-                                   &rom->devid);
-        if ( EFI_ERROR(status) )
-        {
-            efi_bs->FreePool(rom);
-            continue;
-        }
-
-        rom->segment = segment;
-        rom->bus = bus;
-        rom->devfn = (device << 3) | function;
-        memcpy(rom->data, pci->RomImage, pci->RomSize);
-
-        va = (void *)rom + DIRECTMAP_VIRT_START;
-        if ( last )
-            last->next = va;
-        else
-            efi_pci_roms = va;
-        last = rom;
-    }
-
-    efi_bs->FreePool(handles);
-}
-
-static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
-{
-   if ( bpp < 0 )
-       return bpp;
-   if ( !mask )
-       return -EINVAL;
-   for ( *pos = 0; !(mask & 1); ++*pos )
-       mask >>= 1;
-   for ( *sz = 0; mask & 1; ++sz)
-       mask >>= 1;
-   if ( mask )
-       return -EINVAL;
-   return max(*pos + *sz, bpp);
-}
-
-extern const intpte_t __page_tables_start[], __page_tables_end[];
-#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \
-                           (intpte_t *)(v) < __page_tables_end)
-
-#define PE_BASE_RELOC_ABS      0
-#define PE_BASE_RELOC_HIGHLOW  3
-#define PE_BASE_RELOC_DIR64   10
-
-extern const struct pe_base_relocs {
-    u32 rva;
-    u32 size;
-    u16 entries[];
-} __base_relocs_start[], __base_relocs_end[];
-
-static void __init relocate_image(unsigned long delta)
-{
-    const struct pe_base_relocs *base_relocs;
-
-    for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; )
-    {
-        unsigned int i, n;
-
-        n = (base_relocs->size - sizeof(*base_relocs)) /
-            sizeof(*base_relocs->entries);
-        for ( i = 0; i < n; ++i )
-        {
-            unsigned long addr = xen_phys_start + base_relocs->rva +
-                                 (base_relocs->entries[i] & 0xfff);
-
-            switch ( base_relocs->entries[i] >> 12 )
-            {
-            case PE_BASE_RELOC_ABS:
-                break;
-            case PE_BASE_RELOC_HIGHLOW:
-                if ( delta )
-                {
-                    *(u32 *)addr += delta;
-                    if ( in_page_tables(addr) )
-                        *(u32 *)addr += xen_phys_start;
-                }
-                break;
-            case PE_BASE_RELOC_DIR64:
-                if ( delta )
-                {
-                    *(u64 *)addr += delta;
-                    if ( in_page_tables(addr) )
-                        *(intpte_t *)addr += xen_phys_start;
-                }
-                break;
-            default:
-                blexit(L"Unsupported relocation type");
-            }
-        }
-        base_relocs = (const void *)(base_relocs->entries + i + (i & 1));
-    }
-}
-
-extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
-extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
-
-static void __init relocate_trampoline(unsigned long phys)
-{
-    const s32 *trampoline_ptr;
-
-    trampoline_phys = phys;
-    /* Apply relocations to trampoline. */
-    for ( trampoline_ptr = __trampoline_rel_start;
-          trampoline_ptr < __trampoline_rel_stop;
-          ++trampoline_ptr )
-        *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
-    for ( trampoline_ptr = __trampoline_seg_start;
-          trampoline_ptr < __trampoline_seg_stop;
-          ++trampoline_ptr )
-        *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
-}
-
-void EFIAPI __init noreturn
-efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
-{
-    static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL;
-    static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
-    static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL;
-    static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL;
-    static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID;
-    EFI_LOADED_IMAGE *loaded_image;
-    EFI_STATUS status;
-    unsigned int i, argc;
-    CHAR16 **argv, *file_name, *cfg_file_name = NULL;
-    UINTN cols, rows, depth, size, map_key, info_size, gop_mode = ~0;
-    EFI_HANDLE *handles = NULL;
-    EFI_SHIM_LOCK_PROTOCOL *shim_lock;
-    EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
-    EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
-    EFI_FILE_HANDLE dir_handle;
-    union string section = { NULL }, name;
-    struct e820entry *e;
-    u64 efer;
-    bool_t base_video = 0;
-
-    efi_ih = ImageHandle;
-    efi_bs = SystemTable->BootServices;
-    efi_rs = SystemTable->RuntimeServices;
-    efi_ct = SystemTable->ConfigurationTable;
-    efi_num_ct = SystemTable->NumberOfTableEntries;
-    efi_version = SystemTable->Hdr.Revision;
-    efi_fw_vendor = SystemTable->FirmwareVendor;
-    efi_fw_revision = SystemTable->FirmwareRevision;
-
-    StdOut = SystemTable->ConOut;
-    StdErr = SystemTable->StdErr ?: StdOut;
-
-    status = efi_bs->HandleProtocol(ImageHandle, &loaded_image_guid,
-                                    (void **)&loaded_image);
-    if ( status != EFI_SUCCESS )
-        PrintErrMesg(L"No Loaded Image Protocol", status);
-
-    xen_phys_start = (UINTN)loaded_image->ImageBase;
-    if ( (xen_phys_start + loaded_image->ImageSize - 1) >> 32 )
-        blexit(L"Xen must be loaded below 4Gb.");
-    if ( xen_phys_start & ((1 << L2_PAGETABLE_SHIFT) - 1) )
-        blexit(L"Xen must be loaded at a 2Mb boundary.");
-    trampoline_xen_phys_start = xen_phys_start;
-
-    /* Get the file system interface. */
-    dir_handle = get_parent_handle(loaded_image, &file_name);
-
-    argc = get_argv(0, NULL, loaded_image->LoadOptions,
-                    loaded_image->LoadOptionsSize);
-    if ( argc > 0 &&
-         efi_bs->AllocatePool(EfiLoaderData,
-                              (argc + 1) * sizeof(*argv) +
-                                  loaded_image->LoadOptionsSize,
-                              (void **)&argv) == EFI_SUCCESS )
-        get_argv(argc, argv, loaded_image->LoadOptions,
-                 loaded_image->LoadOptionsSize);
-    else
-        argc = 0;
-    for ( i = 1; i < argc; ++i )
-    {
-        CHAR16 *ptr = argv[i];
-
-        if ( !ptr )
-            break;
-        if ( *ptr == L'/' || *ptr == L'-' )
-        {
-            if ( wstrcmp(ptr + 1, L"basevideo") == 0 )
-                base_video = 1;
-            else if ( wstrncmp(ptr + 1, L"cfg=", 4) == 0 )
-                cfg_file_name = ptr + 5;
-            else if ( i + 1 < argc && wstrcmp(ptr + 1, L"cfg") == 0 )
-                cfg_file_name = argv[++i];
-            else if ( wstrcmp(ptr + 1, L"help") == 0 ||
-                      (ptr[1] == L'?' && !ptr[2]) )
-            {
-                PrintStr(L"Xen EFI Loader options:\r\n");
-                PrintStr(L"-basevideo   retain current video mode\r\n");
-                PrintStr(L"-cfg=<file>  specify configuration file\r\n");
-                PrintStr(L"-help, -?    display this help\r\n");
-                blexit(NULL);
-            }
-            else
-            {
-                PrintStr(L"WARNING: Unknown command line option '");
-                PrintStr(ptr);
-                PrintStr(L"' ignored\r\n");
-            }
-        }
-        else
-            section.w = ptr;
-    }
-
-    if ( !base_video )
-    {
-        unsigned int best;
-
-        for ( i = 0, size = 0, best = StdOut->Mode->Mode;
-              i < StdOut->Mode->MaxMode; ++i )
-        {
-            if ( StdOut->QueryMode(StdOut, i, &cols, &rows) == EFI_SUCCESS &&
-                 cols * rows > size )
-            {
-                size = cols * rows;
-                best = i;
-            }
-        }
-        if ( best != StdOut->Mode->Mode )
-            StdOut->SetMode(StdOut, best);
-    }
-
-    PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION)
-             XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n");
-
-    relocate_image(0);
-
-    if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
-                           &cols, &rows) == EFI_SUCCESS )
-    {
-        vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
-        vga_console_info.u.text_mode_3.columns = cols;
-        vga_console_info.u.text_mode_3.rows = rows;
-        vga_console_info.u.text_mode_3.font_height = 16;
-    }
-
-    size = 0;
-    status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size, NULL);
-    if ( status == EFI_BUFFER_TOO_SMALL )
-        status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
-    if ( !EFI_ERROR(status) )
-        status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size,
-                                      handles);
-    if ( EFI_ERROR(status) )
-        size = 0;
-    for ( i = 0; i < size / sizeof(*handles); ++i )
-    {
-        status = efi_bs->HandleProtocol(handles[i], &gop_guid, (void **)&gop);
-        if ( EFI_ERROR(status) )
-            continue;
-        status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
-        if ( !EFI_ERROR(status) )
-            break;
-    }
-    if ( handles )
-        efi_bs->FreePool(handles);
-    if ( EFI_ERROR(status) )
-        gop = NULL;
-
-    /* Read and parse the config file. */
-    if ( !cfg_file_name )
-    {
-        CHAR16 *tail;
-
-        while ( (tail = point_tail(file_name)) != NULL )
-        {
-            wstrcpy(tail, L".cfg");
-            if ( read_file(dir_handle, file_name, &cfg) )
-                break;
-            *tail = 0;
-        }
-        if ( !tail )
-            blexit(L"No configuration file found.");
-        PrintStr(L"Using configuration file '");
-        PrintStr(file_name);
-        PrintStr(L"'\r\n");
-    }
-    else if ( !read_file(dir_handle, cfg_file_name, &cfg) )
-        blexit(L"Configuration file not found.");
-    pre_parse(&cfg);
-
-    if ( section.w )
-        w2s(&section);
-    else
-        section.s = get_value(&cfg, "global", "default");
-
-    for ( ; ; )
-    {
-        name.s = get_value(&cfg, section.s, "kernel");
-        if ( name.s )
-            break;
-        name.s = get_value(&cfg, "global", "chain");
-        if ( !name.s )
-            break;
-        efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
-        cfg.addr = 0;
-        if ( !read_file(dir_handle, s2w(&name), &cfg) )
-        {
-            PrintStr(L"Chained configuration file '");
-            PrintStr(name.w);
-            efi_bs->FreePool(name.w);
-            blexit(L"'not found.");
-        }
-        pre_parse(&cfg);
-        efi_bs->FreePool(name.w);
-    }
-    if ( !name.s )
-        blexit(L"No Dom0 kernel image specified.");
-    split_value(name.s);
-    read_file(dir_handle, s2w(&name), &kernel);
-    efi_bs->FreePool(name.w);
-
-    if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
-                    (void **)&shim_lock)) &&
-         (status = shim_lock->Verify(kernel.ptr, kernel.size)) != EFI_SUCCESS )
-        PrintErrMesg(L"Dom0 kernel image could not be verified", status);
-
-    name.s = get_value(&cfg, section.s, "ramdisk");
-    if ( name.s )
-    {
-        split_value(name.s);
-        read_file(dir_handle, s2w(&name), &ramdisk);
-        efi_bs->FreePool(name.w);
-    }
-
-    name.s = get_value(&cfg, section.s, "ucode");
-    if ( !name.s )
-        name.s = get_value(&cfg, "global", "ucode");
-    if ( name.s )
-    {
-        microcode_set_module(mbi.mods_count);
-        split_value(name.s);
-        read_file(dir_handle, s2w(&name), &ucode);
-        efi_bs->FreePool(name.w);
-    }
-
-    name.s = get_value(&cfg, section.s, "xsm");
-    if ( name.s )
-    {
-        split_value(name.s);
-        read_file(dir_handle, s2w(&name), &xsm);
-        efi_bs->FreePool(name.w);
-    }
-
-    name.s = get_value(&cfg, section.s, "options");
-    if ( name.s )
-        place_string(&mbi.cmdline, name.s);
-    /* Insert image name last, as it gets prefixed to the other options. */
-    if ( argc )
-    {
-        name.w = *argv;
-        w2s(&name);
-    }
-    else
-        name.s = "xen";
-    place_string(&mbi.cmdline, name.s);
-
-    cols = rows = depth = 0;
-    if ( !base_video )
-    {
-        name.cs = get_value(&cfg, section.s, "video");
-        if ( !name.cs )
-            name.cs = get_value(&cfg, "global", "video");
-        if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
-        {
-            cols = simple_strtoul(name.cs + 4, &name.cs, 10);
-            if ( *name.cs == 'x' )
-                rows = simple_strtoul(name.cs + 1, &name.cs, 10);
-            if ( *name.cs == 'x' )
-                depth = simple_strtoul(name.cs + 1, &name.cs, 10);
-            if ( *name.cs )
-                cols = rows = depth = 0;
-        }
-    }
-
-    efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
-    cfg.addr = 0;
-
-    dir_handle->Close(dir_handle);
-
-    if ( gop && !base_video )
-    {
-        for ( i = size = 0; i < gop->Mode->MaxMode; ++i )
-        {
-            unsigned int bpp = 0;
-
-            status = gop->QueryMode(gop, i, &info_size, &mode_info);
-            if ( EFI_ERROR(status) )
-                continue;
-            switch ( mode_info->PixelFormat )
-            {
-            case PixelBitMask:
-                bpp = hweight32(mode_info->PixelInformation.RedMask |
-                                mode_info->PixelInformation.GreenMask |
-                                mode_info->PixelInformation.BlueMask);
-                break;
-            case PixelRedGreenBlueReserved8BitPerColor:
-            case PixelBlueGreenRedReserved8BitPerColor:
-                bpp = 24;
-                break;
-            default:
-                continue;
-            }
-            if ( cols == mode_info->HorizontalResolution &&
-                 rows == mode_info->VerticalResolution &&
-                 (!depth || bpp == depth) )
-            {
-                gop_mode = i;
-                break;
-            }
-            if ( !cols && !rows &&
-                 mode_info->HorizontalResolution *
-                 mode_info->VerticalResolution > size )
-            {
-                size = mode_info->HorizontalResolution *
-                       mode_info->VerticalResolution;
-                gop_mode = i;
-            }
-        }
-    }
-
-    if ( mbi.cmdline )
-        mbi.flags |= MBI_CMDLINE;
-    /*
-     * These must not be initialized statically, since the value must
-     * not get relocated when processing base relocations below.
-     */
-    mbi.boot_loader_name = (long)"EFI";
-    mbi.mods_addr = (long)mb_modules;
-
-    place_string(&mbi.mem_upper, NULL);
-
-    /* Collect EDD info. */
-    BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE);
-    BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE);
-    size = 0;
-    status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, NULL);
-    if ( status == EFI_BUFFER_TOO_SMALL )
-        status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
-    if ( !EFI_ERROR(status) )
-        status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size,
-                                      handles);
-    if ( EFI_ERROR(status) )
-        size = 0;
-    for ( i = 0; i < size / sizeof(*handles); ++i )
-    {
-        EFI_BLOCK_IO *bio;
-        EFI_DEV_PATH_PTR devp;
-        struct edd_info *info = boot_edd_info + boot_edd_info_nr;
-        struct edd_device_params *params = &info->edd_device_params;
-        enum { root, acpi, pci, ctrlr } state = root;
-
-        status = efi_bs->HandleProtocol(handles[i], &bio_guid, (void **)&bio);
-        if ( EFI_ERROR(status) ||
-             bio->Media->RemovableMedia ||
-             bio->Media->LogicalPartition )
-            continue;
-        if ( boot_edd_info_nr < EDD_INFO_MAX )
-        {
-            info->device = 0x80 + boot_edd_info_nr; /* fake */
-            info->version = 0x11;
-            params->length = offsetof(struct edd_device_params, dpte_ptr);
-            params->number_of_sectors = bio->Media->LastBlock + 1;
-            params->bytes_per_sector = bio->Media->BlockSize;
-            params->dpte_ptr = ~0;
-        }
-        ++boot_edd_info_nr;
-        status = efi_bs->HandleProtocol(handles[i], &devp_guid,
-                                        (void **)&devp);
-        if ( EFI_ERROR(status) )
-            continue;
-        for ( ; !IsDevicePathEnd(devp.DevPath);
-              devp.DevPath = NextDevicePathNode(devp.DevPath) )
-        {
-            switch ( DevicePathType(devp.DevPath) )
-            {
-                const u8 *p;
-
-            case ACPI_DEVICE_PATH:
-                if ( state != root || boot_edd_info_nr > EDD_INFO_MAX )
-                    break;
-                switch ( DevicePathSubType(devp.DevPath) )
-                {
-                case ACPI_DP:
-                    if ( devp.Acpi->HID != EISA_PNP_ID(0xA03) &&
-                         devp.Acpi->HID != EISA_PNP_ID(0xA08) )
-                        break;
-                    params->interface_path.pci.bus = devp.Acpi->UID;
-                    state = acpi;
-                    break;
-                case EXPANDED_ACPI_DP:
-                    /* XXX */
-                    break;
-                }
-                break;
-            case HARDWARE_DEVICE_PATH:
-                if ( state != acpi ||
-                     DevicePathSubType(devp.DevPath) != HW_PCI_DP ||
-                     boot_edd_info_nr > EDD_INFO_MAX )
-                    break;
-                state = pci;
-                edd_put_string(params->host_bus_type, "PCI");
-                params->interface_path.pci.slot = devp.Pci->Device;
-                params->interface_path.pci.function = devp.Pci->Function;
-                break;
-            case MESSAGING_DEVICE_PATH:
-                if ( state != pci || boot_edd_info_nr > EDD_INFO_MAX )
-                    break;
-                state = ctrlr;
-                switch ( DevicePathSubType(devp.DevPath) )
-                {
-                case MSG_ATAPI_DP:
-                    edd_put_string(params->interface_type, "ATAPI");
-                    params->interface_path.pci.channel =
-                        devp.Atapi->PrimarySecondary;
-                    params->device_path.atapi.device = devp.Atapi->SlaveMaster;
-                    params->device_path.atapi.lun = devp.Atapi->Lun;
-                    break;
-                case MSG_SCSI_DP:
-                    edd_put_string(params->interface_type, "SCSI");
-                    params->device_path.scsi.id = devp.Scsi->Pun;
-                    params->device_path.scsi.lun = devp.Scsi->Lun;
-                    break;
-                case MSG_FIBRECHANNEL_DP:
-                    edd_put_string(params->interface_type, "FIBRE");
-                    params->device_path.fibre.wwid = devp.FibreChannel->WWN;
-                    params->device_path.fibre.lun = devp.FibreChannel->Lun;
-                    break;
-                case MSG_1394_DP:
-                    edd_put_string(params->interface_type, "1394");
-                    params->device_path.i1394.eui = devp.F1394->Guid;
-                    break;
-                case MSG_USB_DP:
-                case MSG_USB_CLASS_DP:
-                    edd_put_string(params->interface_type, "USB");
-                    break;
-                case MSG_I2O_DP:
-                    edd_put_string(params->interface_type, "I2O");
-                    params->device_path.i2o.identity_tag = devp.I2O->Tid;
-                    break;
-                default:
-                    continue;
-                }
-                info->version = 0x30;
-                params->length = sizeof(struct edd_device_params);
-                params->key = 0xbedd;
-                params->device_path_info_length =
-                    sizeof(struct edd_device_params) -
-                    offsetof(struct edd_device_params, key);
-                for ( p = (const u8 *)&params->key; p < &params->checksum; ++p )
-                    params->checksum -= *p;
-                break;
-            case MEDIA_DEVICE_PATH:
-                if ( DevicePathSubType(devp.DevPath) == MEDIA_HARDDRIVE_DP &&
-                     devp.HardDrive->MBRType == MBR_TYPE_PCAT &&
-                     boot_mbr_signature_nr < EDD_MBR_SIG_MAX )
-                {
-                    struct mbr_signature *sig = boot_mbr_signature +
-                                                boot_mbr_signature_nr;
-
-                    sig->device = 0x80 + boot_edd_info_nr; /* fake */
-                    memcpy(&sig->signature, devp.HardDrive->Signature,
-                           sizeof(sig->signature));
-                    ++boot_mbr_signature_nr;
-                }
-                break;
-            }
-        }
-    }
-    if ( handles )
-        efi_bs->FreePool(handles);
-    if ( boot_edd_info_nr > EDD_INFO_MAX )
-        boot_edd_info_nr = EDD_INFO_MAX;
-
-    /* XXX Collect EDID info. */
-
-    if ( cpuid_eax(0x80000000) > 0x80000000 )
-    {
-        cpuid_ext_features = cpuid_edx(0x80000001);
-        boot_cpu_data.x86_capability[1] = cpuid_ext_features;
-    }
-
-    /* Obtain basic table pointers. */
-    for ( i = 0; i < efi_num_ct; ++i )
-    {
-        static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
-        static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
-        static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
-        static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
-
-        if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
-	       efi.acpi20 = (long)efi_ct[i].VendorTable;
-        if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
-	       efi.acpi = (long)efi_ct[i].VendorTable;
-        if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
-	       efi.mps = (long)efi_ct[i].VendorTable;
-        if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
-	       efi.smbios = (long)efi_ct[i].VendorTable;
-    }
-
-    if (efi.smbios != EFI_INVALID_TABLE_ADDR)
-        dmi_efi_get_table((void *)(long)efi.smbios);
-
-    /* Collect PCI ROM contents. */
-    setup_efi_pci();
-
-    /* Get snapshot of variable store parameters. */
-    status = (efi_rs->Hdr.Revision >> 16) >= 2 ?
-             efi_rs->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE |
-                                       EFI_VARIABLE_BOOTSERVICE_ACCESS |
-                                       EFI_VARIABLE_RUNTIME_ACCESS,
-                                       &efi_boot_max_var_store_size,
-                                       &efi_boot_remain_var_store_size,
-                                       &efi_boot_max_var_size) :
-             EFI_INCOMPATIBLE_VERSION;
-    if ( EFI_ERROR(status) )
-    {
-        efi_boot_max_var_store_size = 0;
-        efi_boot_remain_var_store_size = 0;
-        efi_boot_max_var_size = status;
-        PrintStr(L"Warning: Could not query variable store: ");
-        DisplayUint(status, 0);
-        PrintStr(newline);
-    }
-
-    /* Allocate space for trampoline (in first Mb). */
-    cfg.addr = 0x100000;
-    cfg.size = trampoline_end - trampoline_start;
-    status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
-                                   PFN_UP(cfg.size), &cfg.addr);
-    if ( status == EFI_SUCCESS )
-        relocate_trampoline(cfg.addr);
-    else
-    {
-        cfg.addr = 0;
-        PrintStr(L"Trampoline space cannot be allocated; will try fallback.\r\n");
-    }
-
-    /* Initialise L2 identity-map and boot-map page table entries (16MB). */
-    for ( i = 0; i < 8; ++i )
-    {
-        unsigned int slot = (xen_phys_start >> L2_PAGETABLE_SHIFT) + i;
-        paddr_t addr = slot << L2_PAGETABLE_SHIFT;
-
-        l2_identmap[slot] = l2e_from_paddr(addr, PAGE_HYPERVISOR|_PAGE_PSE);
-        slot &= L2_PAGETABLE_ENTRIES - 1;
-        l2_bootmap[slot] = l2e_from_paddr(addr, __PAGE_HYPERVISOR|_PAGE_PSE);
-    }
-    /* Initialise L3 boot-map page directory entries. */
-    l3_bootmap[l3_table_offset(xen_phys_start)] =
-        l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
-    l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] =
-        l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
-
-    if ( gop )
-    {
-        int bpp = 0;
-
-        /* Set graphics mode. */
-        if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode )
-            gop->SetMode(gop, gop_mode);
-
-        /* Get graphics and frame buffer info. */
-        status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
-        if ( !EFI_ERROR(status) )
-            switch ( mode_info->PixelFormat )
-            {
-            case PixelRedGreenBlueReserved8BitPerColor:
-                vga_console_info.u.vesa_lfb.red_pos = 0;
-                vga_console_info.u.vesa_lfb.red_size = 8;
-                vga_console_info.u.vesa_lfb.green_pos = 8;
-                vga_console_info.u.vesa_lfb.green_size = 8;
-                vga_console_info.u.vesa_lfb.blue_pos = 16;
-                vga_console_info.u.vesa_lfb.blue_size = 8;
-                vga_console_info.u.vesa_lfb.rsvd_pos = 24;
-                vga_console_info.u.vesa_lfb.rsvd_size = 8;
-                bpp = 32;
-                break;
-            case PixelBlueGreenRedReserved8BitPerColor:
-                vga_console_info.u.vesa_lfb.red_pos = 16;
-                vga_console_info.u.vesa_lfb.red_size = 8;
-                vga_console_info.u.vesa_lfb.green_pos = 8;
-                vga_console_info.u.vesa_lfb.green_size = 8;
-                vga_console_info.u.vesa_lfb.blue_pos = 0;
-                vga_console_info.u.vesa_lfb.blue_size = 8;
-                vga_console_info.u.vesa_lfb.rsvd_pos = 24;
-                vga_console_info.u.vesa_lfb.rsvd_size = 8;
-                bpp = 32;
-                break;
-            case PixelBitMask:
-                bpp = set_color(mode_info->PixelInformation.RedMask, bpp,
-                                &vga_console_info.u.vesa_lfb.red_pos,
-                                &vga_console_info.u.vesa_lfb.red_size);
-                bpp = set_color(mode_info->PixelInformation.GreenMask, bpp,
-                                &vga_console_info.u.vesa_lfb.green_pos,
-                                &vga_console_info.u.vesa_lfb.green_size);
-                bpp = set_color(mode_info->PixelInformation.BlueMask, bpp,
-                                &vga_console_info.u.vesa_lfb.blue_pos,
-                                &vga_console_info.u.vesa_lfb.blue_size);
-                bpp = set_color(mode_info->PixelInformation.ReservedMask, bpp,
-                                &vga_console_info.u.vesa_lfb.rsvd_pos,
-                                &vga_console_info.u.vesa_lfb.rsvd_size);
-                if ( bpp > 0 )
-                    break;
-                /* fall through */
-            default:
-                PrintErr(L"Current graphics mode is unsupported!\r\n");
-                status = EFI_UNSUPPORTED;
-                break;
-            }
-        if ( !EFI_ERROR(status) )
-        {
-            vga_console_info.video_type = XEN_VGATYPE_EFI_LFB;
-            vga_console_info.u.vesa_lfb.gbl_caps = 2; /* possibly non-VGA */
-            vga_console_info.u.vesa_lfb.width =
-                mode_info->HorizontalResolution;
-            vga_console_info.u.vesa_lfb.height = mode_info->VerticalResolution;
-            vga_console_info.u.vesa_lfb.bits_per_pixel = bpp;
-            vga_console_info.u.vesa_lfb.bytes_per_line =
-                (mode_info->PixelsPerScanLine * bpp + 7) >> 3;
-            vga_console_info.u.vesa_lfb.lfb_base = gop->Mode->FrameBufferBase;
-            vga_console_info.u.vesa_lfb.lfb_size =
-                (gop->Mode->FrameBufferSize + 0xffff) >> 16;
-        }
-    }
-
-    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
-                         &efi_mdesc_size, &mdesc_ver);
-    mbi.mem_upper -= efi_memmap_size;
-    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
-    if ( mbi.mem_upper < xen_phys_start )
-        blexit(L"Out of static memory");
-    efi_memmap = (void *)(long)mbi.mem_upper;
-    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
-                                  &efi_mdesc_size, &mdesc_ver);
-    if ( EFI_ERROR(status) )
-        PrintErrMesg(L"Cannot obtain memory map", status);
-
-    /* Populate E820 table and check trampoline area availability. */
-    e = e820map - 1;
-    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
-    {
-        EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
-        u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
-        u32 type;
-
-        switch ( desc->Type )
-        {
-        default:
-            type = E820_RESERVED;
-            break;
-        case EfiConventionalMemory:
-        case EfiBootServicesCode:
-        case EfiBootServicesData:
-            if ( !trampoline_phys && desc->PhysicalStart + len <= 0x100000 &&
-                 len >= cfg.size && desc->PhysicalStart + len > cfg.addr )
-                cfg.addr = (desc->PhysicalStart + len - cfg.size) & PAGE_MASK;
-            /* fall through */
-        case EfiLoaderCode:
-        case EfiLoaderData:
-            if ( desc->Attribute & EFI_MEMORY_WB )
-                type = E820_RAM;
-            else
-        case EfiUnusableMemory:
-                type = E820_UNUSABLE;
-            break;
-        case EfiACPIReclaimMemory:
-            type = E820_ACPI;
-            break;
-        case EfiACPIMemoryNVS:
-            type = E820_NVS;
-            break;
-        }
-        if ( e820nr && type == e->type &&
-             desc->PhysicalStart == e->addr + e->size )
-            e->size += len;
-        else if ( !len || e820nr >= E820MAX )
-            continue;
-        else
-        {
-            ++e;
-            e->addr = desc->PhysicalStart;
-            e->size = len;
-            e->type = type;
-            ++e820nr;
-        }
-    }
-    if ( !trampoline_phys )
-    {
-        if ( !cfg.addr )
-            blexit(L"No memory for trampoline");
-        relocate_trampoline(cfg.addr);
-    }
-
-    status = efi_bs->ExitBootServices(ImageHandle, map_key);
-    if ( EFI_ERROR(status) )
-        PrintErrMesg(L"Cannot exit boot services", status);
-
-    /* Adjust pointers into EFI. */
-    efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
-    efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
-#endif
-    efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
-    efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
-
-    relocate_image(__XEN_VIRT_START - xen_phys_start);
-    memcpy((void *)trampoline_phys, trampoline_start, cfg.size);
-
-    /* Set system registers and transfer control. */
-    asm volatile("pushq $0\n\tpopfq");
-    rdmsrl(MSR_EFER, efer);
-    efer |= EFER_SCE;
-    if ( cpuid_ext_features & (1 << (X86_FEATURE_NX & 0x1f)) )
-        efer |= EFER_NX;
-    wrmsrl(MSR_EFER, efer);
-    write_cr0(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP |
-              X86_CR0_AM | X86_CR0_PG);
-    asm volatile ( "mov    %[cr4], %%cr4\n\t"
-                   "mov    %[cr3], %%cr3\n\t"
-                   "movabs $__start_xen, %[rip]\n\t"
-                   "lgdt   gdt_descr(%%rip)\n\t"
-                   "mov    stack_start(%%rip), %%rsp\n\t"
-                   "mov    %[ds], %%ss\n\t"
-                   "mov    %[ds], %%ds\n\t"
-                   "mov    %[ds], %%es\n\t"
-                   "mov    %[ds], %%fs\n\t"
-                   "mov    %[ds], %%gs\n\t"
-                   "movl   %[cs], 8(%%rsp)\n\t"
-                   "mov    %[rip], (%%rsp)\n\t"
-                   "lretq  %[stkoff]-16"
-                   : [rip] "=&r" (efer/* any dead 64-bit variable */)
-                   : [cr3] "r" (idle_pg_table),
-                     [cr4] "r" (mmu_cr4_features),
-                     [cs] "ir" (__HYPERVISOR_CS),
-                     [ds] "r" (__HYPERVISOR_DS),
-                     [stkoff] "i" (STACK_SIZE - sizeof(struct cpu_info)),
-                     "D" (&mbi)
-                   : "memory" );
-    for( ; ; ); /* not reached */
-}
-
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
-static __init void copy_mapping(unsigned long mfn, unsigned long end,
-                                bool_t (*is_valid)(unsigned long smfn,
-                                                   unsigned long emfn))
-{
-    unsigned long next;
-
-    for ( ; mfn < end; mfn = next )
-    {
-        l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
-        l3_pgentry_t *l3src, *l3dst;
-        unsigned long va = (unsigned long)mfn_to_virt(mfn);
-
-        next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
-        if ( !is_valid(mfn, min(next, end)) )
-            continue;
-        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
-        {
-            l3dst = alloc_xen_pagetable();
-            BUG_ON(!l3dst);
-            clear_page(l3dst);
-            efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] =
-                l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR);
-        }
-        else
-            l3dst = l4e_to_l3e(l4e);
-        l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]);
-        l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)];
-    }
-}
-
-static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn)
-{
-    unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1;
-
-    return !(smfn & pfn_hole_mask) &&
-           find_next_bit(pdx_group_valid, sz,
-                         pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz;
-}
-
-static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn)
-{
-    return 1;
-}
-#endif
-
-#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
-                                 (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
-
-void __init efi_init_memory(void)
-{
-    unsigned int i;
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
-    struct rt_extra {
-        struct rt_extra *next;
-        unsigned long smfn, emfn;
-        unsigned int prot;
-    } *extra, *extra_head = NULL;
-#endif
-
-    printk(XENLOG_INFO "EFI memory map:\n");
-    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
-    {
-        EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
-        u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
-        unsigned long smfn, emfn;
-        unsigned int prot = PAGE_HYPERVISOR;
-
-        printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
-                           " type=%u attr=%016" PRIx64 "\n",
-               desc->PhysicalStart, desc->PhysicalStart + len - 1,
-               desc->Type, desc->Attribute);
-
-        if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) )
-            continue;
-
-        desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
-
-        smfn = PFN_DOWN(desc->PhysicalStart);
-        emfn = PFN_UP(desc->PhysicalStart + len);
-
-        if ( desc->Attribute & EFI_MEMORY_WB )
-            /* nothing */;
-        else if ( desc->Attribute & EFI_MEMORY_WT )
-            prot |= _PAGE_PWT | MAP_SMALL_PAGES;
-        else if ( desc->Attribute & EFI_MEMORY_WC )
-            prot |= _PAGE_PAT | MAP_SMALL_PAGES;
-        else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) )
-            prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
-        else
-        {
-            printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n",
-                   smfn, emfn - 1);
-            continue;
-        }
-
-        if ( desc->Attribute & EFI_MEMORY_WP )
-            prot &= _PAGE_RW;
-        if ( desc->Attribute & EFI_MEMORY_XP )
-            prot |= _PAGE_NX_BIT;
-
-        if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) &&
-             !(smfn & pfn_hole_mask) &&
-             !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
-        {
-            if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
-                prot &= ~_PAGE_GLOBAL;
-            if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
-                                  smfn, emfn - smfn, prot) == 0 )
-                desc->VirtualStart =
-                    (unsigned long)maddr_to_virt(desc->PhysicalStart);
-            else
-                printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n",
-                       smfn, emfn - 1);
-        }
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
-        else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) &&
-                  (extra = xmalloc(struct rt_extra)) != NULL )
-        {
-            extra->smfn = smfn;
-            extra->emfn = emfn;
-            extra->prot = prot & ~_PAGE_GLOBAL;
-            extra->next = extra_head;
-            extra_head = extra;
-            desc->VirtualStart = desc->PhysicalStart;
-        }
-#endif
-        else
-        {
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
-            /* XXX allocate e.g. down from FIXADDR_START */
-#endif
-            printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n",
-                   smfn, emfn - 1);
-        }
-    }
-
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
-    efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
-                                 mdesc_ver, efi_memmap);
-#else
-    /* Set up 1:1 page tables to do runtime calls in "physical" mode. */
-    efi_l4_pgtable = alloc_xen_pagetable();
-    BUG_ON(!efi_l4_pgtable);
-    clear_page(efi_l4_pgtable);
-
-    copy_mapping(0, max_page, ram_range_valid);
-
-    /* Insert non-RAM runtime mappings inside the direct map. */
-    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
-    {
-        const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
-
-        if ( (desc->Attribute & EFI_MEMORY_RUNTIME) &&
-             desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
-             desc->VirtualStart != desc->PhysicalStart )
-            copy_mapping(PFN_DOWN(desc->PhysicalStart),
-                         PFN_UP(desc->PhysicalStart +
-                                (desc->NumberOfPages << EFI_PAGE_SHIFT)),
-                         rt_range_valid);
-    }
-
-    /* Insert non-RAM runtime mappings outside of the direct map. */
-    while ( (extra = extra_head) != NULL )
-    {
-        unsigned long addr = extra->smfn << PAGE_SHIFT;
-        l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)];
-        l3_pgentry_t *pl3e;
-        l2_pgentry_t *pl2e;
-        l1_pgentry_t *l1t;
-
-        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
-        {
-            pl3e = alloc_xen_pagetable();
-            BUG_ON(!pl3e);
-            clear_page(pl3e);
-            efi_l4_pgtable[l4_table_offset(addr)] =
-                l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR);
-        }
-        else
-            pl3e = l4e_to_l3e(l4e);
-        pl3e += l3_table_offset(addr);
-        if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
-        {
-            pl2e = alloc_xen_pagetable();
-            BUG_ON(!pl2e);
-            clear_page(pl2e);
-            *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR);
-        }
-        else
-        {
-            BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
-            pl2e = l3e_to_l2e(*pl3e);
-        }
-        pl2e += l2_table_offset(addr);
-        if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
-        {
-            l1t = alloc_xen_pagetable();
-            BUG_ON(!l1t);
-            clear_page(l1t);
-            *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR);
-        }
-        else
-        {
-            BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
-            l1t = l2e_to_l1e(*pl2e);
-        }
-        for ( i = l1_table_offset(addr);
-              i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn;
-              ++i, ++extra->smfn )
-            l1t[i] = l1e_from_pfn(extra->smfn, extra->prot);
-
-        if ( extra->smfn == extra->emfn )
-        {
-            extra_head = extra->next;
-            xfree(extra);
-        }
-    }
-
-    /* Insert Xen mappings. */
-    for ( i = l4_table_offset(HYPERVISOR_VIRT_START);
-          i < l4_table_offset(DIRECTMAP_VIRT_END); ++i )
-        efi_l4_pgtable[i] = idle_pg_table[i];
-#endif
-}
diff --git a/xen/arch/x86/efi/boot.c b/xen/arch/x86/efi/boot.c
new file mode 120000
index 0000000..04e09a6
--- /dev/null
+++ b/xen/arch/x86/efi/boot.c
@@ -0,0 +1 @@
+../../../common/efi/boot.c
\ No newline at end of file
diff --git a/xen/arch/x86/efi/runtime.c b/xen/arch/x86/efi/runtime.c
index 166852d..6788a1a 100644
--- a/xen/arch/x86/efi/runtime.c
+++ b/xen/arch/x86/efi/runtime.c
@@ -1,4 +1,4 @@
-#include "efi.h"
+#include <asm/efi.h>
 #include <xen/cache.h>
 #include <xen/errno.h>
 #include <xen/guest_access.h>
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
new file mode 100644
index 0000000..14e2f46
--- /dev/null
+++ b/xen/common/efi/boot.c
@@ -0,0 +1,1723 @@
+#include <asm/efi.h>
+#include <efi/efiprot.h>
+#include <efi/efipciio.h>
+#include <public/xen.h>
+#include <xen/compile.h>
+#include <xen/ctype.h>
+#include <xen/dmi.h>
+#include <xen/init.h>
+#include <xen/keyhandler.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/multiboot.h>
+#include <xen/pci_regs.h>
+#include <xen/pfn.h>
+#if EFI_PAGE_SIZE != PAGE_SIZE
+# error Cannot use xen/pfn.h here!
+#endif
+#include <xen/string.h>
+#include <xen/stringify.h>
+#include <xen/vga.h>
+#include <asm/e820.h>
+#include <asm/edd.h>
+#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
+#include <asm/fixmap.h>
+#undef __ASSEMBLY__
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+/* Using SetVirtualAddressMap() is incompatible with kexec: */
+#undef USE_SET_VIRTUAL_ADDRESS_MAP
+
+#define SHIM_LOCK_PROTOCOL_GUID \
+  { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
+
+typedef EFI_STATUS
+(/* _not_ EFIAPI */ *EFI_SHIM_LOCK_VERIFY) (
+    IN VOID *Buffer,
+    IN UINT32 Size);
+
+typedef struct {
+    EFI_SHIM_LOCK_VERIFY Verify;
+} EFI_SHIM_LOCK_PROTOCOL;
+
+extern char start[];
+extern u32 cpuid_ext_features;
+
+union string {
+    CHAR16 *w;
+    char *s;
+    const char *cs;
+};
+
+struct file {
+    UINTN size;
+    union {
+        EFI_PHYSICAL_ADDRESS addr;
+        void *ptr;
+    };
+};
+
+static EFI_BOOT_SERVICES *__initdata efi_bs;
+static EFI_HANDLE __initdata efi_ih;
+
+static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdOut;
+static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdErr;
+
+static UINT32 __initdata mdesc_ver;
+
+static struct file __initdata cfg;
+static struct file __initdata kernel;
+static struct file __initdata ramdisk;
+static struct file __initdata ucode;
+static struct file __initdata xsm;
+
+static multiboot_info_t __initdata mbi = {
+    .flags = MBI_MODULES | MBI_LOADERNAME
+};
+static module_t __initdata mb_modules[3];
+
+static CHAR16 __initdata newline[] = L"\r\n";
+
+#define PrintStr(s) StdOut->OutputString(StdOut, s)
+#define PrintErr(s) StdErr->OutputString(StdErr, s)
+
+static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer)
+{
+    if ( Val >= 10 )
+        Buffer = FormatDec(Val / 10, Buffer);
+    *Buffer = (CHAR16)(L'0' + Val % 10);
+    return Buffer + 1;
+}
+
+static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer)
+{
+    if ( Width > 1 || Val >= 0x10 )
+        Buffer = FormatHex(Val >> 4, Width ? Width - 1 : 0, Buffer);
+    *Buffer = (CHAR16)((Val &= 0xf) < 10 ? L'0' + Val : L'a' + Val - 10);
+    return Buffer + 1;
+}
+
+static void __init DisplayUint(UINT64 Val, INTN Width)
+{
+    CHAR16 PrintString[32], *end;
+
+    if (Width < 0)
+        end = FormatDec(Val, PrintString);
+    else
+    {
+        PrintStr(L"0x");
+        end = FormatHex(Val, Width, PrintString);
+    }
+    *end = 0;
+    PrintStr(PrintString);
+}
+
+static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s)
+{
+    CHAR16 *r = d;
+
+    while ( (*d++ = *s++) != 0 )
+        ;
+    return r;
+}
+
+static int __init wstrcmp(const CHAR16 *s1, const CHAR16 *s2)
+{
+    while ( *s1 && *s1 == *s2 )
+    {
+        ++s1;
+        ++s2;
+    }
+    return *s1 - *s2;
+}
+
+static int __init wstrncmp(const CHAR16 *s1, const CHAR16 *s2, UINTN n)
+{
+    while ( n && *s1 && *s1 == *s2 )
+    {
+        --n;
+        ++s1;
+        ++s2;
+    }
+    return n ? *s1 - *s2 : 0;
+}
+
+static CHAR16 *__init s2w(union string *str)
+{
+    const char *s = str->s;
+    CHAR16 *w;
+    void *ptr;
+
+    if ( efi_bs->AllocatePool(EfiLoaderData, (strlen(s) + 1) * sizeof(*w),
+                              &ptr) != EFI_SUCCESS )
+        return NULL;
+
+    w = str->w = ptr;
+    do {
+        *w = *s++;
+    } while ( *w++ );
+
+    return str->w;
+}
+
+static char *__init w2s(const union string *str)
+{
+    const CHAR16 *w = str->w;
+    char *s = str->s;
+
+    do {
+        if ( *w > 0x007f )
+            return NULL;
+        *s = *w++;
+    } while ( *s++ );
+
+    return str->s;
+}
+
+static bool_t __init match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2)
+{
+    return guid1->Data1 == guid2->Data1 &&
+           guid1->Data2 == guid2->Data2 &&
+           guid1->Data3 == guid2->Data3 &&
+           !memcmp(guid1->Data4, guid2->Data4, sizeof(guid1->Data4));
+}
+
+static void __init noreturn blexit(const CHAR16 *str)
+{
+    if ( str )
+        PrintStr((CHAR16 *)str);
+    PrintStr(newline);
+
+    if ( cfg.addr )
+        efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
+    if ( kernel.addr )
+        efi_bs->FreePages(kernel.addr, PFN_UP(kernel.size));
+    if ( ramdisk.addr )
+        efi_bs->FreePages(ramdisk.addr, PFN_UP(ramdisk.size));
+    if ( ucode.addr )
+        efi_bs->FreePages(ucode.addr, PFN_UP(ucode.size));
+    if ( xsm.addr )
+        efi_bs->FreePages(xsm.addr, PFN_UP(xsm.size));
+
+    efi_bs->Exit(efi_ih, EFI_SUCCESS, 0, NULL);
+    unreachable(); /* not reached */
+}
+
+/* generic routine for printing error messages */
+static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode)
+{
+    StdOut = StdErr;
+    PrintErr((CHAR16 *)mesg);
+    PrintErr(L": ");
+
+    switch (ErrCode)
+    {
+    case EFI_NOT_FOUND:
+        mesg = L"Not found";
+        break;
+    case EFI_NO_MEDIA:
+        mesg = L"The device has no media";
+        break;
+    case EFI_MEDIA_CHANGED:
+        mesg = L"Media changed";
+        break;
+    case EFI_DEVICE_ERROR:
+        mesg = L"Device error";
+        break;
+    case EFI_VOLUME_CORRUPTED:
+        mesg = L"Volume corrupted";
+        break;
+    case EFI_ACCESS_DENIED:
+        mesg = L"Access denied";
+        break;
+    case EFI_OUT_OF_RESOURCES:
+        mesg = L"Out of resources";
+        break;
+    case EFI_VOLUME_FULL:
+        mesg = L"Volume is full";
+        break;
+    case EFI_SECURITY_VIOLATION:
+        mesg = L"Security violation";
+        break;
+    case EFI_CRC_ERROR:
+        mesg = L"CRC error";
+        break;
+    case EFI_COMPROMISED_DATA:
+        mesg = L"Compromised data";
+        break;
+    default:
+        PrintErr(L"ErrCode: ");
+        DisplayUint(ErrCode, 0);
+        mesg = NULL;
+        break;
+    }
+    blexit(mesg);
+}
+
+static void __init place_string(u32 *addr, const char *s)
+{
+    static char *__initdata alloc = start;
+
+    if ( s && *s )
+    {
+        size_t len1 = strlen(s) + 1;
+        const char *old = (char *)(long)*addr;
+        size_t len2 = *addr ? strlen(old) + 1 : 0;
+
+        alloc -= len1 + len2;
+        /*
+         * Insert new string before already existing one. This is needed
+         * for options passed on the command line to override options from
+         * the configuration file.
+         */
+        memcpy(alloc, s, len1);
+        if ( *addr )
+        {
+            alloc[len1 - 1] = ' ';
+            memcpy(alloc + len1, old, len2);
+        }
+    }
+    *addr = (long)alloc;
+}
+
+static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
+                                    CHAR16 *cmdline, UINTN cmdsize)
+{
+    CHAR16 *ptr = (CHAR16 *)(argv + argc + 1), *prev = NULL;
+    bool_t prev_sep = TRUE;
+
+    for ( ; cmdsize > sizeof(*cmdline) && *cmdline;
+            cmdsize -= sizeof(*cmdline), ++cmdline )
+    {
+        bool_t cur_sep = *cmdline == L' ' || *cmdline == L'\t';
+
+        if ( !prev_sep )
+        {
+            if ( cur_sep )
+                ++ptr;
+            else if ( argv )
+            {
+                *ptr = *cmdline;
+                *++ptr = 0;
+            }
+        }
+        else if ( !cur_sep )
+        {
+            if ( !argv )
+                ++argc;
+            else if ( prev && wstrcmp(prev, L"--") == 0 )
+            {
+                union string rest = { .w = cmdline };
+
+                --argv;
+                place_string(&mbi.cmdline, w2s(&rest));
+                break;
+            }
+            else
+            {
+                *argv++ = prev = ptr;
+                *ptr = *cmdline;
+                *++ptr = 0;
+            }
+        }
+        prev_sep = cur_sep;
+    }
+    if ( argv )
+        *argv = NULL;
+    return argc;
+}
+
+static EFI_FILE_HANDLE __init get_parent_handle(EFI_LOADED_IMAGE *loaded_image,
+                                                CHAR16 **leaf)
+{
+    static EFI_GUID __initdata fs_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
+    EFI_FILE_HANDLE dir_handle;
+    EFI_DEVICE_PATH *dp;
+    CHAR16 *pathend, *ptr;
+    EFI_STATUS ret;
+
+    do {
+        EFI_FILE_IO_INTERFACE *fio;
+
+        /* Get the file system interface. */
+        ret = efi_bs->HandleProtocol(loaded_image->DeviceHandle,
+                                     &fs_protocol, (void **)&fio);
+        if ( EFI_ERROR(ret) )
+            PrintErrMesg(L"Couldn't obtain the File System Protocol Interface",
+                         ret);
+        ret = fio->OpenVolume(fio, &dir_handle);
+    } while ( ret == EFI_MEDIA_CHANGED );
+    if ( ret != EFI_SUCCESS )
+        PrintErrMesg(L"OpenVolume failure", ret);
+
+#define buffer ((CHAR16 *)keyhandler_scratch)
+#define BUFFERSIZE sizeof(keyhandler_scratch)
+    for ( dp = loaded_image->FilePath, *buffer = 0;
+          DevicePathType(dp) != END_DEVICE_PATH_TYPE;
+          dp = (void *)dp + DevicePathNodeLength(dp) )
+    {
+        FILEPATH_DEVICE_PATH *fp;
+
+        if ( DevicePathType(dp) != MEDIA_DEVICE_PATH ||
+             DevicePathSubType(dp) != MEDIA_FILEPATH_DP )
+            blexit(L"Unsupported device path component");
+
+        if ( *buffer )
+        {
+            EFI_FILE_HANDLE new_handle;
+
+            ret = dir_handle->Open(dir_handle, &new_handle, buffer,
+                                   EFI_FILE_MODE_READ, 0);
+            if ( ret != EFI_SUCCESS )
+            {
+                PrintErr(L"Open failed for ");
+                PrintErrMesg(buffer, ret);
+            }
+            dir_handle->Close(dir_handle);
+            dir_handle = new_handle;
+        }
+        fp = (void *)dp;
+        if ( BUFFERSIZE < DevicePathNodeLength(dp) -
+                          sizeof(*dp) + sizeof(*buffer) )
+            blexit(L"Increase BUFFERSIZE");
+        memcpy(buffer, fp->PathName, DevicePathNodeLength(dp) - sizeof(*dp));
+        buffer[(DevicePathNodeLength(dp) - sizeof(*dp)) / sizeof(*buffer)] = 0;
+    }
+    for ( ptr = buffer, pathend = NULL; *ptr; ++ptr )
+        if ( *ptr == L'\\' )
+            pathend = ptr;
+    if ( pathend )
+    {
+        *pathend = 0;
+        *leaf = pathend + 1;
+        if ( *buffer )
+        {
+            EFI_FILE_HANDLE new_handle;
+
+            ret = dir_handle->Open(dir_handle, &new_handle, buffer,
+                                   EFI_FILE_MODE_READ, 0);
+            if ( ret != EFI_SUCCESS ) {
+                PrintErr(L"Open failed for ");
+                PrintErrMesg(buffer, ret);
+            }
+            dir_handle->Close(dir_handle);
+            dir_handle = new_handle;
+        }
+    }
+    else
+        *leaf = buffer;
+#undef BUFFERSIZE
+#undef buffer
+
+    return dir_handle;
+}
+
+static CHAR16 *__init point_tail(CHAR16 *fn)
+{
+    CHAR16 *tail = NULL;
+
+    for ( ; ; ++fn )
+        switch ( *fn )
+        {
+        case 0:
+            return tail;
+        case L'.':
+        case L'-':
+        case L'_':
+            tail = fn;
+            break;
+        }
+}
+
+static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
+                               struct file *file)
+{
+    EFI_FILE_HANDLE FileHandle = NULL;
+    UINT64 size;
+    EFI_STATUS ret;
+    CHAR16 *what = NULL;
+
+    if ( !name )
+        PrintErrMesg(L"No filename", EFI_OUT_OF_RESOURCES);
+    ret = dir_handle->Open(dir_handle, &FileHandle, name,
+                           EFI_FILE_MODE_READ, 0);
+    if ( file == &cfg && ret == EFI_NOT_FOUND )
+        return 0;
+    if ( EFI_ERROR(ret) )
+        what = L"Open";
+    else
+        ret = FileHandle->SetPosition(FileHandle, -1);
+    if ( EFI_ERROR(ret) )
+        what = what ?: L"Seek";
+    else
+        ret = FileHandle->GetPosition(FileHandle, &size);
+    if ( EFI_ERROR(ret) )
+        what = what ?: L"Get size";
+    else
+        ret = FileHandle->SetPosition(FileHandle, 0);
+    if ( EFI_ERROR(ret) )
+        what = what ?: L"Seek";
+    else
+    {
+        file->addr = min(1UL << (32 + PAGE_SHIFT),
+                         HYPERVISOR_VIRT_END - DIRECTMAP_VIRT_START);
+        ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
+                                    PFN_UP(size), &file->addr);
+    }
+    if ( EFI_ERROR(ret) )
+    {
+        file->addr = 0;
+        what = what ?: L"Allocation";
+    }
+    else
+    {
+        if ( file != &cfg )
+        {
+            PrintStr(name);
+            PrintStr(L": ");
+            DisplayUint(file->addr, 2 * sizeof(file->addr));
+            PrintStr(L"-");
+            DisplayUint(file->addr + size, 2 * sizeof(file->addr));
+            PrintStr(newline);
+            mb_modules[mbi.mods_count].mod_start = file->addr >> PAGE_SHIFT;
+            mb_modules[mbi.mods_count].mod_end = size;
+            ++mbi.mods_count;
+        }
+
+        file->size = size;
+        ret = FileHandle->Read(FileHandle, &file->size, file->ptr);
+        if ( !EFI_ERROR(ret) && file->size != size )
+            ret = EFI_ABORTED;
+        if ( EFI_ERROR(ret) )
+            what = L"Read";
+    }
+
+    if ( FileHandle )
+        FileHandle->Close(FileHandle);
+
+    if ( what )
+    {
+        PrintErr(what);
+        PrintErr(L" failed for ");
+        PrintErrMesg(name, ret);
+    }
+
+    return 1;
+}
+
+static void __init pre_parse(const struct file *cfg)
+{
+    char *ptr = cfg->ptr, *end = ptr + cfg->size;
+    bool_t start = 1, comment = 0;
+
+    for ( ; ptr < end; ++ptr )
+    {
+        if ( iscntrl(*ptr) )
+        {
+            comment = 0;
+            start = 1;
+            *ptr = 0;
+        }
+        else if ( comment || (start && isspace(*ptr)) )
+            *ptr = 0;
+        else if ( *ptr == '#' || (start && *ptr == ';') )
+        {
+            comment = 1;
+            *ptr = 0;
+        }
+        else
+            start = 0;
+    }
+    if ( cfg->size && end[-1] )
+         PrintStr(L"No newline at end of config file,"
+                   " last line will be ignored.\r\n");
+}
+
+static char *__init get_value(const struct file *cfg, const char *section,
+                              const char *item)
+{
+    char *ptr = cfg->ptr, *end = ptr + cfg->size;
+    size_t slen = section ? strlen(section) : 0, ilen = strlen(item);
+    bool_t match = !slen;
+
+    for ( ; ptr < end; ++ptr )
+    {
+        switch ( *ptr )
+        {
+        case 0:
+            continue;
+        case '[':
+            if ( !slen )
+                break;
+            if ( match )
+                return NULL;
+            match = strncmp(++ptr, section, slen) == 0 && ptr[slen] == ']';
+            break;
+        default:
+            if ( match && strncmp(ptr, item, ilen) == 0 && ptr[ilen] == '=' )
+                return ptr + ilen + 1;
+            break;
+        }
+        ptr += strlen(ptr);
+    }
+    return NULL;
+}
+
+static void __init split_value(char *s)
+{
+    while ( *s && isspace(*s) )
+        ++s;
+    place_string(&mb_modules[mbi.mods_count].string, s);
+    while ( *s && !isspace(*s) )
+        ++s;
+    *s = 0;
+}
+
+static void __init edd_put_string(u8 *dst, size_t n, const char *src)
+{
+    while ( n-- && *src )
+       *dst++ = *src++;
+    if ( *src )
+       PrintErrMesg(L"Internal error populating EDD info",
+                    EFI_BUFFER_TOO_SMALL);
+    while ( n-- )
+       *dst++ = ' ';
+}
+#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s)
+
+static void __init setup_efi_pci(void)
+{
+    EFI_STATUS status;
+    EFI_HANDLE *handles;
+    static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL;
+    UINTN i, nr_pci, size = 0;
+    struct efi_pci_rom *last = NULL;
+
+    status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL);
+    if ( status == EFI_BUFFER_TOO_SMALL )
+        status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
+    if ( !EFI_ERROR(status) )
+        status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size,
+                                      handles);
+    if ( EFI_ERROR(status) )
+        size = 0;
+
+    nr_pci = size / sizeof(*handles);
+    for ( i = 0; i < nr_pci; ++i )
+    {
+        EFI_PCI_IO *pci = NULL;
+        u64 attributes;
+        struct efi_pci_rom *rom, *va;
+        UINTN segment, bus, device, function;
+
+        status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci);
+        if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize )
+            continue;
+
+        status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0,
+                                 &attributes);
+        if ( EFI_ERROR(status) ||
+             !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) ||
+             EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device,
+                       &function)) )
+            continue;
+
+        DisplayUint(segment, 4);
+        PrintStr(L":");
+        DisplayUint(bus, 2);
+        PrintStr(L":");
+        DisplayUint(device, 2);
+        PrintStr(L".");
+        DisplayUint(function, 1);
+        PrintStr(L": ROM: ");
+        DisplayUint(pci->RomSize, 0);
+        PrintStr(L" bytes at ");
+        DisplayUint((UINTN)pci->RomImage, 0);
+        PrintStr(newline);
+
+        size = pci->RomSize + sizeof(*rom);
+        status = efi_bs->AllocatePool(EfiRuntimeServicesData, size,
+                                      (void **)&rom);
+        if ( EFI_ERROR(status) )
+            continue;
+
+        rom->next = NULL;
+        rom->size = pci->RomSize;
+
+        status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
+                               &rom->vendor);
+        if ( !EFI_ERROR(status) )
+            status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
+                                   &rom->devid);
+        if ( EFI_ERROR(status) )
+        {
+            efi_bs->FreePool(rom);
+            continue;
+        }
+
+        rom->segment = segment;
+        rom->bus = bus;
+        rom->devfn = (device << 3) | function;
+        memcpy(rom->data, pci->RomImage, pci->RomSize);
+
+        va = (void *)rom + DIRECTMAP_VIRT_START;
+        if ( last )
+            last->next = va;
+        else
+            efi_pci_roms = va;
+        last = rom;
+    }
+
+    efi_bs->FreePool(handles);
+}
+
+static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
+{
+   if ( bpp < 0 )
+       return bpp;
+   if ( !mask )
+       return -EINVAL;
+   for ( *pos = 0; !(mask & 1); ++*pos )
+       mask >>= 1;
+   for ( *sz = 0; mask & 1; ++sz)
+       mask >>= 1;
+   if ( mask )
+       return -EINVAL;
+   return max(*pos + *sz, bpp);
+}
+
+extern const intpte_t __page_tables_start[], __page_tables_end[];
+#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \
+                           (intpte_t *)(v) < __page_tables_end)
+
+#define PE_BASE_RELOC_ABS      0
+#define PE_BASE_RELOC_HIGHLOW  3
+#define PE_BASE_RELOC_DIR64   10
+
+extern const struct pe_base_relocs {
+    u32 rva;
+    u32 size;
+    u16 entries[];
+} __base_relocs_start[], __base_relocs_end[];
+
+static void __init relocate_image(unsigned long delta)
+{
+    const struct pe_base_relocs *base_relocs;
+
+    for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; )
+    {
+        unsigned int i, n;
+
+        n = (base_relocs->size - sizeof(*base_relocs)) /
+            sizeof(*base_relocs->entries);
+        for ( i = 0; i < n; ++i )
+        {
+            unsigned long addr = xen_phys_start + base_relocs->rva +
+                                 (base_relocs->entries[i] & 0xfff);
+
+            switch ( base_relocs->entries[i] >> 12 )
+            {
+            case PE_BASE_RELOC_ABS:
+                break;
+            case PE_BASE_RELOC_HIGHLOW:
+                if ( delta )
+                {
+                    *(u32 *)addr += delta;
+                    if ( in_page_tables(addr) )
+                        *(u32 *)addr += xen_phys_start;
+                }
+                break;
+            case PE_BASE_RELOC_DIR64:
+                if ( delta )
+                {
+                    *(u64 *)addr += delta;
+                    if ( in_page_tables(addr) )
+                        *(intpte_t *)addr += xen_phys_start;
+                }
+                break;
+            default:
+                blexit(L"Unsupported relocation type");
+            }
+        }
+        base_relocs = (const void *)(base_relocs->entries + i + (i & 1));
+    }
+}
+
+extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
+extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
+
+static void __init relocate_trampoline(unsigned long phys)
+{
+    const s32 *trampoline_ptr;
+
+    trampoline_phys = phys;
+    /* Apply relocations to trampoline. */
+    for ( trampoline_ptr = __trampoline_rel_start;
+          trampoline_ptr < __trampoline_rel_stop;
+          ++trampoline_ptr )
+        *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
+    for ( trampoline_ptr = __trampoline_seg_start;
+          trampoline_ptr < __trampoline_seg_stop;
+          ++trampoline_ptr )
+        *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
+}
+
+void EFIAPI __init noreturn
+efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
+{
+    static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL;
+    static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+    static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL;
+    static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL;
+    static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID;
+    EFI_LOADED_IMAGE *loaded_image;
+    EFI_STATUS status;
+    unsigned int i, argc;
+    CHAR16 **argv, *file_name, *cfg_file_name = NULL;
+    UINTN cols, rows, depth, size, map_key, info_size, gop_mode = ~0;
+    EFI_HANDLE *handles = NULL;
+    EFI_SHIM_LOCK_PROTOCOL *shim_lock;
+    EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
+    EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
+    EFI_FILE_HANDLE dir_handle;
+    union string section = { NULL }, name;
+    struct e820entry *e;
+    u64 efer;
+    bool_t base_video = 0;
+
+    efi_ih = ImageHandle;
+    efi_bs = SystemTable->BootServices;
+    efi_rs = SystemTable->RuntimeServices;
+    efi_ct = SystemTable->ConfigurationTable;
+    efi_num_ct = SystemTable->NumberOfTableEntries;
+    efi_version = SystemTable->Hdr.Revision;
+    efi_fw_vendor = SystemTable->FirmwareVendor;
+    efi_fw_revision = SystemTable->FirmwareRevision;
+
+    StdOut = SystemTable->ConOut;
+    StdErr = SystemTable->StdErr ?: StdOut;
+
+    status = efi_bs->HandleProtocol(ImageHandle, &loaded_image_guid,
+                                    (void **)&loaded_image);
+    if ( status != EFI_SUCCESS )
+        PrintErrMesg(L"No Loaded Image Protocol", status);
+
+    xen_phys_start = (UINTN)loaded_image->ImageBase;
+    if ( (xen_phys_start + loaded_image->ImageSize - 1) >> 32 )
+        blexit(L"Xen must be loaded below 4Gb.");
+    if ( xen_phys_start & ((1 << L2_PAGETABLE_SHIFT) - 1) )
+        blexit(L"Xen must be loaded at a 2Mb boundary.");
+    trampoline_xen_phys_start = xen_phys_start;
+
+    /* Get the file system interface. */
+    dir_handle = get_parent_handle(loaded_image, &file_name);
+
+    argc = get_argv(0, NULL, loaded_image->LoadOptions,
+                    loaded_image->LoadOptionsSize);
+    if ( argc > 0 &&
+         efi_bs->AllocatePool(EfiLoaderData,
+                              (argc + 1) * sizeof(*argv) +
+                                  loaded_image->LoadOptionsSize,
+                              (void **)&argv) == EFI_SUCCESS )
+        get_argv(argc, argv, loaded_image->LoadOptions,
+                 loaded_image->LoadOptionsSize);
+    else
+        argc = 0;
+    for ( i = 1; i < argc; ++i )
+    {
+        CHAR16 *ptr = argv[i];
+
+        if ( !ptr )
+            break;
+        if ( *ptr == L'/' || *ptr == L'-' )
+        {
+            if ( wstrcmp(ptr + 1, L"basevideo") == 0 )
+                base_video = 1;
+            else if ( wstrncmp(ptr + 1, L"cfg=", 4) == 0 )
+                cfg_file_name = ptr + 5;
+            else if ( i + 1 < argc && wstrcmp(ptr + 1, L"cfg") == 0 )
+                cfg_file_name = argv[++i];
+            else if ( wstrcmp(ptr + 1, L"help") == 0 ||
+                      (ptr[1] == L'?' && !ptr[2]) )
+            {
+                PrintStr(L"Xen EFI Loader options:\r\n");
+                PrintStr(L"-basevideo   retain current video mode\r\n");
+                PrintStr(L"-cfg=<file>  specify configuration file\r\n");
+                PrintStr(L"-help, -?    display this help\r\n");
+                blexit(NULL);
+            }
+            else
+            {
+                PrintStr(L"WARNING: Unknown command line option '");
+                PrintStr(ptr);
+                PrintStr(L"' ignored\r\n");
+            }
+        }
+        else
+            section.w = ptr;
+    }
+
+    if ( !base_video )
+    {
+        unsigned int best;
+
+        for ( i = 0, size = 0, best = StdOut->Mode->Mode;
+              i < StdOut->Mode->MaxMode; ++i )
+        {
+            if ( StdOut->QueryMode(StdOut, i, &cols, &rows) == EFI_SUCCESS &&
+                 cols * rows > size )
+            {
+                size = cols * rows;
+                best = i;
+            }
+        }
+        if ( best != StdOut->Mode->Mode )
+            StdOut->SetMode(StdOut, best);
+    }
+
+    PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION)
+             XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n");
+
+    relocate_image(0);
+
+    if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
+                           &cols, &rows) == EFI_SUCCESS )
+    {
+        vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
+        vga_console_info.u.text_mode_3.columns = cols;
+        vga_console_info.u.text_mode_3.rows = rows;
+        vga_console_info.u.text_mode_3.font_height = 16;
+    }
+
+    size = 0;
+    status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size, NULL);
+    if ( status == EFI_BUFFER_TOO_SMALL )
+        status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
+    if ( !EFI_ERROR(status) )
+        status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size,
+                                      handles);
+    if ( EFI_ERROR(status) )
+        size = 0;
+    for ( i = 0; i < size / sizeof(*handles); ++i )
+    {
+        status = efi_bs->HandleProtocol(handles[i], &gop_guid, (void **)&gop);
+        if ( EFI_ERROR(status) )
+            continue;
+        status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
+        if ( !EFI_ERROR(status) )
+            break;
+    }
+    if ( handles )
+        efi_bs->FreePool(handles);
+    if ( EFI_ERROR(status) )
+        gop = NULL;
+
+    /* Read and parse the config file. */
+    if ( !cfg_file_name )
+    {
+        CHAR16 *tail;
+
+        while ( (tail = point_tail(file_name)) != NULL )
+        {
+            wstrcpy(tail, L".cfg");
+            if ( read_file(dir_handle, file_name, &cfg) )
+                break;
+            *tail = 0;
+        }
+        if ( !tail )
+            blexit(L"No configuration file found.");
+        PrintStr(L"Using configuration file '");
+        PrintStr(file_name);
+        PrintStr(L"'\r\n");
+    }
+    else if ( !read_file(dir_handle, cfg_file_name, &cfg) )
+        blexit(L"Configuration file not found.");
+    pre_parse(&cfg);
+
+    if ( section.w )
+        w2s(&section);
+    else
+        section.s = get_value(&cfg, "global", "default");
+
+    for ( ; ; )
+    {
+        name.s = get_value(&cfg, section.s, "kernel");
+        if ( name.s )
+            break;
+        name.s = get_value(&cfg, "global", "chain");
+        if ( !name.s )
+            break;
+        efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
+        cfg.addr = 0;
+        if ( !read_file(dir_handle, s2w(&name), &cfg) )
+        {
+            PrintStr(L"Chained configuration file '");
+            PrintStr(name.w);
+            efi_bs->FreePool(name.w);
+            blexit(L"'not found.");
+        }
+        pre_parse(&cfg);
+        efi_bs->FreePool(name.w);
+    }
+    if ( !name.s )
+        blexit(L"No Dom0 kernel image specified.");
+    split_value(name.s);
+    read_file(dir_handle, s2w(&name), &kernel);
+    efi_bs->FreePool(name.w);
+
+    if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
+                    (void **)&shim_lock)) &&
+         (status = shim_lock->Verify(kernel.ptr, kernel.size)) != EFI_SUCCESS )
+        PrintErrMesg(L"Dom0 kernel image could not be verified", status);
+
+    name.s = get_value(&cfg, section.s, "ramdisk");
+    if ( name.s )
+    {
+        split_value(name.s);
+        read_file(dir_handle, s2w(&name), &ramdisk);
+        efi_bs->FreePool(name.w);
+    }
+
+    name.s = get_value(&cfg, section.s, "ucode");
+    if ( !name.s )
+        name.s = get_value(&cfg, "global", "ucode");
+    if ( name.s )
+    {
+        microcode_set_module(mbi.mods_count);
+        split_value(name.s);
+        read_file(dir_handle, s2w(&name), &ucode);
+        efi_bs->FreePool(name.w);
+    }
+
+    name.s = get_value(&cfg, section.s, "xsm");
+    if ( name.s )
+    {
+        split_value(name.s);
+        read_file(dir_handle, s2w(&name), &xsm);
+        efi_bs->FreePool(name.w);
+    }
+
+    name.s = get_value(&cfg, section.s, "options");
+    if ( name.s )
+        place_string(&mbi.cmdline, name.s);
+    /* Insert image name last, as it gets prefixed to the other options. */
+    if ( argc )
+    {
+        name.w = *argv;
+        w2s(&name);
+    }
+    else
+        name.s = "xen";
+    place_string(&mbi.cmdline, name.s);
+
+    cols = rows = depth = 0;
+    if ( !base_video )
+    {
+        name.cs = get_value(&cfg, section.s, "video");
+        if ( !name.cs )
+            name.cs = get_value(&cfg, "global", "video");
+        if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
+        {
+            cols = simple_strtoul(name.cs + 4, &name.cs, 10);
+            if ( *name.cs == 'x' )
+                rows = simple_strtoul(name.cs + 1, &name.cs, 10);
+            if ( *name.cs == 'x' )
+                depth = simple_strtoul(name.cs + 1, &name.cs, 10);
+            if ( *name.cs )
+                cols = rows = depth = 0;
+        }
+    }
+
+    efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
+    cfg.addr = 0;
+
+    dir_handle->Close(dir_handle);
+
+    if ( gop && !base_video )
+    {
+        for ( i = size = 0; i < gop->Mode->MaxMode; ++i )
+        {
+            unsigned int bpp = 0;
+
+            status = gop->QueryMode(gop, i, &info_size, &mode_info);
+            if ( EFI_ERROR(status) )
+                continue;
+            switch ( mode_info->PixelFormat )
+            {
+            case PixelBitMask:
+                bpp = hweight32(mode_info->PixelInformation.RedMask |
+                                mode_info->PixelInformation.GreenMask |
+                                mode_info->PixelInformation.BlueMask);
+                break;
+            case PixelRedGreenBlueReserved8BitPerColor:
+            case PixelBlueGreenRedReserved8BitPerColor:
+                bpp = 24;
+                break;
+            default:
+                continue;
+            }
+            if ( cols == mode_info->HorizontalResolution &&
+                 rows == mode_info->VerticalResolution &&
+                 (!depth || bpp == depth) )
+            {
+                gop_mode = i;
+                break;
+            }
+            if ( !cols && !rows &&
+                 mode_info->HorizontalResolution *
+                 mode_info->VerticalResolution > size )
+            {
+                size = mode_info->HorizontalResolution *
+                       mode_info->VerticalResolution;
+                gop_mode = i;
+            }
+        }
+    }
+
+    if ( mbi.cmdline )
+        mbi.flags |= MBI_CMDLINE;
+    /*
+     * These must not be initialized statically, since the value must
+     * not get relocated when processing base relocations below.
+     */
+    mbi.boot_loader_name = (long)"EFI";
+    mbi.mods_addr = (long)mb_modules;
+
+    place_string(&mbi.mem_upper, NULL);
+
+    /* Collect EDD info. */
+    BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE);
+    BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE);
+    size = 0;
+    status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, NULL);
+    if ( status == EFI_BUFFER_TOO_SMALL )
+        status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
+    if ( !EFI_ERROR(status) )
+        status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size,
+                                      handles);
+    if ( EFI_ERROR(status) )
+        size = 0;
+    for ( i = 0; i < size / sizeof(*handles); ++i )
+    {
+        EFI_BLOCK_IO *bio;
+        EFI_DEV_PATH_PTR devp;
+        struct edd_info *info = boot_edd_info + boot_edd_info_nr;
+        struct edd_device_params *params = &info->edd_device_params;
+        enum { root, acpi, pci, ctrlr } state = root;
+
+        status = efi_bs->HandleProtocol(handles[i], &bio_guid, (void **)&bio);
+        if ( EFI_ERROR(status) ||
+             bio->Media->RemovableMedia ||
+             bio->Media->LogicalPartition )
+            continue;
+        if ( boot_edd_info_nr < EDD_INFO_MAX )
+        {
+            info->device = 0x80 + boot_edd_info_nr; /* fake */
+            info->version = 0x11;
+            params->length = offsetof(struct edd_device_params, dpte_ptr);
+            params->number_of_sectors = bio->Media->LastBlock + 1;
+            params->bytes_per_sector = bio->Media->BlockSize;
+            params->dpte_ptr = ~0;
+        }
+        ++boot_edd_info_nr;
+        status = efi_bs->HandleProtocol(handles[i], &devp_guid,
+                                        (void **)&devp);
+        if ( EFI_ERROR(status) )
+            continue;
+        for ( ; !IsDevicePathEnd(devp.DevPath);
+              devp.DevPath = NextDevicePathNode(devp.DevPath) )
+        {
+            switch ( DevicePathType(devp.DevPath) )
+            {
+                const u8 *p;
+
+            case ACPI_DEVICE_PATH:
+                if ( state != root || boot_edd_info_nr > EDD_INFO_MAX )
+                    break;
+                switch ( DevicePathSubType(devp.DevPath) )
+                {
+                case ACPI_DP:
+                    if ( devp.Acpi->HID != EISA_PNP_ID(0xA03) &&
+                         devp.Acpi->HID != EISA_PNP_ID(0xA08) )
+                        break;
+                    params->interface_path.pci.bus = devp.Acpi->UID;
+                    state = acpi;
+                    break;
+                case EXPANDED_ACPI_DP:
+                    /* XXX */
+                    break;
+                }
+                break;
+            case HARDWARE_DEVICE_PATH:
+                if ( state != acpi ||
+                     DevicePathSubType(devp.DevPath) != HW_PCI_DP ||
+                     boot_edd_info_nr > EDD_INFO_MAX )
+                    break;
+                state = pci;
+                edd_put_string(params->host_bus_type, "PCI");
+                params->interface_path.pci.slot = devp.Pci->Device;
+                params->interface_path.pci.function = devp.Pci->Function;
+                break;
+            case MESSAGING_DEVICE_PATH:
+                if ( state != pci || boot_edd_info_nr > EDD_INFO_MAX )
+                    break;
+                state = ctrlr;
+                switch ( DevicePathSubType(devp.DevPath) )
+                {
+                case MSG_ATAPI_DP:
+                    edd_put_string(params->interface_type, "ATAPI");
+                    params->interface_path.pci.channel =
+                        devp.Atapi->PrimarySecondary;
+                    params->device_path.atapi.device = devp.Atapi->SlaveMaster;
+                    params->device_path.atapi.lun = devp.Atapi->Lun;
+                    break;
+                case MSG_SCSI_DP:
+                    edd_put_string(params->interface_type, "SCSI");
+                    params->device_path.scsi.id = devp.Scsi->Pun;
+                    params->device_path.scsi.lun = devp.Scsi->Lun;
+                    break;
+                case MSG_FIBRECHANNEL_DP:
+                    edd_put_string(params->interface_type, "FIBRE");
+                    params->device_path.fibre.wwid = devp.FibreChannel->WWN;
+                    params->device_path.fibre.lun = devp.FibreChannel->Lun;
+                    break;
+                case MSG_1394_DP:
+                    edd_put_string(params->interface_type, "1394");
+                    params->device_path.i1394.eui = devp.F1394->Guid;
+                    break;
+                case MSG_USB_DP:
+                case MSG_USB_CLASS_DP:
+                    edd_put_string(params->interface_type, "USB");
+                    break;
+                case MSG_I2O_DP:
+                    edd_put_string(params->interface_type, "I2O");
+                    params->device_path.i2o.identity_tag = devp.I2O->Tid;
+                    break;
+                default:
+                    continue;
+                }
+                info->version = 0x30;
+                params->length = sizeof(struct edd_device_params);
+                params->key = 0xbedd;
+                params->device_path_info_length =
+                    sizeof(struct edd_device_params) -
+                    offsetof(struct edd_device_params, key);
+                for ( p = (const u8 *)&params->key; p < &params->checksum; ++p )
+                    params->checksum -= *p;
+                break;
+            case MEDIA_DEVICE_PATH:
+                if ( DevicePathSubType(devp.DevPath) == MEDIA_HARDDRIVE_DP &&
+                     devp.HardDrive->MBRType == MBR_TYPE_PCAT &&
+                     boot_mbr_signature_nr < EDD_MBR_SIG_MAX )
+                {
+                    struct mbr_signature *sig = boot_mbr_signature +
+                                                boot_mbr_signature_nr;
+
+                    sig->device = 0x80 + boot_edd_info_nr; /* fake */
+                    memcpy(&sig->signature, devp.HardDrive->Signature,
+                           sizeof(sig->signature));
+                    ++boot_mbr_signature_nr;
+                }
+                break;
+            }
+        }
+    }
+    if ( handles )
+        efi_bs->FreePool(handles);
+    if ( boot_edd_info_nr > EDD_INFO_MAX )
+        boot_edd_info_nr = EDD_INFO_MAX;
+
+    /* XXX Collect EDID info. */
+
+    if ( cpuid_eax(0x80000000) > 0x80000000 )
+    {
+        cpuid_ext_features = cpuid_edx(0x80000001);
+        boot_cpu_data.x86_capability[1] = cpuid_ext_features;
+    }
+
+    /* Obtain basic table pointers. */
+    for ( i = 0; i < efi_num_ct; ++i )
+    {
+        static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
+        static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
+        static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
+        static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
+
+        if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
+	       efi.acpi20 = (long)efi_ct[i].VendorTable;
+        if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
+	       efi.acpi = (long)efi_ct[i].VendorTable;
+        if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
+	       efi.mps = (long)efi_ct[i].VendorTable;
+        if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
+	       efi.smbios = (long)efi_ct[i].VendorTable;
+    }
+
+    if (efi.smbios != EFI_INVALID_TABLE_ADDR)
+        dmi_efi_get_table((void *)(long)efi.smbios);
+
+    /* Collect PCI ROM contents. */
+    setup_efi_pci();
+
+    /* Get snapshot of variable store parameters. */
+    status = (efi_rs->Hdr.Revision >> 16) >= 2 ?
+             efi_rs->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE |
+                                       EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                                       EFI_VARIABLE_RUNTIME_ACCESS,
+                                       &efi_boot_max_var_store_size,
+                                       &efi_boot_remain_var_store_size,
+                                       &efi_boot_max_var_size) :
+             EFI_INCOMPATIBLE_VERSION;
+    if ( EFI_ERROR(status) )
+    {
+        efi_boot_max_var_store_size = 0;
+        efi_boot_remain_var_store_size = 0;
+        efi_boot_max_var_size = status;
+        PrintStr(L"Warning: Could not query variable store: ");
+        DisplayUint(status, 0);
+        PrintStr(newline);
+    }
+
+    /* Allocate space for trampoline (in first Mb). */
+    cfg.addr = 0x100000;
+    cfg.size = trampoline_end - trampoline_start;
+    status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
+                                   PFN_UP(cfg.size), &cfg.addr);
+    if ( status == EFI_SUCCESS )
+        relocate_trampoline(cfg.addr);
+    else
+    {
+        cfg.addr = 0;
+        PrintStr(L"Trampoline space cannot be allocated; will try fallback.\r\n");
+    }
+
+    /* Initialise L2 identity-map and boot-map page table entries (16MB). */
+    for ( i = 0; i < 8; ++i )
+    {
+        unsigned int slot = (xen_phys_start >> L2_PAGETABLE_SHIFT) + i;
+        paddr_t addr = slot << L2_PAGETABLE_SHIFT;
+
+        l2_identmap[slot] = l2e_from_paddr(addr, PAGE_HYPERVISOR|_PAGE_PSE);
+        slot &= L2_PAGETABLE_ENTRIES - 1;
+        l2_bootmap[slot] = l2e_from_paddr(addr, __PAGE_HYPERVISOR|_PAGE_PSE);
+    }
+    /* Initialise L3 boot-map page directory entries. */
+    l3_bootmap[l3_table_offset(xen_phys_start)] =
+        l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
+    l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] =
+        l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
+
+    if ( gop )
+    {
+        int bpp = 0;
+
+        /* Set graphics mode. */
+        if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode )
+            gop->SetMode(gop, gop_mode);
+
+        /* Get graphics and frame buffer info. */
+        status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
+        if ( !EFI_ERROR(status) )
+            switch ( mode_info->PixelFormat )
+            {
+            case PixelRedGreenBlueReserved8BitPerColor:
+                vga_console_info.u.vesa_lfb.red_pos = 0;
+                vga_console_info.u.vesa_lfb.red_size = 8;
+                vga_console_info.u.vesa_lfb.green_pos = 8;
+                vga_console_info.u.vesa_lfb.green_size = 8;
+                vga_console_info.u.vesa_lfb.blue_pos = 16;
+                vga_console_info.u.vesa_lfb.blue_size = 8;
+                vga_console_info.u.vesa_lfb.rsvd_pos = 24;
+                vga_console_info.u.vesa_lfb.rsvd_size = 8;
+                bpp = 32;
+                break;
+            case PixelBlueGreenRedReserved8BitPerColor:
+                vga_console_info.u.vesa_lfb.red_pos = 16;
+                vga_console_info.u.vesa_lfb.red_size = 8;
+                vga_console_info.u.vesa_lfb.green_pos = 8;
+                vga_console_info.u.vesa_lfb.green_size = 8;
+                vga_console_info.u.vesa_lfb.blue_pos = 0;
+                vga_console_info.u.vesa_lfb.blue_size = 8;
+                vga_console_info.u.vesa_lfb.rsvd_pos = 24;
+                vga_console_info.u.vesa_lfb.rsvd_size = 8;
+                bpp = 32;
+                break;
+            case PixelBitMask:
+                bpp = set_color(mode_info->PixelInformation.RedMask, bpp,
+                                &vga_console_info.u.vesa_lfb.red_pos,
+                                &vga_console_info.u.vesa_lfb.red_size);
+                bpp = set_color(mode_info->PixelInformation.GreenMask, bpp,
+                                &vga_console_info.u.vesa_lfb.green_pos,
+                                &vga_console_info.u.vesa_lfb.green_size);
+                bpp = set_color(mode_info->PixelInformation.BlueMask, bpp,
+                                &vga_console_info.u.vesa_lfb.blue_pos,
+                                &vga_console_info.u.vesa_lfb.blue_size);
+                bpp = set_color(mode_info->PixelInformation.ReservedMask, bpp,
+                                &vga_console_info.u.vesa_lfb.rsvd_pos,
+                                &vga_console_info.u.vesa_lfb.rsvd_size);
+                if ( bpp > 0 )
+                    break;
+                /* fall through */
+            default:
+                PrintErr(L"Current graphics mode is unsupported!\r\n");
+                status = EFI_UNSUPPORTED;
+                break;
+            }
+        if ( !EFI_ERROR(status) )
+        {
+            vga_console_info.video_type = XEN_VGATYPE_EFI_LFB;
+            vga_console_info.u.vesa_lfb.gbl_caps = 2; /* possibly non-VGA */
+            vga_console_info.u.vesa_lfb.width =
+                mode_info->HorizontalResolution;
+            vga_console_info.u.vesa_lfb.height = mode_info->VerticalResolution;
+            vga_console_info.u.vesa_lfb.bits_per_pixel = bpp;
+            vga_console_info.u.vesa_lfb.bytes_per_line =
+                (mode_info->PixelsPerScanLine * bpp + 7) >> 3;
+            vga_console_info.u.vesa_lfb.lfb_base = gop->Mode->FrameBufferBase;
+            vga_console_info.u.vesa_lfb.lfb_size =
+                (gop->Mode->FrameBufferSize + 0xffff) >> 16;
+        }
+    }
+
+    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
+                         &efi_mdesc_size, &mdesc_ver);
+    mbi.mem_upper -= efi_memmap_size;
+    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
+    if ( mbi.mem_upper < xen_phys_start )
+        blexit(L"Out of static memory");
+    efi_memmap = (void *)(long)mbi.mem_upper;
+    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
+                                  &efi_mdesc_size, &mdesc_ver);
+    if ( EFI_ERROR(status) )
+        PrintErrMesg(L"Cannot obtain memory map", status);
+
+    /* Populate E820 table and check trampoline area availability. */
+    e = e820map - 1;
+    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+    {
+        EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+        u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
+        u32 type;
+
+        switch ( desc->Type )
+        {
+        default:
+            type = E820_RESERVED;
+            break;
+        case EfiConventionalMemory:
+        case EfiBootServicesCode:
+        case EfiBootServicesData:
+            if ( !trampoline_phys && desc->PhysicalStart + len <= 0x100000 &&
+                 len >= cfg.size && desc->PhysicalStart + len > cfg.addr )
+                cfg.addr = (desc->PhysicalStart + len - cfg.size) & PAGE_MASK;
+            /* fall through */
+        case EfiLoaderCode:
+        case EfiLoaderData:
+            if ( desc->Attribute & EFI_MEMORY_WB )
+                type = E820_RAM;
+            else
+        case EfiUnusableMemory:
+                type = E820_UNUSABLE;
+            break;
+        case EfiACPIReclaimMemory:
+            type = E820_ACPI;
+            break;
+        case EfiACPIMemoryNVS:
+            type = E820_NVS;
+            break;
+        }
+        if ( e820nr && type == e->type &&
+             desc->PhysicalStart == e->addr + e->size )
+            e->size += len;
+        else if ( !len || e820nr >= E820MAX )
+            continue;
+        else
+        {
+            ++e;
+            e->addr = desc->PhysicalStart;
+            e->size = len;
+            e->type = type;
+            ++e820nr;
+        }
+    }
+    if ( !trampoline_phys )
+    {
+        if ( !cfg.addr )
+            blexit(L"No memory for trampoline");
+        relocate_trampoline(cfg.addr);
+    }
+
+    status = efi_bs->ExitBootServices(ImageHandle, map_key);
+    if ( EFI_ERROR(status) )
+        PrintErrMesg(L"Cannot exit boot services", status);
+
+    /* Adjust pointers into EFI. */
+    efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+    efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
+#endif
+    efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
+    efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
+
+    relocate_image(__XEN_VIRT_START - xen_phys_start);
+    memcpy((void *)trampoline_phys, trampoline_start, cfg.size);
+
+    /* Set system registers and transfer control. */
+    asm volatile("pushq $0\n\tpopfq");
+    rdmsrl(MSR_EFER, efer);
+    efer |= EFER_SCE;
+    if ( cpuid_ext_features & (1 << (X86_FEATURE_NX & 0x1f)) )
+        efer |= EFER_NX;
+    wrmsrl(MSR_EFER, efer);
+    write_cr0(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP |
+              X86_CR0_AM | X86_CR0_PG);
+    asm volatile ( "mov    %[cr4], %%cr4\n\t"
+                   "mov    %[cr3], %%cr3\n\t"
+                   "movabs $__start_xen, %[rip]\n\t"
+                   "lgdt   gdt_descr(%%rip)\n\t"
+                   "mov    stack_start(%%rip), %%rsp\n\t"
+                   "mov    %[ds], %%ss\n\t"
+                   "mov    %[ds], %%ds\n\t"
+                   "mov    %[ds], %%es\n\t"
+                   "mov    %[ds], %%fs\n\t"
+                   "mov    %[ds], %%gs\n\t"
+                   "movl   %[cs], 8(%%rsp)\n\t"
+                   "mov    %[rip], (%%rsp)\n\t"
+                   "lretq  %[stkoff]-16"
+                   : [rip] "=&r" (efer/* any dead 64-bit variable */)
+                   : [cr3] "r" (idle_pg_table),
+                     [cr4] "r" (mmu_cr4_features),
+                     [cs] "ir" (__HYPERVISOR_CS),
+                     [ds] "r" (__HYPERVISOR_DS),
+                     [stkoff] "i" (STACK_SIZE - sizeof(struct cpu_info)),
+                     "D" (&mbi)
+                   : "memory" );
+    for( ; ; ); /* not reached */
+}
+
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+static __init void copy_mapping(unsigned long mfn, unsigned long end,
+                                bool_t (*is_valid)(unsigned long smfn,
+                                                   unsigned long emfn))
+{
+    unsigned long next;
+
+    for ( ; mfn < end; mfn = next )
+    {
+        l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
+        l3_pgentry_t *l3src, *l3dst;
+        unsigned long va = (unsigned long)mfn_to_virt(mfn);
+
+        next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
+        if ( !is_valid(mfn, min(next, end)) )
+            continue;
+        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+        {
+            l3dst = alloc_xen_pagetable();
+            BUG_ON(!l3dst);
+            clear_page(l3dst);
+            efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] =
+                l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR);
+        }
+        else
+            l3dst = l4e_to_l3e(l4e);
+        l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]);
+        l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)];
+    }
+}
+
+static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn)
+{
+    unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1;
+
+    return !(smfn & pfn_hole_mask) &&
+           find_next_bit(pdx_group_valid, sz,
+                         pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz;
+}
+
+static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn)
+{
+    return 1;
+}
+#endif
+
+#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
+                                 (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
+
+void __init efi_init_memory(void)
+{
+    unsigned int i;
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+    struct rt_extra {
+        struct rt_extra *next;
+        unsigned long smfn, emfn;
+        unsigned int prot;
+    } *extra, *extra_head = NULL;
+#endif
+
+    printk(XENLOG_INFO "EFI memory map:\n");
+    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+    {
+        EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+        u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
+        unsigned long smfn, emfn;
+        unsigned int prot = PAGE_HYPERVISOR;
+
+        printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
+                           " type=%u attr=%016" PRIx64 "\n",
+               desc->PhysicalStart, desc->PhysicalStart + len - 1,
+               desc->Type, desc->Attribute);
+
+        if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) )
+            continue;
+
+        desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
+
+        smfn = PFN_DOWN(desc->PhysicalStart);
+        emfn = PFN_UP(desc->PhysicalStart + len);
+
+        if ( desc->Attribute & EFI_MEMORY_WB )
+            /* nothing */;
+        else if ( desc->Attribute & EFI_MEMORY_WT )
+            prot |= _PAGE_PWT | MAP_SMALL_PAGES;
+        else if ( desc->Attribute & EFI_MEMORY_WC )
+            prot |= _PAGE_PAT | MAP_SMALL_PAGES;
+        else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) )
+            prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
+        else
+        {
+            printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n",
+                   smfn, emfn - 1);
+            continue;
+        }
+
+        if ( desc->Attribute & EFI_MEMORY_WP )
+            prot &= _PAGE_RW;
+        if ( desc->Attribute & EFI_MEMORY_XP )
+            prot |= _PAGE_NX_BIT;
+
+        if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) &&
+             !(smfn & pfn_hole_mask) &&
+             !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
+        {
+            if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
+                prot &= ~_PAGE_GLOBAL;
+            if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
+                                  smfn, emfn - smfn, prot) == 0 )
+                desc->VirtualStart =
+                    (unsigned long)maddr_to_virt(desc->PhysicalStart);
+            else
+                printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n",
+                       smfn, emfn - 1);
+        }
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+        else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) &&
+                  (extra = xmalloc(struct rt_extra)) != NULL )
+        {
+            extra->smfn = smfn;
+            extra->emfn = emfn;
+            extra->prot = prot & ~_PAGE_GLOBAL;
+            extra->next = extra_head;
+            extra_head = extra;
+            desc->VirtualStart = desc->PhysicalStart;
+        }
+#endif
+        else
+        {
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+            /* XXX allocate e.g. down from FIXADDR_START */
+#endif
+            printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n",
+                   smfn, emfn - 1);
+        }
+    }
+
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+    efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
+                                 mdesc_ver, efi_memmap);
+#else
+    /* Set up 1:1 page tables to do runtime calls in "physical" mode. */
+    efi_l4_pgtable = alloc_xen_pagetable();
+    BUG_ON(!efi_l4_pgtable);
+    clear_page(efi_l4_pgtable);
+
+    copy_mapping(0, max_page, ram_range_valid);
+
+    /* Insert non-RAM runtime mappings inside the direct map. */
+    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+    {
+        const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+
+        if ( (desc->Attribute & EFI_MEMORY_RUNTIME) &&
+             desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
+             desc->VirtualStart != desc->PhysicalStart )
+            copy_mapping(PFN_DOWN(desc->PhysicalStart),
+                         PFN_UP(desc->PhysicalStart +
+                                (desc->NumberOfPages << EFI_PAGE_SHIFT)),
+                         rt_range_valid);
+    }
+
+    /* Insert non-RAM runtime mappings outside of the direct map. */
+    while ( (extra = extra_head) != NULL )
+    {
+        unsigned long addr = extra->smfn << PAGE_SHIFT;
+        l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)];
+        l3_pgentry_t *pl3e;
+        l2_pgentry_t *pl2e;
+        l1_pgentry_t *l1t;
+
+        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+        {
+            pl3e = alloc_xen_pagetable();
+            BUG_ON(!pl3e);
+            clear_page(pl3e);
+            efi_l4_pgtable[l4_table_offset(addr)] =
+                l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR);
+        }
+        else
+            pl3e = l4e_to_l3e(l4e);
+        pl3e += l3_table_offset(addr);
+        if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
+        {
+            pl2e = alloc_xen_pagetable();
+            BUG_ON(!pl2e);
+            clear_page(pl2e);
+            *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR);
+        }
+        else
+        {
+            BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
+            pl2e = l3e_to_l2e(*pl3e);
+        }
+        pl2e += l2_table_offset(addr);
+        if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
+        {
+            l1t = alloc_xen_pagetable();
+            BUG_ON(!l1t);
+            clear_page(l1t);
+            *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR);
+        }
+        else
+        {
+            BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
+            l1t = l2e_to_l1e(*pl2e);
+        }
+        for ( i = l1_table_offset(addr);
+              i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn;
+              ++i, ++extra->smfn )
+            l1t[i] = l1e_from_pfn(extra->smfn, extra->prot);
+
+        if ( extra->smfn == extra->emfn )
+        {
+            extra_head = extra->next;
+            xfree(extra);
+        }
+    }
+
+    /* Insert Xen mappings. */
+    for ( i = l4_table_offset(HYPERVISOR_VIRT_START);
+          i < l4_table_offset(DIRECTMAP_VIRT_END); ++i )
+        efi_l4_pgtable[i] = idle_pg_table[i];
+#endif
+}
diff --git a/xen/arch/x86/efi/efi.h b/xen/include/asm-x86/efi.h
similarity index 100%
rename from xen/arch/x86/efi/efi.h
rename to xen/include/asm-x86/efi.h
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 02/15] Move x86 specific funtions/variables to arch header
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
  2014-09-10  0:51 ` [PATCH V4 01/15] move x86 EFI boot code to common/efi Roy Franz
@ 2014-09-10  0:51 ` Roy Franz
  2014-09-11 14:03   ` Jan Beulich
  2014-09-10  0:51 ` [PATCH V4 03/15] create arch functions to get and process EFI memory map Roy Franz
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:51 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

Move the global variables and functions that can be moved as-is
from the common boot.c file to the x86 implementation header file.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 460 ++---------------------------------------
 xen/include/asm-x86/efi-boot.h | 451 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 464 insertions(+), 447 deletions(-)
 create mode 100644 xen/include/asm-x86/efi-boot.h

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 14e2f46..ca604be 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -18,16 +18,6 @@
 #include <xen/string.h>
 #include <xen/stringify.h>
 #include <xen/vga.h>
-#include <asm/e820.h>
-#include <asm/edd.h>
-#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
-#include <asm/fixmap.h>
-#undef __ASSEMBLY__
-#include <asm/msr.h>
-#include <asm/processor.h>
-
-/* Using SetVirtualAddressMap() is incompatible with kexec: */
-#undef USE_SET_VIRTUAL_ADDRESS_MAP
 
 #define SHIM_LOCK_PROTOCOL_GUID \
   { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
@@ -41,8 +31,10 @@ typedef struct {
     EFI_SHIM_LOCK_VERIFY Verify;
 } EFI_SHIM_LOCK_PROTOCOL;
 
-extern char start[];
-extern u32 cpuid_ext_features;
+static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer);
+static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer);
+static void __init DisplayUint(UINT64 Val, INTN Width);
+static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s);
 
 union string {
     CHAR16 *w;
@@ -69,19 +61,18 @@ static UINT32 __initdata mdesc_ver;
 static struct file __initdata cfg;
 static struct file __initdata kernel;
 static struct file __initdata ramdisk;
-static struct file __initdata ucode;
 static struct file __initdata xsm;
-
-static multiboot_info_t __initdata mbi = {
-    .flags = MBI_MODULES | MBI_LOADERNAME
-};
-static module_t __initdata mb_modules[3];
-
 static CHAR16 __initdata newline[] = L"\r\n";
 
 #define PrintStr(s) StdOut->OutputString(StdOut, s)
 #define PrintErr(s) StdErr->OutputString(StdErr, s)
 
+/*
+ * Include architecture specific implementation here, which references the
+ * static globals defined above.
+ */
+#include <asm/efi-boot.h>
+
 static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer)
 {
     if ( Val >= 10 )
@@ -255,32 +246,6 @@ static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode)
     blexit(mesg);
 }
 
-static void __init place_string(u32 *addr, const char *s)
-{
-    static char *__initdata alloc = start;
-
-    if ( s && *s )
-    {
-        size_t len1 = strlen(s) + 1;
-        const char *old = (char *)(long)*addr;
-        size_t len2 = *addr ? strlen(old) + 1 : 0;
-
-        alloc -= len1 + len2;
-        /*
-         * Insert new string before already existing one. This is needed
-         * for options passed on the command line to override options from
-         * the configuration file.
-         */
-        memcpy(alloc, s, len1);
-        if ( *addr )
-        {
-            alloc[len1 - 1] = ' ';
-            memcpy(alloc + len1, old, len2);
-        }
-    }
-    *addr = (long)alloc;
-}
-
 static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
                                     CHAR16 *cmdline, UINTN cmdsize)
 {
@@ -574,104 +539,6 @@ static void __init split_value(char *s)
     *s = 0;
 }
 
-static void __init edd_put_string(u8 *dst, size_t n, const char *src)
-{
-    while ( n-- && *src )
-       *dst++ = *src++;
-    if ( *src )
-       PrintErrMesg(L"Internal error populating EDD info",
-                    EFI_BUFFER_TOO_SMALL);
-    while ( n-- )
-       *dst++ = ' ';
-}
-#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s)
-
-static void __init setup_efi_pci(void)
-{
-    EFI_STATUS status;
-    EFI_HANDLE *handles;
-    static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL;
-    UINTN i, nr_pci, size = 0;
-    struct efi_pci_rom *last = NULL;
-
-    status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL);
-    if ( status == EFI_BUFFER_TOO_SMALL )
-        status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
-    if ( !EFI_ERROR(status) )
-        status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size,
-                                      handles);
-    if ( EFI_ERROR(status) )
-        size = 0;
-
-    nr_pci = size / sizeof(*handles);
-    for ( i = 0; i < nr_pci; ++i )
-    {
-        EFI_PCI_IO *pci = NULL;
-        u64 attributes;
-        struct efi_pci_rom *rom, *va;
-        UINTN segment, bus, device, function;
-
-        status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci);
-        if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize )
-            continue;
-
-        status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0,
-                                 &attributes);
-        if ( EFI_ERROR(status) ||
-             !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) ||
-             EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device,
-                       &function)) )
-            continue;
-
-        DisplayUint(segment, 4);
-        PrintStr(L":");
-        DisplayUint(bus, 2);
-        PrintStr(L":");
-        DisplayUint(device, 2);
-        PrintStr(L".");
-        DisplayUint(function, 1);
-        PrintStr(L": ROM: ");
-        DisplayUint(pci->RomSize, 0);
-        PrintStr(L" bytes at ");
-        DisplayUint((UINTN)pci->RomImage, 0);
-        PrintStr(newline);
-
-        size = pci->RomSize + sizeof(*rom);
-        status = efi_bs->AllocatePool(EfiRuntimeServicesData, size,
-                                      (void **)&rom);
-        if ( EFI_ERROR(status) )
-            continue;
-
-        rom->next = NULL;
-        rom->size = pci->RomSize;
-
-        status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
-                               &rom->vendor);
-        if ( !EFI_ERROR(status) )
-            status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
-                                   &rom->devid);
-        if ( EFI_ERROR(status) )
-        {
-            efi_bs->FreePool(rom);
-            continue;
-        }
-
-        rom->segment = segment;
-        rom->bus = bus;
-        rom->devfn = (device << 3) | function;
-        memcpy(rom->data, pci->RomImage, pci->RomSize);
-
-        va = (void *)rom + DIRECTMAP_VIRT_START;
-        if ( last )
-            last->next = va;
-        else
-            efi_pci_roms = va;
-        last = rom;
-    }
-
-    efi_bs->FreePool(handles);
-}
-
 static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
 {
    if ( bpp < 0 )
@@ -687,82 +554,6 @@ static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
    return max(*pos + *sz, bpp);
 }
 
-extern const intpte_t __page_tables_start[], __page_tables_end[];
-#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \
-                           (intpte_t *)(v) < __page_tables_end)
-
-#define PE_BASE_RELOC_ABS      0
-#define PE_BASE_RELOC_HIGHLOW  3
-#define PE_BASE_RELOC_DIR64   10
-
-extern const struct pe_base_relocs {
-    u32 rva;
-    u32 size;
-    u16 entries[];
-} __base_relocs_start[], __base_relocs_end[];
-
-static void __init relocate_image(unsigned long delta)
-{
-    const struct pe_base_relocs *base_relocs;
-
-    for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; )
-    {
-        unsigned int i, n;
-
-        n = (base_relocs->size - sizeof(*base_relocs)) /
-            sizeof(*base_relocs->entries);
-        for ( i = 0; i < n; ++i )
-        {
-            unsigned long addr = xen_phys_start + base_relocs->rva +
-                                 (base_relocs->entries[i] & 0xfff);
-
-            switch ( base_relocs->entries[i] >> 12 )
-            {
-            case PE_BASE_RELOC_ABS:
-                break;
-            case PE_BASE_RELOC_HIGHLOW:
-                if ( delta )
-                {
-                    *(u32 *)addr += delta;
-                    if ( in_page_tables(addr) )
-                        *(u32 *)addr += xen_phys_start;
-                }
-                break;
-            case PE_BASE_RELOC_DIR64:
-                if ( delta )
-                {
-                    *(u64 *)addr += delta;
-                    if ( in_page_tables(addr) )
-                        *(intpte_t *)addr += xen_phys_start;
-                }
-                break;
-            default:
-                blexit(L"Unsupported relocation type");
-            }
-        }
-        base_relocs = (const void *)(base_relocs->entries + i + (i & 1));
-    }
-}
-
-extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
-extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
-
-static void __init relocate_trampoline(unsigned long phys)
-{
-    const s32 *trampoline_ptr;
-
-    trampoline_phys = phys;
-    /* Apply relocations to trampoline. */
-    for ( trampoline_ptr = __trampoline_rel_start;
-          trampoline_ptr < __trampoline_rel_stop;
-          ++trampoline_ptr )
-        *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
-    for ( trampoline_ptr = __trampoline_seg_start;
-          trampoline_ptr < __trampoline_seg_stop;
-          ++trampoline_ptr )
-        *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
-}
-
 void EFIAPI __init noreturn
 efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 {
@@ -879,7 +670,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION)
              XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n");
 
-    relocate_image(0);
+    efi_arch_relocate_image(0);
 
     if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
                            &cols, &rows) == EFI_SUCCESS )
@@ -1258,7 +1049,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
         dmi_efi_get_table((void *)(long)efi.smbios);
 
     /* Collect PCI ROM contents. */
-    setup_efi_pci();
+    efi_arch_pci();
 
     /* Get snapshot of variable store parameters. */
     status = (efi_rs->Hdr.Revision >> 16) >= 2 ?
@@ -1460,7 +1251,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
     efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
 
-    relocate_image(__XEN_VIRT_START - xen_phys_start);
+    efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
     memcpy((void *)trampoline_phys, trampoline_start, cfg.size);
 
     /* Set system registers and transfer control. */
@@ -1496,228 +1287,3 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     for( ; ; ); /* not reached */
 }
 
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
-static __init void copy_mapping(unsigned long mfn, unsigned long end,
-                                bool_t (*is_valid)(unsigned long smfn,
-                                                   unsigned long emfn))
-{
-    unsigned long next;
-
-    for ( ; mfn < end; mfn = next )
-    {
-        l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
-        l3_pgentry_t *l3src, *l3dst;
-        unsigned long va = (unsigned long)mfn_to_virt(mfn);
-
-        next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
-        if ( !is_valid(mfn, min(next, end)) )
-            continue;
-        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
-        {
-            l3dst = alloc_xen_pagetable();
-            BUG_ON(!l3dst);
-            clear_page(l3dst);
-            efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] =
-                l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR);
-        }
-        else
-            l3dst = l4e_to_l3e(l4e);
-        l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]);
-        l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)];
-    }
-}
-
-static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn)
-{
-    unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1;
-
-    return !(smfn & pfn_hole_mask) &&
-           find_next_bit(pdx_group_valid, sz,
-                         pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz;
-}
-
-static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn)
-{
-    return 1;
-}
-#endif
-
-#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
-                                 (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
-
-void __init efi_init_memory(void)
-{
-    unsigned int i;
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
-    struct rt_extra {
-        struct rt_extra *next;
-        unsigned long smfn, emfn;
-        unsigned int prot;
-    } *extra, *extra_head = NULL;
-#endif
-
-    printk(XENLOG_INFO "EFI memory map:\n");
-    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
-    {
-        EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
-        u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
-        unsigned long smfn, emfn;
-        unsigned int prot = PAGE_HYPERVISOR;
-
-        printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
-                           " type=%u attr=%016" PRIx64 "\n",
-               desc->PhysicalStart, desc->PhysicalStart + len - 1,
-               desc->Type, desc->Attribute);
-
-        if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) )
-            continue;
-
-        desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
-
-        smfn = PFN_DOWN(desc->PhysicalStart);
-        emfn = PFN_UP(desc->PhysicalStart + len);
-
-        if ( desc->Attribute & EFI_MEMORY_WB )
-            /* nothing */;
-        else if ( desc->Attribute & EFI_MEMORY_WT )
-            prot |= _PAGE_PWT | MAP_SMALL_PAGES;
-        else if ( desc->Attribute & EFI_MEMORY_WC )
-            prot |= _PAGE_PAT | MAP_SMALL_PAGES;
-        else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) )
-            prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
-        else
-        {
-            printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n",
-                   smfn, emfn - 1);
-            continue;
-        }
-
-        if ( desc->Attribute & EFI_MEMORY_WP )
-            prot &= _PAGE_RW;
-        if ( desc->Attribute & EFI_MEMORY_XP )
-            prot |= _PAGE_NX_BIT;
-
-        if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) &&
-             !(smfn & pfn_hole_mask) &&
-             !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
-        {
-            if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
-                prot &= ~_PAGE_GLOBAL;
-            if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
-                                  smfn, emfn - smfn, prot) == 0 )
-                desc->VirtualStart =
-                    (unsigned long)maddr_to_virt(desc->PhysicalStart);
-            else
-                printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n",
-                       smfn, emfn - 1);
-        }
-#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
-        else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) &&
-                  (extra = xmalloc(struct rt_extra)) != NULL )
-        {
-            extra->smfn = smfn;
-            extra->emfn = emfn;
-            extra->prot = prot & ~_PAGE_GLOBAL;
-            extra->next = extra_head;
-            extra_head = extra;
-            desc->VirtualStart = desc->PhysicalStart;
-        }
-#endif
-        else
-        {
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
-            /* XXX allocate e.g. down from FIXADDR_START */
-#endif
-            printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n",
-                   smfn, emfn - 1);
-        }
-    }
-
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
-    efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
-                                 mdesc_ver, efi_memmap);
-#else
-    /* Set up 1:1 page tables to do runtime calls in "physical" mode. */
-    efi_l4_pgtable = alloc_xen_pagetable();
-    BUG_ON(!efi_l4_pgtable);
-    clear_page(efi_l4_pgtable);
-
-    copy_mapping(0, max_page, ram_range_valid);
-
-    /* Insert non-RAM runtime mappings inside the direct map. */
-    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
-    {
-        const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
-
-        if ( (desc->Attribute & EFI_MEMORY_RUNTIME) &&
-             desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
-             desc->VirtualStart != desc->PhysicalStart )
-            copy_mapping(PFN_DOWN(desc->PhysicalStart),
-                         PFN_UP(desc->PhysicalStart +
-                                (desc->NumberOfPages << EFI_PAGE_SHIFT)),
-                         rt_range_valid);
-    }
-
-    /* Insert non-RAM runtime mappings outside of the direct map. */
-    while ( (extra = extra_head) != NULL )
-    {
-        unsigned long addr = extra->smfn << PAGE_SHIFT;
-        l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)];
-        l3_pgentry_t *pl3e;
-        l2_pgentry_t *pl2e;
-        l1_pgentry_t *l1t;
-
-        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
-        {
-            pl3e = alloc_xen_pagetable();
-            BUG_ON(!pl3e);
-            clear_page(pl3e);
-            efi_l4_pgtable[l4_table_offset(addr)] =
-                l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR);
-        }
-        else
-            pl3e = l4e_to_l3e(l4e);
-        pl3e += l3_table_offset(addr);
-        if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
-        {
-            pl2e = alloc_xen_pagetable();
-            BUG_ON(!pl2e);
-            clear_page(pl2e);
-            *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR);
-        }
-        else
-        {
-            BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
-            pl2e = l3e_to_l2e(*pl3e);
-        }
-        pl2e += l2_table_offset(addr);
-        if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
-        {
-            l1t = alloc_xen_pagetable();
-            BUG_ON(!l1t);
-            clear_page(l1t);
-            *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR);
-        }
-        else
-        {
-            BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
-            l1t = l2e_to_l1e(*pl2e);
-        }
-        for ( i = l1_table_offset(addr);
-              i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn;
-              ++i, ++extra->smfn )
-            l1t[i] = l1e_from_pfn(extra->smfn, extra->prot);
-
-        if ( extra->smfn == extra->emfn )
-        {
-            extra_head = extra->next;
-            xfree(extra);
-        }
-    }
-
-    /* Insert Xen mappings. */
-    for ( i = l4_table_offset(HYPERVISOR_VIRT_START);
-          i < l4_table_offset(DIRECTMAP_VIRT_END); ++i )
-        efi_l4_pgtable[i] = idle_pg_table[i];
-#endif
-}
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
new file mode 100644
index 0000000..4ad83ca
--- /dev/null
+++ b/xen/include/asm-x86/efi-boot.h
@@ -0,0 +1,451 @@
+/*
+ * Architecture specific implementation for EFI boot code.  This file
+ * is intended to be included by XXX _only_, and therefore can define
+ * arch specific global variables.
+ */
+#include <asm/e820.h>
+#include <asm/edd.h>
+#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
+#include <asm/fixmap.h>
+#undef __ASSEMBLY__
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+static struct file __initdata ucode;
+static multiboot_info_t __initdata mbi = {
+    .flags = MBI_MODULES | MBI_LOADERNAME
+};
+static module_t __initdata mb_modules[3];
+
+static void noreturn blexit(const CHAR16 *str);
+static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
+
+/* Using SetVirtualAddressMap() is incompatible with kexec: */
+#undef USE_SET_VIRTUAL_ADDRESS_MAP
+extern char start[];
+extern u32 cpuid_ext_features;
+
+static void __init edd_put_string(u8 *dst, size_t n, const char *src)
+{
+    while ( n-- && *src )
+       *dst++ = *src++;
+    if ( *src )
+       PrintErrMesg(L"Internal error populating EDD info",
+                    EFI_BUFFER_TOO_SMALL);
+    while ( n-- )
+       *dst++ = ' ';
+}
+#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s)
+
+static void __init efi_arch_pci(void)
+{
+    EFI_STATUS status;
+    EFI_HANDLE *handles;
+    static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL;
+    UINTN i, nr_pci, size = 0;
+    struct efi_pci_rom *last = NULL;
+
+    status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL);
+    if ( status == EFI_BUFFER_TOO_SMALL )
+        status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
+    if ( !EFI_ERROR(status) )
+        status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size,
+                                      handles);
+    if ( EFI_ERROR(status) )
+        size = 0;
+
+    nr_pci = size / sizeof(*handles);
+    for ( i = 0; i < nr_pci; ++i )
+    {
+        EFI_PCI_IO *pci = NULL;
+        u64 attributes;
+        struct efi_pci_rom *rom, *va;
+        UINTN segment, bus, device, function;
+
+        status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci);
+        if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize )
+            continue;
+
+        status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0,
+                                 &attributes);
+        if ( EFI_ERROR(status) ||
+             !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) ||
+             EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device,
+                       &function)) )
+            continue;
+
+        DisplayUint(segment, 4);
+        PrintStr(L":");
+        DisplayUint(bus, 2);
+        PrintStr(L":");
+        DisplayUint(device, 2);
+        PrintStr(L".");
+        DisplayUint(function, 1);
+        PrintStr(L": ROM: ");
+        DisplayUint(pci->RomSize, 0);
+        PrintStr(L" bytes at ");
+        DisplayUint((UINTN)pci->RomImage, 0);
+        PrintStr(newline);
+
+        size = pci->RomSize + sizeof(*rom);
+        status = efi_bs->AllocatePool(EfiRuntimeServicesData, size,
+                                      (void **)&rom);
+        if ( EFI_ERROR(status) )
+            continue;
+
+        rom->next = NULL;
+        rom->size = pci->RomSize;
+
+        status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1,
+                               &rom->vendor);
+        if ( !EFI_ERROR(status) )
+            status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1,
+                                   &rom->devid);
+        if ( EFI_ERROR(status) )
+        {
+            efi_bs->FreePool(rom);
+            continue;
+        }
+
+        rom->segment = segment;
+        rom->bus = bus;
+        rom->devfn = (device << 3) | function;
+        memcpy(rom->data, pci->RomImage, pci->RomSize);
+
+        va = (void *)rom + DIRECTMAP_VIRT_START;
+        if ( last )
+            last->next = va;
+        else
+            efi_pci_roms = va;
+        last = rom;
+    }
+
+    efi_bs->FreePool(handles);
+}
+
+extern const intpte_t __page_tables_start[], __page_tables_end[];
+#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \
+                           (intpte_t *)(v) < __page_tables_end)
+
+#define PE_BASE_RELOC_ABS      0
+#define PE_BASE_RELOC_HIGHLOW  3
+#define PE_BASE_RELOC_DIR64   10
+
+extern const struct pe_base_relocs {
+    u32 rva;
+    u32 size;
+    u16 entries[];
+} __base_relocs_start[], __base_relocs_end[];
+
+static void __init efi_arch_relocate_image(unsigned long delta)
+{
+    const struct pe_base_relocs *base_relocs;
+
+    for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; )
+    {
+        unsigned int i, n;
+
+        n = (base_relocs->size - sizeof(*base_relocs)) /
+            sizeof(*base_relocs->entries);
+        for ( i = 0; i < n; ++i )
+        {
+            unsigned long addr = xen_phys_start + base_relocs->rva +
+                                 (base_relocs->entries[i] & 0xfff);
+
+            switch ( base_relocs->entries[i] >> 12 )
+            {
+            case PE_BASE_RELOC_ABS:
+                break;
+            case PE_BASE_RELOC_HIGHLOW:
+                if ( delta )
+                {
+                    *(u32 *)addr += delta;
+                    if ( in_page_tables(addr) )
+                        *(u32 *)addr += xen_phys_start;
+                }
+                break;
+            case PE_BASE_RELOC_DIR64:
+                if ( delta )
+                {
+                    *(u64 *)addr += delta;
+                    if ( in_page_tables(addr) )
+                        *(intpte_t *)addr += xen_phys_start;
+                }
+                break;
+            default:
+                blexit(L"Unsupported relocation type");
+            }
+        }
+        base_relocs = (const void *)(base_relocs->entries + i + (i & 1));
+    }
+}
+
+extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
+extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
+
+static void __init relocate_trampoline(unsigned long phys)
+{
+    const s32 *trampoline_ptr;
+
+    trampoline_phys = phys;
+    /* Apply relocations to trampoline. */
+    for ( trampoline_ptr = __trampoline_rel_start;
+          trampoline_ptr < __trampoline_rel_stop;
+          ++trampoline_ptr )
+        *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
+    for ( trampoline_ptr = __trampoline_seg_start;
+          trampoline_ptr < __trampoline_seg_stop;
+          ++trampoline_ptr )
+        *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
+}
+
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+static __init void copy_mapping(unsigned long mfn, unsigned long end,
+                                bool_t (*is_valid)(unsigned long smfn,
+                                                   unsigned long emfn))
+{
+    unsigned long next;
+
+    for ( ; mfn < end; mfn = next )
+    {
+        l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
+        l3_pgentry_t *l3src, *l3dst;
+        unsigned long va = (unsigned long)mfn_to_virt(mfn);
+
+        next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
+        if ( !is_valid(mfn, min(next, end)) )
+            continue;
+        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+        {
+            l3dst = alloc_xen_pagetable();
+            BUG_ON(!l3dst);
+            clear_page(l3dst);
+            efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] =
+                l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR);
+        }
+        else
+            l3dst = l4e_to_l3e(l4e);
+        l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]);
+        l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)];
+    }
+}
+
+static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn)
+{
+    unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1;
+
+    return !(smfn & pfn_hole_mask) &&
+           find_next_bit(pdx_group_valid, sz,
+                         pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz;
+}
+
+static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn)
+{
+    return 1;
+}
+#endif
+
+#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
+                                 (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
+void __init efi_init_memory(void)
+{
+    unsigned int i;
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+    struct rt_extra {
+        struct rt_extra *next;
+        unsigned long smfn, emfn;
+        unsigned int prot;
+    } *extra, *extra_head = NULL;
+#endif
+
+    printk(XENLOG_INFO "EFI memory map:\n");
+    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+    {
+        EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+        u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
+        unsigned long smfn, emfn;
+        unsigned int prot = PAGE_HYPERVISOR;
+
+        printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64
+                           " type=%u attr=%016" PRIx64 "\n",
+               desc->PhysicalStart, desc->PhysicalStart + len - 1,
+               desc->Type, desc->Attribute);
+
+        if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) )
+            continue;
+
+        desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
+
+        smfn = PFN_DOWN(desc->PhysicalStart);
+        emfn = PFN_UP(desc->PhysicalStart + len);
+
+        if ( desc->Attribute & EFI_MEMORY_WB )
+            /* nothing */;
+        else if ( desc->Attribute & EFI_MEMORY_WT )
+            prot |= _PAGE_PWT | MAP_SMALL_PAGES;
+        else if ( desc->Attribute & EFI_MEMORY_WC )
+            prot |= _PAGE_PAT | MAP_SMALL_PAGES;
+        else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) )
+            prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES;
+        else
+        {
+            printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n",
+                   smfn, emfn - 1);
+            continue;
+        }
+
+        if ( desc->Attribute & EFI_MEMORY_WP )
+            prot &= _PAGE_RW;
+        if ( desc->Attribute & EFI_MEMORY_XP )
+            prot |= _PAGE_NX_BIT;
+
+        if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) &&
+             !(smfn & pfn_hole_mask) &&
+             !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
+        {
+            if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
+                prot &= ~_PAGE_GLOBAL;
+            if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
+                                  smfn, emfn - smfn, prot) == 0 )
+                desc->VirtualStart =
+                    (unsigned long)maddr_to_virt(desc->PhysicalStart);
+            else
+                printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n",
+                       smfn, emfn - 1);
+        }
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
+        else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) &&
+                  (extra = xmalloc(struct rt_extra)) != NULL )
+        {
+            extra->smfn = smfn;
+            extra->emfn = emfn;
+            extra->prot = prot & ~_PAGE_GLOBAL;
+            extra->next = extra_head;
+            extra_head = extra;
+            desc->VirtualStart = desc->PhysicalStart;
+        }
+#endif
+        else
+        {
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+            /* XXX allocate e.g. down from FIXADDR_START */
+#endif
+            printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n",
+                   smfn, emfn - 1);
+        }
+    }
+
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+    efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
+                                 mdesc_ver, efi_memmap);
+#else
+    /* Set up 1:1 page tables to do runtime calls in "physical" mode. */
+    efi_l4_pgtable = alloc_xen_pagetable();
+    BUG_ON(!efi_l4_pgtable);
+    clear_page(efi_l4_pgtable);
+
+    copy_mapping(0, max_page, ram_range_valid);
+
+    /* Insert non-RAM runtime mappings inside the direct map. */
+    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+    {
+        const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+
+        if ( (desc->Attribute & EFI_MEMORY_RUNTIME) &&
+             desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
+             desc->VirtualStart != desc->PhysicalStart )
+            copy_mapping(PFN_DOWN(desc->PhysicalStart),
+                         PFN_UP(desc->PhysicalStart +
+                                (desc->NumberOfPages << EFI_PAGE_SHIFT)),
+                         rt_range_valid);
+    }
+
+    /* Insert non-RAM runtime mappings outside of the direct map. */
+    while ( (extra = extra_head) != NULL )
+    {
+        unsigned long addr = extra->smfn << PAGE_SHIFT;
+        l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)];
+        l3_pgentry_t *pl3e;
+        l2_pgentry_t *pl2e;
+        l1_pgentry_t *l1t;
+
+        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+        {
+            pl3e = alloc_xen_pagetable();
+            BUG_ON(!pl3e);
+            clear_page(pl3e);
+            efi_l4_pgtable[l4_table_offset(addr)] =
+                l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR);
+        }
+        else
+            pl3e = l4e_to_l3e(l4e);
+        pl3e += l3_table_offset(addr);
+        if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
+        {
+            pl2e = alloc_xen_pagetable();
+            BUG_ON(!pl2e);
+            clear_page(pl2e);
+            *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR);
+        }
+        else
+        {
+            BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
+            pl2e = l3e_to_l2e(*pl3e);
+        }
+        pl2e += l2_table_offset(addr);
+        if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
+        {
+            l1t = alloc_xen_pagetable();
+            BUG_ON(!l1t);
+            clear_page(l1t);
+            *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR);
+        }
+        else
+        {
+            BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
+            l1t = l2e_to_l1e(*pl2e);
+        }
+        for ( i = l1_table_offset(addr);
+              i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn;
+              ++i, ++extra->smfn )
+            l1t[i] = l1e_from_pfn(extra->smfn, extra->prot);
+
+        if ( extra->smfn == extra->emfn )
+        {
+            extra_head = extra->next;
+            xfree(extra);
+        }
+    }
+
+    /* Insert Xen mappings. */
+    for ( i = l4_table_offset(HYPERVISOR_VIRT_START);
+          i < l4_table_offset(DIRECTMAP_VIRT_END); ++i )
+        efi_l4_pgtable[i] = idle_pg_table[i];
+#endif
+}
+
+static void __init place_string(u32 *addr, const char *s)
+{
+    static char *__initdata alloc = start;
+
+    if ( s && *s )
+    {
+        size_t len1 = strlen(s) + 1;
+        const char *old = (char *)(long)*addr;
+        size_t len2 = *addr ? strlen(old) + 1 : 0;
+
+        alloc -= len1 + len2;
+        /*
+         * Insert new string before already existing one. This is needed
+         * for options passed on the command line to override options from
+         * the configuration file.
+         */
+        memcpy(alloc, s, len1);
+        if ( *addr )
+        {
+            alloc[len1 - 1] = ' ';
+            memcpy(alloc + len1, old, len2);
+        }
+    }
+    *addr = (long)alloc;
+}
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 03/15] create arch functions to get and process EFI memory map.
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
  2014-09-10  0:51 ` [PATCH V4 01/15] move x86 EFI boot code to common/efi Roy Franz
  2014-09-10  0:51 ` [PATCH V4 02/15] Move x86 specific funtions/variables to arch header Roy Franz
@ 2014-09-10  0:51 ` Roy Franz
  2014-09-11 14:11   ` Jan Beulich
  2014-09-10  0:51 ` [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices Roy Franz
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:51 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

The memory used to store the EFI memory map is allocated in an
architecture specific way, and the processing of the memory
map itself uses x86 specific data structures. This patch
adds architecture specific funtions so each architecture
can provide its own implementation.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 75 +++++-------------------------------
 xen/include/asm-x86/efi-boot.h | 86 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+), 66 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index ca604be..16ffe35 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -56,8 +56,6 @@ static EFI_HANDLE __initdata efi_ih;
 static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdOut;
 static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdErr;
 
-static UINT32 __initdata mdesc_ver;
-
 static struct file __initdata cfg;
 static struct file __initdata kernel;
 static struct file __initdata ramdisk;
@@ -566,16 +564,18 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     EFI_STATUS status;
     unsigned int i, argc;
     CHAR16 **argv, *file_name, *cfg_file_name = NULL;
-    UINTN cols, rows, depth, size, map_key, info_size, gop_mode = ~0;
+    UINTN cols, rows, depth, size, info_size, gop_mode = ~0;
     EFI_HANDLE *handles = NULL;
     EFI_SHIM_LOCK_PROTOCOL *shim_lock;
     EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
     EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
     EFI_FILE_HANDLE dir_handle;
     union string section = { NULL }, name;
-    struct e820entry *e;
     u64 efer;
     bool_t base_video = 0;
+    UINT32 mmap_desc_ver = 0;
+    UINTN mmap_size, mmap_desc_size, mmap_key = 0;
+    void *mmap;
 
     efi_ih = ImageHandle;
     efi_bs = SystemTable->BootServices;
@@ -875,8 +875,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     mbi.boot_loader_name = (long)"EFI";
     mbi.mods_addr = (long)mb_modules;
 
-    place_string(&mbi.mem_upper, NULL);
-
     /* Collect EDD info. */
     BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE);
     BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE);
@@ -1171,67 +1169,12 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
         }
     }
 
-    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
-                         &efi_mdesc_size, &mdesc_ver);
-    mbi.mem_upper -= efi_memmap_size;
-    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
-    if ( mbi.mem_upper < xen_phys_start )
-        blexit(L"Out of static memory");
-    efi_memmap = (void *)(long)mbi.mem_upper;
-    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
-                                  &efi_mdesc_size, &mdesc_ver);
-    if ( EFI_ERROR(status) )
-        PrintErrMesg(L"Cannot obtain memory map", status);
+    efi_arch_get_memory_map(&mmap_size, &mmap, &mmap_key,
+                                  &mmap_desc_size, &mmap_desc_ver);
 
-    /* Populate E820 table and check trampoline area availability. */
-    e = e820map - 1;
-    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
-    {
-        EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
-        u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
-        u32 type;
+    efi_arch_process_memory_map(SystemTable, mmap, mmap_size,
+                                mmap_desc_size, mmap_desc_ver);
 
-        switch ( desc->Type )
-        {
-        default:
-            type = E820_RESERVED;
-            break;
-        case EfiConventionalMemory:
-        case EfiBootServicesCode:
-        case EfiBootServicesData:
-            if ( !trampoline_phys && desc->PhysicalStart + len <= 0x100000 &&
-                 len >= cfg.size && desc->PhysicalStart + len > cfg.addr )
-                cfg.addr = (desc->PhysicalStart + len - cfg.size) & PAGE_MASK;
-            /* fall through */
-        case EfiLoaderCode:
-        case EfiLoaderData:
-            if ( desc->Attribute & EFI_MEMORY_WB )
-                type = E820_RAM;
-            else
-        case EfiUnusableMemory:
-                type = E820_UNUSABLE;
-            break;
-        case EfiACPIReclaimMemory:
-            type = E820_ACPI;
-            break;
-        case EfiACPIMemoryNVS:
-            type = E820_NVS;
-            break;
-        }
-        if ( e820nr && type == e->type &&
-             desc->PhysicalStart == e->addr + e->size )
-            e->size += len;
-        else if ( !len || e820nr >= E820MAX )
-            continue;
-        else
-        {
-            ++e;
-            e->addr = desc->PhysicalStart;
-            e->size = len;
-            e->type = type;
-            ++e820nr;
-        }
-    }
     if ( !trampoline_phys )
     {
         if ( !cfg.addr )
@@ -1239,7 +1182,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
         relocate_trampoline(cfg.addr);
     }
 
-    status = efi_bs->ExitBootServices(ImageHandle, map_key);
+    status = efi_bs->ExitBootServices(ImageHandle, mmap_key);
     if ( EFI_ERROR(status) )
         PrintErrMesg(L"Cannot exit boot services", status);
 
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
index 4ad83ca..3fe6747 100644
--- a/xen/include/asm-x86/efi-boot.h
+++ b/xen/include/asm-x86/efi-boot.h
@@ -449,3 +449,89 @@ static void __init place_string(u32 *addr, const char *s)
     }
     *addr = (long)alloc;
 }
+
+static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
+                                               void *map,
+                                               UINTN map_size,
+                                               UINTN desc_size,
+                                               UINT32 desc_ver)
+{
+    struct e820entry *e;
+    int i;
+
+    /* Set global EFI memory map variables */
+    efi_memmap_size = map_size;
+    efi_mdesc_size = desc_size;
+    efi_memmap = map;
+
+    /* Populate E820 table and check trampoline area availability. */
+    e = e820map - 1;
+    for ( i = 0; i < map_size; i += desc_size )
+    {
+        EFI_MEMORY_DESCRIPTOR *desc = map + i;
+        u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
+        u32 type;
+
+        switch ( desc->Type )
+        {
+        default:
+            type = E820_RESERVED;
+            break;
+        case EfiConventionalMemory:
+        case EfiBootServicesCode:
+        case EfiBootServicesData:
+            if ( !trampoline_phys && desc->PhysicalStart + len <= 0x100000 &&
+                 len >= cfg.size && desc->PhysicalStart + len > cfg.addr )
+                cfg.addr = (desc->PhysicalStart + len - cfg.size) & PAGE_MASK;
+            /* fall through */
+        case EfiLoaderCode:
+        case EfiLoaderData:
+            if ( desc->Attribute & EFI_MEMORY_WB )
+                type = E820_RAM;
+            else
+        case EfiUnusableMemory:
+                type = E820_UNUSABLE;
+            break;
+        case EfiACPIReclaimMemory:
+            type = E820_ACPI;
+            break;
+        case EfiACPIMemoryNVS:
+            type = E820_NVS;
+            break;
+        }
+        if ( e820nr && type == e->type &&
+             desc->PhysicalStart == e->addr + e->size )
+            e->size += len;
+        else if ( !len || e820nr >= E820MAX )
+            continue;
+        else
+        {
+            ++e;
+            e->addr = desc->PhysicalStart;
+            e->size = len;
+            e->type = type;
+            ++e820nr;
+        }
+    }
+
+}
+
+static void __init efi_arch_get_memory_map(UINTN *map_size,
+                                             void **map,
+                                             UINTN *map_key, UINTN *desc_size,
+                                             UINT32 *desc_ver)
+{
+    EFI_STATUS status;
+    efi_bs->GetMemoryMap(map_size, NULL, map_key,
+                         desc_size, desc_ver);
+    place_string(&mbi.mem_upper, NULL);
+    mbi.mem_upper -= *map_size;
+    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
+    if ( mbi.mem_upper < xen_phys_start )
+        blexit(L"Out of static memory");
+    *map = (void *)(long)mbi.mem_upper;
+    status = efi_bs->GetMemoryMap(map_size, *map, map_key,
+                                  desc_size, desc_ver);
+    if ( EFI_ERROR(status) )
+        PrintErrMesg(L"Cannot obtain memory map", status);
+}
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (2 preceding siblings ...)
  2014-09-10  0:51 ` [PATCH V4 03/15] create arch functions to get and process EFI memory map Roy Franz
@ 2014-09-10  0:51 ` Roy Franz
  2014-09-11 14:13   ` Jan Beulich
  2014-09-10  0:51 ` [PATCH V4 05/15] Add efi_arch_cfg_file() to handle arch specific cfg file fields Roy Franz
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:51 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

The UEFI ExitBootServices function is invoked to transition the
system to the 'runtime' mode of operation, and is done right before
transitioning from the EFI loader code into Xen proper. x86 does some
arch specific memory management (trampoline) before exit boot services,
and the code that transitions from the EFI application state to Xen
is architecture specific.  This patch adds two functions, one pre
and one post ExitBootServices to allow each architecture to
to handle these cases in a customized manner.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 50 ++----------------------------------
 xen/include/asm-x86/efi-boot.h | 57 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 48 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 16ffe35..ca86beb 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -571,7 +571,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
     EFI_FILE_HANDLE dir_handle;
     union string section = { NULL }, name;
-    u64 efer;
     bool_t base_video = 0;
     UINT32 mmap_desc_ver = 0;
     UINTN mmap_size, mmap_desc_size, mmap_key = 0;
@@ -1175,58 +1174,13 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     efi_arch_process_memory_map(SystemTable, mmap, mmap_size,
                                 mmap_desc_size, mmap_desc_ver);
 
-    if ( !trampoline_phys )
-    {
-        if ( !cfg.addr )
-            blexit(L"No memory for trampoline");
-        relocate_trampoline(cfg.addr);
-    }
+    efi_arch_pre_exit_boot();
 
     status = efi_bs->ExitBootServices(ImageHandle, mmap_key);
     if ( EFI_ERROR(status) )
         PrintErrMesg(L"Cannot exit boot services", status);
 
-    /* Adjust pointers into EFI. */
-    efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
-#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
-    efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
-#endif
-    efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
-    efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
-
-    efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
-    memcpy((void *)trampoline_phys, trampoline_start, cfg.size);
-
-    /* Set system registers and transfer control. */
-    asm volatile("pushq $0\n\tpopfq");
-    rdmsrl(MSR_EFER, efer);
-    efer |= EFER_SCE;
-    if ( cpuid_ext_features & (1 << (X86_FEATURE_NX & 0x1f)) )
-        efer |= EFER_NX;
-    wrmsrl(MSR_EFER, efer);
-    write_cr0(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP |
-              X86_CR0_AM | X86_CR0_PG);
-    asm volatile ( "mov    %[cr4], %%cr4\n\t"
-                   "mov    %[cr3], %%cr3\n\t"
-                   "movabs $__start_xen, %[rip]\n\t"
-                   "lgdt   gdt_descr(%%rip)\n\t"
-                   "mov    stack_start(%%rip), %%rsp\n\t"
-                   "mov    %[ds], %%ss\n\t"
-                   "mov    %[ds], %%ds\n\t"
-                   "mov    %[ds], %%es\n\t"
-                   "mov    %[ds], %%fs\n\t"
-                   "mov    %[ds], %%gs\n\t"
-                   "movl   %[cs], 8(%%rsp)\n\t"
-                   "mov    %[rip], (%%rsp)\n\t"
-                   "lretq  %[stkoff]-16"
-                   : [rip] "=&r" (efer/* any dead 64-bit variable */)
-                   : [cr3] "r" (idle_pg_table),
-                     [cr4] "r" (mmu_cr4_features),
-                     [cs] "ir" (__HYPERVISOR_CS),
-                     [ds] "r" (__HYPERVISOR_DS),
-                     [stkoff] "i" (STACK_SIZE - sizeof(struct cpu_info)),
-                     "D" (&mbi)
-                   : "memory" );
+    efi_arch_post_exit_boot();
     for( ; ; ); /* not reached */
 }
 
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
index 3fe6747..518c319 100644
--- a/xen/include/asm-x86/efi-boot.h
+++ b/xen/include/asm-x86/efi-boot.h
@@ -535,3 +535,60 @@ static void __init efi_arch_get_memory_map(UINTN *map_size,
     if ( EFI_ERROR(status) )
         PrintErrMesg(L"Cannot obtain memory map", status);
 }
+
+static void __init efi_arch_pre_exit_boot(void)
+{
+    if ( !trampoline_phys )
+    {
+        if ( !cfg.addr )
+            blexit(L"No memory for trampoline");
+        relocate_trampoline(cfg.addr);
+    }
+}
+
+static void __init efi_arch_post_exit_boot(void)
+{
+    u64 efer;
+
+    /* Adjust pointers into EFI. */
+    efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
+    efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
+#endif
+    efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
+    efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
+
+    efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
+    memcpy((void *)trampoline_phys, trampoline_start, cfg.size);
+
+    /* Set system registers and transfer control. */
+    asm volatile("pushq $0\n\tpopfq");
+    rdmsrl(MSR_EFER, efer);
+    efer |= EFER_SCE;
+    if ( cpuid_ext_features & (1 << (X86_FEATURE_NX & 0x1f)) )
+        efer |= EFER_NX;
+    wrmsrl(MSR_EFER, efer);
+    write_cr0(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP |
+              X86_CR0_AM | X86_CR0_PG);
+    asm volatile ( "mov    %[cr4], %%cr4\n\t"
+                   "mov    %[cr3], %%cr3\n\t"
+                   "movabs $__start_xen, %[rip]\n\t"
+                   "lgdt   gdt_descr(%%rip)\n\t"
+                   "mov    stack_start(%%rip), %%rsp\n\t"
+                   "mov    %[ds], %%ss\n\t"
+                   "mov    %[ds], %%ds\n\t"
+                   "mov    %[ds], %%es\n\t"
+                   "mov    %[ds], %%fs\n\t"
+                   "mov    %[ds], %%gs\n\t"
+                   "movl   %[cs], 8(%%rsp)\n\t"
+                   "mov    %[rip], (%%rsp)\n\t"
+                   "lretq  %[stkoff]-16"
+                   : [rip] "=&r" (efer/* any dead 64-bit variable */)
+                   : [cr3] "r" (idle_pg_table),
+                     [cr4] "r" (mmu_cr4_features),
+                     [cs] "ir" (__HYPERVISOR_CS),
+                     [ds] "r" (__HYPERVISOR_DS),
+                     [stkoff] "i" (STACK_SIZE - sizeof(struct cpu_info)),
+                     "D" (&mbi)
+                   : "memory" );
+}
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 05/15] Add efi_arch_cfg_file() to handle arch specific cfg file fields
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (3 preceding siblings ...)
  2014-09-10  0:51 ` [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices Roy Franz
@ 2014-09-10  0:51 ` Roy Franz
  2014-09-11 14:16   ` Jan Beulich
  2014-09-10  0:51 ` [PATCH V4 06/15] Add efi_arch_handle_cmdline() for processing commandline Roy Franz
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:51 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

Different architectures have some different configuration file
fields that need to be handled.  In particular, x86 has ucode
and ARM has device tree files to be loaded.  This arch specific
function is used to allow each architecture to implement these
features in arch specific code.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 30 ++++++++++++++----------------
 xen/include/asm-x86/efi-boot.h | 15 +++++++++++++++
 2 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index ca86beb..a33a8f6 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -31,11 +31,6 @@ typedef struct {
     EFI_SHIM_LOCK_VERIFY Verify;
 } EFI_SHIM_LOCK_PROTOCOL;
 
-static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer);
-static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer);
-static void __init DisplayUint(UINT64 Val, INTN Width);
-static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s);
-
 union string {
     CHAR16 *w;
     char *s;
@@ -50,6 +45,17 @@ struct file {
     };
 };
 
+static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer);
+static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer);
+static void __init DisplayUint(UINT64 Val, INTN Width);
+static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s);
+static char *__init get_value(const struct file *cfg, const char *section,
+                              const char *item);
+static void __init split_value(char *s);
+static CHAR16 *__init s2w(union string *str);
+static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
+                               struct file *file);
+
 static EFI_BOOT_SERVICES *__initdata efi_bs;
 static EFI_HANDLE __initdata efi_ih;
 
@@ -752,6 +758,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     }
     if ( !name.s )
         blexit(L"No Dom0 kernel image specified.");
+
+    efi_arch_cfg_file(dir_handle, section.s);
+
     split_value(name.s);
     read_file(dir_handle, s2w(&name), &kernel);
     efi_bs->FreePool(name.w);
@@ -769,17 +778,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
         efi_bs->FreePool(name.w);
     }
 
-    name.s = get_value(&cfg, section.s, "ucode");
-    if ( !name.s )
-        name.s = get_value(&cfg, "global", "ucode");
-    if ( name.s )
-    {
-        microcode_set_module(mbi.mods_count);
-        split_value(name.s);
-        read_file(dir_handle, s2w(&name), &ucode);
-        efi_bs->FreePool(name.w);
-    }
-
     name.s = get_value(&cfg, section.s, "xsm");
     if ( name.s )
     {
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
index 518c319..3937955 100644
--- a/xen/include/asm-x86/efi-boot.h
+++ b/xen/include/asm-x86/efi-boot.h
@@ -592,3 +592,18 @@ static void __init efi_arch_post_exit_boot(void)
                      "D" (&mbi)
                    : "memory" );
 }
+
+static void __init efi_arch_cfg_file(EFI_FILE_HANDLE dir_handle, char *section)
+{
+    union string name;
+    name.s = get_value(&cfg, section, "ucode");
+    if ( !name.s )
+        name.s = get_value(&cfg, "global", "ucode");
+    if ( name.s )
+    {
+        microcode_set_module(mbi.mods_count);
+        split_value(name.s);
+        read_file(dir_handle, s2w(&name), &ucode);
+        efi_bs->FreePool(name.w);
+    }
+}
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 06/15] Add efi_arch_handle_cmdline() for processing commandline
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (4 preceding siblings ...)
  2014-09-10  0:51 ` [PATCH V4 05/15] Add efi_arch_cfg_file() to handle arch specific cfg file fields Roy Franz
@ 2014-09-10  0:51 ` Roy Franz
  2014-09-11 14:22   ` Jan Beulich
  2014-09-10  0:51 ` [PATCH V4 07/15] Move x86 specific video and disk probing code Roy Franz
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:51 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

Add arch function for processing the Xen commandline and
updating internal structures.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 41 +++++++++++------------------------------
 xen/include/asm-x86/efi-boot.h | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index a33a8f6..fd9d382 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -53,6 +53,7 @@ static char *__init get_value(const struct file *cfg, const char *section,
                               const char *item);
 static void __init split_value(char *s);
 static CHAR16 *__init s2w(union string *str);
+static char *__init w2s(const union string *str);
 static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
                                struct file *file);
 
@@ -251,7 +252,8 @@ static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode)
 }
 
 static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
-                                    CHAR16 *cmdline, UINTN cmdsize)
+                                    CHAR16 *cmdline, UINTN cmdsize,
+                                    CHAR16 **options)
 {
     CHAR16 *ptr = (CHAR16 *)(argv + argc + 1), *prev = NULL;
     bool_t prev_sep = TRUE;
@@ -277,10 +279,8 @@ static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
                 ++argc;
             else if ( prev && wstrcmp(prev, L"--") == 0 )
             {
-                union string rest = { .w = cmdline };
-
-                --argv;
-                place_string(&mbi.cmdline, w2s(&rest));
+                if ( options )
+                    *options = cmdline;
                 break;
             }
             else
@@ -569,7 +569,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     EFI_LOADED_IMAGE *loaded_image;
     EFI_STATUS status;
     unsigned int i, argc;
-    CHAR16 **argv, *file_name, *cfg_file_name = NULL;
+    CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL;
     UINTN cols, rows, depth, size, info_size, gop_mode = ~0;
     EFI_HANDLE *handles = NULL;
     EFI_SHIM_LOCK_PROTOCOL *shim_lock;
@@ -610,14 +610,14 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     dir_handle = get_parent_handle(loaded_image, &file_name);
 
     argc = get_argv(0, NULL, loaded_image->LoadOptions,
-                    loaded_image->LoadOptionsSize);
+                    loaded_image->LoadOptionsSize, &options);
     if ( argc > 0 &&
          efi_bs->AllocatePool(EfiLoaderData,
                               (argc + 1) * sizeof(*argv) +
                                   loaded_image->LoadOptionsSize,
                               (void **)&argv) == EFI_SUCCESS )
         get_argv(argc, argv, loaded_image->LoadOptions,
-                 loaded_image->LoadOptionsSize);
+                 loaded_image->LoadOptionsSize, &options);
     else
         argc = 0;
     for ( i = 1; i < argc; ++i )
@@ -786,19 +786,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
         efi_bs->FreePool(name.w);
     }
 
-    name.s = get_value(&cfg, section.s, "options");
-    if ( name.s )
-        place_string(&mbi.cmdline, name.s);
-    /* Insert image name last, as it gets prefixed to the other options. */
-    if ( argc )
-    {
-        name.w = *argv;
-        w2s(&name);
-    }
-    else
-        name.s = "xen";
-    place_string(&mbi.cmdline, name.s);
-
     cols = rows = depth = 0;
     if ( !base_video )
     {
@@ -817,6 +804,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
         }
     }
 
+    name.s = get_value(&cfg, section.s, "options");
+    efi_arch_handle_cmdline(argc ? *argv : NULL, options, name.s);
+
     efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
     cfg.addr = 0;
 
@@ -863,15 +853,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
         }
     }
 
-    if ( mbi.cmdline )
-        mbi.flags |= MBI_CMDLINE;
-    /*
-     * These must not be initialized statically, since the value must
-     * not get relocated when processing base relocations below.
-     */
-    mbi.boot_loader_name = (long)"EFI";
-    mbi.mods_addr = (long)mb_modules;
-
     /* Collect EDD info. */
     BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE);
     BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE);
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
index 3937955..d72b02b 100644
--- a/xen/include/asm-x86/efi-boot.h
+++ b/xen/include/asm-x86/efi-boot.h
@@ -607,3 +607,37 @@ static void __init efi_arch_cfg_file(EFI_FILE_HANDLE dir_handle, char *section)
         efi_bs->FreePool(name.w);
     }
 }
+
+static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
+                                           CHAR16 *cmdline_options,
+                                           char *cfgfile_options)
+{
+    union string name;
+
+    if ( cmdline_options )
+    {
+        name.w = cmdline_options;
+        w2s(&name);
+        place_string(&mbi.cmdline, name.s);
+    }
+    if ( cfgfile_options )
+        place_string(&mbi.cmdline, cfgfile_options);
+    /* Insert image name last, as it gets prefixed to the other options. */
+    if ( image_name )
+    {
+        name.w = image_name;
+        w2s(&name);
+    }
+    else
+        name.s = "xen";
+    place_string(&mbi.cmdline, name.s);
+
+    if ( mbi.cmdline )
+        mbi.flags |= MBI_CMDLINE;
+    /*
+     * These must not be initialized statically, since the value must
+     * not get relocated when processing base relocations below.
+     */
+    mbi.boot_loader_name = (long)"EFI";
+    mbi.mods_addr = (long)mb_modules;
+}
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 07/15] Move x86 specific video and disk probing code
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (5 preceding siblings ...)
  2014-09-10  0:51 ` [PATCH V4 06/15] Add efi_arch_handle_cmdline() for processing commandline Roy Franz
@ 2014-09-10  0:51 ` Roy Franz
  2014-09-11 14:26   ` Jan Beulich
  2014-09-10  0:51 ` [PATCH V4 08/15] Add efi_arch_memory() for arch specific memory setup Roy Franz
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:51 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

Move x86 specific video (VGA) and disk (EDD) probing to arch specific
file.  This code is x86 only, so move it to arch specific code.  The
efi_arch_edd() and efi_arch_video() will be empty for ARM.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 284 +-------------------------------------
 xen/include/asm-x86/efi-boot.h | 299 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 302 insertions(+), 281 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index fd9d382..3fe04fd 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -543,34 +543,17 @@ static void __init split_value(char *s)
     *s = 0;
 }
 
-static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
-{
-   if ( bpp < 0 )
-       return bpp;
-   if ( !mask )
-       return -EINVAL;
-   for ( *pos = 0; !(mask & 1); ++*pos )
-       mask >>= 1;
-   for ( *sz = 0; mask & 1; ++sz)
-       mask >>= 1;
-   if ( mask )
-       return -EINVAL;
-   return max(*pos + *sz, bpp);
-}
-
 void EFIAPI __init noreturn
 efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 {
     static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL;
     static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
-    static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL;
-    static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL;
     static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID;
     EFI_LOADED_IMAGE *loaded_image;
     EFI_STATUS status;
     unsigned int i, argc;
     CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL;
-    UINTN cols, rows, depth, size, info_size, gop_mode = ~0;
+    UINTN cols, rows, depth, size, info_size;
     EFI_HANDLE *handles = NULL;
     EFI_SHIM_LOCK_PROTOCOL *shim_lock;
     EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
@@ -677,15 +660,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 
     efi_arch_relocate_image(0);
 
-    if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
-                           &cols, &rows) == EFI_SUCCESS )
-    {
-        vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
-        vga_console_info.u.text_mode_3.columns = cols;
-        vga_console_info.u.text_mode_3.rows = rows;
-        vga_console_info.u.text_mode_3.font_height = 16;
-    }
-
     size = 0;
     status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size, NULL);
     if ( status == EFI_BUFFER_TOO_SMALL )
@@ -811,189 +785,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     cfg.addr = 0;
 
     dir_handle->Close(dir_handle);
-
-    if ( gop && !base_video )
-    {
-        for ( i = size = 0; i < gop->Mode->MaxMode; ++i )
-        {
-            unsigned int bpp = 0;
-
-            status = gop->QueryMode(gop, i, &info_size, &mode_info);
-            if ( EFI_ERROR(status) )
-                continue;
-            switch ( mode_info->PixelFormat )
-            {
-            case PixelBitMask:
-                bpp = hweight32(mode_info->PixelInformation.RedMask |
-                                mode_info->PixelInformation.GreenMask |
-                                mode_info->PixelInformation.BlueMask);
-                break;
-            case PixelRedGreenBlueReserved8BitPerColor:
-            case PixelBlueGreenRedReserved8BitPerColor:
-                bpp = 24;
-                break;
-            default:
-                continue;
-            }
-            if ( cols == mode_info->HorizontalResolution &&
-                 rows == mode_info->VerticalResolution &&
-                 (!depth || bpp == depth) )
-            {
-                gop_mode = i;
-                break;
-            }
-            if ( !cols && !rows &&
-                 mode_info->HorizontalResolution *
-                 mode_info->VerticalResolution > size )
-            {
-                size = mode_info->HorizontalResolution *
-                       mode_info->VerticalResolution;
-                gop_mode = i;
-            }
-        }
-    }
-
-    /* Collect EDD info. */
-    BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE);
-    BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE);
-    size = 0;
-    status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, NULL);
-    if ( status == EFI_BUFFER_TOO_SMALL )
-        status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
-    if ( !EFI_ERROR(status) )
-        status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size,
-                                      handles);
-    if ( EFI_ERROR(status) )
-        size = 0;
-    for ( i = 0; i < size / sizeof(*handles); ++i )
-    {
-        EFI_BLOCK_IO *bio;
-        EFI_DEV_PATH_PTR devp;
-        struct edd_info *info = boot_edd_info + boot_edd_info_nr;
-        struct edd_device_params *params = &info->edd_device_params;
-        enum { root, acpi, pci, ctrlr } state = root;
-
-        status = efi_bs->HandleProtocol(handles[i], &bio_guid, (void **)&bio);
-        if ( EFI_ERROR(status) ||
-             bio->Media->RemovableMedia ||
-             bio->Media->LogicalPartition )
-            continue;
-        if ( boot_edd_info_nr < EDD_INFO_MAX )
-        {
-            info->device = 0x80 + boot_edd_info_nr; /* fake */
-            info->version = 0x11;
-            params->length = offsetof(struct edd_device_params, dpte_ptr);
-            params->number_of_sectors = bio->Media->LastBlock + 1;
-            params->bytes_per_sector = bio->Media->BlockSize;
-            params->dpte_ptr = ~0;
-        }
-        ++boot_edd_info_nr;
-        status = efi_bs->HandleProtocol(handles[i], &devp_guid,
-                                        (void **)&devp);
-        if ( EFI_ERROR(status) )
-            continue;
-        for ( ; !IsDevicePathEnd(devp.DevPath);
-              devp.DevPath = NextDevicePathNode(devp.DevPath) )
-        {
-            switch ( DevicePathType(devp.DevPath) )
-            {
-                const u8 *p;
-
-            case ACPI_DEVICE_PATH:
-                if ( state != root || boot_edd_info_nr > EDD_INFO_MAX )
-                    break;
-                switch ( DevicePathSubType(devp.DevPath) )
-                {
-                case ACPI_DP:
-                    if ( devp.Acpi->HID != EISA_PNP_ID(0xA03) &&
-                         devp.Acpi->HID != EISA_PNP_ID(0xA08) )
-                        break;
-                    params->interface_path.pci.bus = devp.Acpi->UID;
-                    state = acpi;
-                    break;
-                case EXPANDED_ACPI_DP:
-                    /* XXX */
-                    break;
-                }
-                break;
-            case HARDWARE_DEVICE_PATH:
-                if ( state != acpi ||
-                     DevicePathSubType(devp.DevPath) != HW_PCI_DP ||
-                     boot_edd_info_nr > EDD_INFO_MAX )
-                    break;
-                state = pci;
-                edd_put_string(params->host_bus_type, "PCI");
-                params->interface_path.pci.slot = devp.Pci->Device;
-                params->interface_path.pci.function = devp.Pci->Function;
-                break;
-            case MESSAGING_DEVICE_PATH:
-                if ( state != pci || boot_edd_info_nr > EDD_INFO_MAX )
-                    break;
-                state = ctrlr;
-                switch ( DevicePathSubType(devp.DevPath) )
-                {
-                case MSG_ATAPI_DP:
-                    edd_put_string(params->interface_type, "ATAPI");
-                    params->interface_path.pci.channel =
-                        devp.Atapi->PrimarySecondary;
-                    params->device_path.atapi.device = devp.Atapi->SlaveMaster;
-                    params->device_path.atapi.lun = devp.Atapi->Lun;
-                    break;
-                case MSG_SCSI_DP:
-                    edd_put_string(params->interface_type, "SCSI");
-                    params->device_path.scsi.id = devp.Scsi->Pun;
-                    params->device_path.scsi.lun = devp.Scsi->Lun;
-                    break;
-                case MSG_FIBRECHANNEL_DP:
-                    edd_put_string(params->interface_type, "FIBRE");
-                    params->device_path.fibre.wwid = devp.FibreChannel->WWN;
-                    params->device_path.fibre.lun = devp.FibreChannel->Lun;
-                    break;
-                case MSG_1394_DP:
-                    edd_put_string(params->interface_type, "1394");
-                    params->device_path.i1394.eui = devp.F1394->Guid;
-                    break;
-                case MSG_USB_DP:
-                case MSG_USB_CLASS_DP:
-                    edd_put_string(params->interface_type, "USB");
-                    break;
-                case MSG_I2O_DP:
-                    edd_put_string(params->interface_type, "I2O");
-                    params->device_path.i2o.identity_tag = devp.I2O->Tid;
-                    break;
-                default:
-                    continue;
-                }
-                info->version = 0x30;
-                params->length = sizeof(struct edd_device_params);
-                params->key = 0xbedd;
-                params->device_path_info_length =
-                    sizeof(struct edd_device_params) -
-                    offsetof(struct edd_device_params, key);
-                for ( p = (const u8 *)&params->key; p < &params->checksum; ++p )
-                    params->checksum -= *p;
-                break;
-            case MEDIA_DEVICE_PATH:
-                if ( DevicePathSubType(devp.DevPath) == MEDIA_HARDDRIVE_DP &&
-                     devp.HardDrive->MBRType == MBR_TYPE_PCAT &&
-                     boot_mbr_signature_nr < EDD_MBR_SIG_MAX )
-                {
-                    struct mbr_signature *sig = boot_mbr_signature +
-                                                boot_mbr_signature_nr;
-
-                    sig->device = 0x80 + boot_edd_info_nr; /* fake */
-                    memcpy(&sig->signature, devp.HardDrive->Signature,
-                           sizeof(sig->signature));
-                    ++boot_mbr_signature_nr;
-                }
-                break;
-            }
-        }
-    }
-    if ( handles )
-        efi_bs->FreePool(handles);
-    if ( boot_edd_info_nr > EDD_INFO_MAX )
-        boot_edd_info_nr = EDD_INFO_MAX;
+    efi_arch_edd();
 
     /* XXX Collect EDID info. */
 
@@ -1075,77 +867,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] =
         l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
 
-    if ( gop )
-    {
-        int bpp = 0;
-
-        /* Set graphics mode. */
-        if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode )
-            gop->SetMode(gop, gop_mode);
-
-        /* Get graphics and frame buffer info. */
-        status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
-        if ( !EFI_ERROR(status) )
-            switch ( mode_info->PixelFormat )
-            {
-            case PixelRedGreenBlueReserved8BitPerColor:
-                vga_console_info.u.vesa_lfb.red_pos = 0;
-                vga_console_info.u.vesa_lfb.red_size = 8;
-                vga_console_info.u.vesa_lfb.green_pos = 8;
-                vga_console_info.u.vesa_lfb.green_size = 8;
-                vga_console_info.u.vesa_lfb.blue_pos = 16;
-                vga_console_info.u.vesa_lfb.blue_size = 8;
-                vga_console_info.u.vesa_lfb.rsvd_pos = 24;
-                vga_console_info.u.vesa_lfb.rsvd_size = 8;
-                bpp = 32;
-                break;
-            case PixelBlueGreenRedReserved8BitPerColor:
-                vga_console_info.u.vesa_lfb.red_pos = 16;
-                vga_console_info.u.vesa_lfb.red_size = 8;
-                vga_console_info.u.vesa_lfb.green_pos = 8;
-                vga_console_info.u.vesa_lfb.green_size = 8;
-                vga_console_info.u.vesa_lfb.blue_pos = 0;
-                vga_console_info.u.vesa_lfb.blue_size = 8;
-                vga_console_info.u.vesa_lfb.rsvd_pos = 24;
-                vga_console_info.u.vesa_lfb.rsvd_size = 8;
-                bpp = 32;
-                break;
-            case PixelBitMask:
-                bpp = set_color(mode_info->PixelInformation.RedMask, bpp,
-                                &vga_console_info.u.vesa_lfb.red_pos,
-                                &vga_console_info.u.vesa_lfb.red_size);
-                bpp = set_color(mode_info->PixelInformation.GreenMask, bpp,
-                                &vga_console_info.u.vesa_lfb.green_pos,
-                                &vga_console_info.u.vesa_lfb.green_size);
-                bpp = set_color(mode_info->PixelInformation.BlueMask, bpp,
-                                &vga_console_info.u.vesa_lfb.blue_pos,
-                                &vga_console_info.u.vesa_lfb.blue_size);
-                bpp = set_color(mode_info->PixelInformation.ReservedMask, bpp,
-                                &vga_console_info.u.vesa_lfb.rsvd_pos,
-                                &vga_console_info.u.vesa_lfb.rsvd_size);
-                if ( bpp > 0 )
-                    break;
-                /* fall through */
-            default:
-                PrintErr(L"Current graphics mode is unsupported!\r\n");
-                status = EFI_UNSUPPORTED;
-                break;
-            }
-        if ( !EFI_ERROR(status) )
-        {
-            vga_console_info.video_type = XEN_VGATYPE_EFI_LFB;
-            vga_console_info.u.vesa_lfb.gbl_caps = 2; /* possibly non-VGA */
-            vga_console_info.u.vesa_lfb.width =
-                mode_info->HorizontalResolution;
-            vga_console_info.u.vesa_lfb.height = mode_info->VerticalResolution;
-            vga_console_info.u.vesa_lfb.bits_per_pixel = bpp;
-            vga_console_info.u.vesa_lfb.bytes_per_line =
-                (mode_info->PixelsPerScanLine * bpp + 7) >> 3;
-            vga_console_info.u.vesa_lfb.lfb_base = gop->Mode->FrameBufferBase;
-            vga_console_info.u.vesa_lfb.lfb_size =
-                (gop->Mode->FrameBufferSize + 0xffff) >> 16;
-        }
-    }
+    efi_arch_video(base_video, cols, rows, depth, gop);
 
     efi_arch_get_memory_map(&mmap_size, &mmap, &mmap_key,
                                   &mmap_desc_size, &mmap_desc_ver);
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
index d72b02b..900465d 100644
--- a/xen/include/asm-x86/efi-boot.h
+++ b/xen/include/asm-x86/efi-boot.h
@@ -641,3 +641,302 @@ static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
     mbi.boot_loader_name = (long)"EFI";
     mbi.mods_addr = (long)mb_modules;
 }
+
+static void __init efi_arch_edd(void)
+{
+    static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL;
+    static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL;
+    EFI_HANDLE *handles = NULL;
+    int i;
+    UINTN size;
+    EFI_STATUS status;
+
+    /* Collect EDD info. */
+    BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE);
+    BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE);
+    size = 0;
+    status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, NULL);
+    if ( status == EFI_BUFFER_TOO_SMALL )
+        status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
+    if ( !EFI_ERROR(status) )
+        status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size,
+                                      handles);
+    if ( EFI_ERROR(status) )
+        size = 0;
+    for ( i = 0; i < size / sizeof(*handles); ++i )
+    {
+        EFI_BLOCK_IO *bio;
+        EFI_DEV_PATH_PTR devp;
+        struct edd_info *info = boot_edd_info + boot_edd_info_nr;
+        struct edd_device_params *params = &info->edd_device_params;
+        enum { root, acpi, pci, ctrlr } state = root;
+
+        status = efi_bs->HandleProtocol(handles[i], &bio_guid, (void **)&bio);
+        if ( EFI_ERROR(status) ||
+             bio->Media->RemovableMedia ||
+             bio->Media->LogicalPartition )
+            continue;
+        if ( boot_edd_info_nr < EDD_INFO_MAX )
+        {
+            info->device = 0x80 + boot_edd_info_nr; /* fake */
+            info->version = 0x11;
+            params->length = offsetof(struct edd_device_params, dpte_ptr);
+            params->number_of_sectors = bio->Media->LastBlock + 1;
+            params->bytes_per_sector = bio->Media->BlockSize;
+            params->dpte_ptr = ~0;
+        }
+        ++boot_edd_info_nr;
+        status = efi_bs->HandleProtocol(handles[i], &devp_guid,
+                                        (void **)&devp);
+        if ( EFI_ERROR(status) )
+            continue;
+        for ( ; !IsDevicePathEnd(devp.DevPath);
+              devp.DevPath = NextDevicePathNode(devp.DevPath) )
+        {
+            switch ( DevicePathType(devp.DevPath) )
+            {
+                const u8 *p;
+
+            case ACPI_DEVICE_PATH:
+                if ( state != root || boot_edd_info_nr > EDD_INFO_MAX )
+                    break;
+                switch ( DevicePathSubType(devp.DevPath) )
+                {
+                case ACPI_DP:
+                    if ( devp.Acpi->HID != EISA_PNP_ID(0xA03) &&
+                         devp.Acpi->HID != EISA_PNP_ID(0xA08) )
+                        break;
+                    params->interface_path.pci.bus = devp.Acpi->UID;
+                    state = acpi;
+                    break;
+                case EXPANDED_ACPI_DP:
+                    /* XXX */
+                    break;
+                }
+                break;
+            case HARDWARE_DEVICE_PATH:
+                if ( state != acpi ||
+                     DevicePathSubType(devp.DevPath) != HW_PCI_DP ||
+                     boot_edd_info_nr > EDD_INFO_MAX )
+                    break;
+                state = pci;
+                edd_put_string(params->host_bus_type, "PCI");
+                params->interface_path.pci.slot = devp.Pci->Device;
+                params->interface_path.pci.function = devp.Pci->Function;
+                break;
+            case MESSAGING_DEVICE_PATH:
+                if ( state != pci || boot_edd_info_nr > EDD_INFO_MAX )
+                    break;
+                state = ctrlr;
+                switch ( DevicePathSubType(devp.DevPath) )
+                {
+                case MSG_ATAPI_DP:
+                    edd_put_string(params->interface_type, "ATAPI");
+                    params->interface_path.pci.channel =
+                        devp.Atapi->PrimarySecondary;
+                    params->device_path.atapi.device = devp.Atapi->SlaveMaster;
+                    params->device_path.atapi.lun = devp.Atapi->Lun;
+                    break;
+                case MSG_SCSI_DP:
+                    edd_put_string(params->interface_type, "SCSI");
+                    params->device_path.scsi.id = devp.Scsi->Pun;
+                    params->device_path.scsi.lun = devp.Scsi->Lun;
+                    break;
+                case MSG_FIBRECHANNEL_DP:
+                    edd_put_string(params->interface_type, "FIBRE");
+                    params->device_path.fibre.wwid = devp.FibreChannel->WWN;
+                    params->device_path.fibre.lun = devp.FibreChannel->Lun;
+                    break;
+                case MSG_1394_DP:
+                    edd_put_string(params->interface_type, "1394");
+                    params->device_path.i1394.eui = devp.F1394->Guid;
+                    break;
+                case MSG_USB_DP:
+                case MSG_USB_CLASS_DP:
+                    edd_put_string(params->interface_type, "USB");
+                    break;
+                case MSG_I2O_DP:
+                    edd_put_string(params->interface_type, "I2O");
+                    params->device_path.i2o.identity_tag = devp.I2O->Tid;
+                    break;
+                default:
+                    continue;
+                }
+                info->version = 0x30;
+                params->length = sizeof(struct edd_device_params);
+                params->key = 0xbedd;
+                params->device_path_info_length =
+                    sizeof(struct edd_device_params) -
+                    offsetof(struct edd_device_params, key);
+                for ( p = (const u8 *)&params->key; p < &params->checksum; ++p )
+                    params->checksum -= *p;
+                break;
+            case MEDIA_DEVICE_PATH:
+                if ( DevicePathSubType(devp.DevPath) == MEDIA_HARDDRIVE_DP &&
+                     devp.HardDrive->MBRType == MBR_TYPE_PCAT &&
+                     boot_mbr_signature_nr < EDD_MBR_SIG_MAX )
+                {
+                    struct mbr_signature *sig = boot_mbr_signature +
+                                                boot_mbr_signature_nr;
+
+                    sig->device = 0x80 + boot_edd_info_nr; /* fake */
+                    memcpy(&sig->signature, devp.HardDrive->Signature,
+                           sizeof(sig->signature));
+                    ++boot_mbr_signature_nr;
+                }
+                break;
+            }
+        }
+    }
+    if ( handles )
+        efi_bs->FreePool(handles);
+    if ( boot_edd_info_nr > EDD_INFO_MAX )
+        boot_edd_info_nr = EDD_INFO_MAX;
+}
+
+static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
+{
+   if ( bpp < 0 )
+       return bpp;
+   if ( !mask )
+       return -EINVAL;
+   for ( *pos = 0; !(mask & 1); ++*pos )
+       mask >>= 1;
+   for ( *sz = 0; mask & 1; ++sz)
+       mask >>= 1;
+   if ( mask )
+       return -EINVAL;
+   return max(*pos + *sz, bpp);
+}
+
+static void __init efi_arch_video(bool_t base_video,
+                                  UINTN cols, UINTN rows, UINTN depth,
+                                  EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
+{
+    int i;
+    EFI_STATUS status;
+    UINTN size, info_size, gop_mode = ~0;
+    EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
+
+    if ( gop && !base_video )
+    {
+        for ( i = size = 0; i < gop->Mode->MaxMode; ++i )
+        {
+            unsigned int bpp = 0;
+
+            status = gop->QueryMode(gop, i, &info_size, &mode_info);
+            if ( EFI_ERROR(status) )
+                continue;
+            switch ( mode_info->PixelFormat )
+            {
+            case PixelBitMask:
+                bpp = hweight32(mode_info->PixelInformation.RedMask |
+                                mode_info->PixelInformation.GreenMask |
+                                mode_info->PixelInformation.BlueMask);
+                break;
+            case PixelRedGreenBlueReserved8BitPerColor:
+            case PixelBlueGreenRedReserved8BitPerColor:
+                bpp = 24;
+                break;
+            default:
+                continue;
+            }
+            if ( cols == mode_info->HorizontalResolution &&
+                 rows == mode_info->VerticalResolution &&
+                 (!depth || bpp == depth) )
+            {
+                gop_mode = i;
+                break;
+            }
+            if ( !cols && !rows &&
+                 mode_info->HorizontalResolution *
+                 mode_info->VerticalResolution > size )
+            {
+                size = mode_info->HorizontalResolution *
+                       mode_info->VerticalResolution;
+                gop_mode = i;
+            }
+        }
+    }
+
+    if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
+                           &cols, &rows) == EFI_SUCCESS )
+    {
+        vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
+        vga_console_info.u.text_mode_3.columns = cols;
+        vga_console_info.u.text_mode_3.rows = rows;
+        vga_console_info.u.text_mode_3.font_height = 16;
+    }
+
+    if ( gop )
+    {
+        int bpp = 0;
+
+        /* Set graphics mode. */
+        if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode )
+            gop->SetMode(gop, gop_mode);
+
+        /* Get graphics and frame buffer info. */
+        status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
+        if ( !EFI_ERROR(status) )
+            switch ( mode_info->PixelFormat )
+            {
+            case PixelRedGreenBlueReserved8BitPerColor:
+                vga_console_info.u.vesa_lfb.red_pos = 0;
+                vga_console_info.u.vesa_lfb.red_size = 8;
+                vga_console_info.u.vesa_lfb.green_pos = 8;
+                vga_console_info.u.vesa_lfb.green_size = 8;
+                vga_console_info.u.vesa_lfb.blue_pos = 16;
+                vga_console_info.u.vesa_lfb.blue_size = 8;
+                vga_console_info.u.vesa_lfb.rsvd_pos = 24;
+                vga_console_info.u.vesa_lfb.rsvd_size = 8;
+                bpp = 32;
+                break;
+            case PixelBlueGreenRedReserved8BitPerColor:
+                vga_console_info.u.vesa_lfb.red_pos = 16;
+                vga_console_info.u.vesa_lfb.red_size = 8;
+                vga_console_info.u.vesa_lfb.green_pos = 8;
+                vga_console_info.u.vesa_lfb.green_size = 8;
+                vga_console_info.u.vesa_lfb.blue_pos = 0;
+                vga_console_info.u.vesa_lfb.blue_size = 8;
+                vga_console_info.u.vesa_lfb.rsvd_pos = 24;
+                vga_console_info.u.vesa_lfb.rsvd_size = 8;
+                bpp = 32;
+                break;
+            case PixelBitMask:
+                bpp = set_color(mode_info->PixelInformation.RedMask, bpp,
+                                &vga_console_info.u.vesa_lfb.red_pos,
+                                &vga_console_info.u.vesa_lfb.red_size);
+                bpp = set_color(mode_info->PixelInformation.GreenMask, bpp,
+                                &vga_console_info.u.vesa_lfb.green_pos,
+                                &vga_console_info.u.vesa_lfb.green_size);
+                bpp = set_color(mode_info->PixelInformation.BlueMask, bpp,
+                                &vga_console_info.u.vesa_lfb.blue_pos,
+                                &vga_console_info.u.vesa_lfb.blue_size);
+                bpp = set_color(mode_info->PixelInformation.ReservedMask, bpp,
+                                &vga_console_info.u.vesa_lfb.rsvd_pos,
+                                &vga_console_info.u.vesa_lfb.rsvd_size);
+                if ( bpp > 0 )
+                    break;
+                /* fall through */
+            default:
+                PrintErr(L"Current graphics mode is unsupported!\r\n");
+                status = EFI_UNSUPPORTED;
+                break;
+            }
+        if ( !EFI_ERROR(status) )
+        {
+            vga_console_info.video_type = XEN_VGATYPE_EFI_LFB;
+            vga_console_info.u.vesa_lfb.gbl_caps = 2; /* possibly non-VGA */
+            vga_console_info.u.vesa_lfb.width =
+                mode_info->HorizontalResolution;
+            vga_console_info.u.vesa_lfb.height = mode_info->VerticalResolution;
+            vga_console_info.u.vesa_lfb.bits_per_pixel = bpp;
+            vga_console_info.u.vesa_lfb.bytes_per_line =
+                (mode_info->PixelsPerScanLine * bpp + 7) >> 3;
+            vga_console_info.u.vesa_lfb.lfb_base = gop->Mode->FrameBufferBase;
+            vga_console_info.u.vesa_lfb.lfb_size =
+                (gop->Mode->FrameBufferSize + 0xffff) >> 16;
+        }
+    }
+}
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 08/15] Add efi_arch_memory() for arch specific memory setup
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (6 preceding siblings ...)
  2014-09-10  0:51 ` [PATCH V4 07/15] Move x86 specific video and disk probing code Roy Franz
@ 2014-09-10  0:51 ` Roy Franz
  2014-09-11 14:27   ` Jan Beulich
  2014-09-10  0:51 ` [PATCH V4 09/15] Add arch specific module handling to read_file() Roy Franz
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:51 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

This patch adds efi_arch_memory() to allow each architecture a hook
to use for do memory setup.  x86 uses this for trampoline memory setup
and some pagetable setup.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 29 +----------------------------
 xen/include/asm-x86/efi-boot.h | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 28 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 3fe04fd..9ee3b4a 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -838,34 +838,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
         PrintStr(newline);
     }
 
-    /* Allocate space for trampoline (in first Mb). */
-    cfg.addr = 0x100000;
-    cfg.size = trampoline_end - trampoline_start;
-    status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
-                                   PFN_UP(cfg.size), &cfg.addr);
-    if ( status == EFI_SUCCESS )
-        relocate_trampoline(cfg.addr);
-    else
-    {
-        cfg.addr = 0;
-        PrintStr(L"Trampoline space cannot be allocated; will try fallback.\r\n");
-    }
-
-    /* Initialise L2 identity-map and boot-map page table entries (16MB). */
-    for ( i = 0; i < 8; ++i )
-    {
-        unsigned int slot = (xen_phys_start >> L2_PAGETABLE_SHIFT) + i;
-        paddr_t addr = slot << L2_PAGETABLE_SHIFT;
-
-        l2_identmap[slot] = l2e_from_paddr(addr, PAGE_HYPERVISOR|_PAGE_PSE);
-        slot &= L2_PAGETABLE_ENTRIES - 1;
-        l2_bootmap[slot] = l2e_from_paddr(addr, __PAGE_HYPERVISOR|_PAGE_PSE);
-    }
-    /* Initialise L3 boot-map page directory entries. */
-    l3_bootmap[l3_table_offset(xen_phys_start)] =
-        l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
-    l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] =
-        l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
+    efi_arch_memory();
 
     efi_arch_video(base_video, cols, rows, depth, gop);
 
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
index 900465d..629a4c0 100644
--- a/xen/include/asm-x86/efi-boot.h
+++ b/xen/include/asm-x86/efi-boot.h
@@ -940,3 +940,38 @@ static void __init efi_arch_video(bool_t base_video,
         }
     }
 }
+
+static void __init efi_arch_memory(void)
+{
+    int i;
+    EFI_STATUS status;
+
+    /* Allocate space for trampoline (in first Mb). */
+    cfg.addr = 0x100000;
+    cfg.size = trampoline_end - trampoline_start;
+    status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
+                                   PFN_UP(cfg.size), &cfg.addr);
+    if ( status == EFI_SUCCESS )
+        relocate_trampoline(cfg.addr);
+    else
+    {
+        cfg.addr = 0;
+        PrintStr(L"Trampoline space cannot be allocated; will try fallback.\r\n");
+    }
+
+    /* Initialise L2 identity-map and boot-map page table entries (16MB). */
+    for ( i = 0; i < 8; ++i )
+    {
+        unsigned int slot = (xen_phys_start >> L2_PAGETABLE_SHIFT) + i;
+        paddr_t addr = slot << L2_PAGETABLE_SHIFT;
+
+        l2_identmap[slot] = l2e_from_paddr(addr, PAGE_HYPERVISOR|_PAGE_PSE);
+        slot &= L2_PAGETABLE_ENTRIES - 1;
+        l2_bootmap[slot] = l2e_from_paddr(addr, __PAGE_HYPERVISOR|_PAGE_PSE);
+    }
+    /* Initialise L3 boot-map page directory entries. */
+    l3_bootmap[l3_table_offset(xen_phys_start)] =
+        l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
+    l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] =
+        l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
+}
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 09/15] Add arch specific module handling to read_file()
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (7 preceding siblings ...)
  2014-09-10  0:51 ` [PATCH V4 08/15] Add efi_arch_memory() for arch specific memory setup Roy Franz
@ 2014-09-10  0:51 ` Roy Franz
  2014-09-11 14:40   ` Jan Beulich
  2014-09-10  0:52 ` [PATCH V4 10/15] Add SMBIOS and runtime services setup arch functions Roy Franz
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:51 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

Each architecture tracks modules differently internally,
so add efi_arch_handle_module() routine to enable the common
code to invoke the proper handling of modules as the are loaded.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 98 +++++++++++++++++++++++-------------------
 xen/include/asm-x86/efi-boot.h | 15 +++++--
 2 files changed, 66 insertions(+), 47 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 9ee3b4a..5296d88 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -51,11 +51,10 @@ static void __init DisplayUint(UINT64 Val, INTN Width);
 static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s);
 static char *__init get_value(const struct file *cfg, const char *section,
                               const char *item);
-static void __init split_value(char *s);
 static CHAR16 *__init s2w(union string *str);
 static char *__init w2s(const union string *str);
-static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
-                               struct file *file);
+static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, struct file *file,
+                               char *name_options);
 
 static EFI_BOOT_SERVICES *__initdata efi_bs;
 static EFI_HANDLE __initdata efi_ih;
@@ -398,18 +397,39 @@ static CHAR16 *__init point_tail(CHAR16 *fn)
             break;
         }
 }
+/*
+ * Truncate string at first space, and return pointer
+ * to remainder of string.
+ */
+static char * __init truncate_string(char *s)
+{
+    while ( *s && !isspace(*s) )
+        ++s;
+    if ( *s )
+    {
+        *s = 0;
+        return(s + 1);
+    }
+    return(NULL);
+}
 
-static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
-                               struct file *file)
+static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, struct file *file,
+                               char *name_options)
 {
     EFI_FILE_HANDLE FileHandle = NULL;
     UINT64 size;
     EFI_STATUS ret;
     CHAR16 *what = NULL;
+    char *options;
+    union string name;
+
+    options = truncate_string(name_options);
 
-    if ( !name )
+    name.s=name_options;
+    s2w(&name);
+    if ( !name.w )
         PrintErrMesg(L"No filename", EFI_OUT_OF_RESOURCES);
-    ret = dir_handle->Open(dir_handle, &FileHandle, name,
+    ret = dir_handle->Open(dir_handle, &FileHandle, name.w,
                            EFI_FILE_MODE_READ, 0);
     if ( file == &cfg && ret == EFI_NOT_FOUND )
         return 0;
@@ -441,20 +461,18 @@ static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
     }
     else
     {
+        file->size = size;
         if ( file != &cfg )
         {
-            PrintStr(name);
+            PrintStr(name.w);
             PrintStr(L": ");
             DisplayUint(file->addr, 2 * sizeof(file->addr));
             PrintStr(L"-");
             DisplayUint(file->addr + size, 2 * sizeof(file->addr));
             PrintStr(newline);
-            mb_modules[mbi.mods_count].mod_start = file->addr >> PAGE_SHIFT;
-            mb_modules[mbi.mods_count].mod_end = size;
-            ++mbi.mods_count;
+            efi_arch_handle_module(file, name_options, options);
         }
 
-        file->size = size;
         ret = FileHandle->Read(FileHandle, &file->size, file->ptr);
         if ( !EFI_ERROR(ret) && file->size != size )
             ret = EFI_ABORTED;
@@ -469,7 +487,7 @@ static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
     {
         PrintErr(what);
         PrintErr(L" failed for ");
-        PrintErrMesg(name, ret);
+        PrintErrMesg(name.w, ret);
     }
 
     return 1;
@@ -525,7 +543,13 @@ static char *__init get_value(const struct file *cfg, const char *section,
             break;
         default:
             if ( match && strncmp(ptr, item, ilen) == 0 && ptr[ilen] == '=' )
-                return ptr + ilen + 1;
+            {
+                ptr += ilen + 1;
+                /* strip off any leading spaces */
+                while ( *ptr && isspace(*ptr) )
+                    ptr++;
+                return ptr;
+            }
             break;
         }
         ptr += strlen(ptr);
@@ -533,16 +557,6 @@ static char *__init get_value(const struct file *cfg, const char *section,
     return NULL;
 }
 
-static void __init split_value(char *s)
-{
-    while ( *s && isspace(*s) )
-        ++s;
-    place_string(&mb_modules[mbi.mods_count].string, s);
-    while ( *s && !isspace(*s) )
-        ++s;
-    *s = 0;
-}
-
 void EFIAPI __init noreturn
 efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 {
@@ -552,14 +566,14 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     EFI_LOADED_IMAGE *loaded_image;
     EFI_STATUS status;
     unsigned int i, argc;
-    CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL;
+    CHAR16 **argv, *options = NULL;
     UINTN cols, rows, depth, size, info_size;
     EFI_HANDLE *handles = NULL;
     EFI_SHIM_LOCK_PROTOCOL *shim_lock;
     EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
     EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
     EFI_FILE_HANDLE dir_handle;
-    union string section = { NULL }, name;
+    union string section = { NULL }, name, file_name, cfg_file_name = {NULL};
     bool_t base_video = 0;
     UINT32 mmap_desc_ver = 0;
     UINTN mmap_size, mmap_desc_size, mmap_key = 0;
@@ -590,7 +604,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     trampoline_xen_phys_start = xen_phys_start;
 
     /* Get the file system interface. */
-    dir_handle = get_parent_handle(loaded_image, &file_name);
+    dir_handle = get_parent_handle(loaded_image, &file_name.w);
 
     argc = get_argv(0, NULL, loaded_image->LoadOptions,
                     loaded_image->LoadOptionsSize, &options);
@@ -614,9 +628,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
             if ( wstrcmp(ptr + 1, L"basevideo") == 0 )
                 base_video = 1;
             else if ( wstrncmp(ptr + 1, L"cfg=", 4) == 0 )
-                cfg_file_name = ptr + 5;
+                cfg_file_name.w = ptr + 5;
             else if ( i + 1 < argc && wstrcmp(ptr + 1, L"cfg") == 0 )
-                cfg_file_name = argv[++i];
+                cfg_file_name.w = argv[++i];
             else if ( wstrcmp(ptr + 1, L"help") == 0 ||
                       (ptr[1] == L'?' && !ptr[2]) )
             {
@@ -684,24 +698,26 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
         gop = NULL;
 
     /* Read and parse the config file. */
-    if ( !cfg_file_name )
+    if ( !cfg_file_name.w )
     {
         CHAR16 *tail;
 
-        while ( (tail = point_tail(file_name)) != NULL )
+        while ( (tail = point_tail(file_name.w)) != NULL )
         {
             wstrcpy(tail, L".cfg");
-            if ( read_file(dir_handle, file_name, &cfg) )
+            if ( read_file(dir_handle, &cfg, w2s(&file_name)) )
                 break;
             *tail = 0;
         }
         if ( !tail )
             blexit(L"No configuration file found.");
         PrintStr(L"Using configuration file '");
-        PrintStr(file_name);
+        s2w(&file_name);
+        PrintStr(file_name.w);
         PrintStr(L"'\r\n");
+        efi_bs->FreePool(file_name.w);
     }
-    else if ( !read_file(dir_handle, cfg_file_name, &cfg) )
+    else if ( !read_file(dir_handle, &cfg, w2s(&cfg_file_name)) )
         blexit(L"Configuration file not found.");
     pre_parse(&cfg);
 
@@ -720,7 +736,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
             break;
         efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
         cfg.addr = 0;
-        if ( !read_file(dir_handle, s2w(&name), &cfg) )
+        if ( !read_file(dir_handle, &cfg, name.s) )
         {
             PrintStr(L"Chained configuration file '");
             PrintStr(name.w);
@@ -735,9 +751,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 
     efi_arch_cfg_file(dir_handle, section.s);
 
-    split_value(name.s);
-    read_file(dir_handle, s2w(&name), &kernel);
-    efi_bs->FreePool(name.w);
+    read_file(dir_handle, &kernel, name.s);
 
     if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
                     (void **)&shim_lock)) &&
@@ -747,17 +761,13 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     name.s = get_value(&cfg, section.s, "ramdisk");
     if ( name.s )
     {
-        split_value(name.s);
-        read_file(dir_handle, s2w(&name), &ramdisk);
-        efi_bs->FreePool(name.w);
+        read_file(dir_handle, &ramdisk, name.s);
     }
 
     name.s = get_value(&cfg, section.s, "xsm");
     if ( name.s )
     {
-        split_value(name.s);
-        read_file(dir_handle, s2w(&name), &xsm);
-        efi_bs->FreePool(name.w);
+        read_file(dir_handle, &xsm, name.s);
     }
 
     cols = rows = depth = 0;
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
index 629a4c0..b09e12c 100644
--- a/xen/include/asm-x86/efi-boot.h
+++ b/xen/include/asm-x86/efi-boot.h
@@ -602,9 +602,7 @@ static void __init efi_arch_cfg_file(EFI_FILE_HANDLE dir_handle, char *section)
     if ( name.s )
     {
         microcode_set_module(mbi.mods_count);
-        split_value(name.s);
-        read_file(dir_handle, s2w(&name), &ucode);
-        efi_bs->FreePool(name.w);
+        read_file(dir_handle, &ucode, name.s);
     }
 }
 
@@ -975,3 +973,14 @@ static void __init efi_arch_memory(void)
     l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] =
         l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
 }
+
+static void __init efi_arch_handle_module(struct file *file, char *name,
+                                          char *options)
+{
+    place_string(&mb_modules[mbi.mods_count].string, options);
+    place_string(&mb_modules[mbi.mods_count].string, "");
+    place_string(&mb_modules[mbi.mods_count].string, name);
+    mb_modules[mbi.mods_count].mod_start = file->addr >> PAGE_SHIFT;
+    mb_modules[mbi.mods_count].mod_end = file->size;
+    ++mbi.mods_count;
+}
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 10/15] Add SMBIOS and runtime services setup arch functions.
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (8 preceding siblings ...)
  2014-09-10  0:51 ` [PATCH V4 09/15] Add arch specific module handling to read_file() Roy Franz
@ 2014-09-10  0:52 ` Roy Franz
  2014-09-11 14:44   ` Jan Beulich
  2014-09-10  0:52 ` [PATCH V4 11/15] Add several misc. arch functions for EFI boot code Roy Franz
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:52 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

Add architecture specific funtions for setting up SMBIOS and
runtime services data structures.  These are not fundamentally
x86 specific, but ARM currently lacks implementations.  These functions
may not be needed when ARM SMBIOS and runtime service support is added.
Both SMBIOS and EFI runtime service support depend on this EFI boot
patch series.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 50 ++++----------------------------------
 xen/include/asm-x86/efi-boot.h | 55 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 45 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 5296d88..013597b 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -55,6 +55,8 @@ static CHAR16 *__init s2w(union string *str);
 static char *__init w2s(const union string *str);
 static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, struct file *file,
                                char *name_options);
+static bool_t __init __maybe_unused match_guid(const EFI_GUID *guid1,
+                                               const EFI_GUID *guid2);
 
 static EFI_BOOT_SERVICES *__initdata efi_bs;
 static EFI_HANDLE __initdata efi_ih;
@@ -170,7 +172,7 @@ static char *__init w2s(const union string *str)
     return str->s;
 }
 
-static bool_t __init match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2)
+static bool_t __init __maybe_unused match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2)
 {
     return guid1->Data1 == guid2->Data1 &&
            guid1->Data2 == guid2->Data2 &&
@@ -581,12 +583,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 
     efi_ih = ImageHandle;
     efi_bs = SystemTable->BootServices;
-    efi_rs = SystemTable->RuntimeServices;
-    efi_ct = SystemTable->ConfigurationTable;
-    efi_num_ct = SystemTable->NumberOfTableEntries;
-    efi_version = SystemTable->Hdr.Revision;
-    efi_fw_vendor = SystemTable->FirmwareVendor;
-    efi_fw_revision = SystemTable->FirmwareRevision;
 
     StdOut = SystemTable->ConOut;
     StdErr = SystemTable->StdErr ?: StdOut;
@@ -805,49 +801,13 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
         boot_cpu_data.x86_capability[1] = cpuid_ext_features;
     }
 
-    /* Obtain basic table pointers. */
-    for ( i = 0; i < efi_num_ct; ++i )
-    {
-        static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
-        static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
-        static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
-        static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
-
-        if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
-	       efi.acpi20 = (long)efi_ct[i].VendorTable;
-        if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
-	       efi.acpi = (long)efi_ct[i].VendorTable;
-        if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
-	       efi.mps = (long)efi_ct[i].VendorTable;
-        if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
-	       efi.smbios = (long)efi_ct[i].VendorTable;
-    }
+    efi_arch_runtime_setup(SystemTable);
 
-    if (efi.smbios != EFI_INVALID_TABLE_ADDR)
-        dmi_efi_get_table((void *)(long)efi.smbios);
+    efi_arch_smbios();
 
     /* Collect PCI ROM contents. */
     efi_arch_pci();
 
-    /* Get snapshot of variable store parameters. */
-    status = (efi_rs->Hdr.Revision >> 16) >= 2 ?
-             efi_rs->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE |
-                                       EFI_VARIABLE_BOOTSERVICE_ACCESS |
-                                       EFI_VARIABLE_RUNTIME_ACCESS,
-                                       &efi_boot_max_var_store_size,
-                                       &efi_boot_remain_var_store_size,
-                                       &efi_boot_max_var_size) :
-             EFI_INCOMPATIBLE_VERSION;
-    if ( EFI_ERROR(status) )
-    {
-        efi_boot_max_var_store_size = 0;
-        efi_boot_remain_var_store_size = 0;
-        efi_boot_max_var_size = status;
-        PrintStr(L"Warning: Could not query variable store: ");
-        DisplayUint(status, 0);
-        PrintStr(newline);
-    }
-
     efi_arch_memory();
 
     efi_arch_video(base_video, cols, rows, depth, gop);
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
index b09e12c..b2e8599 100644
--- a/xen/include/asm-x86/efi-boot.h
+++ b/xen/include/asm-x86/efi-boot.h
@@ -984,3 +984,58 @@ static void __init efi_arch_handle_module(struct file *file, char *name,
     mb_modules[mbi.mods_count].mod_end = file->size;
     ++mbi.mods_count;
 }
+
+static void __init efi_arch_smbios(void)
+{
+    if (efi.smbios != EFI_INVALID_TABLE_ADDR)
+        dmi_efi_get_table((void *)(long)efi.smbios);
+}
+
+static void __init efi_arch_runtime_setup(EFI_SYSTEM_TABLE *SystemTable)
+{
+    EFI_STATUS status;
+    int i;
+
+    efi_rs = SystemTable->RuntimeServices;
+    efi_ct = SystemTable->ConfigurationTable;
+    efi_num_ct = SystemTable->NumberOfTableEntries;
+    efi_version = SystemTable->Hdr.Revision;
+    efi_fw_vendor = SystemTable->FirmwareVendor;
+    efi_fw_revision = SystemTable->FirmwareRevision;
+
+    /* Obtain basic table pointers. */
+    for ( i = 0; i < efi_num_ct; ++i )
+    {
+        static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
+        static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
+        static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
+        static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
+
+        if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
+	       efi.acpi20 = (long)efi_ct[i].VendorTable;
+        if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
+	       efi.acpi = (long)efi_ct[i].VendorTable;
+        if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
+	       efi.mps = (long)efi_ct[i].VendorTable;
+        if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
+	       efi.smbios = (long)efi_ct[i].VendorTable;
+    }
+    /* Get snapshot of variable store parameters. */
+    status = (efi_rs->Hdr.Revision >> 16) >= 2 ?
+             efi_rs->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE |
+                                       EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                                       EFI_VARIABLE_RUNTIME_ACCESS,
+                                       &efi_boot_max_var_store_size,
+                                       &efi_boot_remain_var_store_size,
+                                       &efi_boot_max_var_size) :
+             EFI_INCOMPATIBLE_VERSION;
+    if ( EFI_ERROR(status) )
+    {
+        efi_boot_max_var_store_size = 0;
+        efi_boot_remain_var_store_size = 0;
+        efi_boot_max_var_size = status;
+        PrintStr(L"Warning: Could not query variable store: ");
+        DisplayUint(status, 0);
+        PrintStr(newline);
+    }
+}
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 11/15] Add several misc. arch functions for EFI boot code.
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (9 preceding siblings ...)
  2014-09-10  0:52 ` [PATCH V4 10/15] Add SMBIOS and runtime services setup arch functions Roy Franz
@ 2014-09-10  0:52 ` Roy Franz
  2014-09-11 14:45   ` Jan Beulich
  2014-09-10  0:52 ` [PATCH V4 12/15] Add efi_arch_use_config_file() function to control use of config file Roy Franz
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:52 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

Add efi_arch_blexit() for arch specific cleanup on error exit,
efi_arch_load_addr_check() to do the arch specific verifications
of where the UEFI firmware loaded Xen, and efi_arch_cpu() for
probing CPU features.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 18 ++++--------------
 xen/include/asm-x86/efi-boot.h | 24 ++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 013597b..1630dde 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -192,11 +192,11 @@ static void __init noreturn blexit(const CHAR16 *str)
         efi_bs->FreePages(kernel.addr, PFN_UP(kernel.size));
     if ( ramdisk.addr )
         efi_bs->FreePages(ramdisk.addr, PFN_UP(ramdisk.size));
-    if ( ucode.addr )
-        efi_bs->FreePages(ucode.addr, PFN_UP(ucode.size));
     if ( xsm.addr )
         efi_bs->FreePages(xsm.addr, PFN_UP(xsm.size));
 
+    efi_arch_blexit();
+
     efi_bs->Exit(efi_ih, EFI_SUCCESS, 0, NULL);
     unreachable(); /* not reached */
 }
@@ -592,12 +592,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     if ( status != EFI_SUCCESS )
         PrintErrMesg(L"No Loaded Image Protocol", status);
 
-    xen_phys_start = (UINTN)loaded_image->ImageBase;
-    if ( (xen_phys_start + loaded_image->ImageSize - 1) >> 32 )
-        blexit(L"Xen must be loaded below 4Gb.");
-    if ( xen_phys_start & ((1 << L2_PAGETABLE_SHIFT) - 1) )
-        blexit(L"Xen must be loaded at a 2Mb boundary.");
-    trampoline_xen_phys_start = xen_phys_start;
+    efi_arch_load_addr_check(loaded_image);
 
     /* Get the file system interface. */
     dir_handle = get_parent_handle(loaded_image, &file_name.w);
@@ -794,12 +789,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     efi_arch_edd();
 
     /* XXX Collect EDID info. */
-
-    if ( cpuid_eax(0x80000000) > 0x80000000 )
-    {
-        cpuid_ext_features = cpuid_edx(0x80000001);
-        boot_cpu_data.x86_capability[1] = cpuid_ext_features;
-    }
+    efi_arch_cpu();
 
     efi_arch_runtime_setup(SystemTable);
 
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
index b2e8599..e7e9b15 100644
--- a/xen/include/asm-x86/efi-boot.h
+++ b/xen/include/asm-x86/efi-boot.h
@@ -985,6 +985,14 @@ static void __init efi_arch_handle_module(struct file *file, char *name,
     ++mbi.mods_count;
 }
 
+static void __init efi_arch_cpu(void)
+{
+    if ( cpuid_eax(0x80000000) > 0x80000000 )
+    {
+        cpuid_ext_features = cpuid_edx(0x80000001);
+        boot_cpu_data.x86_capability[1] = cpuid_ext_features;
+    }
+}
 static void __init efi_arch_smbios(void)
 {
     if (efi.smbios != EFI_INVALID_TABLE_ADDR)
@@ -1039,3 +1047,19 @@ static void __init efi_arch_runtime_setup(EFI_SYSTEM_TABLE *SystemTable)
         PrintStr(newline);
     }
 }
+
+static void __init efi_arch_blexit(void)
+{
+    if ( ucode.addr )
+        efi_bs->FreePages(ucode.addr, PFN_UP(ucode.size));
+}
+
+static void __init efi_arch_load_addr_check(EFI_LOADED_IMAGE *loaded_image)
+{
+    xen_phys_start = (UINTN)loaded_image->ImageBase;
+    if ( (xen_phys_start + loaded_image->ImageSize - 1) >> 32 )
+        blexit(L"Xen must be loaded below 4Gb.");
+    if ( xen_phys_start & ((1 << L2_PAGETABLE_SHIFT) - 1) )
+        blexit(L"Xen must be loaded at a 2Mb boundary.");
+    trampoline_xen_phys_start = xen_phys_start;
+}
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 12/15] Add efi_arch_use_config_file() function to control use of config file
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (10 preceding siblings ...)
  2014-09-10  0:52 ` [PATCH V4 11/15] Add several misc. arch functions for EFI boot code Roy Franz
@ 2014-09-10  0:52 ` Roy Franz
  2014-09-11 14:49   ` Jan Beulich
  2014-09-10  0:52 ` [PATCH V4 13/15] add arm64 cache flushing code from linux v3.16 Roy Franz
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:52 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

The x86 EFI build of Xen always uses a configuration file to load modules, but
the ARM version can either use a config file to specify the modules, or be
loaded by GRUB in which case GRUB loads the modules and adds them to the DTB
that is passed to Xen.  Add the efi_arch_use_config_file() to indicate if a
configuration file is required.  For x86, this will always be true.  ARM will
examine the DTB passed via EFI configuration table (if any), and if it contains
module information will use that that not use the configuration file at all.
Add Emacs footer to efi-boot.h and boot.c

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/efi/boot.c          | 177 ++++++++++++++++++++++-------------------
 xen/include/asm-x86/efi-boot.h |  14 ++++
 2 files changed, 108 insertions(+), 83 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 1630dde..36bcfe4 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -574,8 +574,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     EFI_SHIM_LOCK_PROTOCOL *shim_lock;
     EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
     EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
-    EFI_FILE_HANDLE dir_handle;
-    union string section = { NULL }, name, file_name, cfg_file_name = {NULL};
+    union string section = { NULL }, name = { NULL }, file_name, cfg_file_name = {NULL};
     bool_t base_video = 0;
     UINT32 mmap_desc_ver = 0;
     UINTN mmap_size, mmap_desc_size, mmap_key = 0;
@@ -594,9 +593,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 
     efi_arch_load_addr_check(loaded_image);
 
-    /* Get the file system interface. */
-    dir_handle = get_parent_handle(loaded_image, &file_name.w);
-
     argc = get_argv(0, NULL, loaded_image->LoadOptions,
                     loaded_image->LoadOptionsSize, &options);
     if ( argc > 0 &&
@@ -688,104 +684,111 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     if ( EFI_ERROR(status) )
         gop = NULL;
 
-    /* Read and parse the config file. */
-    if ( !cfg_file_name.w )
+    if ( efi_arch_use_config_file(SystemTable) )
     {
-        CHAR16 *tail;
+        EFI_FILE_HANDLE dir_handle;
 
-        while ( (tail = point_tail(file_name.w)) != NULL )
+        /* Get the file system interface. */
+        dir_handle = get_parent_handle(loaded_image, &file_name.w);
+        /* Read and parse the config file. */
+        if ( !cfg_file_name.w )
         {
-            wstrcpy(tail, L".cfg");
-            if ( read_file(dir_handle, &cfg, w2s(&file_name)) )
-                break;
-            *tail = 0;
+            CHAR16 *tail;
+
+            while ( (tail = point_tail(file_name.w)) != NULL )
+            {
+                wstrcpy(tail, L".cfg");
+                if ( read_file(dir_handle, &cfg, w2s(&file_name)) )
+                    break;
+                *tail = 0;
+            }
+            if ( !tail )
+                blexit(L"No configuration file found.");
+            PrintStr(L"Using configuration file '");
+            s2w(&file_name);
+            PrintStr(file_name.w);
+            PrintStr(L"'\r\n");
+            efi_bs->FreePool(file_name.w);
         }
-        if ( !tail )
-            blexit(L"No configuration file found.");
-        PrintStr(L"Using configuration file '");
-        s2w(&file_name);
-        PrintStr(file_name.w);
-        PrintStr(L"'\r\n");
-        efi_bs->FreePool(file_name.w);
-    }
-    else if ( !read_file(dir_handle, &cfg, w2s(&cfg_file_name)) )
-        blexit(L"Configuration file not found.");
-    pre_parse(&cfg);
+        else if ( !read_file(dir_handle, &cfg, w2s(&cfg_file_name)) )
+            blexit(L"Configuration file not found.");
+        pre_parse(&cfg);
 
-    if ( section.w )
-        w2s(&section);
-    else
-        section.s = get_value(&cfg, "global", "default");
+        if ( section.w )
+            w2s(&section);
+        else
+            section.s = get_value(&cfg, "global", "default");
 
-    for ( ; ; )
-    {
-        name.s = get_value(&cfg, section.s, "kernel");
-        if ( name.s )
-            break;
-        name.s = get_value(&cfg, "global", "chain");
-        if ( !name.s )
-            break;
-        efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
-        cfg.addr = 0;
-        if ( !read_file(dir_handle, &cfg, name.s) )
+        for ( ; ; )
         {
-            PrintStr(L"Chained configuration file '");
-            PrintStr(name.w);
+            name.s = get_value(&cfg, section.s, "kernel");
+            if ( name.s )
+                break;
+            name.s = get_value(&cfg, "global", "chain");
+            if ( !name.s )
+                break;
+            efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
+            cfg.addr = 0;
+            if ( !read_file(dir_handle, &cfg, name.s) )
+            {
+                PrintStr(L"Chained configuration file '");
+                PrintStr(name.w);
+                efi_bs->FreePool(name.w);
+                blexit(L"'not found.");
+            }
+            pre_parse(&cfg);
             efi_bs->FreePool(name.w);
-            blexit(L"'not found.");
         }
-        pre_parse(&cfg);
-        efi_bs->FreePool(name.w);
-    }
-    if ( !name.s )
-        blexit(L"No Dom0 kernel image specified.");
-
-    efi_arch_cfg_file(dir_handle, section.s);
+        if ( !name.s )
+            blexit(L"No Dom0 kernel image specified.");
 
-    read_file(dir_handle, &kernel, name.s);
+        efi_arch_cfg_file(dir_handle, section.s);
 
-    if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
-                    (void **)&shim_lock)) &&
-         (status = shim_lock->Verify(kernel.ptr, kernel.size)) != EFI_SUCCESS )
+        read_file(dir_handle, &kernel, name.s);
+        if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
+                                               (void **)&shim_lock)) &&
+             (status = shim_lock->Verify(kernel.ptr, kernel.size)) != EFI_SUCCESS )
         PrintErrMesg(L"Dom0 kernel image could not be verified", status);
 
-    name.s = get_value(&cfg, section.s, "ramdisk");
-    if ( name.s )
-    {
-        read_file(dir_handle, &ramdisk, name.s);
-    }
+        name.s = get_value(&cfg, section.s, "ramdisk");
+        if ( name.s )
+        {
+            read_file(dir_handle, &ramdisk, name.s);
+        }
 
-    name.s = get_value(&cfg, section.s, "xsm");
-    if ( name.s )
-    {
-        read_file(dir_handle, &xsm, name.s);
-    }
+        name.s = get_value(&cfg, section.s, "xsm");
+        if ( name.s )
+        {
+            read_file(dir_handle, &xsm, name.s);
+        }
 
-    cols = rows = depth = 0;
-    if ( !base_video )
-    {
-        name.cs = get_value(&cfg, section.s, "video");
-        if ( !name.cs )
-            name.cs = get_value(&cfg, "global", "video");
-        if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
+        cols = rows = depth = 0;
+        if ( !base_video )
         {
-            cols = simple_strtoul(name.cs + 4, &name.cs, 10);
-            if ( *name.cs == 'x' )
-                rows = simple_strtoul(name.cs + 1, &name.cs, 10);
-            if ( *name.cs == 'x' )
-                depth = simple_strtoul(name.cs + 1, &name.cs, 10);
-            if ( *name.cs )
-                cols = rows = depth = 0;
+            name.cs = get_value(&cfg, section.s, "video");
+            if ( !name.cs )
+                name.cs = get_value(&cfg, "global", "video");
+            if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
+            {
+                cols = simple_strtoul(name.cs + 4, &name.cs, 10);
+                if ( *name.cs == 'x' )
+                    rows = simple_strtoul(name.cs + 1, &name.cs, 10);
+                if ( *name.cs == 'x' )
+                    depth = simple_strtoul(name.cs + 1, &name.cs, 10);
+                if ( *name.cs )
+                    cols = rows = depth = 0;
+            }
         }
-    }
+        name.s = get_value(&cfg, section.s, "options");
 
-    name.s = get_value(&cfg, section.s, "options");
-    efi_arch_handle_cmdline(argc ? *argv : NULL, options, name.s);
+        efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
+        cfg.addr = 0;
+
+        dir_handle->Close(dir_handle);
 
-    efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
-    cfg.addr = 0;
+        efi_arch_handle_cmdline(argc ? *argv : NULL, options, name.s);
+    }
 
-    dir_handle->Close(dir_handle);
     efi_arch_edd();
 
     /* XXX Collect EDID info. */
@@ -818,3 +821,11 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     for( ; ; ); /* not reached */
 }
 
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h
index e7e9b15..65483d3 100644
--- a/xen/include/asm-x86/efi-boot.h
+++ b/xen/include/asm-x86/efi-boot.h
@@ -1063,3 +1063,17 @@ static void __init efi_arch_load_addr_check(EFI_LOADED_IMAGE *loaded_image)
         blexit(L"Xen must be loaded at a 2Mb boundary.");
     trampoline_xen_phys_start = xen_phys_start;
 }
+
+static __init bool_t efi_arch_use_config_file(EFI_SYSTEM_TABLE *SystemTable)
+{
+    return 1; /* x86 always uses a config file */
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 13/15] add arm64 cache flushing code from linux v3.16
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (11 preceding siblings ...)
  2014-09-10  0:52 ` [PATCH V4 12/15] Add efi_arch_use_config_file() function to control use of config file Roy Franz
@ 2014-09-10  0:52 ` Roy Franz
  2014-09-10  0:52 ` [PATCH V4 14/15] Update libfdt to v1.4.0 Roy Franz
  2014-09-10  0:52 ` [PATCH V4 15/15] Add ARM EFI boot support Roy Franz
  14 siblings, 0 replies; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:52 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

__flush_dcache_all added from arch/arm64/mm/cache.S, with helper macros from
arch/arm64/include/asm/assembler.h, from v3.16.  The cache flushing is required
when transitioning from EFI code that runs with cache enable to Xen startup
code which expects the cache to be disabled.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/arch/arm/arm64/Makefile |   1 +
 xen/arch/arm/arm64/cache.S  | 100 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 101 insertions(+)
 create mode 100644 xen/arch/arm/arm64/cache.S

diff --git a/xen/arch/arm/arm64/Makefile b/xen/arch/arm/arm64/Makefile
index d2d5875..c7243f5 100644
--- a/xen/arch/arm/arm64/Makefile
+++ b/xen/arch/arm/arm64/Makefile
@@ -7,5 +7,6 @@ obj-y += domain.o
 obj-y += vfp.o
 obj-y += smpboot.o
 obj-y += domctl.o
+obj-y += cache.o
 
 obj-$(EARLY_PRINTK) += debug.o
diff --git a/xen/arch/arm/arm64/cache.S b/xen/arch/arm/arm64/cache.S
new file mode 100644
index 0000000..fb6dff1
--- /dev/null
+++ b/xen/arch/arm/arm64/cache.S
@@ -0,0 +1,100 @@
+/*
+ * Cache maintenance
+ *
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 1996-2000 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Enable and disable interrupts.
+ */
+	.macro	disable_irq
+	msr	daifset, #2
+	.endm
+
+	.macro	enable_irq
+	msr	daifclr, #2
+	.endm
+
+/*
+ * Save/disable and restore interrupts.
+ */
+	.macro	save_and_disable_irqs, olddaif
+	mrs	\olddaif, daif
+	disable_irq
+	.endm
+
+	.macro	restore_irqs, olddaif
+	msr	daif, \olddaif
+	.endm
+
+/*
+ *	__flush_dcache_all()
+ *
+ *	Flush the whole D-cache.
+ *
+ *	Corrupted registers: x0-x7, x9-x11
+ */
+	ENTRY(__flush_dcache_all)
+__flush_dcache_all:
+	dmb	sy				// ensure ordering with previous memory accesses
+	mrs	x0, clidr_el1			// read clidr
+	and	x3, x0, #0x7000000		// extract loc from clidr
+	lsr	x3, x3, #23			// left align loc bit field
+	cbz	x3, finished			// if loc is 0, then no need to clean
+	mov	x10, #0				// start clean at cache level 0
+loop1:
+	add	x2, x10, x10, lsr #1		// work out 3x current cache level
+	lsr	x1, x0, x2			// extract cache type bits from clidr
+	and	x1, x1, #7			// mask of the bits for current cache only
+	cmp	x1, #2				// see what cache we have at this level
+	b.lt	skip				// skip if no cache, or just i-cache
+	save_and_disable_irqs x9		// make CSSELR and CCSIDR access atomic
+	msr	csselr_el1, x10			// select current cache level in csselr
+	isb					// isb to sych the new cssr&csidr
+	mrs	x1, ccsidr_el1			// read the new ccsidr
+	restore_irqs x9
+	and	x2, x1, #7			// extract the length of the cache lines
+	add	x2, x2, #4			// add 4 (line length offset)
+	mov	x4, #0x3ff
+	and	x4, x4, x1, lsr #3		// find maximum number on the way size
+	clz	w5, w4				// find bit position of way size increment
+	mov	x7, #0x7fff
+	and	x7, x7, x1, lsr #13		// extract max number of the index size
+loop2:
+	mov	x9, x4				// create working copy of max way size
+loop3:
+	lsl	x6, x9, x5
+	orr	x11, x10, x6			// factor way and cache number into x11
+	lsl	x6, x7, x2
+	orr	x11, x11, x6			// factor index number into x11
+	dc	cisw, x11			// clean & invalidate by set/way
+	subs	x9, x9, #1			// decrement the way
+	b.ge	loop3
+	subs	x7, x7, #1			// decrement the index
+	b.ge	loop2
+skip:
+	add	x10, x10, #2			// increment cache number
+	cmp	x3, x10
+	b.gt	loop1
+finished:
+	mov	x10, #0				// swith back to cache level 0
+	msr	csselr_el1, x10			// select current cache level in csselr
+	dsb	sy
+	isb
+	ret
+ENDPROC(__flush_dcache_all)
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 14/15] Update libfdt to v1.4.0
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (12 preceding siblings ...)
  2014-09-10  0:52 ` [PATCH V4 13/15] add arm64 cache flushing code from linux v3.16 Roy Franz
@ 2014-09-10  0:52 ` Roy Franz
  2014-09-10  0:52 ` [PATCH V4 15/15] Add ARM EFI boot support Roy Franz
  14 siblings, 0 replies; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:52 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

Update libfdt to v1.4.0 of libfdt taken from git://git.jdl.com/software/dtc.git
Xen changes to libfdt_env.h carried over from existing libfdt (v1.3.0)
This update provides the fdt_create_empty_tree() function used by the ARM
EFI boot code.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 xen/common/libfdt/Makefile.libfdt   |   4 +-
 xen/common/libfdt/fdt.c             |  30 +++-
 xen/common/libfdt/fdt_empty_tree.c  |  84 ++++++++++
 xen/common/libfdt/fdt_ro.c          |   7 +-
 xen/common/libfdt/fdt_rw.c          |  31 +++-
 xen/common/libfdt/fdt_sw.c          |   4 +-
 xen/common/libfdt/fdt_wip.c         |   2 +-
 xen/common/libfdt/version.lds       |   6 +
 xen/include/xen/libfdt/fdt.h        |  93 ++++++++---
 xen/include/xen/libfdt/libfdt.h     | 315 +++++++++++++++++++++++++++++++++---
 xen/include/xen/libfdt/libfdt_env.h |   4 +
 11 files changed, 529 insertions(+), 51 deletions(-)
 create mode 100644 xen/common/libfdt/fdt_empty_tree.c

diff --git a/xen/common/libfdt/Makefile.libfdt b/xen/common/libfdt/Makefile.libfdt
index d55a6f8..91126c0 100644
--- a/xen/common/libfdt/Makefile.libfdt
+++ b/xen/common/libfdt/Makefile.libfdt
@@ -4,7 +4,7 @@
 # be easily embeddable into other systems of Makefiles.
 #
 LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
-LIBFDT_INCLUDES = fdt.h libfdt.h
+LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
 LIBFDT_VERSION = version.lds
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/xen/common/libfdt/fdt.c b/xen/common/libfdt/fdt.c
index e56833a..2ce6a44 100644
--- a/xen/common/libfdt/fdt.c
+++ b/xen/common/libfdt/fdt.c
@@ -92,7 +92,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
 
 uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
 {
-	const uint32_t *tagp, *lenp;
+	const fdt32_t *tagp, *lenp;
 	uint32_t tag;
 	int offset = startoffset;
 	const char *p;
@@ -198,6 +198,34 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
 	return offset;
 }
 
+int fdt_first_subnode(const void *fdt, int offset)
+{
+	int depth = 0;
+
+	offset = fdt_next_node(fdt, offset, &depth);
+	if (offset < 0 || depth != 1)
+		return -FDT_ERR_NOTFOUND;
+
+	return offset;
+}
+
+int fdt_next_subnode(const void *fdt, int offset)
+{
+	int depth = 1;
+
+	/*
+	 * With respect to the parent, the depth of the next subnode will be
+	 * the same as the last.
+	 */
+	do {
+		offset = fdt_next_node(fdt, offset, &depth);
+		if (offset < 0 || depth < 1)
+			return -FDT_ERR_NOTFOUND;
+	} while (depth > 1);
+
+	return offset;
+}
+
 const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
 {
 	int len = strlen(s) + 1;
diff --git a/xen/common/libfdt/fdt_empty_tree.c b/xen/common/libfdt/fdt_empty_tree.c
new file mode 100644
index 0000000..f72d13b
--- /dev/null
+++ b/xen/common/libfdt/fdt_empty_tree.c
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_create_empty_tree(void *buf, int bufsize)
+{
+	int err;
+
+	err = fdt_create(buf, bufsize);
+	if (err)
+		return err;
+
+	err = fdt_finish_reservemap(buf);
+	if (err)
+		return err;
+
+	err = fdt_begin_node(buf, "");
+	if (err)
+		return err;
+
+	err =  fdt_end_node(buf);
+	if (err)
+		return err;
+
+	err = fdt_finish(buf);
+	if (err)
+		return err;
+
+	return fdt_open_into(buf, buf, bufsize);
+}
+
diff --git a/xen/common/libfdt/fdt_ro.c b/xen/common/libfdt/fdt_ro.c
index 02b6d68..50007f6 100644
--- a/xen/common/libfdt/fdt_ro.c
+++ b/xen/common/libfdt/fdt_ro.c
@@ -322,7 +322,7 @@ const void *fdt_getprop(const void *fdt, int nodeoffset,
 
 uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
 {
-	const uint32_t *php;
+	const fdt32_t *php;
 	int len;
 
 	/* FIXME: This is a bit sub-optimal, since we potentially scan
@@ -515,8 +515,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
 	return offset; /* error from fdt_next_node() */
 }
 
-static int _fdt_stringlist_contains(const char *strlist, int listlen,
-				    const char *str)
+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
 {
 	int len = strlen(str);
 	const char *p;
@@ -542,7 +541,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 	prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
 	if (!prop)
 		return len;
-	if (_fdt_stringlist_contains(prop, len, compatible))
+	if (fdt_stringlist_contains(prop, len, compatible))
 		return 0;
 	else
 		return 1;
diff --git a/xen/common/libfdt/fdt_rw.c b/xen/common/libfdt/fdt_rw.c
index 994037b..fdba618 100644
--- a/xen/common/libfdt/fdt_rw.c
+++ b/xen/common/libfdt/fdt_rw.c
@@ -289,6 +289,33 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
 	return 0;
 }
 
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+		   const void *val, int len)
+{
+	struct fdt_property *prop;
+	int err, oldlen, newlen;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+	if (prop) {
+		newlen = len + oldlen;
+		err = _fdt_splice_struct(fdt, prop->data,
+					 FDT_TAGALIGN(oldlen),
+					 FDT_TAGALIGN(newlen));
+		if (err)
+			return err;
+		prop->len = cpu_to_fdt32(newlen);
+		memcpy(prop->data + oldlen, val, len);
+	} else {
+		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+		if (err)
+			return err;
+		memcpy(prop->data, val, len);
+	}
+	return 0;
+}
+
 int fdt_delprop(void *fdt, int nodeoffset, const char *name)
 {
 	struct fdt_property *prop;
@@ -312,7 +339,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
 	int nodelen;
 	int err;
 	uint32_t tag;
-	uint32_t *endtag;
+	fdt32_t *endtag;
 
 	FDT_RW_CHECK_HEADER(fdt);
 
@@ -339,7 +366,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
 	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
 	memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
 	memcpy(nh->name, name, namelen);
-	endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
+	endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
 	*endtag = cpu_to_fdt32(FDT_END_NODE);
 
 	return offset;
diff --git a/xen/common/libfdt/fdt_sw.c b/xen/common/libfdt/fdt_sw.c
index 55ebebf..f422754 100644
--- a/xen/common/libfdt/fdt_sw.c
+++ b/xen/common/libfdt/fdt_sw.c
@@ -153,7 +153,7 @@ int fdt_begin_node(void *fdt, const char *name)
 
 int fdt_end_node(void *fdt)
 {
-	uint32_t *en;
+	fdt32_t *en;
 
 	FDT_SW_CHECK_HEADER(fdt);
 
@@ -213,7 +213,7 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
 int fdt_finish(void *fdt)
 {
 	char *p = (char *)fdt;
-	uint32_t *end;
+	fdt32_t *end;
 	int oldstroffset, newstroffset;
 	uint32_t tag;
 	int offset, nextoffset;
diff --git a/xen/common/libfdt/fdt_wip.c b/xen/common/libfdt/fdt_wip.c
index 6025fa1..c5bbb68 100644
--- a/xen/common/libfdt/fdt_wip.c
+++ b/xen/common/libfdt/fdt_wip.c
@@ -74,7 +74,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
 
 static void _fdt_nop_region(void *start, int len)
 {
-	uint32_t *p;
+	fdt32_t *p;
 
 	for (p = start; (char *)p < ((char *)start + len); p++)
 		*p = cpu_to_fdt32(FDT_NOP);
diff --git a/xen/common/libfdt/version.lds b/xen/common/libfdt/version.lds
index 3c3994e..80b322b 100644
--- a/xen/common/libfdt/version.lds
+++ b/xen/common/libfdt/version.lds
@@ -48,6 +48,12 @@ LIBFDT_1.2 {
 		fdt_strerror;
 		fdt_offset_ptr;
 		fdt_next_tag;
+		fdt_appendprop;
+		fdt_create_empty_tree;
+		fdt_first_property_offset;
+		fdt_get_property_by_offset;
+		fdt_getprop_by_offset;
+		fdt_next_property_offset;
 
 	local:
 		*;
diff --git a/xen/include/xen/libfdt/fdt.h b/xen/include/xen/libfdt/fdt.h
index 48ccfd9..526aedb 100644
--- a/xen/include/xen/libfdt/fdt.h
+++ b/xen/include/xen/libfdt/fdt.h
@@ -1,48 +1,99 @@
 #ifndef _FDT_H
 #define _FDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright 2012 Kim Phillips, Freescale Semiconductor.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
 #ifndef __ASSEMBLY__
 
 struct fdt_header {
-	uint32_t magic;			 /* magic word FDT_MAGIC */
-	uint32_t totalsize;		 /* total size of DT block */
-	uint32_t off_dt_struct;		 /* offset to structure */
-	uint32_t off_dt_strings;	 /* offset to strings */
-	uint32_t off_mem_rsvmap;	 /* offset to memory reserve map */
-	uint32_t version;		 /* format version */
-	uint32_t last_comp_version;	 /* last compatible version */
+	fdt32_t magic;			 /* magic word FDT_MAGIC */
+	fdt32_t totalsize;		 /* total size of DT block */
+	fdt32_t off_dt_struct;		 /* offset to structure */
+	fdt32_t off_dt_strings;		 /* offset to strings */
+	fdt32_t off_mem_rsvmap;		 /* offset to memory reserve map */
+	fdt32_t version;		 /* format version */
+	fdt32_t last_comp_version;	 /* last compatible version */
 
 	/* version 2 fields below */
-	uint32_t boot_cpuid_phys;	 /* Which physical CPU id we're
+	fdt32_t boot_cpuid_phys;	 /* Which physical CPU id we're
 					    booting on */
 	/* version 3 fields below */
-	uint32_t size_dt_strings;	 /* size of the strings block */
+	fdt32_t size_dt_strings;	 /* size of the strings block */
 
 	/* version 17 fields below */
-	uint32_t size_dt_struct;	 /* size of the structure block */
+	fdt32_t size_dt_struct;		 /* size of the structure block */
 };
 
 struct fdt_reserve_entry {
-	uint64_t address;
-	uint64_t size;
+	fdt64_t address;
+	fdt64_t size;
 };
 
 struct fdt_node_header {
-	uint32_t tag;
+	fdt32_t tag;
 	char name[0];
 };
 
 struct fdt_property {
-	uint32_t tag;
-	uint32_t len;
-	uint32_t nameoff;
+	fdt32_t tag;
+	fdt32_t len;
+	fdt32_t nameoff;
 	char data[0];
 };
 
 #endif /* !__ASSEMBLY */
 
 #define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
-#define FDT_TAGSIZE	sizeof(uint32_t)
+#define FDT_TAGSIZE	sizeof(fdt32_t)
 
 #define FDT_BEGIN_NODE	0x1		/* Start node: full name */
 #define FDT_END_NODE	0x2		/* End node */
@@ -51,10 +102,10 @@ struct fdt_property {
 #define FDT_NOP		0x4		/* nop */
 #define FDT_END		0x9
 
-#define FDT_V1_SIZE	(7*sizeof(uint32_t))
-#define FDT_V2_SIZE	(FDT_V1_SIZE + sizeof(uint32_t))
-#define FDT_V3_SIZE	(FDT_V2_SIZE + sizeof(uint32_t))
+#define FDT_V1_SIZE	(7*sizeof(fdt32_t))
+#define FDT_V2_SIZE	(FDT_V1_SIZE + sizeof(fdt32_t))
+#define FDT_V3_SIZE	(FDT_V2_SIZE + sizeof(fdt32_t))
 #define FDT_V16_SIZE	FDT_V3_SIZE
-#define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(uint32_t))
+#define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(fdt32_t))
 
 #endif /* _FDT_H */
diff --git a/xen/include/xen/libfdt/libfdt.h b/xen/include/xen/libfdt/libfdt.h
index 6086047..37349f1 100644
--- a/xen/include/xen/libfdt/libfdt.h
+++ b/xen/include/xen/libfdt/libfdt.h
@@ -136,6 +136,28 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
 
 int fdt_next_node(const void *fdt, int offset, int *depth);
 
+/**
+ * fdt_first_subnode() - get offset of first direct subnode
+ *
+ * @fdt:	FDT blob
+ * @offset:	Offset of node to check
+ * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
+ */
+int fdt_first_subnode(const void *fdt, int offset);
+
+/**
+ * fdt_next_subnode() - get offset of next direct subnode
+ *
+ * After first calling fdt_first_subnode(), call this function repeatedly to
+ * get direct subnodes of a parent node.
+ *
+ * @fdt:	FDT blob
+ * @offset:	Offset of previous subnode
+ * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
+ * subnodes
+ */
+int fdt_next_subnode(const void *fdt, int offset);
+
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
@@ -582,7 +604,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
  * value of the property named 'name' in the node /aliases.
  *
  * returns:
- *	a pointer to the expansion of the alias named 'name', of it exists
+ *	a pointer to the expansion of the alias named 'name', if it exists
  *	NULL, if the given alias or the /aliases node does not exist
  */
 const char *fdt_get_alias(const void *fdt, const char *name);
@@ -816,6 +838,20 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
 				  const char *compatible);
 
+/**
+ * fdt_stringlist_contains - check a string list property for a string
+ * @strlist: Property containing a list of strings to check
+ * @listlen: Length of property
+ * @str: String to search for
+ *
+ * This is a utility function provided for convenience. The list contains
+ * one or more strings, each terminated by \0, as is found in a device tree
+ * "compatible" property.
+ *
+ * @return: 1 if the string is found in the list, 0 not found, or invalid list
+ */
+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
+
 /**********************************************************************/
 /* Write-in-place functions                                           */
 /**********************************************************************/
@@ -852,17 +888,17 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
 			const void *val, int len);
 
 /**
- * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
  * @name: name of the property to change
- * @val: cell (32-bit integer) value to replace the property with
+ * @val: 32-bit integer value to replace the property with
  *
- * fdt_setprop_inplace_cell() replaces the value of a given property
- * with the 32-bit integer cell value in val, converting val to
- * big-endian if necessary.  This function cannot change the size of a
- * property, and so will only work if the property already exists and
- * has length 4.
+ * fdt_setprop_inplace_u32() replaces the value of a given property
+ * with the 32-bit integer value in val, converting val to big-endian
+ * if necessary.  This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 4.
  *
  * This function will alter only the bytes in the blob which contain
  * the given property value, and will not alter or move any other part
@@ -871,7 +907,42 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
  * returns:
  *	0, on success
  *	-FDT_ERR_NOSPACE, if the property's length is not equal to 4
-  *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
+					  const char *name, uint32_t val)
+{
+	fdt32_t tmp = cpu_to_fdt32(val);
+	return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to replace the property with
+ *
+ * fdt_setprop_inplace_u64() replaces the value of a given property
+ * with the 64-bit integer value in val, converting val to big-endian
+ * if necessary.  This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 8.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, if the property's length is not equal to 8
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
  *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
  *	-FDT_ERR_BADMAGIC,
  *	-FDT_ERR_BADVERSION,
@@ -879,11 +950,22 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
  *	-FDT_ERR_BADSTRUCTURE,
  *	-FDT_ERR_TRUNCATED, standard meanings
  */
+static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
+					  const char *name, uint64_t val)
+{
+	fdt64_t tmp = cpu_to_fdt64(val);
+	return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ *
+ * This is an alternative name for fdt_setprop_inplace_u32()
+ */
 static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
 					   const char *name, uint32_t val)
 {
-	val = cpu_to_fdt32(val);
-	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+	return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
 }
 
 /**
@@ -945,10 +1027,19 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
 int fdt_finish_reservemap(void *fdt);
 int fdt_begin_node(void *fdt, const char *name);
 int fdt_property(void *fdt, const char *name, const void *val, int len);
+static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
+{
+	fdt32_t tmp = cpu_to_fdt32(val);
+	return fdt_property(fdt, name, &tmp, sizeof(tmp));
+}
+static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
+{
+	fdt64_t tmp = cpu_to_fdt64(val);
+	return fdt_property(fdt, name, &tmp, sizeof(tmp));
+}
 static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
 {
-	val = cpu_to_fdt32(val);
-	return fdt_property(fdt, name, &val, sizeof(val));
+	return fdt_property_u32(fdt, name, val);
 }
 #define fdt_property_string(fdt, name, str) \
 	fdt_property(fdt, name, str, strlen(str)+1)
@@ -959,6 +1050,7 @@ int fdt_finish(void *fdt);
 /* Read-write functions                                               */
 /**********************************************************************/
 
+int fdt_create_empty_tree(void *buf, int bufsize);
 int fdt_open_into(const void *fdt, void *buf, int bufsize);
 int fdt_pack(void *fdt);
 
@@ -1068,14 +1160,14 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
 		const void *val, int len);
 
 /**
- * fdt_setprop_cell - set a property to a single cell value
+ * fdt_setprop_u32 - set a property to a 32-bit integer
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
  * @name: name of the property to change
  * @val: 32-bit integer value for the property (native endian)
  *
- * fdt_setprop_cell() sets the value of the named property in the
- * given node to the given cell value (converting to big-endian if
+ * fdt_setprop_u32() sets the value of the named property in the given
+ * node to the given 32-bit integer value (converting to big-endian if
  * necessary), or creates a new property with that value if it does
  * not already exist.
  *
@@ -1095,11 +1187,57 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
  *	-FDT_ERR_BADLAYOUT,
  *	-FDT_ERR_TRUNCATED, standard meanings
  */
+static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
+				  uint32_t val)
+{
+	fdt32_t tmp = cpu_to_fdt32(val);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_setprop_u64 - set a property to a 64-bit integer
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_u64() sets the value of the named property in the given
+ * node to the given 64-bit integer value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
+				  uint64_t val)
+{
+	fdt64_t tmp = cpu_to_fdt64(val);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ *
+ * This is an alternative name for fdt_setprop_u32()
+ */
 static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
 				   uint32_t val)
 {
-	val = cpu_to_fdt32(val);
-	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+	return fdt_setprop_u32(fdt, nodeoffset, name, val);
 }
 
 /**
@@ -1134,6 +1272,147 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
 	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
 
 /**
+ * fdt_appendprop - append to or create a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to append to
+ * @val: pointer to data to append to the property value
+ * @len: length of the data to append to the property value
+ *
+ * fdt_appendprop() appends the value to the named property in the
+ * given node, creating the property if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+		   const void *val, int len);
+
+/**
+ * fdt_appendprop_u32 - append a 32-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u32() appends the given 32-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
+				     const char *name, uint32_t val)
+{
+	fdt32_t tmp = cpu_to_fdt32(val);
+	return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_appendprop_u64 - append a 64-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u64() appends the given 64-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
+				     const char *name, uint64_t val)
+{
+	fdt64_t tmp = cpu_to_fdt64(val);
+	return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+}
+
+/**
+ * fdt_appendprop_cell - append a single cell value to a property
+ *
+ * This is an alternative name for fdt_appendprop_u32()
+ */
+static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
+				      const char *name, uint32_t val)
+{
+	return fdt_appendprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
+ * fdt_appendprop_string - append a string to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value to append to the property
+ *
+ * fdt_appendprop_string() appends the given string to the value of
+ * the named property in the given node, or creates a new property
+ * with that value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_appendprop_string(fdt, nodeoffset, name, str) \
+	fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
  * fdt_delprop - delete a property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to nop
diff --git a/xen/include/xen/libfdt/libfdt_env.h b/xen/include/xen/libfdt/libfdt_env.h
index 2f1b03c..89a794b 100644
--- a/xen/include/xen/libfdt/libfdt_env.h
+++ b/xen/include/xen/libfdt/libfdt_env.h
@@ -6,6 +6,10 @@
 #include <xen/string.h>
 #include <asm/byteorder.h>
 
+typedef uint16_t fdt16_t;
+typedef uint32_t fdt32_t;
+typedef uint64_t fdt64_t;
+
 #define fdt16_to_cpu(x) be16_to_cpu(x)
 #define cpu_to_fdt16(x) cpu_to_be16(x)
 #define fdt32_to_cpu(x) be32_to_cpu(x)
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
                   ` (13 preceding siblings ...)
  2014-09-10  0:52 ` [PATCH V4 14/15] Update libfdt to v1.4.0 Roy Franz
@ 2014-09-10  0:52 ` Roy Franz
  2014-09-11 14:53   ` Jan Beulich
  2014-09-12  0:49   ` Stefano Stabellini
  14 siblings, 2 replies; 71+ messages in thread
From: Roy Franz @ 2014-09-10  0:52 UTC (permalink / raw)
  To: xen-devel, ian.campbell, stefano.stabellini, tim, jbeulich, keir
  Cc: Roy Franz, fu.wei

This patch adds EFI boot support for ARM based on the previous refactoring of
the x86 EFI boot code.  All ARM specific code is in the ARM efi-boot.h header
file, with the main EFI entry point common/efi/boot.c.  The PE/COFF header is
open-coded in head.S, which allows us to have a single binary be both an EFI
executable and a normal arm64 IMAGE file. There is currently no PE/COFF
toolchain support for arm64, so it is not possible to create the PE/COFF header
in the same manner as on x86.  This also simplifies the build as compared to
x86, as we always build the same executable, whereas x86 builds 2.  An ARM
version of efi-bind.h is added, which is based on the x86_64 version with the
x86 specific portions removed.  The Makefile in common/efi is different for x86
and ARM, as for ARM we always build in EFI support.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 config/arm64.mk                     |   1 +
 xen/arch/arm/arm64/head.S           | 150 ++++++++-
 xen/arch/arm/xen.lds.S              |   1 +
 xen/common/Makefile                 |   1 +
 xen/common/efi/Makefile             |   3 +
 xen/include/asm-arm/arm64/efibind.h | 216 +++++++++++++
 xen/include/asm-arm/efi-boot.h      | 630 ++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/efi.h           |  29 ++
 xen/include/asm-arm/efibind.h       |   2 +
 xen/include/asm-arm/setup.h         |   2 +-
 10 files changed, 1031 insertions(+), 4 deletions(-)
 create mode 100644 xen/common/efi/Makefile
 create mode 100644 xen/include/asm-arm/arm64/efibind.h
 create mode 100644 xen/include/asm-arm/efi-boot.h
 create mode 100644 xen/include/asm-arm/efi.h
 create mode 100644 xen/include/asm-arm/efibind.h

diff --git a/config/arm64.mk b/config/arm64.mk
index 15b57a4..e6aab0e 100644
--- a/config/arm64.mk
+++ b/config/arm64.mk
@@ -1,6 +1,7 @@
 CONFIG_ARM := y
 CONFIG_ARM_64 := y
 CONFIG_ARM_$(XEN_OS) := y
+CONFIG_EFI := y
 
 CONFIG_XEN_INSTALL_SUFFIX :=
 
diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
index 43b5e72..158c102 100644
--- a/xen/arch/arm/arm64/head.S
+++ b/xen/arch/arm/arm64/head.S
@@ -24,6 +24,8 @@
 #include <asm/page.h>
 #include <asm/asm_defns.h>
 #include <asm/early_printk.h>
+#include <efi/efierr.h>
+#include <asm/arm64/efibind.h>
 
 #define PT_PT     0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
 #define PT_MEM    0xf7d /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=0 P=1 */
@@ -104,8 +106,14 @@ GLOBAL(start)
         /*
          * DO NOT MODIFY. Image header expected by Linux boot-loaders.
          */
-        b       real_start           /* branch to kernel start, magic */
-        .long   0                    /* reserved */
+efi_head:
+        /*
+         * This add instruction has no meaningful effect except that
+         * its opcode forms the magic "MZ" signature of a PE/COFF file
+         * that is required for UEFI applications.
+         */
+        add     x13, x18, #0x16
+        b       real_start           /* branch to kernel start */
         .quad   0                    /* Image load offset from start of RAM */
         .quad   0                    /* reserved */
         .quad   0                    /* reserved */
@@ -116,8 +124,113 @@ GLOBAL(start)
         .byte   0x52
         .byte   0x4d
         .byte   0x64
-        .word   0                    /* reserved */
+        .long   pe_header - efi_head        /* Offset to the PE header. */
+
+        /*
+         * Add the PE/COFF header to the file.  The address of this header
+         * is at offset 0x3c in the file, and is part of Linux "Image"
+         * header.  The arm64 Linux Image format is designed to support
+         * being both an 'Image' format binary and a PE/COFF binary.
+         * The PE/COFF format is defined by Microsoft, and is available
+         * from: http://msdn.microsoft.com/en-us/gg463119.aspx
+         * Version 8.3 adds support for arm64 and UEFI usage.
+         */
+
+        .align  3
+pe_header:
+        .ascii  "PE"
+        .short  0
+coff_header:
+        .short  0xaa64                          /* AArch64 */
+        .short  2                               /* nr_sections */
+        .long   0                               /* TimeDateStamp */
+        .long   0                               /* PointerToSymbolTable */
+        .long   1                               /* NumberOfSymbols */
+        .short  section_table - optional_header /* SizeOfOptionalHeader */
+        .short  0x206                           /* Characteristics. */
+                                                /* IMAGE_FILE_DEBUG_STRIPPED | */
+                                                /* IMAGE_FILE_EXECUTABLE_IMAGE | */
+                                                /* IMAGE_FILE_LINE_NUMS_STRIPPED */
+optional_header:
+        .short  0x20b                           /* PE32+ format */
+        .byte   0x02                            /* MajorLinkerVersion */
+        .byte   0x14                            /* MinorLinkerVersion */
+        .long   _end - real_start               /* SizeOfCode */
+        .long   0                               /* SizeOfInitializedData */
+        .long   0                               /* SizeOfUninitializedData */
+        .long   efi_start - efi_head            /* AddressOfEntryPoint */
+        .long   real_start - efi_head           /* BaseOfCode */
+
+extra_header_fields:
+        .quad   0                               /* ImageBase */
+        .long   0x1000                          /* SectionAlignment (4 KByte) */
+        .long   0x8                             /* FileAlignment */
+        .short  0                               /* MajorOperatingSystemVersion */
+        .short  0                               /* MinorOperatingSystemVersion */
+        .short  0                               /* MajorImageVersion */
+        .short  0                               /* MinorImageVersion */
+        .short  0                               /* MajorSubsystemVersion */
+        .short  0                               /* MinorSubsystemVersion */
+        .long   0                               /* Win32VersionValue */
+
+        .long   _end - efi_head                 /* SizeOfImage */
+
+        /* Everything before the kernel image is considered part of the header */
+        .long   real_start - efi_head           /* SizeOfHeaders */
+        .long   0                               /* CheckSum */
+        .short  0xa                             /* Subsystem (EFI application) */
+        .short  0                               /* DllCharacteristics */
+        .quad   0                               /* SizeOfStackReserve */
+        .quad   0                               /* SizeOfStackCommit */
+        .quad   0                               /* SizeOfHeapReserve */
+        .quad   0                               /* SizeOfHeapCommit */
+        .long   0                               /* LoaderFlags */
+        .long   0x6                             /* NumberOfRvaAndSizes */
+
+        .quad   0                               /* ExportTable */
+        .quad   0                               /* ImportTable */
+        .quad   0                               /* ResourceTable */
+        .quad   0                               /* ExceptionTable */
+        .quad   0                               /* CertificationTable */
+        .quad   0                               /* BaseRelocationTable */
+
+        /* Section table */
+section_table:
 
+        /*
+         * The EFI application loader requires a relocation section
+         * because EFI applications must be relocatable.  This is a
+         * dummy section as far as we are concerned.
+         */
+        .ascii  ".reloc"
+        .byte   0
+        .byte   0                               /* end of 0 padding of section name */
+        .long   0
+        .long   0
+        .long   0                               /* SizeOfRawData */
+        .long   0                               /* PointerToRawData */
+        .long   0                               /* PointerToRelocations */
+        .long   0                               /* PointerToLineNumbers */
+        .short  0                               /* NumberOfRelocations */
+        .short  0                               /* NumberOfLineNumbers */
+        .long   0x42100040                      /* Characteristics (section flags) */
+
+
+        .ascii  ".text"
+        .byte   0
+        .byte   0
+        .byte   0                               /* end of 0 padding of section name */
+        .long   _end - real_start               /* VirtualSize */
+        .long   real_start - efi_head           /* VirtualAddress */
+        .long   __init_end_efi - real_start     /* SizeOfRawData */
+        .long   real_start - efi_head           /* PointerToRawData */
+
+        .long   0                /* PointerToRelocations (0 for executables) */
+        .long   0                /* PointerToLineNumbers (0 for executables) */
+        .short  0                /* NumberOfRelocations  (0 for executables) */
+        .short  0                /* NumberOfLineNumbers  (0 for executables) */
+        .long   0xe0500020       /* Characteristics (section flags) */
+        .align  5
 real_start:
         msr   DAIFSet, 0xf           /* Disable all interrupts */
 
@@ -617,6 +730,37 @@ putn:   ret
 ENTRY(lookup_processor_type)
         mov  x0, #0
         ret
+/*
+ *  Function to transition from EFI loader in C, to Xen entry point.
+ *  void noreturn efi_xen_start(void *fdt_ptr);
+ */
+ENTRY(efi_xen_start)
+        /*
+         * Turn off cache and MMU as Xen expects. EFI enables them, but also
+         * mandates a 1:1 (unity) VA->PA mapping, so we can turn off the
+         * MMU while executing EFI code before entering Xen.
+         * The EFI loader calls this to start Xen.
+         * Preserve x0 (fdf pointer) across call to __flush_dcache_all,
+         * restore for entry into Xen.
+         */
+        mov   x20, x0
+        bl    __flush_dcache_all
+        ic    ialluis
+
+        /* Turn off Dcache and MMU */
+        mrs   x0, sctlr_el2
+        bic   x0, x0, #1 << 0        /* clear SCTLR.M */
+        bic   x0, x0, #1 << 2        /* clear SCTLR.C */
+        msr   sctlr_el2, x0
+        isb
+
+        /* Jump to Xen entry point */
+        mov   x0, x20
+        mov   x1, xzr
+        mov   x2, xzr
+        mov   x3, xzr
+        b     real_start
+ENDPROC(efi_xen_start)
 
 /*
  * Local variables:
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index 079e085..d8b0cfe 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -135,6 +135,7 @@ SECTIONS
        *(.xsm_initcall.init)
        __xsm_initcall_end = .;
   } :text
+  __init_end_efi = .;
   . = ALIGN(STACK_SIZE);
   __init_end = .;
 
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 3683ae3..e78cb29 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -67,4 +67,5 @@ subdir-$(x86_64) += hvm
 subdir-$(coverage) += gcov
 
 subdir-y += libelf
+subdir-$(CONFIG_EFI) += efi
 subdir-$(HAS_DEVICE_TREE) += libfdt
diff --git a/xen/common/efi/Makefile b/xen/common/efi/Makefile
new file mode 100644
index 0000000..195b2f3
--- /dev/null
+++ b/xen/common/efi/Makefile
@@ -0,0 +1,3 @@
+CFLAGS += -fshort-wchar
+
+obj-y += boot.init.o
diff --git a/xen/include/asm-arm/arm64/efibind.h b/xen/include/asm-arm/arm64/efibind.h
new file mode 100644
index 0000000..2b0bf40
--- /dev/null
+++ b/xen/include/asm-arm/arm64/efibind.h
@@ -0,0 +1,216 @@
+/*++
+
+Copyright (c) 1998  Intel Corporation
+
+Module Name:
+
+    efefind.h
+
+Abstract:
+
+    EFI to compile bindings
+
+
+
+
+Revision History
+
+--*/
+
+#ifndef __GNUC__
+#pragma pack()
+#endif
+
+#define EFIERR(a)           (0x8000000000000000 | a)
+#define EFI_ERROR_MASK      0x8000000000000000
+#define EFIERR_OEM(a)       (0xc000000000000000 | a)
+
+#define BAD_POINTER         0xFBFBFBFBFBFBFBFB
+#define MAX_ADDRESS         0xFFFFFFFFFFFFFFFF
+
+#define EFI_STUB_ERROR      MAX_ADDRESS
+
+#ifndef __ASSEMBLY__
+//
+// Basic int types of various widths
+//
+
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )
+
+    // No ANSI C 1999/2000 stdint.h integer width declarations
+
+    #if defined(__GNUC__)
+        typedef unsigned long long  uint64_t __attribute__((aligned (8)));
+        typedef long long           int64_t __attribute__((aligned (8)));
+        typedef unsigned int        uint32_t;
+        typedef int                 int32_t;
+        typedef unsigned short      uint16_t;
+        typedef short               int16_t;
+        typedef unsigned char       uint8_t;
+        typedef char                int8_t;
+    #elif defined(UNIX_LP64)
+
+        /*  Use LP64 programming model from C_FLAGS for integer width declarations */
+
+       typedef unsigned long       uint64_t;
+       typedef long                int64_t;
+       typedef unsigned int        uint32_t;
+       typedef int                 int32_t;
+       typedef unsigned short      uint16_t;
+       typedef short               int16_t;
+       typedef unsigned char       uint8_t;
+       typedef char                int8_t;
+    #else
+
+       /*  Assume P64 programming model from C_FLAGS for integer width declarations */
+
+       typedef unsigned long long  uint64_t __attribute__((aligned (8)));
+       typedef long long           int64_t __attribute__((aligned (8)));
+       typedef unsigned int        uint32_t;
+       typedef int                 int32_t;
+       typedef unsigned short      uint16_t;
+       typedef short               int16_t;
+       typedef unsigned char       uint8_t;
+       typedef char                int8_t;
+    #endif
+#endif
+
+//
+// Basic EFI types of various widths
+//
+
+#ifndef __WCHAR_TYPE__
+# define __WCHAR_TYPE__ short
+#endif
+
+typedef uint64_t   UINT64;
+typedef int64_t    INT64;
+
+#ifndef _BASETSD_H_
+    typedef uint32_t   UINT32;
+    typedef int32_t    INT32;
+#endif
+
+typedef uint16_t   UINT16;
+typedef int16_t    INT16;
+typedef uint8_t    UINT8;
+typedef int8_t     INT8;
+typedef __WCHAR_TYPE__ WCHAR;
+
+#undef VOID
+#define VOID    void
+
+
+typedef int64_t    INTN;
+typedef uint64_t   UINTN;
+
+#define POST_CODE(_Data)
+
+
+#define BREAKPOINT()        while (TRUE);    // Make it hang on Bios[Dbg]32
+
+//
+// Pointers must be aligned to these address to function
+//
+
+#define MIN_ALIGNMENT_SIZE  4
+
+#define ALIGN_VARIABLE(Value ,Adjustment) \
+            (UINTN)Adjustment = 0; \
+            if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
+                (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \
+            Value = (UINTN)Value + (UINTN)Adjustment
+
+
+//
+// Define macros to build data structure signatures from characters.
+//
+
+#define EFI_SIGNATURE_16(A,B)             ((A) | (B<<8))
+#define EFI_SIGNATURE_32(A,B,C,D)         (EFI_SIGNATURE_16(A,B)     | (EFI_SIGNATURE_16(C,D)     << 16))
+#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
+
+#define EXPORTAPI
+
+
+//
+// EFIAPI - prototype calling convention for EFI function pointers
+// BOOTSERVICE - prototype for implementation of a boot service interface
+// RUNTIMESERVICE - prototype for implementation of a runtime service interface
+// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service
+// RUNTIME_CODE - pragma macro for declaring runtime code
+//
+
+#ifndef EFIAPI                  // Forces EFI calling conventions reguardless of compiler options
+        #define EFIAPI          // Substitute expresion to force C calling convention
+#endif
+
+#define BOOTSERVICE
+//#define RUNTIMESERVICE(proto,a)    alloc_text("rtcode",a); proto a
+//#define RUNTIMEFUNCTION(proto,a)   alloc_text("rtcode",a); proto a
+#define RUNTIMESERVICE
+#define RUNTIMEFUNCTION
+
+
+#define RUNTIME_CODE(a)         alloc_text("rtcode", a)
+#define BEGIN_RUNTIME_DATA()    data_seg("rtdata")
+#define END_RUNTIME_DATA()      data_seg("")
+
+#define VOLATILE    volatile
+
+#define MEMORY_FENCE()
+
+
+//
+// When build similiar to FW, then link everything together as
+// one big module.
+//
+
+#define EFI_DRIVER_ENTRY_POINT(InitFunction)    \
+    UINTN                                       \
+    InitializeDriver (                          \
+        VOID    *ImageHandle,                   \
+        VOID    *SystemTable                    \
+        )                                       \
+    {                                           \
+        return InitFunction(ImageHandle,        \
+                SystemTable);                   \
+    }                                           \
+                                                \
+    EFI_STATUS efi_main(                        \
+        EFI_HANDLE image,                       \
+        EFI_SYSTEM_TABLE *systab                \
+        ) __attribute__((weak,                  \
+                alias ("InitializeDriver")));
+
+#define LOAD_INTERNAL_DRIVER(_if, type, name, entry)    \
+        (_if)->LoadInternal(type, name, entry)
+
+
+//
+// Some compilers don't support the forward reference construct:
+//  typedef struct XXXXX
+//
+// The following macro provide a workaround for such cases.
+//
+#ifdef NO_INTERFACE_DECL
+#define INTERFACE_DECL(x)
+#else
+#ifdef __GNUC__
+#define INTERFACE_DECL(x) struct x
+#else
+#define INTERFACE_DECL(x) typedef struct x
+#endif
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/efi-boot.h b/xen/include/asm-arm/efi-boot.h
new file mode 100644
index 0000000..2db0966
--- /dev/null
+++ b/xen/include/asm-arm/efi-boot.h
@@ -0,0 +1,630 @@
+/*
+ * Architecture specific implementation for EFI boot code.  This file
+ * is intended to be included by XXX _only_, and therefore can define
+ * arch specific global variables.
+ */
+#include <xen/libfdt/libfdt.h>
+#include <asm/setup.h>
+
+static void noreturn blexit(const CHAR16 *str);
+static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
+void noreturn efi_xen_start(void *fdt_ptr);
+
+#define DEVICE_TREE_GUID \
+{0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0}}
+
+static struct file __initdata dtbfile;
+static void __initdata *fdt;
+static void __initdata *memmap;
+
+static int __init setup_chosen_node(void *fdt, int *addr_cells, int *size_cells)
+{
+    int node;
+    const struct fdt_property *prop;
+    int len;
+    uint32_t val;
+
+    if ( !fdt || !addr_cells || !size_cells )
+        return -1;
+
+    /* locate chosen node, which is where we add Xen module info. */
+    node = fdt_subnode_offset(fdt, 0, "chosen");
+    if ( node < 0 )
+    {
+        node = fdt_add_subnode(fdt, 0, "chosen");
+        if ( node < 0 )
+            return node;
+    }
+
+    /* Get or set #address-cells and #size-cells */
+    prop = fdt_get_property(fdt, node, "#address-cells", &len);
+    if ( !prop )
+    {
+        val = cpu_to_fdt32(2);
+        if ( fdt_setprop(fdt, node, "#address-cells", &val, sizeof(val)) )
+            return -1;
+        *addr_cells = 2;
+    }
+    else
+        *addr_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
+
+    prop = fdt_get_property(fdt, node, "#size-cells", &len);
+    if ( !prop )
+    {
+        val = cpu_to_fdt32(2);
+        if ( fdt_setprop(fdt, node, "#size-cells", &val, sizeof(val)) )
+            return -1;
+        *size_cells = 2;
+    }
+    else
+        *size_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
+
+    /*
+     * Make sure ranges is empty if it exists, otherwise create empty ranges
+     * property.
+     */
+    prop = fdt_get_property(fdt, node, "ranges", &len);
+    if ( !prop )
+    {
+        val = cpu_to_fdt32(0);
+        if ( fdt_setprop(fdt, node, "ranges", &val, 0) )
+            return -1;
+    }
+    else if ( fdt32_to_cpu(prop->len) )
+            return -1;  /* Non-empty ranges property */
+    return node;
+}
+
+/*
+ * Set a single 'reg' property taking into account the
+ * configured addr and size cell sizes.
+ */
+static int __init fdt_set_reg(void *fdt, int node, int addr_cells,
+                              int size_cells, uint64_t addr, uint64_t len)
+{
+    uint8_t data[16]; /* at most 2 64 bit words */
+    void *p = data;
+
+    /* Make sure that the values provided can be represented in
+     * the reg property.
+     */
+    if ( addr_cells == 1 && (addr >> 32) )
+        return -1;
+    if ( size_cells == 1 && (len >> 32) )
+        return -1;
+
+    if ( addr_cells == 1 )
+    {
+        *(uint32_t *)p = cpu_to_fdt32(addr);
+        p += sizeof(uint32_t);
+    }
+    else if ( addr_cells == 2 )
+    {
+        *(uint64_t *)p = cpu_to_fdt64(addr);
+        p += sizeof(uint64_t);
+    }
+    else
+        return -1;
+
+    if ( size_cells == 1 )
+    {
+        *(uint32_t *)p = cpu_to_fdt32(len);
+        p += sizeof(uint32_t);
+    }
+    else if ( size_cells == 2 )
+    {
+        *(uint64_t *)p = cpu_to_fdt64(len);
+        p += sizeof(uint64_t);
+    }
+    else
+        return -1;
+
+    return(fdt_setprop(fdt, node, "reg", data, p - (void *)data));
+}
+
+static void __init *lookup_fdt_config_table(EFI_SYSTEM_TABLE *sys_table)
+{
+    const EFI_GUID fdt_guid = DEVICE_TREE_GUID;
+    EFI_CONFIGURATION_TABLE *tables;
+    void *fdt = NULL;
+    int i;
+
+    tables = sys_table->ConfigurationTable;
+    for ( i = 0; i < sys_table->NumberOfTableEntries; i++ )
+    {
+        if ( match_guid(&tables[i].VendorGuid, &fdt_guid) )
+        {
+            fdt = tables[i].VendorTable;
+            break;
+        }
+    }
+    return fdt;
+}
+
+static EFI_STATUS __init efi_get_memory_map(void **map,
+                                            UINTN *mmap_size,
+                                            UINTN *desc_size,
+                                            UINT32 *desc_ver,
+                                            UINTN *key_ptr)
+{
+    EFI_MEMORY_DESCRIPTOR *m = NULL;
+    EFI_STATUS status;
+    unsigned long key;
+    u32 desc_version;
+
+    *map = NULL;
+    *mmap_size = EFI_PAGE_SIZE;
+again:
+    *mmap_size += EFI_PAGE_SIZE;  /* Page size is allocation granularity */
+    status = efi_bs->AllocatePool(EfiLoaderData, *mmap_size, (void **)&m);
+    if ( status != EFI_SUCCESS )
+        return status;
+
+    *desc_size = 0;
+    key = 0;
+    status = efi_bs->GetMemoryMap(mmap_size, m, &key, desc_size, &desc_version);
+    if ( status == EFI_BUFFER_TOO_SMALL )
+    {
+        efi_bs->FreePool(m);
+        goto again;
+    }
+
+    if ( status != EFI_SUCCESS )
+    {
+        efi_bs->FreePool(m);
+        return status;
+    }
+
+    if ( key_ptr && status == EFI_SUCCESS )
+        *key_ptr = key;
+    if ( desc_ver && status == EFI_SUCCESS )
+        *desc_ver = desc_version;
+
+    *map = m;
+    return status;
+}
+
+static EFI_STATUS __init efi_process_memory_map_bootinfo(EFI_MEMORY_DESCRIPTOR *map,
+                                                UINTN mmap_size,
+                                                UINTN desc_size)
+{
+    int Index;
+    int i = 0;
+
+    EFI_MEMORY_DESCRIPTOR *desc_ptr = map;
+
+    for ( Index = 0; Index < (mmap_size / desc_size); Index++ )
+    {
+        if ( desc_ptr->Type == EfiConventionalMemory
+             || desc_ptr->Type == EfiBootServicesCode
+             || desc_ptr->Type == EfiBootServicesData )
+        {
+            bootinfo.mem.bank[i].start = desc_ptr->PhysicalStart;
+            bootinfo.mem.bank[i].size = desc_ptr->NumberOfPages * EFI_PAGE_SIZE;
+            if ( ++i >= NR_MEM_BANKS )
+            {
+                PrintStr(L"Warning: All ");
+                DisplayUint(NR_MEM_BANKS, -1);
+                PrintStr(L" bootinfo mem banks exhausted.\r\n");
+                break;
+            }
+        }
+        desc_ptr = NextMemoryDescriptor(desc_ptr, desc_size);
+    }
+
+    bootinfo.mem.nr_banks = i;
+    return EFI_SUCCESS;
+
+}
+
+/*
+ * Add the FDT nodes for the standard EFI information, which consist
+ * of the System table address, the address of the final EFI memory map,
+ * and memory map information.
+ */
+EFI_STATUS __init fdt_add_uefi_nodes(EFI_SYSTEM_TABLE *sys_table,
+                                            void *fdt,
+                                            EFI_MEMORY_DESCRIPTOR *memory_map,
+                                            UINTN map_size,
+                                            UINTN desc_size,
+                                            UINT32 desc_ver)
+{
+    int node;
+    int status;
+    u32 fdt_val32;
+    u64 fdt_val64;
+    int prev;
+    /*
+     * Delete any memory nodes present.  The EFI memory map is the only
+     * memory description provided to Xen.
+     */
+    prev = 0;
+    for (;;)
+    {
+        const char *type;
+        int len;
+
+        node = fdt_next_node(fdt, prev, NULL);
+        if ( node < 0 )
+            break;
+
+        type = fdt_getprop(fdt, node, "device_type", &len);
+        if ( type && strncmp(type, "memory", len) == 0 )
+        {
+            fdt_del_node(fdt, node);
+            continue;
+        }
+
+        prev = node;
+    }
+
+    /* Add FDT entries for EFI runtime services in chosen node. */
+    node = fdt_subnode_offset(fdt, 0, "chosen");
+    if ( node < 0 )
+    {
+        node = fdt_add_subnode(fdt, 0, "chosen");
+        if ( node < 0 )
+        {
+            status = node; /* node is error code when negative */
+            goto fdt_set_fail;
+        }
+    }
+
+    fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)sys_table);
+    status = fdt_setprop(fdt, node, "linux,uefi-system-table",
+                         &fdt_val64, sizeof(fdt_val64));
+    if ( status )
+        goto fdt_set_fail;
+
+    fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)memory_map);
+    status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
+                         &fdt_val64,  sizeof(fdt_val64));
+    if ( status )
+        goto fdt_set_fail;
+
+    fdt_val32 = cpu_to_fdt32(map_size);
+    status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
+                         &fdt_val32,  sizeof(fdt_val32));
+    if ( status )
+        goto fdt_set_fail;
+
+    fdt_val32 = cpu_to_fdt32(desc_size);
+    status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
+                         &fdt_val32, sizeof(fdt_val32));
+    if ( status )
+        goto fdt_set_fail;
+
+    fdt_val32 = cpu_to_fdt32(desc_ver);
+    status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
+                         &fdt_val32, sizeof(fdt_val32));
+    if ( status )
+        goto fdt_set_fail;
+
+    return EFI_SUCCESS;
+
+fdt_set_fail:
+    if ( status == -FDT_ERR_NOSPACE )
+        return EFI_BUFFER_TOO_SMALL;
+
+    return EFI_LOAD_ERROR;
+}
+
+/*
+ * Allocates new memory for a larger FDT, and frees existing memory if
+ * struct file size is non-zero.  Updates file struct with new memory
+ * address/size for later freeing.  If fdtfile.ptr is NULL, an empty FDT
+ * is created.
+ */
+static void __init *fdt_increase_size(struct file *fdtfile, int add_size)
+{
+    EFI_STATUS status;
+    EFI_PHYSICAL_ADDRESS fdt_addr;
+    int fdt_size;
+    int pages;
+    void *new_fdt;
+
+    if ( fdtfile->ptr )
+        fdt_size = fdt_totalsize(fdtfile->ptr);
+    else
+        fdt_size = 0;
+
+    pages = PFN_UP(fdt_size) + PFN_UP(add_size);
+    status = efi_bs->AllocatePages(AllocateAnyPages, EfiLoaderData,
+                                   pages, &fdt_addr);
+
+    if ( status != EFI_SUCCESS )
+        return NULL;
+
+    new_fdt = (void *)fdt_addr;
+
+    if ( fdt_size )
+    {
+        if ( fdt_open_into(dtbfile.ptr, new_fdt, pages * EFI_PAGE_SIZE) )
+            return NULL;
+    }
+    else
+    {
+        /*
+         * Create an empty FDT if not provided one, which is the expected case
+         * when booted from the UEFI shell on an ACPI only system.  We will use
+         * the FDT to pass the EFI information to Xen, as well as nodes for
+         * any modules the stub loads.  The ACPI tables are part of the UEFI
+         * system table that is passed in the FDT.
+         */
+        if ( fdt_create_empty_tree(new_fdt, pages * EFI_PAGE_SIZE) )
+            return NULL;
+    }
+
+    /*
+     * Now that we have the new FDT allocated and copied, free the
+     * original and update the struct file so that the error handling
+     * code will free it.  If the original FDT came from a configuration
+     * table, we don't own that memory and can't free it.
+     */
+    if ( dtbfile.size )
+        efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
+
+    /* Update 'file' info for new memory so we clean it up on error exits */
+    dtbfile.addr = fdt_addr;
+    dtbfile.size = pages * EFI_PAGE_SIZE;
+    return new_fdt;
+}
+
+static void __init efi_arch_pci(void)
+{
+}
+
+static void __init efi_arch_relocate_image(unsigned long delta)
+{
+}
+
+static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
+                                               void *map,
+                                               UINTN map_size,
+                                               UINTN desc_size,
+                                               UINT32 desc_ver)
+{
+    EFI_STATUS status;
+
+    status = efi_process_memory_map_bootinfo(map, map_size, desc_size);
+    if ( EFI_ERROR(status) )
+        blexit(L"ERROR processing EFI memory map\r\n");
+
+    status = fdt_add_uefi_nodes(SystemTable, fdt, map, map_size, desc_size,
+                                desc_ver);
+    if ( EFI_ERROR(status) )
+        PrintErrMesg(L"ERROR updating FDT\r\n", status);
+}
+
+static void __init efi_arch_pre_exit_boot(void)
+{
+}
+
+static void __init efi_arch_post_exit_boot(void)
+{
+    efi_xen_start(fdt);
+}
+
+static void __init efi_arch_cfg_file(EFI_FILE_HANDLE dir_handle, char *section)
+{
+    union string name;
+    name.s = get_value(&cfg, section, "dtb");
+    if ( name.s )
+    {
+        if ( !read_file(dir_handle, &dtbfile, name.s))
+            blexit(NULL);
+    }
+    fdt = fdt_increase_size(&dtbfile, cfg.size + EFI_PAGE_SIZE);
+    if ( !fdt )
+        blexit(L"Unable to create new FDT\r\n");
+}
+
+static void __init efi_arch_get_memory_map(UINTN *map_size,
+                                             void **map,
+                                             UINTN *map_key, UINTN *desc_size,
+                                             UINT32 *desc_ver)
+{
+    EFI_STATUS status;
+
+    status = efi_get_memory_map(map, map_size, desc_size, desc_ver, map_key);
+    if ( EFI_ERROR(status) )
+        blexit(L"ERROR getting EFI memory map.\r\n");
+    memmap = *map;
+}
+
+static void __init efi_arch_edd(void)
+{
+}
+
+static void __init efi_arch_video(bool_t base_video,
+                                  UINTN cols, UINTN rows, UINTN depth,
+                                  EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
+{
+}
+
+static void __init efi_arch_memory(void)
+{
+}
+
+static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
+                                           CHAR16 *cmdline_options,
+                                           char *cfgfile_options)
+{
+    union string name;
+    char *buf;
+    EFI_STATUS status;
+    int prop_len;
+    int chosen;
+
+    /* locate chosen node, which is where we add Xen module info. */
+    chosen = fdt_subnode_offset(fdt, 0, "chosen");
+    if ( chosen < 0 )
+        blexit(L"ERROR unable to find chosen node\r\n");
+
+    status = efi_bs->AllocatePool(EfiBootServicesData, EFI_PAGE_SIZE, (void **)&buf);
+    if ( EFI_ERROR(status) )
+        PrintErrMesg(L"ERROR allocating memory.\r\n", status);
+
+    if ( image_name )
+    {
+        name.w = image_name;
+        w2s(&name);
+    }
+    else
+        name.s = "xen";
+
+    prop_len = 0;
+    prop_len += snprintf(buf + prop_len,
+                           EFI_PAGE_SIZE - prop_len, "%s", name.s);
+    if ( prop_len >= EFI_PAGE_SIZE )
+        blexit(L"FDT string overflow");
+
+    if ( cfgfile_options )
+    {
+        prop_len += snprintf(buf + prop_len,
+                               EFI_PAGE_SIZE - prop_len, " %s", cfgfile_options);
+        if ( prop_len >= EFI_PAGE_SIZE )
+            blexit(L"FDT string overflow");
+    }
+
+    if ( cmdline_options )
+    {
+        name.w = cmdline_options;
+        w2s(&name);
+    }
+    else
+        name.s = NULL;
+
+    if ( name.s )
+    {
+        prop_len += snprintf(buf + prop_len,
+                               EFI_PAGE_SIZE - prop_len, " %s", name.s);
+        if ( prop_len >= EFI_PAGE_SIZE )
+            blexit(L"FDT string overflow");
+    }
+
+    if ( fdt_setprop_string(fdt, chosen, "xen,xen-bootargs", buf) < 0 )
+        blexit(L"unable to set xen,xen-bootargs property.");
+
+    efi_bs->FreePool(buf);
+}
+
+static void __init efi_arch_handle_module(struct file *file, char *name,
+                                          char *options)
+{
+    int node;
+    int chosen;
+    int addr_len, size_len;
+
+    if ( file == &dtbfile )
+        return;
+    chosen = setup_chosen_node(fdt, &addr_len, &size_len);
+    if ( chosen < 0 )
+        blexit(L"Unable to setup chosen node\r\n");
+
+    if ( file == &ramdisk )
+    {
+        char ramdisk_compat[] = "multiboot,ramdisk\0multiboot,module";
+        node = fdt_add_subnode(fdt, chosen, "ramdisk");
+        if ( node < 0 )
+            blexit(L"Error adding ramdisk FDT node.");
+        if ( fdt_setprop(fdt, node, "compatible", ramdisk_compat,
+                         sizeof(ramdisk_compat)) < 0 )
+            blexit(L"unable to set compatible property.");
+        if ( fdt_set_reg(fdt, node, addr_len, size_len, ramdisk.addr,
+                    ramdisk.size) < 0 )
+            blexit(L"unable to set reg property.");
+    }
+    else if ( file == &xsm )
+    {
+        char xsm_compat[] = "xen,xsm-policy\0multiboot,module";
+        node = fdt_add_subnode(fdt, chosen, "xsm");
+        if ( node < 0 )
+            blexit(L"Error adding xsm FDT node.");
+        if ( fdt_setprop(fdt, node, "compatible", xsm_compat,
+                         sizeof(xsm_compat)) < 0 )
+            blexit(L"unable to set compatible property.");
+        if ( fdt_set_reg(fdt, node, addr_len, size_len, xsm.addr,
+                    xsm.size) < 0 )
+            blexit(L"unable to set reg property.");
+    }
+    else if ( file == &kernel )
+    {
+        char kernel_compat[] = "multiboot,kernel\0multiboot,module";
+        node = fdt_add_subnode(fdt, chosen, "kernel");
+        if ( node < 0 )
+            blexit(L"Error adding dom0 FDT node.");
+        if ( fdt_setprop(fdt, node, "compatible", kernel_compat,
+                         sizeof(kernel_compat)) < 0 )
+            blexit(L"unable to set compatible property.");
+        if ( options && fdt_setprop_string(fdt, node, "bootargs", options) < 0 )
+            blexit(L"unable to set bootargs property.");
+        if ( fdt_set_reg(fdt, node, addr_len, size_len, kernel.addr,
+                         kernel.size) < 0 )
+            blexit(L"unable to set reg property.");
+    }
+    else
+        blexit(L"Unknown module type\r\n");
+}
+
+static void __init efi_arch_cpu(void)
+{
+}
+
+static void __init efi_arch_smbios(void)
+{
+}
+
+static void __init efi_arch_blexit(void)
+{
+    if ( dtbfile.addr && dtbfile.size )
+        efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
+    if ( memmap )
+        efi_bs->FreePool(memmap);
+}
+
+static void __init efi_arch_load_addr_check(EFI_LOADED_IMAGE *loaded_image)
+{
+    if ( (unsigned long)loaded_image->ImageBase & ((1 << 12) - 1) )
+        blexit(L"Xen must be loaded at a 4 KByte boundary.");
+}
+
+static void __init efi_arch_runtime_setup(EFI_SYSTEM_TABLE *SystemTable)
+{
+}
+
+static __init bool_t efi_arch_use_config_file(EFI_SYSTEM_TABLE *SystemTable)
+{
+    /*
+     * For arm, we may get a device tree from GRUB (or other bootloader)
+     * that contains modules that have already been loaded into memory.  In
+     * this case, we do not use a configuration file, and rely on the
+     * bootloader to have loaded all required modules and appropriate
+     * options.
+     */
+
+    fdt = lookup_fdt_config_table(SystemTable);
+    dtbfile.ptr = fdt;
+    dtbfile.size = 0;  /* Config table memory can't be freed, so set size to 0 */
+    if ( !fdt || fdt_node_offset_by_compatible(fdt, 0, "multiboot,module") < 0 )
+    {
+        /*
+         * We either have no FDT, or one without modules, so we must have a
+         * Xen EFI configuration file to specify modules.  (dom0 required)
+         */
+        return 1;
+    }
+    PrintStr(L"Using modules provided by bootloader in FDT\r\n");
+    /* We have modules already defined in fdt, just add space. */
+    fdt = fdt_increase_size(&dtbfile, EFI_PAGE_SIZE);
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/efi.h b/xen/include/asm-arm/efi.h
new file mode 100644
index 0000000..aae4716
--- /dev/null
+++ b/xen/include/asm-arm/efi.h
@@ -0,0 +1,29 @@
+#include <asm/efibind.h>
+#include <efi/efidef.h>
+#include <efi/efierr.h>
+#include <efi/eficon.h>
+#include <efi/efidevp.h>
+#include <efi/eficapsule.h>
+#include <efi/efiapi.h>
+#include <xen/efi.h>
+#include <xen/spinlock.h>
+#include <asm/page.h>
+
+extern unsigned int efi_num_ct;
+extern EFI_CONFIGURATION_TABLE *efi_ct;
+
+extern unsigned int efi_version, efi_fw_revision;
+extern const CHAR16 *efi_fw_vendor;
+
+extern EFI_RUNTIME_SERVICES *efi_rs;
+
+extern UINTN efi_memmap_size, efi_mdesc_size;
+extern void *efi_memmap;
+
+extern const struct efi_pci_rom *efi_pci_roms;
+
+extern UINT64 efi_boot_max_var_store_size, efi_boot_remain_var_store_size,
+              efi_boot_max_var_size;
+
+unsigned long efi_rs_enter(void);
+void efi_rs_leave(unsigned long);
diff --git a/xen/include/asm-arm/efibind.h b/xen/include/asm-arm/efibind.h
new file mode 100644
index 0000000..09dca7a
--- /dev/null
+++ b/xen/include/asm-arm/efibind.h
@@ -0,0 +1,2 @@
+#include <xen/types.h>
+#include <asm/arm64/efibind.h>
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 36e5704..40814e6 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -3,7 +3,7 @@
 
 #include <public/version.h>
 
-#define NR_MEM_BANKS 8
+#define NR_MEM_BANKS 32
 
 #define MAX_MODULES 5 /* Current maximum useful modules */
 
-- 
2.1.0.rc1

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 01/15] move x86 EFI boot code to common/efi
  2014-09-10  0:51 ` [PATCH V4 01/15] move x86 EFI boot code to common/efi Roy Franz
@ 2014-09-11 13:50   ` Jan Beulich
  2014-09-11 17:16     ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 13:50 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> --- /dev/null
> +++ b/xen/arch/x86/efi/boot.c
> @@ -0,0 +1 @@
> +../../../common/efi/boot.c
> \ No newline at end of file

That's certainly not how I envisioned it - I rather expected the
symlink to be created at build time. That's in any event the more
portable solution (for example I tend to keep source trees on
Windows machines for reference, and I don't think symlinks get
properly expressed there when e.g. extracted from a tarball -
may depend on the tool used of course).

Just create it together with the include/asm one.

And then, as said before, I don't think relocating just boot.c is
going to be sufficient, in which case it would seem more consistent
to move all relevant files in one go.

> diff --git a/xen/arch/x86/efi/efi.h b/xen/include/asm-x86/efi.h
> similarity index 100%
> rename from xen/arch/x86/efi/efi.h
> rename to xen/include/asm-x86/efi.h

This adjustment (and the related ones) seems unnecessary. The
header is strictly local to xen/arch/x86/efi/ (and should remain
unexposed after the move, but might of course be moved along
with the other files).

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 02/15] Move x86 specific funtions/variables to arch header
  2014-09-10  0:51 ` [PATCH V4 02/15] Move x86 specific funtions/variables to arch header Roy Franz
@ 2014-09-11 14:03   ` Jan Beulich
  2014-09-11 17:33     ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:03 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> -/* Using SetVirtualAddressMap() is incompatible with kexec: */
> -#undef USE_SET_VIRTUAL_ADDRESS_MAP

In which way is this arch-specific?

> @@ -41,8 +31,10 @@ typedef struct {
>      EFI_SHIM_LOCK_VERIFY Verify;
>  } EFI_SHIM_LOCK_PROTOCOL;
>  
> -extern char start[];
> -extern u32 cpuid_ext_features;
> +static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer);
> +static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer);
> +static void __init DisplayUint(UINT64 Val, INTN Width);
> +static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s);

Why do you need these declarations? And if you need them, no
__init annotations here please (they only belong on the
definitions).

> -static void __init place_string(u32 *addr, const char *s)
> -{
> -    static char *__initdata alloc = start;
> -
> -    if ( s && *s )
> -    {
> -        size_t len1 = strlen(s) + 1;
> -        const char *old = (char *)(long)*addr;
> -        size_t len2 = *addr ? strlen(old) + 1 : 0;
> -
> -        alloc -= len1 + len2;
> -        /*
> -         * Insert new string before already existing one. This is needed
> -         * for options passed on the command line to override options from
> -         * the configuration file.
> -         */
> -        memcpy(alloc, s, len1);
> -        if ( *addr )
> -        {
> -            alloc[len1 - 1] = ' ';
> -            memcpy(alloc + len1, old, len2);
> -        }
> -    }
> -    *addr = (long)alloc;
> -}

How much of this is really arch-specific?

> -static void __init setup_efi_pci(void)

And this doesn't seem arch-specific either (it only depends on
HAS_PCI or some such).

> -static void __init relocate_image(unsigned long delta)

I can see that some of this may need an arch abstraction, but why
would you not want to do this on ARM (or elsewhere)? In fact - how
do you get away without?

> --- /dev/null
> +++ b/xen/include/asm-x86/efi-boot.h
> @@ -0,0 +1,451 @@
> +/*
> + * Architecture specific implementation for EFI boot code.  This file
> + * is intended to be included by XXX _only_, and therefore can define
> + * arch specific global variables.
> + */
> +#include <asm/e820.h>
> +#include <asm/edd.h>
> +#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
> +#include <asm/fixmap.h>
> +#undef __ASSEMBLY__
> +#include <asm/msr.h>
> +#include <asm/processor.h>
> +
> +static struct file __initdata ucode;
> +static multiboot_info_t __initdata mbi = {
> +    .flags = MBI_MODULES | MBI_LOADERNAME
> +};
> +static module_t __initdata mb_modules[3];
> +
> +static void noreturn blexit(const CHAR16 *str);
> +static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);

What are these two doing here?

> +void __init efi_init_memory(void)

Now that I look at it again, I think a good part of this is arch-
independent too.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 03/15] create arch functions to get and process EFI memory map.
  2014-09-10  0:51 ` [PATCH V4 03/15] create arch functions to get and process EFI memory map Roy Franz
@ 2014-09-11 14:11   ` Jan Beulich
  2014-09-11 17:40     ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:11 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> --- a/xen/common/efi/boot.c
> +++ b/xen/common/efi/boot.c
> @@ -56,8 +56,6 @@ static EFI_HANDLE __initdata efi_ih;
>  static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdOut;
>  static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdErr;
>  
> -static UINT32 __initdata mdesc_ver;

Is this correct for the USE_SET_VIRTUAL_ADDRESS_MAP case?

> @@ -1171,67 +1169,12 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>          }
>      }
>  
> -    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
> -                         &efi_mdesc_size, &mdesc_ver);
> -    mbi.mem_upper -= efi_memmap_size;
> -    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
> -    if ( mbi.mem_upper < xen_phys_start )
> -        blexit(L"Out of static memory");
> -    efi_memmap = (void *)(long)mbi.mem_upper;
> -    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
> -                                  &efi_mdesc_size, &mdesc_ver);
> -    if ( EFI_ERROR(status) )
> -        PrintErrMesg(L"Cannot obtain memory map", status);
> +    efi_arch_get_memory_map(&mmap_size, &mmap, &mmap_key,
> +                                  &mmap_desc_size, &mmap_desc_ver);

The only arch-specific bit here is where to put the map.

> --- a/xen/include/asm-x86/efi-boot.h
> +++ b/xen/include/asm-x86/efi-boot.h
> @@ -449,3 +449,89 @@ static void __init place_string(u32 *addr, const char *s)
>      }
>      *addr = (long)alloc;
>  }
> +
> +static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
> +                                               void *map,
> +                                               UINTN map_size,
> +                                               UINTN desc_size,
> +                                               UINT32 desc_ver)
> +{
> +    struct e820entry *e;
> +    int i;

This was "unsigned int" originally, and should remain so. Please
avoid type changes, or spell them out in the description if you
find ones which indeed need adjustment.

> +static void __init efi_arch_get_memory_map(UINTN *map_size,
> +                                             void **map,
> +                                             UINTN *map_key, UINTN *desc_size,
> +                                             UINT32 *desc_ver)
> +{
> +    EFI_STATUS status;

Blank line after declarations please.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices
  2014-09-10  0:51 ` [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices Roy Franz
@ 2014-09-11 14:13   ` Jan Beulich
  2014-09-11 17:44     ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:13 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>      status = efi_bs->ExitBootServices(ImageHandle, mmap_key);
>      if ( EFI_ERROR(status) )
>          PrintErrMesg(L"Cannot exit boot services", status);
>  
> -    /* Adjust pointers into EFI. */
> -    efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
> -#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
> -    efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
> -#endif
> -    efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
> -    efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
> -
> -    efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);

Up to here I don't see anything arch-specific again.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 05/15] Add efi_arch_cfg_file() to handle arch specific cfg file fields
  2014-09-10  0:51 ` [PATCH V4 05/15] Add efi_arch_cfg_file() to handle arch specific cfg file fields Roy Franz
@ 2014-09-11 14:16   ` Jan Beulich
  2014-09-11 18:11     ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:16 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> @@ -752,6 +758,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>      }
>      if ( !name.s )
>          blexit(L"No Dom0 kernel image specified.");
> +
> +    efi_arch_cfg_file(dir_handle, section.s);
> +
>      split_value(name.s);
>      read_file(dir_handle, s2w(&name), &kernel);
>      efi_bs->FreePool(name.w);
> @@ -769,17 +778,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>          efi_bs->FreePool(name.w);
>      }
>  
> -    name.s = get_value(&cfg, section.s, "ucode");
> -    if ( !name.s )
> -        name.s = get_value(&cfg, "global", "ucode");
> -    if ( name.s )
> -    {
> -        microcode_set_module(mbi.mods_count);
> -        split_value(name.s);
> -        read_file(dir_handle, s2w(&name), &ucode);
> -        efi_bs->FreePool(name.w);
> -    }
> -
>      name.s = get_value(&cfg, section.s, "xsm");
>      if ( name.s )
>      {

While the ordering shouldn't matter that much, is it intentional that
you move this up ahead of the loading of the kernel? If anything,
I'd see this move down after the XSM loading.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 06/15] Add efi_arch_handle_cmdline() for processing commandline
  2014-09-10  0:51 ` [PATCH V4 06/15] Add efi_arch_handle_cmdline() for processing commandline Roy Franz
@ 2014-09-11 14:22   ` Jan Beulich
  2014-09-11 18:24     ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:22 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> @@ -786,19 +786,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>          efi_bs->FreePool(name.w);
>      }
>  
> -    name.s = get_value(&cfg, section.s, "options");
> -    if ( name.s )
> -        place_string(&mbi.cmdline, name.s);
> -    /* Insert image name last, as it gets prefixed to the other options. */
> -    if ( argc )
> -    {
> -        name.w = *argv;
> -        w2s(&name);
> -    }
> -    else
> -        name.s = "xen";
> -    place_string(&mbi.cmdline, name.s);
> -
>      cols = rows = depth = 0;
>      if ( !base_video )
>      {
> @@ -817,6 +804,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>          }
>      }
>  
> +    name.s = get_value(&cfg, section.s, "options");
> +    efi_arch_handle_cmdline(argc ? *argv : NULL, options, name.s);
> +
>      efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
>      cfg.addr = 0;
>  

Again - is there a particular reason to move this down?

> --- a/xen/include/asm-x86/efi-boot.h
> +++ b/xen/include/asm-x86/efi-boot.h
> @@ -607,3 +607,37 @@ static void __init efi_arch_cfg_file(EFI_FILE_HANDLE 
> dir_handle, char *section)
>          efi_bs->FreePool(name.w);
>      }
>  }
> +
> +static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
> +                                           CHAR16 *cmdline_options,
> +                                           char *cfgfile_options)
> +{
> +    union string name;
> +
> +    if ( cmdline_options )
> +    {
> +        name.w = cmdline_options;
> +        w2s(&name);
> +        place_string(&mbi.cmdline, name.s);
> +    }
> +    if ( cfgfile_options )
> +        place_string(&mbi.cmdline, cfgfile_options);
> +    /* Insert image name last, as it gets prefixed to the other options. */
> +    if ( image_name )
> +    {
> +        name.w = image_name;
> +        w2s(&name);
> +    }
> +    else
> +        name.s = "xen";
> +    place_string(&mbi.cmdline, name.s);
> +
> +    if ( mbi.cmdline )
> +        mbi.flags |= MBI_CMDLINE;
> +    /*
> +     * These must not be initialized statically, since the value must
> +     * not get relocated when processing base relocations below.
> +     */

The "below" here will need adjustment now that this doesn't live in
the same function anymore.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 07/15] Move x86 specific video and disk probing code
  2014-09-10  0:51 ` [PATCH V4 07/15] Move x86 specific video and disk probing code Roy Franz
@ 2014-09-11 14:26   ` Jan Beulich
  2014-09-11 18:30     ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:26 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> @@ -811,189 +785,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>      cfg.addr = 0;
>  
>      dir_handle->Close(dir_handle);
> -
> -    if ( gop && !base_video )
> -    {
> -        for ( i = size = 0; i < gop->Mode->MaxMode; ++i )
> -        {
> -            unsigned int bpp = 0;
> -
> -            status = gop->QueryMode(gop, i, &info_size, &mode_info);
> -            if ( EFI_ERROR(status) )
> -                continue;
> -            switch ( mode_info->PixelFormat )
> -            {
> -            case PixelBitMask:
> -                bpp = hweight32(mode_info->PixelInformation.RedMask |
> -                                mode_info->PixelInformation.GreenMask |
> -                                mode_info->PixelInformation.BlueMask);
> -                break;
> -            case PixelRedGreenBlueReserved8BitPerColor:
> -            case PixelBlueGreenRedReserved8BitPerColor:
> -                bpp = 24;
> -                break;
> -            default:
> -                continue;
> -            }
> -            if ( cols == mode_info->HorizontalResolution &&
> -                 rows == mode_info->VerticalResolution &&
> -                 (!depth || bpp == depth) )
> -            {
> -                gop_mode = i;
> -                break;
> -            }
> -            if ( !cols && !rows &&
> -                 mode_info->HorizontalResolution *
> -                 mode_info->VerticalResolution > size )
> -            {
> -                size = mode_info->HorizontalResolution *
> -                       mode_info->VerticalResolution;
> -                gop_mode = i;
> -            }
> -        }
> -    }

This together with ...
 
> @@ -1075,77 +867,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>      l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] =
>          l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
>  
> -    if ( gop )
> -    {
> -        int bpp = 0;
> -
> -        /* Set graphics mode. */
> -        if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode )
> -            gop->SetMode(gop, gop_mode);

... this isn't arch-specific again.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 08/15] Add efi_arch_memory() for arch specific memory setup
  2014-09-10  0:51 ` [PATCH V4 08/15] Add efi_arch_memory() for arch specific memory setup Roy Franz
@ 2014-09-11 14:27   ` Jan Beulich
  0 siblings, 0 replies; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:27 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> This patch adds efi_arch_memory() to allow each architecture a hook
> to use for do memory setup.  x86 uses this for trampoline memory setup
> and some pagetable setup.
> 
> Signed-off-by: Roy Franz <roy.franz@linaro.org>

Acked-by: Jan Beulich <jbeulich@suse.com>

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 09/15] Add arch specific module handling to read_file()
  2014-09-10  0:51 ` [PATCH V4 09/15] Add arch specific module handling to read_file() Roy Franz
@ 2014-09-11 14:40   ` Jan Beulich
  0 siblings, 0 replies; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:40 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> @@ -398,18 +397,39 @@ static CHAR16 *__init point_tail(CHAR16 *fn)
>              break;
>          }
>  }

Missing blank line here.

> +/*
> + * Truncate string at first space, and return pointer
> + * to remainder of string.
> + */
> +static char * __init truncate_string(char *s)

"split" would seem a more correct naming to me than "truncate".

> +{
> +    while ( *s && !isspace(*s) )
> +        ++s;
> +    if ( *s )
> +    {
> +        *s = 0;
> +        return(s + 1);
> +    }
> +    return(NULL);

No parentheses here please.

>          if ( !EFI_ERROR(ret) && file->size != size )
>              ret = EFI_ABORTED;
> @@ -469,7 +487,7 @@ static bool_t __init read_file(EFI_FILE_HANDLE 
> dir_handle, CHAR16 *name,
>      {
>          PrintErr(what);
>          PrintErr(L" failed for ");
> -        PrintErrMesg(name, ret);
> +        PrintErrMesg(name.w, ret);
>      }
>  
>      return 1;
> @@ -525,7 +543,13 @@ static char *__init get_value(const struct file *cfg, 
> const char *section,
>              break;
>          default:
>              if ( match && strncmp(ptr, item, ilen) == 0 && ptr[ilen] == '=' )
> -                return ptr + ilen + 1;
> +            {
> +                ptr += ilen + 1;
> +                /* strip off any leading spaces */
> +                while ( *ptr && isspace(*ptr) )
> +                    ptr++;
> +                return ptr;
> +            }
>              break;
>          }
>          ptr += strlen(ptr);
> @@ -684,24 +698,26 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>          gop = NULL;
>  
>      /* Read and parse the config file. */
> -    if ( !cfg_file_name )
> +    if ( !cfg_file_name.w )
>      {
>          CHAR16 *tail;
>  
> -        while ( (tail = point_tail(file_name)) != NULL )
> +        while ( (tail = point_tail(file_name.w)) != NULL )
>          {
>              wstrcpy(tail, L".cfg");
> -            if ( read_file(dir_handle, file_name, &cfg) )
> +            if ( read_file(dir_handle, &cfg, w2s(&file_name)) )

No - this conversion is lossy. So far w2s() is being use _only_ when
there's no alternative (i.e. when the final consumer expects ASCII).

>                  break;
>              *tail = 0;
>          }
>          if ( !tail )
>              blexit(L"No configuration file found.");
>          PrintStr(L"Using configuration file '");
> -        PrintStr(file_name);
> +        s2w(&file_name);
> +        PrintStr(file_name.w);
>          PrintStr(L"'\r\n");
> +        efi_bs->FreePool(file_name.w);

And eliminating the conversion above would make the ugliness here
unnecessary too.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 10/15] Add SMBIOS and runtime services setup arch functions.
  2014-09-10  0:52 ` [PATCH V4 10/15] Add SMBIOS and runtime services setup arch functions Roy Franz
@ 2014-09-11 14:44   ` Jan Beulich
  2014-09-11 22:03     ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:44 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
> @@ -805,49 +801,13 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>          boot_cpu_data.x86_capability[1] = cpuid_ext_features;
>      }
>  
> -    /* Obtain basic table pointers. */
> -    for ( i = 0; i < efi_num_ct; ++i )
> -    {
> -        static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
> -        static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
> -        static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
> -        static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
> -
> -        if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
> -	       efi.acpi20 = (long)efi_ct[i].VendorTable;
> -        if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
> -	       efi.acpi = (long)efi_ct[i].VendorTable;
> -        if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
> -	       efi.mps = (long)efi_ct[i].VendorTable;
> -        if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
> -	       efi.smbios = (long)efi_ct[i].VendorTable;
> -    }

The only arch specific things I can see throughout this entire patch
are the specific GUIDs and which fields they go into in the internal
structure. The GUIDs can be put in a table, and the fields can be
represented e.g. via offsetof(), paired with the respective GUID.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 11/15] Add several misc. arch functions for EFI boot code.
  2014-09-10  0:52 ` [PATCH V4 11/15] Add several misc. arch functions for EFI boot code Roy Franz
@ 2014-09-11 14:45   ` Jan Beulich
  0 siblings, 0 replies; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:45 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
> Add efi_arch_blexit() for arch specific cleanup on error exit,
> efi_arch_load_addr_check() to do the arch specific verifications
> of where the UEFI firmware loaded Xen, and efi_arch_cpu() for
> probing CPU features.
> 
> Signed-off-by: Roy Franz <roy.franz@linaro.org>

Acked-by: Jan Beulich <jbeulich@suse.com>

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 12/15] Add efi_arch_use_config_file() function to control use of config file
  2014-09-10  0:52 ` [PATCH V4 12/15] Add efi_arch_use_config_file() function to control use of config file Roy Franz
@ 2014-09-11 14:49   ` Jan Beulich
  2014-09-11 23:54     ` Stefano Stabellini
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:49 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
> -    cols = rows = depth = 0;
> -    if ( !base_video )
> -    {
> -        name.cs = get_value(&cfg, section.s, "video");
> -        if ( !name.cs )
> -            name.cs = get_value(&cfg, "global", "video");
> -        if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
> +        cols = rows = depth = 0;
> +        if ( !base_video )
>          {
> -            cols = simple_strtoul(name.cs + 4, &name.cs, 10);
> -            if ( *name.cs == 'x' )
> -                rows = simple_strtoul(name.cs + 1, &name.cs, 10);
> -            if ( *name.cs == 'x' )
> -                depth = simple_strtoul(name.cs + 1, &name.cs, 10);
> -            if ( *name.cs )
> -                cols = rows = depth = 0;
> +            name.cs = get_value(&cfg, section.s, "video");
> +            if ( !name.cs )
> +                name.cs = get_value(&cfg, "global", "video");
> +            if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
> +            {
> +                cols = simple_strtoul(name.cs + 4, &name.cs, 10);
> +                if ( *name.cs == 'x' )
> +                    rows = simple_strtoul(name.cs + 1, &name.cs, 10);
> +                if ( *name.cs == 'x' )
> +                    depth = simple_strtoul(name.cs + 1, &name.cs, 10);
> +                if ( *name.cs )
> +                    cols = rows = depth = 0;
> +            }

So how is this video mode selection being represented then without
config file? Don't you need to at least add a command line option for
that?

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-10  0:52 ` [PATCH V4 15/15] Add ARM EFI boot support Roy Franz
@ 2014-09-11 14:53   ` Jan Beulich
  2014-09-11 22:26     ` Roy Franz
  2014-09-12  0:49   ` Stefano Stabellini
  1 sibling, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-11 14:53 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, fu.wei

>>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
> --- a/xen/common/Makefile
> +++ b/xen/common/Makefile
> @@ -67,4 +67,5 @@ subdir-$(x86_64) += hvm
>  subdir-$(coverage) += gcov
>  
>  subdir-y += libelf
> +subdir-$(CONFIG_EFI) += efi
>  subdir-$(HAS_DEVICE_TREE) += libfdt

Hmm, this will suggest to the reader that either x86 doesn't support
EFI, or it gets built this way too. Both of which is wrong. I think the
symlink mechanism should be used the same way as for x86.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 01/15] move x86 EFI boot code to common/efi
  2014-09-11 13:50   ` Jan Beulich
@ 2014-09-11 17:16     ` Roy Franz
  2014-09-12  6:55       ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-11 17:16 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

On Thu, Sep 11, 2014 at 6:50 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>> --- /dev/null
>> +++ b/xen/arch/x86/efi/boot.c
>> @@ -0,0 +1 @@
>> +../../../common/efi/boot.c
>> \ No newline at end of file
>
> That's certainly not how I envisioned it - I rather expected the
> symlink to be created at build time. That's in any event the more
> portable solution (for example I tend to keep source trees on
> Windows machines for reference, and I don't think symlinks get
> properly expressed there when e.g. extracted from a tarball -
> may depend on the tool used of course).
>
> Just create it together with the include/asm one.

OK, I will create the symlink at build time
>
> And then, as said before, I don't think relocating just boot.c is
> going to be sufficient, in which case it would seem more consistent
> to move all relevant files in one go.

I can move the other file - I think runtime.c would be the only other to move,
but it is not used by this patchset.  This patchset is limited to EFI
boot support.
Runtime services support, ACPI, etc all depend on this functionality,
but are not
being addressed in this patchset.
I can move runtime.c to common/efi, but the only place it will be used
is x86/efi.

This touches on an issue in a number of the following patches - some
of the things moved to
the arch specific file are EFI related things that are not truly
architecture specific, but are not yet
implemented for ARM and are beyond the scope of this patchset.  My
intent is for these to be adjusted
when those features (such as runtime services) are implemented for
ARM.  There are other non-EFI specific
things like VGA, which aren't currently in the ARM build, but are
setup in boot.c, but aren't truly architecture specific.

>
>> diff --git a/xen/arch/x86/efi/efi.h b/xen/include/asm-x86/efi.h
>> similarity index 100%
>> rename from xen/arch/x86/efi/efi.h
>> rename to xen/include/asm-x86/efi.h
>
> This adjustment (and the related ones) seems unnecessary. The
> header is strictly local to xen/arch/x86/efi/ (and should remain
> unexposed after the move, but might of course be moved along
> with the other files).

Yup - I moved this when I moved boot.c, and forgot to undo this when
boot.c is linked back to its original location.

>
> Jan
>

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 02/15] Move x86 specific funtions/variables to arch header
  2014-09-11 14:03   ` Jan Beulich
@ 2014-09-11 17:33     ` Roy Franz
  2014-09-12  7:04       ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-11 17:33 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

On Thu, Sep 11, 2014 at 7:03 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>> -/* Using SetVirtualAddressMap() is incompatible with kexec: */
>> -#undef USE_SET_VIRTUAL_ADDRESS_MAP
>
> In which way is this arch-specific?
The define is only used by the x86 specific code.  I can move it back
to the common code.


>
>> @@ -41,8 +31,10 @@ typedef struct {
>>      EFI_SHIM_LOCK_VERIFY Verify;
>>  } EFI_SHIM_LOCK_PROTOCOL;
>>
>> -extern char start[];
>> -extern u32 cpuid_ext_features;
>> +static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer);
>> +static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer);
>> +static void __init DisplayUint(UINT64 Val, INTN Width);
>> +static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s);
>
> Why do you need these declarations? And if you need them, no
> __init annotations here please (they only belong on the
> definitions).

These are forward declarations of functions provided by boot.c but
used in efi-boot.h.  I was trying to keep the
#include of efi-boot.h near the top of the file.  I can move it to
below where these functions are defined and remove
the forward declarations.
I will remove the __init if they stay.

>
>> -static void __init place_string(u32 *addr, const char *s)
>> -{
>> -    static char *__initdata alloc = start;
>> -
>> -    if ( s && *s )
>> -    {
>> -        size_t len1 = strlen(s) + 1;
>> -        const char *old = (char *)(long)*addr;
>> -        size_t len2 = *addr ? strlen(old) + 1 : 0;
>> -
>> -        alloc -= len1 + len2;
>> -        /*
>> -         * Insert new string before already existing one. This is needed
>> -         * for options passed on the command line to override options from
>> -         * the configuration file.
>> -         */
>> -        memcpy(alloc, s, len1);
>> -        if ( *addr )
>> -        {
>> -            alloc[len1 - 1] = ' ';
>> -            memcpy(alloc + len1, old, len2);
>> -        }
>> -    }
>> -    *addr = (long)alloc;
>> -}
>
> How much of this is really arch-specific?

This is only used by the x86 code, and this is the x86 specific memory
management that uses
memory allocated by the linker script before start.  The ARM boot code
does not use this.

>
>> -static void __init setup_efi_pci(void)
>
> And this doesn't seem arch-specific either (it only depends on
> HAS_PCI or some such).

This does scanning of PCI ROMS, which is unlikely to do anything
useful on ARM platforms.  I also have
no way to test this on ARM.
I can try to pull this back in, but I may run into dependency issues
such as those with VGA, where I did not
want to pull in otherwise unused (and likely unusable on ARM)
drivers/subsystems in order to keep a little more
code in the common EFI boot path.

>
>> -static void __init relocate_image(unsigned long delta)
>
> I can see that some of this may need an arch abstraction, but why
> would you not want to do this on ARM (or elsewhere)? In fact - how
> do you get away without?

This is done later in boot - I am not familiar with the details.
Maybe Ian can add something here.

>
>> --- /dev/null
>> +++ b/xen/include/asm-x86/efi-boot.h
>> @@ -0,0 +1,451 @@
>> +/*
>> + * Architecture specific implementation for EFI boot code.  This file
>> + * is intended to be included by XXX _only_, and therefore can define
>> + * arch specific global variables.
>> + */
>> +#include <asm/e820.h>
>> +#include <asm/edd.h>
>> +#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
>> +#include <asm/fixmap.h>
>> +#undef __ASSEMBLY__
>> +#include <asm/msr.h>
>> +#include <asm/processor.h>
>> +
>> +static struct file __initdata ucode;
>> +static multiboot_info_t __initdata mbi = {
>> +    .flags = MBI_MODULES | MBI_LOADERNAME
>> +};
>> +static module_t __initdata mb_modules[3];
>> +
>> +static void noreturn blexit(const CHAR16 *str);
>> +static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
>
> What are these two doing here?

These are forward declarations.  I don't think that I can order
everything so that I don't need any forward declarations
anywhere.

>
>> +void __init efi_init_memory(void)
>
> Now that I look at it again, I think a good part of this is arch-
> independent too.
By "this" you mean the code in efi_init_memory?

>
> Jan
>

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 03/15] create arch functions to get and process EFI memory map.
  2014-09-11 14:11   ` Jan Beulich
@ 2014-09-11 17:40     ` Roy Franz
  2014-09-12  7:07       ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-11 17:40 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

On Thu, Sep 11, 2014 at 7:11 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>> --- a/xen/common/efi/boot.c
>> +++ b/xen/common/efi/boot.c
>> @@ -56,8 +56,6 @@ static EFI_HANDLE __initdata efi_ih;
>>  static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdOut;
>>  static SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdErr;
>>
>> -static UINT32 __initdata mdesc_ver;
>
> Is this correct for the USE_SET_VIRTUAL_ADDRESS_MAP case?
I'm not sure.  That is more of a runtime services issue, and along
with the unconditional disabling
of using set virtual address map, I haven't really considered that case.

>
>> @@ -1171,67 +1169,12 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>>          }
>>      }
>>
>> -    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
>> -                         &efi_mdesc_size, &mdesc_ver);
>> -    mbi.mem_upper -= efi_memmap_size;
>> -    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
>> -    if ( mbi.mem_upper < xen_phys_start )
>> -        blexit(L"Out of static memory");
>> -    efi_memmap = (void *)(long)mbi.mem_upper;
>> -    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
>> -                                  &efi_mdesc_size, &mdesc_ver);
>> -    if ( EFI_ERROR(status) )
>> -        PrintErrMesg(L"Cannot obtain memory map", status);
>> +    efi_arch_get_memory_map(&mmap_size, &mmap, &mmap_key,
>> +                                  &mmap_desc_size, &mmap_desc_ver);
>
> The only arch-specific bit here is where to put the map.
Yes, but the ARM method of allocating the space can make the map
bigger.  I can re-arrange
this so that only the memory allocation is in the arch code, but I
think the current implementation
is also reasonable.


>
>> --- a/xen/include/asm-x86/efi-boot.h
>> +++ b/xen/include/asm-x86/efi-boot.h
>> @@ -449,3 +449,89 @@ static void __init place_string(u32 *addr, const char *s)
>>      }
>>      *addr = (long)alloc;
>>  }
>> +
>> +static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
>> +                                               void *map,
>> +                                               UINTN map_size,
>> +                                               UINTN desc_size,
>> +                                               UINT32 desc_ver)
>> +{
>> +    struct e820entry *e;
>> +    int i;
>
> This was "unsigned int" originally, and should remain so. Please
> avoid type changes, or spell them out in the description if you
> find ones which indeed need adjustment.
This was unintentional - I'll fix this.


>
>> +static void __init efi_arch_get_memory_map(UINTN *map_size,
>> +                                             void **map,
>> +                                             UINTN *map_key, UINTN *desc_size,
>> +                                             UINT32 *desc_ver)
>> +{
>> +    EFI_STATUS status;
>
> Blank line after declarations please.

Noted - I'll review this patch-wide.
>
> Jan
>

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices
  2014-09-11 14:13   ` Jan Beulich
@ 2014-09-11 17:44     ` Roy Franz
  2014-09-12  7:08       ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-11 17:44 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

On Thu, Sep 11, 2014 at 7:13 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>>      status = efi_bs->ExitBootServices(ImageHandle, mmap_key);
>>      if ( EFI_ERROR(status) )
>>          PrintErrMesg(L"Cannot exit boot services", status);
>>
>> -    /* Adjust pointers into EFI. */
>> -    efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
>> -#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
>> -    efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
>> -#endif
>> -    efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
>> -    efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
>> -
>> -    efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
>
> Up to here I don't see anything arch-specific again.
This is due to runtime services not being implemented.  The "efi_rs"
variable is defined in the runtime services
file runtime.c, which is not yet ported to ARM.

Short of including ARM runtime service support in the patchset, how
would you like this handled?

>
> Jan
>

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 05/15] Add efi_arch_cfg_file() to handle arch specific cfg file fields
  2014-09-11 14:16   ` Jan Beulich
@ 2014-09-11 18:11     ` Roy Franz
  2014-09-12  7:10       ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-11 18:11 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

On Thu, Sep 11, 2014 at 7:16 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>> @@ -752,6 +758,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>>      }
>>      if ( !name.s )
>>          blexit(L"No Dom0 kernel image specified.");
>> +
>> +    efi_arch_cfg_file(dir_handle, section.s);
>> +
>>      split_value(name.s);
>>      read_file(dir_handle, s2w(&name), &kernel);
>>      efi_bs->FreePool(name.w);
>> @@ -769,17 +778,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>>          efi_bs->FreePool(name.w);
>>      }
>>
>> -    name.s = get_value(&cfg, section.s, "ucode");
>> -    if ( !name.s )
>> -        name.s = get_value(&cfg, "global", "ucode");
>> -    if ( name.s )
>> -    {
>> -        microcode_set_module(mbi.mods_count);
>> -        split_value(name.s);
>> -        read_file(dir_handle, s2w(&name), &ucode);
>> -        efi_bs->FreePool(name.w);
>> -    }
>> -
>>      name.s = get_value(&cfg, section.s, "xsm");
>>      if ( name.s )
>>      {
>
> While the ordering shouldn't matter that much, is it intentional that
> you move this up ahead of the loading of the kernel? If anything,
> I'd see this move down after the XSM loading.
>
> Jan
>
Yes, this is intentional, as in the ARM case the configuration file specifies
the device tree to use, and the kernel and other modules are added to this,
so we need this set up before we actually read the other module files.  For x86
the ordering didn't seem to have any dependencies. I can add a comment
explaining this.

Roy

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 06/15] Add efi_arch_handle_cmdline() for processing commandline
  2014-09-11 14:22   ` Jan Beulich
@ 2014-09-11 18:24     ` Roy Franz
  0 siblings, 0 replies; 71+ messages in thread
From: Roy Franz @ 2014-09-11 18:24 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

On Thu, Sep 11, 2014 at 7:22 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>> @@ -786,19 +786,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>>          efi_bs->FreePool(name.w);
>>      }
>>
>> -    name.s = get_value(&cfg, section.s, "options");
>> -    if ( name.s )
>> -        place_string(&mbi.cmdline, name.s);
>> -    /* Insert image name last, as it gets prefixed to the other options. */
>> -    if ( argc )
>> -    {
>> -        name.w = *argv;
>> -        w2s(&name);
>> -    }
>> -    else
>> -        name.s = "xen";
>> -    place_string(&mbi.cmdline, name.s);
>> -
>>      cols = rows = depth = 0;
>>      if ( !base_video )
>>      {
>> @@ -817,6 +804,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>>          }
>>      }
>>
>> +    name.s = get_value(&cfg, section.s, "options");
>> +    efi_arch_handle_cmdline(argc ? *argv : NULL, options, name.s);
>> +
>>      efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
>>      cfg.addr = 0;
>>
>
> Again - is there a particular reason to move this down?
No, I will move it to the location of the code that was removed.

>
>> --- a/xen/include/asm-x86/efi-boot.h
>> +++ b/xen/include/asm-x86/efi-boot.h
>> @@ -607,3 +607,37 @@ static void __init efi_arch_cfg_file(EFI_FILE_HANDLE
>> dir_handle, char *section)
>>          efi_bs->FreePool(name.w);
>>      }
>>  }
>> +
>> +static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
>> +                                           CHAR16 *cmdline_options,
>> +                                           char *cfgfile_options)
>> +{
>> +    union string name;
>> +
>> +    if ( cmdline_options )
>> +    {
>> +        name.w = cmdline_options;
>> +        w2s(&name);
>> +        place_string(&mbi.cmdline, name.s);
>> +    }
>> +    if ( cfgfile_options )
>> +        place_string(&mbi.cmdline, cfgfile_options);
>> +    /* Insert image name last, as it gets prefixed to the other options. */
>> +    if ( image_name )
>> +    {
>> +        name.w = image_name;
>> +        w2s(&name);
>> +    }
>> +    else
>> +        name.s = "xen";
>> +    place_string(&mbi.cmdline, name.s);
>> +
>> +    if ( mbi.cmdline )
>> +        mbi.flags |= MBI_CMDLINE;
>> +    /*
>> +     * These must not be initialized statically, since the value must
>> +     * not get relocated when processing base relocations below.
>> +     */
>
> The "below" here will need adjustment now that this doesn't live in
> the same function anymore.
I'll fix this.

>
> Jan
>

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 07/15] Move x86 specific video and disk probing code
  2014-09-11 14:26   ` Jan Beulich
@ 2014-09-11 18:30     ` Roy Franz
  2014-09-12  7:12       ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-11 18:30 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

On Thu, Sep 11, 2014 at 7:26 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>> @@ -811,189 +785,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>>      cfg.addr = 0;
>>
>>      dir_handle->Close(dir_handle);
>> -
>> -    if ( gop && !base_video )
>> -    {
>> -        for ( i = size = 0; i < gop->Mode->MaxMode; ++i )
>> -        {
>> -            unsigned int bpp = 0;
>> -
>> -            status = gop->QueryMode(gop, i, &info_size, &mode_info);
>> -            if ( EFI_ERROR(status) )
>> -                continue;
>> -            switch ( mode_info->PixelFormat )
>> -            {
>> -            case PixelBitMask:
>> -                bpp = hweight32(mode_info->PixelInformation.RedMask |
>> -                                mode_info->PixelInformation.GreenMask |
>> -                                mode_info->PixelInformation.BlueMask);
>> -                break;
>> -            case PixelRedGreenBlueReserved8BitPerColor:
>> -            case PixelBlueGreenRedReserved8BitPerColor:
>> -                bpp = 24;
>> -                break;
>> -            default:
>> -                continue;
>> -            }
>> -            if ( cols == mode_info->HorizontalResolution &&
>> -                 rows == mode_info->VerticalResolution &&
>> -                 (!depth || bpp == depth) )
>> -            {
>> -                gop_mode = i;
>> -                break;
>> -            }
>> -            if ( !cols && !rows &&
>> -                 mode_info->HorizontalResolution *
>> -                 mode_info->VerticalResolution > size )
>> -            {
>> -                size = mode_info->HorizontalResolution *
>> -                       mode_info->VerticalResolution;
>> -                gop_mode = i;
>> -            }
>> -        }
>> -    }
>
> This together with ...
>
>> @@ -1075,77 +867,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>>      l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] =
>>          l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
>>
>> -    if ( gop )
>> -    {
>> -        int bpp = 0;
>> -
>> -        /* Set graphics mode. */
>> -        if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode )
>> -            gop->SetMode(gop, gop_mode);
>
> ... this isn't arch-specific again.
>
> Jan
>

I'll review the video stuff again, but I only moved what seemed to be
VGA support specific code to the x86 arch file.
VGA support is currently not part of the ARM build - the VGA setup
code in boot.c updates global variables that are
not present.  I really doubt that VGA support is relevant to ARM so I
move the code to the x86 specific file rather than
trying to add VGA support to ARM.

Roy

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 10/15] Add SMBIOS and runtime services setup arch functions.
  2014-09-11 14:44   ` Jan Beulich
@ 2014-09-11 22:03     ` Roy Franz
  2014-09-11 23:41       ` Stefano Stabellini
  2014-09-12  7:14       ` Jan Beulich
  0 siblings, 2 replies; 71+ messages in thread
From: Roy Franz @ 2014-09-11 22:03 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

On Thu, Sep 11, 2014 at 7:44 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
>> @@ -805,49 +801,13 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>>          boot_cpu_data.x86_capability[1] = cpuid_ext_features;
>>      }
>>
>> -    /* Obtain basic table pointers. */
>> -    for ( i = 0; i < efi_num_ct; ++i )
>> -    {
>> -        static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
>> -        static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
>> -        static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
>> -        static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
>> -
>> -        if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
>> -            efi.acpi20 = (long)efi_ct[i].VendorTable;
>> -        if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
>> -            efi.acpi = (long)efi_ct[i].VendorTable;
>> -        if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
>> -            efi.mps = (long)efi_ct[i].VendorTable;
>> -        if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
>> -            efi.smbios = (long)efi_ct[i].VendorTable;
>> -    }
>
> The only arch specific things I can see throughout this entire patch
> are the specific GUIDs and which fields they go into in the internal
> structure. The GUIDs can be put in a table, and the fields can be
> represented e.g. via offsetof(), paired with the respective GUID.
>
> Jan
>
The efi structure is defined in runtime.c for runtime use, which is
why I moved it,
as I am not addressing runtime services in this patchset.  This is an (ab)use of
the architecture specific head file, using it for features that are
currently only implemented
on that architecture, rather than fundamental architectural differences.

Roy

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-11 14:53   ` Jan Beulich
@ 2014-09-11 22:26     ` Roy Franz
  2014-09-12  7:17       ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-11 22:26 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

On Thu, Sep 11, 2014 at 7:53 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
>> --- a/xen/common/Makefile
>> +++ b/xen/common/Makefile
>> @@ -67,4 +67,5 @@ subdir-$(x86_64) += hvm
>>  subdir-$(coverage) += gcov
>>
>>  subdir-y += libelf
>> +subdir-$(CONFIG_EFI) += efi
>>  subdir-$(HAS_DEVICE_TREE) += libfdt
>
> Hmm, this will suggest to the reader that either x86 doesn't support
> EFI, or it gets built this way too. Both of which is wrong. I think the
> symlink mechanism should be used the same way as for x86.
>
> Jan
>

The common build infrastructure works quite nicely for ARM.  I can
create an arch/arm/efi, and
make symlink, etc. like x86, but this seems silly to me.  The x86 EFI
build is special in the way
it autodetects toolchain capability, but I don't think that these
complications (or side effects of these
x86 specific complications) should be copied for symmetry with x86 as
the only reason.

If the Makefile is misleading, I'd rather address that with a comment
in the Makefile

Roy

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 10/15] Add SMBIOS and runtime services setup arch functions.
  2014-09-11 22:03     ` Roy Franz
@ 2014-09-11 23:41       ` Stefano Stabellini
  2014-09-12  7:14       ` Jan Beulich
  1 sibling, 0 replies; 71+ messages in thread
From: Stefano Stabellini @ 2014-09-11 23:41 UTC (permalink / raw)
  To: Roy Franz
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini,
	Jan Beulich, Fu Wei

On Thu, 11 Sep 2014, Roy Franz wrote:
> On Thu, Sep 11, 2014 at 7:44 AM, Jan Beulich <JBeulich@suse.com> wrote:
> >>>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
> >> @@ -805,49 +801,13 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
> >>          boot_cpu_data.x86_capability[1] = cpuid_ext_features;
> >>      }
> >>
> >> -    /* Obtain basic table pointers. */
> >> -    for ( i = 0; i < efi_num_ct; ++i )
> >> -    {
> >> -        static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
> >> -        static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
> >> -        static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
> >> -        static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
> >> -
> >> -        if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
> >> -            efi.acpi20 = (long)efi_ct[i].VendorTable;
> >> -        if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
> >> -            efi.acpi = (long)efi_ct[i].VendorTable;
> >> -        if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
> >> -            efi.mps = (long)efi_ct[i].VendorTable;
> >> -        if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
> >> -            efi.smbios = (long)efi_ct[i].VendorTable;
> >> -    }
> >
> > The only arch specific things I can see throughout this entire patch
> > are the specific GUIDs and which fields they go into in the internal
> > structure. The GUIDs can be put in a table, and the fields can be
> > represented e.g. via offsetof(), paired with the respective GUID.
> >
> > Jan
> >
> The efi structure is defined in runtime.c for runtime use, which is
> why I moved it,
> as I am not addressing runtime services in this patchset.  This is an (ab)use of
> the architecture specific head file, using it for features that are
> currently only implemented
> on that architecture, rather than fundamental architectural differences.

It might be better to add a couple of flags, such as
support_runtime_services and support_smbios. They would be true on x86
and false on arm. The intention would be clearer that way.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 12/15] Add efi_arch_use_config_file() function to control use of config file
  2014-09-11 14:49   ` Jan Beulich
@ 2014-09-11 23:54     ` Stefano Stabellini
  2014-09-12  7:15       ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Stefano Stabellini @ 2014-09-11 23:54 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, ian.campbell, tim, xen-devel, Roy Franz,
	stefano.stabellini, fu.wei

On Thu, 11 Sep 2014, Jan Beulich wrote:
> >>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
> > -    cols = rows = depth = 0;
> > -    if ( !base_video )
> > -    {
> > -        name.cs = get_value(&cfg, section.s, "video");
> > -        if ( !name.cs )
> > -            name.cs = get_value(&cfg, "global", "video");
> > -        if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
> > +        cols = rows = depth = 0;
> > +        if ( !base_video )
> >          {
> > -            cols = simple_strtoul(name.cs + 4, &name.cs, 10);
> > -            if ( *name.cs == 'x' )
> > -                rows = simple_strtoul(name.cs + 1, &name.cs, 10);
> > -            if ( *name.cs == 'x' )
> > -                depth = simple_strtoul(name.cs + 1, &name.cs, 10);
> > -            if ( *name.cs )
> > -                cols = rows = depth = 0;
> > +            name.cs = get_value(&cfg, section.s, "video");
> > +            if ( !name.cs )
> > +                name.cs = get_value(&cfg, "global", "video");
> > +            if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
> > +            {
> > +                cols = simple_strtoul(name.cs + 4, &name.cs, 10);
> > +                if ( *name.cs == 'x' )
> > +                    rows = simple_strtoul(name.cs + 1, &name.cs, 10);
> > +                if ( *name.cs == 'x' )
> > +                    depth = simple_strtoul(name.cs + 1, &name.cs, 10);
> > +                if ( *name.cs )
> > +                    cols = rows = depth = 0;
> > +            }
> 
> So how is this video mode selection being represented then without
> config file? Don't you need to at least add a command line option for
> that?

The scenario without config file is the one where Xen is loaded by GRUB.
Do we actually need to pass a video mode option in that case?
Wouldn't GRUB take care of changing video mode itself to the value
specified by the user before booting Xen? Xen can query the current
video mode afterwards.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-10  0:52 ` [PATCH V4 15/15] Add ARM EFI boot support Roy Franz
  2014-09-11 14:53   ` Jan Beulich
@ 2014-09-12  0:49   ` Stefano Stabellini
  2014-09-12  3:21     ` Roy Franz
  1 sibling, 1 reply; 71+ messages in thread
From: Stefano Stabellini @ 2014-09-12  0:49 UTC (permalink / raw)
  To: Roy Franz
  Cc: keir, ian.campbell, tim, xen-devel, stefano.stabellini, jbeulich, fu.wei

On Tue, 9 Sep 2014, Roy Franz wrote:
> This patch adds EFI boot support for ARM based on the previous refactoring of
> the x86 EFI boot code.  All ARM specific code is in the ARM efi-boot.h header
> file, with the main EFI entry point common/efi/boot.c.  The PE/COFF header is
> open-coded in head.S, which allows us to have a single binary be both an EFI
> executable and a normal arm64 IMAGE file. There is currently no PE/COFF
> toolchain support for arm64, so it is not possible to create the PE/COFF header
> in the same manner as on x86.  This also simplifies the build as compared to
> x86, as we always build the same executable, whereas x86 builds 2.  An ARM
> version of efi-bind.h is added, which is based on the x86_64 version with the
> x86 specific portions removed.  The Makefile in common/efi is different for x86
> and ARM, as for ARM we always build in EFI support.
> 
> Signed-off-by: Roy Franz <roy.franz@linaro.org>
> ---
>  config/arm64.mk                     |   1 +
>  xen/arch/arm/arm64/head.S           | 150 ++++++++-
>  xen/arch/arm/xen.lds.S              |   1 +
>  xen/common/Makefile                 |   1 +
>  xen/common/efi/Makefile             |   3 +
>  xen/include/asm-arm/arm64/efibind.h | 216 +++++++++++++
>  xen/include/asm-arm/efi-boot.h      | 630 ++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/efi.h           |  29 ++
>  xen/include/asm-arm/efibind.h       |   2 +
>  xen/include/asm-arm/setup.h         |   2 +-
>  10 files changed, 1031 insertions(+), 4 deletions(-)
>  create mode 100644 xen/common/efi/Makefile
>  create mode 100644 xen/include/asm-arm/arm64/efibind.h
>  create mode 100644 xen/include/asm-arm/efi-boot.h
>  create mode 100644 xen/include/asm-arm/efi.h
>  create mode 100644 xen/include/asm-arm/efibind.h
> 
> diff --git a/config/arm64.mk b/config/arm64.mk
> index 15b57a4..e6aab0e 100644
> --- a/config/arm64.mk
> +++ b/config/arm64.mk
> @@ -1,6 +1,7 @@
>  CONFIG_ARM := y
>  CONFIG_ARM_64 := y
>  CONFIG_ARM_$(XEN_OS) := y
> +CONFIG_EFI := y
>  
>  CONFIG_XEN_INSTALL_SUFFIX :=
>  
> diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
> index 43b5e72..158c102 100644
> --- a/xen/arch/arm/arm64/head.S
> +++ b/xen/arch/arm/arm64/head.S
> @@ -24,6 +24,8 @@
>  #include <asm/page.h>
>  #include <asm/asm_defns.h>
>  #include <asm/early_printk.h>
> +#include <efi/efierr.h>
> +#include <asm/arm64/efibind.h>
>  
>  #define PT_PT     0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
>  #define PT_MEM    0xf7d /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=0 P=1 */
> @@ -104,8 +106,14 @@ GLOBAL(start)
>          /*
>           * DO NOT MODIFY. Image header expected by Linux boot-loaders.
>           */
> -        b       real_start           /* branch to kernel start, magic */
> -        .long   0                    /* reserved */
> +efi_head:
> +        /*
> +         * This add instruction has no meaningful effect except that
> +         * its opcode forms the magic "MZ" signature of a PE/COFF file
> +         * that is required for UEFI applications.
> +         */
> +        add     x13, x18, #0x16
> +        b       real_start           /* branch to kernel start */
>          .quad   0                    /* Image load offset from start of RAM */
>          .quad   0                    /* reserved */
>          .quad   0                    /* reserved */
> @@ -116,8 +124,113 @@ GLOBAL(start)
>          .byte   0x52
>          .byte   0x4d
>          .byte   0x64
> -        .word   0                    /* reserved */
> +        .long   pe_header - efi_head        /* Offset to the PE header. */
> +
> +        /*
> +         * Add the PE/COFF header to the file.  The address of this header
> +         * is at offset 0x3c in the file, and is part of Linux "Image"
> +         * header.  The arm64 Linux Image format is designed to support
> +         * being both an 'Image' format binary and a PE/COFF binary.
> +         * The PE/COFF format is defined by Microsoft, and is available
> +         * from: http://msdn.microsoft.com/en-us/gg463119.aspx
> +         * Version 8.3 adds support for arm64 and UEFI usage.
> +         */
> +
> +        .align  3
> +pe_header:
> +        .ascii  "PE"
> +        .short  0
> +coff_header:
> +        .short  0xaa64                          /* AArch64 */
> +        .short  2                               /* nr_sections */
> +        .long   0                               /* TimeDateStamp */
> +        .long   0                               /* PointerToSymbolTable */
> +        .long   1                               /* NumberOfSymbols */
> +        .short  section_table - optional_header /* SizeOfOptionalHeader */
> +        .short  0x206                           /* Characteristics. */
> +                                                /* IMAGE_FILE_DEBUG_STRIPPED | */
> +                                                /* IMAGE_FILE_EXECUTABLE_IMAGE | */
> +                                                /* IMAGE_FILE_LINE_NUMS_STRIPPED */
> +optional_header:
> +        .short  0x20b                           /* PE32+ format */
> +        .byte   0x02                            /* MajorLinkerVersion */
> +        .byte   0x14                            /* MinorLinkerVersion */
> +        .long   _end - real_start               /* SizeOfCode */
> +        .long   0                               /* SizeOfInitializedData */
> +        .long   0                               /* SizeOfUninitializedData */
> +        .long   efi_start - efi_head            /* AddressOfEntryPoint */
> +        .long   real_start - efi_head           /* BaseOfCode */
> +
> +extra_header_fields:
> +        .quad   0                               /* ImageBase */
> +        .long   0x1000                          /* SectionAlignment (4 KByte) */
> +        .long   0x8                             /* FileAlignment */
> +        .short  0                               /* MajorOperatingSystemVersion */
> +        .short  0                               /* MinorOperatingSystemVersion */
> +        .short  0                               /* MajorImageVersion */
> +        .short  0                               /* MinorImageVersion */
> +        .short  0                               /* MajorSubsystemVersion */
> +        .short  0                               /* MinorSubsystemVersion */
> +        .long   0                               /* Win32VersionValue */
> +
> +        .long   _end - efi_head                 /* SizeOfImage */
> +
> +        /* Everything before the kernel image is considered part of the header */
> +        .long   real_start - efi_head           /* SizeOfHeaders */
> +        .long   0                               /* CheckSum */
> +        .short  0xa                             /* Subsystem (EFI application) */
> +        .short  0                               /* DllCharacteristics */
> +        .quad   0                               /* SizeOfStackReserve */
> +        .quad   0                               /* SizeOfStackCommit */
> +        .quad   0                               /* SizeOfHeapReserve */
> +        .quad   0                               /* SizeOfHeapCommit */
> +        .long   0                               /* LoaderFlags */
> +        .long   0x6                             /* NumberOfRvaAndSizes */
> +
> +        .quad   0                               /* ExportTable */
> +        .quad   0                               /* ImportTable */
> +        .quad   0                               /* ResourceTable */
> +        .quad   0                               /* ExceptionTable */
> +        .quad   0                               /* CertificationTable */
> +        .quad   0                               /* BaseRelocationTable */
> +
> +        /* Section table */
> +section_table:
>  
> +        /*
> +         * The EFI application loader requires a relocation section
> +         * because EFI applications must be relocatable.  This is a
> +         * dummy section as far as we are concerned.
> +         */
> +        .ascii  ".reloc"
> +        .byte   0
> +        .byte   0                               /* end of 0 padding of section name */
> +        .long   0
> +        .long   0
> +        .long   0                               /* SizeOfRawData */
> +        .long   0                               /* PointerToRawData */
> +        .long   0                               /* PointerToRelocations */
> +        .long   0                               /* PointerToLineNumbers */
> +        .short  0                               /* NumberOfRelocations */
> +        .short  0                               /* NumberOfLineNumbers */
> +        .long   0x42100040                      /* Characteristics (section flags) */
> +
> +
> +        .ascii  ".text"
> +        .byte   0
> +        .byte   0
> +        .byte   0                               /* end of 0 padding of section name */
> +        .long   _end - real_start               /* VirtualSize */
> +        .long   real_start - efi_head           /* VirtualAddress */
> +        .long   __init_end_efi - real_start     /* SizeOfRawData */
> +        .long   real_start - efi_head           /* PointerToRawData */
> +
> +        .long   0                /* PointerToRelocations (0 for executables) */
> +        .long   0                /* PointerToLineNumbers (0 for executables) */
> +        .short  0                /* NumberOfRelocations  (0 for executables) */
> +        .short  0                /* NumberOfLineNumbers  (0 for executables) */
> +        .long   0xe0500020       /* Characteristics (section flags) */
> +        .align  5
>  real_start:
>          msr   DAIFSet, 0xf           /* Disable all interrupts */
>  
> @@ -617,6 +730,37 @@ putn:   ret
>  ENTRY(lookup_processor_type)
>          mov  x0, #0
>          ret
> +/*
> + *  Function to transition from EFI loader in C, to Xen entry point.
> + *  void noreturn efi_xen_start(void *fdt_ptr);
> + */
> +ENTRY(efi_xen_start)
> +        /*
> +         * Turn off cache and MMU as Xen expects. EFI enables them, but also
> +         * mandates a 1:1 (unity) VA->PA mapping, so we can turn off the
> +         * MMU while executing EFI code before entering Xen.
> +         * The EFI loader calls this to start Xen.
> +         * Preserve x0 (fdf pointer) across call to __flush_dcache_all,
> +         * restore for entry into Xen.
> +         */
> +        mov   x20, x0
> +        bl    __flush_dcache_all
> +        ic    ialluis
> +
> +        /* Turn off Dcache and MMU */
> +        mrs   x0, sctlr_el2
> +        bic   x0, x0, #1 << 0        /* clear SCTLR.M */
> +        bic   x0, x0, #1 << 2        /* clear SCTLR.C */

dsb?


> +        msr   sctlr_el2, x0
> +        isb
> +
> +        /* Jump to Xen entry point */
> +        mov   x0, x20
> +        mov   x1, xzr
> +        mov   x2, xzr
> +        mov   x3, xzr
> +        b     real_start
> +ENDPROC(efi_xen_start)
>  
>  /*
>   * Local variables:
> diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
> index 079e085..d8b0cfe 100644
> --- a/xen/arch/arm/xen.lds.S
> +++ b/xen/arch/arm/xen.lds.S
> @@ -135,6 +135,7 @@ SECTIONS
>         *(.xsm_initcall.init)
>         __xsm_initcall_end = .;
>    } :text
> +  __init_end_efi = .;
>    . = ALIGN(STACK_SIZE);
>    __init_end = .;
>  
> diff --git a/xen/common/Makefile b/xen/common/Makefile
> index 3683ae3..e78cb29 100644
> --- a/xen/common/Makefile
> +++ b/xen/common/Makefile
> @@ -67,4 +67,5 @@ subdir-$(x86_64) += hvm
>  subdir-$(coverage) += gcov
>  
>  subdir-y += libelf
> +subdir-$(CONFIG_EFI) += efi
>  subdir-$(HAS_DEVICE_TREE) += libfdt
> diff --git a/xen/common/efi/Makefile b/xen/common/efi/Makefile
> new file mode 100644
> index 0000000..195b2f3
> --- /dev/null
> +++ b/xen/common/efi/Makefile
> @@ -0,0 +1,3 @@
> +CFLAGS += -fshort-wchar
> +
> +obj-y += boot.init.o
> diff --git a/xen/include/asm-arm/arm64/efibind.h b/xen/include/asm-arm/arm64/efibind.h
> new file mode 100644
> index 0000000..2b0bf40
> --- /dev/null
> +++ b/xen/include/asm-arm/arm64/efibind.h
> @@ -0,0 +1,216 @@
> +/*++
> +
> +Copyright (c) 1998  Intel Corporation
> +
> +Module Name:
> +
> +    efefind.h
> +
> +Abstract:
> +
> +    EFI to compile bindings
> +
> +
> +
> +
> +Revision History
> +
> +--*/
> +
> +#ifndef __GNUC__
> +#pragma pack()
> +#endif
> +
> +#define EFIERR(a)           (0x8000000000000000 | a)
> +#define EFI_ERROR_MASK      0x8000000000000000
> +#define EFIERR_OEM(a)       (0xc000000000000000 | a)
> +
> +#define BAD_POINTER         0xFBFBFBFBFBFBFBFB
> +#define MAX_ADDRESS         0xFFFFFFFFFFFFFFFF
> +
> +#define EFI_STUB_ERROR      MAX_ADDRESS
> +
> +#ifndef __ASSEMBLY__
> +//
> +// Basic int types of various widths
> +//
> +
> +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )
> +
> +    // No ANSI C 1999/2000 stdint.h integer width declarations
> +
> +    #if defined(__GNUC__)
> +        typedef unsigned long long  uint64_t __attribute__((aligned (8)));
> +        typedef long long           int64_t __attribute__((aligned (8)));
> +        typedef unsigned int        uint32_t;
> +        typedef int                 int32_t;
> +        typedef unsigned short      uint16_t;
> +        typedef short               int16_t;
> +        typedef unsigned char       uint8_t;
> +        typedef char                int8_t;
> +    #elif defined(UNIX_LP64)
> +
> +        /*  Use LP64 programming model from C_FLAGS for integer width declarations */
> +
> +       typedef unsigned long       uint64_t;
> +       typedef long                int64_t;
> +       typedef unsigned int        uint32_t;
> +       typedef int                 int32_t;
> +       typedef unsigned short      uint16_t;
> +       typedef short               int16_t;
> +       typedef unsigned char       uint8_t;
> +       typedef char                int8_t;
> +    #else
> +
> +       /*  Assume P64 programming model from C_FLAGS for integer width declarations */
> +
> +       typedef unsigned long long  uint64_t __attribute__((aligned (8)));
> +       typedef long long           int64_t __attribute__((aligned (8)));
> +       typedef unsigned int        uint32_t;
> +       typedef int                 int32_t;
> +       typedef unsigned short      uint16_t;
> +       typedef short               int16_t;
> +       typedef unsigned char       uint8_t;
> +       typedef char                int8_t;
> +    #endif
> +#endif
> +
> +//
> +// Basic EFI types of various widths
> +//
> +
> +#ifndef __WCHAR_TYPE__
> +# define __WCHAR_TYPE__ short
> +#endif
> +
> +typedef uint64_t   UINT64;
> +typedef int64_t    INT64;
> +
> +#ifndef _BASETSD_H_
> +    typedef uint32_t   UINT32;
> +    typedef int32_t    INT32;
> +#endif
> +
> +typedef uint16_t   UINT16;
> +typedef int16_t    INT16;
> +typedef uint8_t    UINT8;
> +typedef int8_t     INT8;
> +typedef __WCHAR_TYPE__ WCHAR;
> +
> +#undef VOID
> +#define VOID    void
> +
> +
> +typedef int64_t    INTN;
> +typedef uint64_t   UINTN;
> +
> +#define POST_CODE(_Data)
> +
> +
> +#define BREAKPOINT()        while (TRUE);    // Make it hang on Bios[Dbg]32
> +
> +//
> +// Pointers must be aligned to these address to function
> +//
> +
> +#define MIN_ALIGNMENT_SIZE  4
> +
> +#define ALIGN_VARIABLE(Value ,Adjustment) \
> +            (UINTN)Adjustment = 0; \
> +            if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
> +                (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \
> +            Value = (UINTN)Value + (UINTN)Adjustment
> +
> +
> +//
> +// Define macros to build data structure signatures from characters.
> +//
> +
> +#define EFI_SIGNATURE_16(A,B)             ((A) | (B<<8))
> +#define EFI_SIGNATURE_32(A,B,C,D)         (EFI_SIGNATURE_16(A,B)     | (EFI_SIGNATURE_16(C,D)     << 16))
> +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
> +
> +#define EXPORTAPI
> +
> +
> +//
> +// EFIAPI - prototype calling convention for EFI function pointers
> +// BOOTSERVICE - prototype for implementation of a boot service interface
> +// RUNTIMESERVICE - prototype for implementation of a runtime service interface
> +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service
> +// RUNTIME_CODE - pragma macro for declaring runtime code
> +//
> +
> +#ifndef EFIAPI                  // Forces EFI calling conventions reguardless of compiler options
> +        #define EFIAPI          // Substitute expresion to force C calling convention
> +#endif
> +
> +#define BOOTSERVICE
> +//#define RUNTIMESERVICE(proto,a)    alloc_text("rtcode",a); proto a
> +//#define RUNTIMEFUNCTION(proto,a)   alloc_text("rtcode",a); proto a
> +#define RUNTIMESERVICE
> +#define RUNTIMEFUNCTION
> +
> +
> +#define RUNTIME_CODE(a)         alloc_text("rtcode", a)
> +#define BEGIN_RUNTIME_DATA()    data_seg("rtdata")
> +#define END_RUNTIME_DATA()      data_seg("")
> +
> +#define VOLATILE    volatile
> +
> +#define MEMORY_FENCE()
> +
> +
> +//
> +// When build similiar to FW, then link everything together as
> +// one big module.
> +//
> +
> +#define EFI_DRIVER_ENTRY_POINT(InitFunction)    \
> +    UINTN                                       \
> +    InitializeDriver (                          \
> +        VOID    *ImageHandle,                   \
> +        VOID    *SystemTable                    \
> +        )                                       \
> +    {                                           \
> +        return InitFunction(ImageHandle,        \
> +                SystemTable);                   \
> +    }                                           \
> +                                                \
> +    EFI_STATUS efi_main(                        \
> +        EFI_HANDLE image,                       \
> +        EFI_SYSTEM_TABLE *systab                \
> +        ) __attribute__((weak,                  \
> +                alias ("InitializeDriver")));
> +
> +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry)    \
> +        (_if)->LoadInternal(type, name, entry)
> +
> +
> +//
> +// Some compilers don't support the forward reference construct:
> +//  typedef struct XXXXX
> +//
> +// The following macro provide a workaround for such cases.
> +//
> +#ifdef NO_INTERFACE_DECL
> +#define INTERFACE_DECL(x)
> +#else
> +#ifdef __GNUC__
> +#define INTERFACE_DECL(x) struct x
> +#else
> +#define INTERFACE_DECL(x) typedef struct x
> +#endif
> +#endif
> +
> +#endif
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/asm-arm/efi-boot.h b/xen/include/asm-arm/efi-boot.h
> new file mode 100644
> index 0000000..2db0966
> --- /dev/null
> +++ b/xen/include/asm-arm/efi-boot.h
> @@ -0,0 +1,630 @@
> +/*
> + * Architecture specific implementation for EFI boot code.  This file
> + * is intended to be included by XXX _only_, and therefore can define
> + * arch specific global variables.
> + */
> +#include <xen/libfdt/libfdt.h>
> +#include <asm/setup.h>
> +
> +static void noreturn blexit(const CHAR16 *str);
> +static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
> +void noreturn efi_xen_start(void *fdt_ptr);
> +
> +#define DEVICE_TREE_GUID \
> +{0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0}}
> +
> +static struct file __initdata dtbfile;
> +static void __initdata *fdt;
> +static void __initdata *memmap;
> +
> +static int __init setup_chosen_node(void *fdt, int *addr_cells, int *size_cells)
> +{
> +    int node;
> +    const struct fdt_property *prop;
> +    int len;
> +    uint32_t val;
> +
> +    if ( !fdt || !addr_cells || !size_cells )
> +        return -1;
> +
> +    /* locate chosen node, which is where we add Xen module info. */
> +    node = fdt_subnode_offset(fdt, 0, "chosen");
> +    if ( node < 0 )
> +    {
> +        node = fdt_add_subnode(fdt, 0, "chosen");
> +        if ( node < 0 )
> +            return node;
> +    }
> +
> +    /* Get or set #address-cells and #size-cells */
> +    prop = fdt_get_property(fdt, node, "#address-cells", &len);
> +    if ( !prop )
> +    {
> +        val = cpu_to_fdt32(2);
> +        if ( fdt_setprop(fdt, node, "#address-cells", &val, sizeof(val)) )
> +            return -1;
> +        *addr_cells = 2;
> +    }
> +    else
> +        *addr_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
> +
> +    prop = fdt_get_property(fdt, node, "#size-cells", &len);
> +    if ( !prop )
> +    {
> +        val = cpu_to_fdt32(2);
> +        if ( fdt_setprop(fdt, node, "#size-cells", &val, sizeof(val)) )
> +            return -1;
> +        *size_cells = 2;
> +    }
> +    else
> +        *size_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
> +
> +    /*
> +     * Make sure ranges is empty if it exists, otherwise create empty ranges
> +     * property.
> +     */
> +    prop = fdt_get_property(fdt, node, "ranges", &len);
> +    if ( !prop )
> +    {
> +        val = cpu_to_fdt32(0);
> +        if ( fdt_setprop(fdt, node, "ranges", &val, 0) )
> +            return -1;
> +    }
> +    else if ( fdt32_to_cpu(prop->len) )
> +            return -1;  /* Non-empty ranges property */
> +    return node;
> +}
> +
> +/*
> + * Set a single 'reg' property taking into account the
> + * configured addr and size cell sizes.
> + */
> +static int __init fdt_set_reg(void *fdt, int node, int addr_cells,
> +                              int size_cells, uint64_t addr, uint64_t len)
> +{
> +    uint8_t data[16]; /* at most 2 64 bit words */
> +    void *p = data;
> +
> +    /* Make sure that the values provided can be represented in
> +     * the reg property.
> +     */
> +    if ( addr_cells == 1 && (addr >> 32) )
> +        return -1;
> +    if ( size_cells == 1 && (len >> 32) )
> +        return -1;
> +
> +    if ( addr_cells == 1 )
> +    {
> +        *(uint32_t *)p = cpu_to_fdt32(addr);
> +        p += sizeof(uint32_t);
> +    }
> +    else if ( addr_cells == 2 )
> +    {
> +        *(uint64_t *)p = cpu_to_fdt64(addr);
> +        p += sizeof(uint64_t);
> +    }
> +    else
> +        return -1;
> +
> +    if ( size_cells == 1 )
> +    {
> +        *(uint32_t *)p = cpu_to_fdt32(len);
> +        p += sizeof(uint32_t);
> +    }
> +    else if ( size_cells == 2 )
> +    {
> +        *(uint64_t *)p = cpu_to_fdt64(len);
> +        p += sizeof(uint64_t);
> +    }
> +    else
> +        return -1;
> +
> +    return(fdt_setprop(fdt, node, "reg", data, p - (void *)data));
> +}
> +
> +static void __init *lookup_fdt_config_table(EFI_SYSTEM_TABLE *sys_table)
> +{
> +    const EFI_GUID fdt_guid = DEVICE_TREE_GUID;
> +    EFI_CONFIGURATION_TABLE *tables;
> +    void *fdt = NULL;
> +    int i;
> +
> +    tables = sys_table->ConfigurationTable;
> +    for ( i = 0; i < sys_table->NumberOfTableEntries; i++ )
> +    {
> +        if ( match_guid(&tables[i].VendorGuid, &fdt_guid) )
> +        {
> +            fdt = tables[i].VendorTable;
> +            break;
> +        }
> +    }
> +    return fdt;
> +}
> +
> +static EFI_STATUS __init efi_get_memory_map(void **map,
> +                                            UINTN *mmap_size,
> +                                            UINTN *desc_size,
> +                                            UINT32 *desc_ver,
> +                                            UINTN *key_ptr)
> +{
> +    EFI_MEMORY_DESCRIPTOR *m = NULL;
> +    EFI_STATUS status;
> +    unsigned long key;
> +    u32 desc_version;
> +
> +    *map = NULL;
> +    *mmap_size = EFI_PAGE_SIZE;
> +again:
> +    *mmap_size += EFI_PAGE_SIZE;  /* Page size is allocation granularity */
> +    status = efi_bs->AllocatePool(EfiLoaderData, *mmap_size, (void **)&m);
> +    if ( status != EFI_SUCCESS )
> +        return status;
> +
> +    *desc_size = 0;
> +    key = 0;
> +    status = efi_bs->GetMemoryMap(mmap_size, m, &key, desc_size, &desc_version);
> +    if ( status == EFI_BUFFER_TOO_SMALL )
> +    {
> +        efi_bs->FreePool(m);
> +        goto again;
> +    }
> +
> +    if ( status != EFI_SUCCESS )
> +    {
> +        efi_bs->FreePool(m);
> +        return status;
> +    }
> +
> +    if ( key_ptr && status == EFI_SUCCESS )
> +        *key_ptr = key;
> +    if ( desc_ver && status == EFI_SUCCESS )
> +        *desc_ver = desc_version;
> +
> +    *map = m;
> +    return status;
> +}
> +
> +static EFI_STATUS __init efi_process_memory_map_bootinfo(EFI_MEMORY_DESCRIPTOR *map,
> +                                                UINTN mmap_size,
> +                                                UINTN desc_size)
> +{
> +    int Index;
> +    int i = 0;
> +
> +    EFI_MEMORY_DESCRIPTOR *desc_ptr = map;
> +
> +    for ( Index = 0; Index < (mmap_size / desc_size); Index++ )
> +    {
> +        if ( desc_ptr->Type == EfiConventionalMemory
> +             || desc_ptr->Type == EfiBootServicesCode
> +             || desc_ptr->Type == EfiBootServicesData )
> +        {
> +            bootinfo.mem.bank[i].start = desc_ptr->PhysicalStart;
> +            bootinfo.mem.bank[i].size = desc_ptr->NumberOfPages * EFI_PAGE_SIZE;
> +            if ( ++i >= NR_MEM_BANKS )
> +            {
> +                PrintStr(L"Warning: All ");
> +                DisplayUint(NR_MEM_BANKS, -1);
> +                PrintStr(L" bootinfo mem banks exhausted.\r\n");
> +                break;
> +            }
> +        }
> +        desc_ptr = NextMemoryDescriptor(desc_ptr, desc_size);
> +    }
> +
> +    bootinfo.mem.nr_banks = i;
> +    return EFI_SUCCESS;
> +
> +}
> +
> +/*
> + * Add the FDT nodes for the standard EFI information, which consist
> + * of the System table address, the address of the final EFI memory map,
> + * and memory map information.
> + */
> +EFI_STATUS __init fdt_add_uefi_nodes(EFI_SYSTEM_TABLE *sys_table,
> +                                            void *fdt,
> +                                            EFI_MEMORY_DESCRIPTOR *memory_map,
> +                                            UINTN map_size,
> +                                            UINTN desc_size,
> +                                            UINT32 desc_ver)
> +{
> +    int node;
> +    int status;
> +    u32 fdt_val32;
> +    u64 fdt_val64;
> +    int prev;
> +    /*
> +     * Delete any memory nodes present.  The EFI memory map is the only
> +     * memory description provided to Xen.
> +     */
> +    prev = 0;
> +    for (;;)
> +    {
> +        const char *type;
> +        int len;
> +
> +        node = fdt_next_node(fdt, prev, NULL);
> +        if ( node < 0 )
> +            break;
> +
> +        type = fdt_getprop(fdt, node, "device_type", &len);
> +        if ( type && strncmp(type, "memory", len) == 0 )
> +        {
> +            fdt_del_node(fdt, node);
> +            continue;
> +        }
> +
> +        prev = node;
> +    }
> +
> +    /* Add FDT entries for EFI runtime services in chosen node. */
> +    node = fdt_subnode_offset(fdt, 0, "chosen");
> +    if ( node < 0 )
> +    {
> +        node = fdt_add_subnode(fdt, 0, "chosen");
> +        if ( node < 0 )
> +        {
> +            status = node; /* node is error code when negative */
> +            goto fdt_set_fail;
> +        }
> +    }

setup_chosen_node?


> +    fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)sys_table);
> +    status = fdt_setprop(fdt, node, "linux,uefi-system-table",
> +                         &fdt_val64, sizeof(fdt_val64));
> +    if ( status )
> +        goto fdt_set_fail;
> +
> +    fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)memory_map);
> +    status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
> +                         &fdt_val64,  sizeof(fdt_val64));
> +    if ( status )
> +        goto fdt_set_fail;
> +
> +    fdt_val32 = cpu_to_fdt32(map_size);
> +    status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
> +                         &fdt_val32,  sizeof(fdt_val32));
> +    if ( status )
> +        goto fdt_set_fail;
> +
> +    fdt_val32 = cpu_to_fdt32(desc_size);
> +    status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
> +                         &fdt_val32, sizeof(fdt_val32));
> +    if ( status )
> +        goto fdt_set_fail;
> +
> +    fdt_val32 = cpu_to_fdt32(desc_ver);
> +    status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
> +                         &fdt_val32, sizeof(fdt_val32));
> +    if ( status )
> +        goto fdt_set_fail;
> +
> +    return EFI_SUCCESS;
> +
> +fdt_set_fail:
> +    if ( status == -FDT_ERR_NOSPACE )
> +        return EFI_BUFFER_TOO_SMALL;
> +
> +    return EFI_LOAD_ERROR;
> +}
> +
> +/*
> + * Allocates new memory for a larger FDT, and frees existing memory if
> + * struct file size is non-zero.  Updates file struct with new memory
> + * address/size for later freeing.  If fdtfile.ptr is NULL, an empty FDT
> + * is created.
> + */
> +static void __init *fdt_increase_size(struct file *fdtfile, int add_size)
> +{
> +    EFI_STATUS status;
> +    EFI_PHYSICAL_ADDRESS fdt_addr;
> +    int fdt_size;
> +    int pages;
> +    void *new_fdt;
> +
> +    if ( fdtfile->ptr )
> +        fdt_size = fdt_totalsize(fdtfile->ptr);
> +    else
> +        fdt_size = 0;
> +
> +    pages = PFN_UP(fdt_size) + PFN_UP(add_size);

Shouldn't this be PFN_UP(fdt_size+add_size)?


> +    status = efi_bs->AllocatePages(AllocateAnyPages, EfiLoaderData,
> +                                   pages, &fdt_addr);
> +
> +    if ( status != EFI_SUCCESS )
> +        return NULL;
> +
> +    new_fdt = (void *)fdt_addr;
> +
> +    if ( fdt_size )
> +    {
> +        if ( fdt_open_into(dtbfile.ptr, new_fdt, pages * EFI_PAGE_SIZE) )
> +            return NULL;
> +    }
> +    else
> +    {
> +        /*
> +         * Create an empty FDT if not provided one, which is the expected case
> +         * when booted from the UEFI shell on an ACPI only system.  We will use
> +         * the FDT to pass the EFI information to Xen, as well as nodes for
> +         * any modules the stub loads.  The ACPI tables are part of the UEFI
> +         * system table that is passed in the FDT.
> +         */
> +        if ( fdt_create_empty_tree(new_fdt, pages * EFI_PAGE_SIZE) )
> +            return NULL;
> +    }
> +
> +    /*
> +     * Now that we have the new FDT allocated and copied, free the
> +     * original and update the struct file so that the error handling
> +     * code will free it.  If the original FDT came from a configuration
> +     * table, we don't own that memory and can't free it.
> +     */
> +    if ( dtbfile.size )
> +        efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
> +
> +    /* Update 'file' info for new memory so we clean it up on error exits */
> +    dtbfile.addr = fdt_addr;
> +    dtbfile.size = pages * EFI_PAGE_SIZE;
> +    return new_fdt;
> +}
> +
> +static void __init efi_arch_pci(void)
> +{
> +}
> +
> +static void __init efi_arch_relocate_image(unsigned long delta)
> +{
> +}
> +
> +static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
> +                                               void *map,
> +                                               UINTN map_size,
> +                                               UINTN desc_size,
> +                                               UINT32 desc_ver)
> +{
> +    EFI_STATUS status;
> +
> +    status = efi_process_memory_map_bootinfo(map, map_size, desc_size);
> +    if ( EFI_ERROR(status) )
> +        blexit(L"ERROR processing EFI memory map\r\n");
> +
> +    status = fdt_add_uefi_nodes(SystemTable, fdt, map, map_size, desc_size,
> +                                desc_ver);
> +    if ( EFI_ERROR(status) )
> +        PrintErrMesg(L"ERROR updating FDT\r\n", status);
> +}
> +
> +static void __init efi_arch_pre_exit_boot(void)
> +{
> +}
> +
> +static void __init efi_arch_post_exit_boot(void)
> +{
> +    efi_xen_start(fdt);
> +}
> +
> +static void __init efi_arch_cfg_file(EFI_FILE_HANDLE dir_handle, char *section)
> +{
> +    union string name;
> +    name.s = get_value(&cfg, section, "dtb");
> +    if ( name.s )
> +    {
> +        if ( !read_file(dir_handle, &dtbfile, name.s))
> +            blexit(NULL);
> +    }
> +    fdt = fdt_increase_size(&dtbfile, cfg.size + EFI_PAGE_SIZE);
> +    if ( !fdt )
> +        blexit(L"Unable to create new FDT\r\n");
> +}
> +
> +static void __init efi_arch_get_memory_map(UINTN *map_size,
> +                                             void **map,
> +                                             UINTN *map_key, UINTN *desc_size,
> +                                             UINT32 *desc_ver)
> +{
> +    EFI_STATUS status;
> +
> +    status = efi_get_memory_map(map, map_size, desc_size, desc_ver, map_key);
> +    if ( EFI_ERROR(status) )
> +        blexit(L"ERROR getting EFI memory map.\r\n");
> +    memmap = *map;
> +}
> +
> +static void __init efi_arch_edd(void)
> +{
> +}
> +
> +static void __init efi_arch_video(bool_t base_video,
> +                                  UINTN cols, UINTN rows, UINTN depth,
> +                                  EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
> +{
> +}
> +
> +static void __init efi_arch_memory(void)
> +{
> +}
> +
> +static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
> +                                           CHAR16 *cmdline_options,
> +                                           char *cfgfile_options)
> +{
> +    union string name;
> +    char *buf;
> +    EFI_STATUS status;
> +    int prop_len;
> +    int chosen;
> +
> +    /* locate chosen node, which is where we add Xen module info. */
> +    chosen = fdt_subnode_offset(fdt, 0, "chosen");
> +    if ( chosen < 0 )
> +        blexit(L"ERROR unable to find chosen node\r\n");
> +
> +    status = efi_bs->AllocatePool(EfiBootServicesData, EFI_PAGE_SIZE, (void **)&buf);
> +    if ( EFI_ERROR(status) )
> +        PrintErrMesg(L"ERROR allocating memory.\r\n", status);
> +
> +    if ( image_name )
> +    {
> +        name.w = image_name;
> +        w2s(&name);
> +    }
> +    else
> +        name.s = "xen";
> +
> +    prop_len = 0;
> +    prop_len += snprintf(buf + prop_len,
> +                           EFI_PAGE_SIZE - prop_len, "%s", name.s);
> +    if ( prop_len >= EFI_PAGE_SIZE )
> +        blexit(L"FDT string overflow");
> +
> +    if ( cfgfile_options )
> +    {
> +        prop_len += snprintf(buf + prop_len,
> +                               EFI_PAGE_SIZE - prop_len, " %s", cfgfile_options);
> +        if ( prop_len >= EFI_PAGE_SIZE )
> +            blexit(L"FDT string overflow");
> +    }
> +
> +    if ( cmdline_options )
> +    {
> +        name.w = cmdline_options;
> +        w2s(&name);
> +    }
> +    else
> +        name.s = NULL;
> +
> +    if ( name.s )
> +    {
> +        prop_len += snprintf(buf + prop_len,
> +                               EFI_PAGE_SIZE - prop_len, " %s", name.s);
> +        if ( prop_len >= EFI_PAGE_SIZE )
> +            blexit(L"FDT string overflow");
> +    }
> +
> +    if ( fdt_setprop_string(fdt, chosen, "xen,xen-bootargs", buf) < 0 )
> +        blexit(L"unable to set xen,xen-bootargs property.");
> +
> +    efi_bs->FreePool(buf);
> +}
> +
> +static void __init efi_arch_handle_module(struct file *file, char *name,
> +                                          char *options)
> +{
> +    int node;
> +    int chosen;
> +    int addr_len, size_len;
> +
> +    if ( file == &dtbfile )
> +        return;
> +    chosen = setup_chosen_node(fdt, &addr_len, &size_len);
> +    if ( chosen < 0 )
> +        blexit(L"Unable to setup chosen node\r\n");
> +
> +    if ( file == &ramdisk )
> +    {
> +        char ramdisk_compat[] = "multiboot,ramdisk\0multiboot,module";
> +        node = fdt_add_subnode(fdt, chosen, "ramdisk");
> +        if ( node < 0 )
> +            blexit(L"Error adding ramdisk FDT node.");
> +        if ( fdt_setprop(fdt, node, "compatible", ramdisk_compat,
> +                         sizeof(ramdisk_compat)) < 0 )
> +            blexit(L"unable to set compatible property.");
> +        if ( fdt_set_reg(fdt, node, addr_len, size_len, ramdisk.addr,
> +                    ramdisk.size) < 0 )
> +            blexit(L"unable to set reg property.");
> +    }
> +    else if ( file == &xsm )
> +    {
> +        char xsm_compat[] = "xen,xsm-policy\0multiboot,module";
> +        node = fdt_add_subnode(fdt, chosen, "xsm");
> +        if ( node < 0 )
> +            blexit(L"Error adding xsm FDT node.");
> +        if ( fdt_setprop(fdt, node, "compatible", xsm_compat,
> +                         sizeof(xsm_compat)) < 0 )
> +            blexit(L"unable to set compatible property.");
> +        if ( fdt_set_reg(fdt, node, addr_len, size_len, xsm.addr,
> +                    xsm.size) < 0 )
> +            blexit(L"unable to set reg property.");
> +    }
> +    else if ( file == &kernel )
> +    {
> +        char kernel_compat[] = "multiboot,kernel\0multiboot,module";
> +        node = fdt_add_subnode(fdt, chosen, "kernel");
> +        if ( node < 0 )
> +            blexit(L"Error adding dom0 FDT node.");
> +        if ( fdt_setprop(fdt, node, "compatible", kernel_compat,
> +                         sizeof(kernel_compat)) < 0 )
> +            blexit(L"unable to set compatible property.");
> +        if ( options && fdt_setprop_string(fdt, node, "bootargs", options) < 0 )
> +            blexit(L"unable to set bootargs property.");
> +        if ( fdt_set_reg(fdt, node, addr_len, size_len, kernel.addr,
> +                         kernel.size) < 0 )
> +            blexit(L"unable to set reg property.");
> +    }
> +    else
> +        blexit(L"Unknown module type\r\n");
> +}
> +
> +static void __init efi_arch_cpu(void)
> +{
> +}
> +
> +static void __init efi_arch_smbios(void)
> +{
> +}
> +
> +static void __init efi_arch_blexit(void)
> +{
> +    if ( dtbfile.addr && dtbfile.size )
> +        efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
> +    if ( memmap )
> +        efi_bs->FreePool(memmap);
> +}
> +
> +static void __init efi_arch_load_addr_check(EFI_LOADED_IMAGE *loaded_image)
> +{
> +    if ( (unsigned long)loaded_image->ImageBase & ((1 << 12) - 1) )
> +        blexit(L"Xen must be loaded at a 4 KByte boundary.");
> +}
> +
> +static void __init efi_arch_runtime_setup(EFI_SYSTEM_TABLE *SystemTable)
> +{
> +}
> +
> +static __init bool_t efi_arch_use_config_file(EFI_SYSTEM_TABLE *SystemTable)
> +{
> +    /*
> +     * For arm, we may get a device tree from GRUB (or other bootloader)
> +     * that contains modules that have already been loaded into memory.  In
> +     * this case, we do not use a configuration file, and rely on the
> +     * bootloader to have loaded all required modules and appropriate
> +     * options.
> +     */
> +
> +    fdt = lookup_fdt_config_table(SystemTable);
> +    dtbfile.ptr = fdt;
> +    dtbfile.size = 0;  /* Config table memory can't be freed, so set size to 0 */
> +    if ( !fdt || fdt_node_offset_by_compatible(fdt, 0, "multiboot,module") < 0 )
> +    {
> +        /*
> +         * We either have no FDT, or one without modules, so we must have a
> +         * Xen EFI configuration file to specify modules.  (dom0 required)
> +         */
> +        return 1;
> +    }
> +    PrintStr(L"Using modules provided by bootloader in FDT\r\n");
> +    /* We have modules already defined in fdt, just add space. */
> +    fdt = fdt_increase_size(&dtbfile, EFI_PAGE_SIZE);
> +    return 0;
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/asm-arm/efi.h b/xen/include/asm-arm/efi.h
> new file mode 100644
> index 0000000..aae4716
> --- /dev/null
> +++ b/xen/include/asm-arm/efi.h
> @@ -0,0 +1,29 @@
> +#include <asm/efibind.h>
> +#include <efi/efidef.h>
> +#include <efi/efierr.h>
> +#include <efi/eficon.h>
> +#include <efi/efidevp.h>
> +#include <efi/eficapsule.h>
> +#include <efi/efiapi.h>
> +#include <xen/efi.h>
> +#include <xen/spinlock.h>
> +#include <asm/page.h>
> +
> +extern unsigned int efi_num_ct;
> +extern EFI_CONFIGURATION_TABLE *efi_ct;
> +
> +extern unsigned int efi_version, efi_fw_revision;
> +extern const CHAR16 *efi_fw_vendor;
> +
> +extern EFI_RUNTIME_SERVICES *efi_rs;
> +
> +extern UINTN efi_memmap_size, efi_mdesc_size;
> +extern void *efi_memmap;
> +
> +extern const struct efi_pci_rom *efi_pci_roms;
> +
> +extern UINT64 efi_boot_max_var_store_size, efi_boot_remain_var_store_size,
> +              efi_boot_max_var_size;
> +
> +unsigned long efi_rs_enter(void);
> +void efi_rs_leave(unsigned long);
> diff --git a/xen/include/asm-arm/efibind.h b/xen/include/asm-arm/efibind.h
> new file mode 100644
> index 0000000..09dca7a
> --- /dev/null
> +++ b/xen/include/asm-arm/efibind.h
> @@ -0,0 +1,2 @@
> +#include <xen/types.h>
> +#include <asm/arm64/efibind.h>
> diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> index 36e5704..40814e6 100644
> --- a/xen/include/asm-arm/setup.h
> +++ b/xen/include/asm-arm/setup.h
> @@ -3,7 +3,7 @@
>  
>  #include <public/version.h>
>  
> -#define NR_MEM_BANKS 8
> +#define NR_MEM_BANKS 32

Why?
At the very least you should write it in the commit message.


>  #define MAX_MODULES 5 /* Current maximum useful modules */
>  
> -- 
> 2.1.0.rc1
> 

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-12  0:49   ` Stefano Stabellini
@ 2014-09-12  3:21     ` Roy Franz
  2014-09-12 17:41       ` Stefano Stabellini
  0 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-12  3:21 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini,
	Jan Beulich, Fu Wei


[-- Attachment #1.1: Type: text/plain, Size: 44423 bytes --]

On Thu, Sep 11, 2014 at 5:49 PM, Stefano Stabellini <
stefano.stabellini@eu.citrix.com> wrote:

> On Tue, 9 Sep 2014, Roy Franz wrote:
> > This patch adds EFI boot support for ARM based on the previous
> refactoring of
> > the x86 EFI boot code.  All ARM specific code is in the ARM efi-boot.h
> header
> > file, with the main EFI entry point common/efi/boot.c.  The PE/COFF
> header is
> > open-coded in head.S, which allows us to have a single binary be both an
> EFI
> > executable and a normal arm64 IMAGE file. There is currently no PE/COFF
> > toolchain support for arm64, so it is not possible to create the PE/COFF
> header
> > in the same manner as on x86.  This also simplifies the build as
> compared to
> > x86, as we always build the same executable, whereas x86 builds 2.  An
> ARM
> > version of efi-bind.h is added, which is based on the x86_64 version
> with the
> > x86 specific portions removed.  The Makefile in common/efi is different
> for x86
> > and ARM, as for ARM we always build in EFI support.
> >
> > Signed-off-by: Roy Franz <roy.franz@linaro.org>
> > ---
> >  config/arm64.mk                     |   1 +
> >  xen/arch/arm/arm64/head.S           | 150 ++++++++-
> >  xen/arch/arm/xen.lds.S              |   1 +
> >  xen/common/Makefile                 |   1 +
> >  xen/common/efi/Makefile             |   3 +
> >  xen/include/asm-arm/arm64/efibind.h | 216 +++++++++++++
> >  xen/include/asm-arm/efi-boot.h      | 630
> ++++++++++++++++++++++++++++++++++++
> >  xen/include/asm-arm/efi.h           |  29 ++
> >  xen/include/asm-arm/efibind.h       |   2 +
> >  xen/include/asm-arm/setup.h         |   2 +-
> >  10 files changed, 1031 insertions(+), 4 deletions(-)
> >  create mode 100644 xen/common/efi/Makefile
> >  create mode 100644 xen/include/asm-arm/arm64/efibind.h
> >  create mode 100644 xen/include/asm-arm/efi-boot.h
> >  create mode 100644 xen/include/asm-arm/efi.h
> >  create mode 100644 xen/include/asm-arm/efibind.h
> >
> > diff --git a/config/arm64.mk b/config/arm64.mk
> > index 15b57a4..e6aab0e 100644
> > --- a/config/arm64.mk
> > +++ b/config/arm64.mk
> > @@ -1,6 +1,7 @@
> >  CONFIG_ARM := y
> >  CONFIG_ARM_64 := y
> >  CONFIG_ARM_$(XEN_OS) := y
> > +CONFIG_EFI := y
> >
> >  CONFIG_XEN_INSTALL_SUFFIX :=
> >
> > diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
> > index 43b5e72..158c102 100644
> > --- a/xen/arch/arm/arm64/head.S
> > +++ b/xen/arch/arm/arm64/head.S
> > @@ -24,6 +24,8 @@
> >  #include <asm/page.h>
> >  #include <asm/asm_defns.h>
> >  #include <asm/early_printk.h>
> > +#include <efi/efierr.h>
> > +#include <asm/arm64/efibind.h>
> >
> >  #define PT_PT     0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1
> */
> >  #define PT_MEM    0xf7d /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=0 P=1
> */
> > @@ -104,8 +106,14 @@ GLOBAL(start)
> >          /*
> >           * DO NOT MODIFY. Image header expected by Linux boot-loaders.
> >           */
> > -        b       real_start           /* branch to kernel start, magic */
> > -        .long   0                    /* reserved */
> > +efi_head:
> > +        /*
> > +         * This add instruction has no meaningful effect except that
> > +         * its opcode forms the magic "MZ" signature of a PE/COFF file
> > +         * that is required for UEFI applications.
> > +         */
> > +        add     x13, x18, #0x16
> > +        b       real_start           /* branch to kernel start */
> >          .quad   0                    /* Image load offset from start of
> RAM */
> >          .quad   0                    /* reserved */
> >          .quad   0                    /* reserved */
> > @@ -116,8 +124,113 @@ GLOBAL(start)
> >          .byte   0x52
> >          .byte   0x4d
> >          .byte   0x64
> > -        .word   0                    /* reserved */
> > +        .long   pe_header - efi_head        /* Offset to the PE header.
> */
> > +
> > +        /*
> > +         * Add the PE/COFF header to the file.  The address of this
> header
> > +         * is at offset 0x3c in the file, and is part of Linux "Image"
> > +         * header.  The arm64 Linux Image format is designed to support
> > +         * being both an 'Image' format binary and a PE/COFF binary.
> > +         * The PE/COFF format is defined by Microsoft, and is available
> > +         * from: http://msdn.microsoft.com/en-us/gg463119.aspx
> > +         * Version 8.3 adds support for arm64 and UEFI usage.
> > +         */
> > +
> > +        .align  3
> > +pe_header:
> > +        .ascii  "PE"
> > +        .short  0
> > +coff_header:
> > +        .short  0xaa64                          /* AArch64 */
> > +        .short  2                               /* nr_sections */
> > +        .long   0                               /* TimeDateStamp */
> > +        .long   0                               /* PointerToSymbolTable
> */
> > +        .long   1                               /* NumberOfSymbols */
> > +        .short  section_table - optional_header /* SizeOfOptionalHeader
> */
> > +        .short  0x206                           /* Characteristics. */
> > +                                                /*
> IMAGE_FILE_DEBUG_STRIPPED | */
> > +                                                /*
> IMAGE_FILE_EXECUTABLE_IMAGE | */
> > +                                                /*
> IMAGE_FILE_LINE_NUMS_STRIPPED */
> > +optional_header:
> > +        .short  0x20b                           /* PE32+ format */
> > +        .byte   0x02                            /* MajorLinkerVersion */
> > +        .byte   0x14                            /* MinorLinkerVersion */
> > +        .long   _end - real_start               /* SizeOfCode */
> > +        .long   0                               /*
> SizeOfInitializedData */
> > +        .long   0                               /*
> SizeOfUninitializedData */
> > +        .long   efi_start - efi_head            /* AddressOfEntryPoint
> */
> > +        .long   real_start - efi_head           /* BaseOfCode */
> > +
> > +extra_header_fields:
> > +        .quad   0                               /* ImageBase */
> > +        .long   0x1000                          /* SectionAlignment (4
> KByte) */
> > +        .long   0x8                             /* FileAlignment */
> > +        .short  0                               /*
> MajorOperatingSystemVersion */
> > +        .short  0                               /*
> MinorOperatingSystemVersion */
> > +        .short  0                               /* MajorImageVersion */
> > +        .short  0                               /* MinorImageVersion */
> > +        .short  0                               /*
> MajorSubsystemVersion */
> > +        .short  0                               /*
> MinorSubsystemVersion */
> > +        .long   0                               /* Win32VersionValue */
> > +
> > +        .long   _end - efi_head                 /* SizeOfImage */
> > +
> > +        /* Everything before the kernel image is considered part of the
> header */
> > +        .long   real_start - efi_head           /* SizeOfHeaders */
> > +        .long   0                               /* CheckSum */
> > +        .short  0xa                             /* Subsystem (EFI
> application) */
> > +        .short  0                               /* DllCharacteristics */
> > +        .quad   0                               /* SizeOfStackReserve */
> > +        .quad   0                               /* SizeOfStackCommit */
> > +        .quad   0                               /* SizeOfHeapReserve */
> > +        .quad   0                               /* SizeOfHeapCommit */
> > +        .long   0                               /* LoaderFlags */
> > +        .long   0x6                             /* NumberOfRvaAndSizes
> */
> > +
> > +        .quad   0                               /* ExportTable */
> > +        .quad   0                               /* ImportTable */
> > +        .quad   0                               /* ResourceTable */
> > +        .quad   0                               /* ExceptionTable */
> > +        .quad   0                               /* CertificationTable */
> > +        .quad   0                               /* BaseRelocationTable
> */
> > +
> > +        /* Section table */
> > +section_table:
> >
> > +        /*
> > +         * The EFI application loader requires a relocation section
> > +         * because EFI applications must be relocatable.  This is a
> > +         * dummy section as far as we are concerned.
> > +         */
> > +        .ascii  ".reloc"
> > +        .byte   0
> > +        .byte   0                               /* end of 0 padding of
> section name */
> > +        .long   0
> > +        .long   0
> > +        .long   0                               /* SizeOfRawData */
> > +        .long   0                               /* PointerToRawData */
> > +        .long   0                               /* PointerToRelocations
> */
> > +        .long   0                               /* PointerToLineNumbers
> */
> > +        .short  0                               /* NumberOfRelocations
> */
> > +        .short  0                               /* NumberOfLineNumbers
> */
> > +        .long   0x42100040                      /* Characteristics
> (section flags) */
> > +
> > +
> > +        .ascii  ".text"
> > +        .byte   0
> > +        .byte   0
> > +        .byte   0                               /* end of 0 padding of
> section name */
> > +        .long   _end - real_start               /* VirtualSize */
> > +        .long   real_start - efi_head           /* VirtualAddress */
> > +        .long   __init_end_efi - real_start     /* SizeOfRawData */
> > +        .long   real_start - efi_head           /* PointerToRawData */
> > +
> > +        .long   0                /* PointerToRelocations (0 for
> executables) */
> > +        .long   0                /* PointerToLineNumbers (0 for
> executables) */
> > +        .short  0                /* NumberOfRelocations  (0 for
> executables) */
> > +        .short  0                /* NumberOfLineNumbers  (0 for
> executables) */
> > +        .long   0xe0500020       /* Characteristics (section flags) */
> > +        .align  5
> >  real_start:
> >          msr   DAIFSet, 0xf           /* Disable all interrupts */
> >
> > @@ -617,6 +730,37 @@ putn:   ret
> >  ENTRY(lookup_processor_type)
> >          mov  x0, #0
> >          ret
> > +/*
> > + *  Function to transition from EFI loader in C, to Xen entry point.
> > + *  void noreturn efi_xen_start(void *fdt_ptr);
> > + */
> > +ENTRY(efi_xen_start)
> > +        /*
> > +         * Turn off cache and MMU as Xen expects. EFI enables them, but
> also
> > +         * mandates a 1:1 (unity) VA->PA mapping, so we can turn off the
> > +         * MMU while executing EFI code before entering Xen.
> > +         * The EFI loader calls this to start Xen.
> > +         * Preserve x0 (fdf pointer) across call to __flush_dcache_all,
> > +         * restore for entry into Xen.
> > +         */
> > +        mov   x20, x0
> > +        bl    __flush_dcache_all
> > +        ic    ialluis
> > +
> > +        /* Turn off Dcache and MMU */
> > +        mrs   x0, sctlr_el2
> > +        bic   x0, x0, #1 << 0        /* clear SCTLR.M */
> > +        bic   x0, x0, #1 << 2        /* clear SCTLR.C */
>
> dsb?
>

The dsb is done at the end of  __flush_dcache_all


>
> > +        msr   sctlr_el2, x0
> > +        isb
> > +
> > +        /* Jump to Xen entry point */
> > +        mov   x0, x20
> > +        mov   x1, xzr
> > +        mov   x2, xzr
> > +        mov   x3, xzr
> > +        b     real_start
> > +ENDPROC(efi_xen_start)
> >
> >  /*
> >   * Local variables:
> > diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
> > index 079e085..d8b0cfe 100644
> > --- a/xen/arch/arm/xen.lds.S
> > +++ b/xen/arch/arm/xen.lds.S
> > @@ -135,6 +135,7 @@ SECTIONS
> >         *(.xsm_initcall.init)
> >         __xsm_initcall_end = .;
> >    } :text
> > +  __init_end_efi = .;
> >    . = ALIGN(STACK_SIZE);
> >    __init_end = .;
> >
> > diff --git a/xen/common/Makefile b/xen/common/Makefile
> > index 3683ae3..e78cb29 100644
> > --- a/xen/common/Makefile
> > +++ b/xen/common/Makefile
> > @@ -67,4 +67,5 @@ subdir-$(x86_64) += hvm
> >  subdir-$(coverage) += gcov
> >
> >  subdir-y += libelf
> > +subdir-$(CONFIG_EFI) += efi
> >  subdir-$(HAS_DEVICE_TREE) += libfdt
> > diff --git a/xen/common/efi/Makefile b/xen/common/efi/Makefile
> > new file mode 100644
> > index 0000000..195b2f3
> > --- /dev/null
> > +++ b/xen/common/efi/Makefile
> > @@ -0,0 +1,3 @@
> > +CFLAGS += -fshort-wchar
> > +
> > +obj-y += boot.init.o
> > diff --git a/xen/include/asm-arm/arm64/efibind.h
> b/xen/include/asm-arm/arm64/efibind.h
> > new file mode 100644
> > index 0000000..2b0bf40
> > --- /dev/null
> > +++ b/xen/include/asm-arm/arm64/efibind.h
> > @@ -0,0 +1,216 @@
> > +/*++
> > +
> > +Copyright (c) 1998  Intel Corporation
> > +
> > +Module Name:
> > +
> > +    efefind.h
> > +
> > +Abstract:
> > +
> > +    EFI to compile bindings
> > +
> > +
> > +
> > +
> > +Revision History
> > +
> > +--*/
> > +
> > +#ifndef __GNUC__
> > +#pragma pack()
> > +#endif
> > +
> > +#define EFIERR(a)           (0x8000000000000000 | a)
> > +#define EFI_ERROR_MASK      0x8000000000000000
> > +#define EFIERR_OEM(a)       (0xc000000000000000 | a)
> > +
> > +#define BAD_POINTER         0xFBFBFBFBFBFBFBFB
> > +#define MAX_ADDRESS         0xFFFFFFFFFFFFFFFF
> > +
> > +#define EFI_STUB_ERROR      MAX_ADDRESS
> > +
> > +#ifndef __ASSEMBLY__
> > +//
> > +// Basic int types of various widths
> > +//
> > +
> > +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )
> > +
> > +    // No ANSI C 1999/2000 stdint.h integer width declarations
> > +
> > +    #if defined(__GNUC__)
> > +        typedef unsigned long long  uint64_t __attribute__((aligned
> (8)));
> > +        typedef long long           int64_t __attribute__((aligned
> (8)));
> > +        typedef unsigned int        uint32_t;
> > +        typedef int                 int32_t;
> > +        typedef unsigned short      uint16_t;
> > +        typedef short               int16_t;
> > +        typedef unsigned char       uint8_t;
> > +        typedef char                int8_t;
> > +    #elif defined(UNIX_LP64)
> > +
> > +        /*  Use LP64 programming model from C_FLAGS for integer width
> declarations */
> > +
> > +       typedef unsigned long       uint64_t;
> > +       typedef long                int64_t;
> > +       typedef unsigned int        uint32_t;
> > +       typedef int                 int32_t;
> > +       typedef unsigned short      uint16_t;
> > +       typedef short               int16_t;
> > +       typedef unsigned char       uint8_t;
> > +       typedef char                int8_t;
> > +    #else
> > +
> > +       /*  Assume P64 programming model from C_FLAGS for integer width
> declarations */
> > +
> > +       typedef unsigned long long  uint64_t __attribute__((aligned
> (8)));
> > +       typedef long long           int64_t __attribute__((aligned (8)));
> > +       typedef unsigned int        uint32_t;
> > +       typedef int                 int32_t;
> > +       typedef unsigned short      uint16_t;
> > +       typedef short               int16_t;
> > +       typedef unsigned char       uint8_t;
> > +       typedef char                int8_t;
> > +    #endif
> > +#endif
> > +
> > +//
> > +// Basic EFI types of various widths
> > +//
> > +
> > +#ifndef __WCHAR_TYPE__
> > +# define __WCHAR_TYPE__ short
> > +#endif
> > +
> > +typedef uint64_t   UINT64;
> > +typedef int64_t    INT64;
> > +
> > +#ifndef _BASETSD_H_
> > +    typedef uint32_t   UINT32;
> > +    typedef int32_t    INT32;
> > +#endif
> > +
> > +typedef uint16_t   UINT16;
> > +typedef int16_t    INT16;
> > +typedef uint8_t    UINT8;
> > +typedef int8_t     INT8;
> > +typedef __WCHAR_TYPE__ WCHAR;
> > +
> > +#undef VOID
> > +#define VOID    void
> > +
> > +
> > +typedef int64_t    INTN;
> > +typedef uint64_t   UINTN;
> > +
> > +#define POST_CODE(_Data)
> > +
> > +
> > +#define BREAKPOINT()        while (TRUE);    // Make it hang on
> Bios[Dbg]32
> > +
> > +//
> > +// Pointers must be aligned to these address to function
> > +//
> > +
> > +#define MIN_ALIGNMENT_SIZE  4
> > +
> > +#define ALIGN_VARIABLE(Value ,Adjustment) \
> > +            (UINTN)Adjustment = 0; \
> > +            if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
> > +                (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value
> % MIN_ALIGNMENT_SIZE); \
> > +            Value = (UINTN)Value + (UINTN)Adjustment
> > +
> > +
> > +//
> > +// Define macros to build data structure signatures from characters.
> > +//
> > +
> > +#define EFI_SIGNATURE_16(A,B)             ((A) | (B<<8))
> > +#define EFI_SIGNATURE_32(A,B,C,D)         (EFI_SIGNATURE_16(A,B)     |
> (EFI_SIGNATURE_16(C,D)     << 16))
> > +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) |
> ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
> > +
> > +#define EXPORTAPI
> > +
> > +
> > +//
> > +// EFIAPI - prototype calling convention for EFI function pointers
> > +// BOOTSERVICE - prototype for implementation of a boot service
> interface
> > +// RUNTIMESERVICE - prototype for implementation of a runtime service
> interface
> > +// RUNTIMEFUNCTION - prototype for implementation of a runtime function
> that is not a service
> > +// RUNTIME_CODE - pragma macro for declaring runtime code
> > +//
> > +
> > +#ifndef EFIAPI                  // Forces EFI calling conventions
> reguardless of compiler options
> > +        #define EFIAPI          // Substitute expresion to force C
> calling convention
> > +#endif
> > +
> > +#define BOOTSERVICE
> > +//#define RUNTIMESERVICE(proto,a)    alloc_text("rtcode",a); proto a
> > +//#define RUNTIMEFUNCTION(proto,a)   alloc_text("rtcode",a); proto a
> > +#define RUNTIMESERVICE
> > +#define RUNTIMEFUNCTION
> > +
> > +
> > +#define RUNTIME_CODE(a)         alloc_text("rtcode", a)
> > +#define BEGIN_RUNTIME_DATA()    data_seg("rtdata")
> > +#define END_RUNTIME_DATA()      data_seg("")
> > +
> > +#define VOLATILE    volatile
> > +
> > +#define MEMORY_FENCE()
> > +
> > +
> > +//
> > +// When build similiar to FW, then link everything together as
> > +// one big module.
> > +//
> > +
> > +#define EFI_DRIVER_ENTRY_POINT(InitFunction)    \
> > +    UINTN                                       \
> > +    InitializeDriver (                          \
> > +        VOID    *ImageHandle,                   \
> > +        VOID    *SystemTable                    \
> > +        )                                       \
> > +    {                                           \
> > +        return InitFunction(ImageHandle,        \
> > +                SystemTable);                   \
> > +    }                                           \
> > +                                                \
> > +    EFI_STATUS efi_main(                        \
> > +        EFI_HANDLE image,                       \
> > +        EFI_SYSTEM_TABLE *systab                \
> > +        ) __attribute__((weak,                  \
> > +                alias ("InitializeDriver")));
> > +
> > +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry)    \
> > +        (_if)->LoadInternal(type, name, entry)
> > +
> > +
> > +//
> > +// Some compilers don't support the forward reference construct:
> > +//  typedef struct XXXXX
> > +//
> > +// The following macro provide a workaround for such cases.
> > +//
> > +#ifdef NO_INTERFACE_DECL
> > +#define INTERFACE_DECL(x)
> > +#else
> > +#ifdef __GNUC__
> > +#define INTERFACE_DECL(x) struct x
> > +#else
> > +#define INTERFACE_DECL(x) typedef struct x
> > +#endif
> > +#endif
> > +
> > +#endif
> > +
> > +/*
> > + * Local variables:
> > + * mode: C
> > + * c-file-style: "BSD"
> > + * c-basic-offset: 4
> > + * tab-width: 4
> > + * indent-tabs-mode: nil
> > + * End:
> > + */
> > diff --git a/xen/include/asm-arm/efi-boot.h
> b/xen/include/asm-arm/efi-boot.h
> > new file mode 100644
> > index 0000000..2db0966
> > --- /dev/null
> > +++ b/xen/include/asm-arm/efi-boot.h
> > @@ -0,0 +1,630 @@
> > +/*
> > + * Architecture specific implementation for EFI boot code.  This file
> > + * is intended to be included by XXX _only_, and therefore can define
> > + * arch specific global variables.
> > + */
> > +#include <xen/libfdt/libfdt.h>
> > +#include <asm/setup.h>
> > +
> > +static void noreturn blexit(const CHAR16 *str);
> > +static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
> > +void noreturn efi_xen_start(void *fdt_ptr);
> > +
> > +#define DEVICE_TREE_GUID \
> > +{0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa,
> 0xe0}}
> > +
> > +static struct file __initdata dtbfile;
> > +static void __initdata *fdt;
> > +static void __initdata *memmap;
> > +
> > +static int __init setup_chosen_node(void *fdt, int *addr_cells, int
> *size_cells)
> > +{
> > +    int node;
> > +    const struct fdt_property *prop;
> > +    int len;
> > +    uint32_t val;
> > +
> > +    if ( !fdt || !addr_cells || !size_cells )
> > +        return -1;
> > +
> > +    /* locate chosen node, which is where we add Xen module info. */
> > +    node = fdt_subnode_offset(fdt, 0, "chosen");
> > +    if ( node < 0 )
> > +    {
> > +        node = fdt_add_subnode(fdt, 0, "chosen");
> > +        if ( node < 0 )
> > +            return node;
> > +    }
> > +
> > +    /* Get or set #address-cells and #size-cells */
> > +    prop = fdt_get_property(fdt, node, "#address-cells", &len);
> > +    if ( !prop )
> > +    {
> > +        val = cpu_to_fdt32(2);
> > +        if ( fdt_setprop(fdt, node, "#address-cells", &val,
> sizeof(val)) )
> > +            return -1;
> > +        *addr_cells = 2;
> > +    }
> > +    else
> > +        *addr_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
> > +
> > +    prop = fdt_get_property(fdt, node, "#size-cells", &len);
> > +    if ( !prop )
> > +    {
> > +        val = cpu_to_fdt32(2);
> > +        if ( fdt_setprop(fdt, node, "#size-cells", &val, sizeof(val)) )
> > +            return -1;
> > +        *size_cells = 2;
> > +    }
> > +    else
> > +        *size_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
> > +
> > +    /*
> > +     * Make sure ranges is empty if it exists, otherwise create empty
> ranges
> > +     * property.
> > +     */
> > +    prop = fdt_get_property(fdt, node, "ranges", &len);
> > +    if ( !prop )
> > +    {
> > +        val = cpu_to_fdt32(0);
> > +        if ( fdt_setprop(fdt, node, "ranges", &val, 0) )
> > +            return -1;
> > +    }
> > +    else if ( fdt32_to_cpu(prop->len) )
> > +            return -1;  /* Non-empty ranges property */
> > +    return node;
> > +}
> > +
> > +/*
> > + * Set a single 'reg' property taking into account the
> > + * configured addr and size cell sizes.
> > + */
> > +static int __init fdt_set_reg(void *fdt, int node, int addr_cells,
> > +                              int size_cells, uint64_t addr, uint64_t
> len)
> > +{
> > +    uint8_t data[16]; /* at most 2 64 bit words */
> > +    void *p = data;
> > +
> > +    /* Make sure that the values provided can be represented in
> > +     * the reg property.
> > +     */
> > +    if ( addr_cells == 1 && (addr >> 32) )
> > +        return -1;
> > +    if ( size_cells == 1 && (len >> 32) )
> > +        return -1;
> > +
> > +    if ( addr_cells == 1 )
> > +    {
> > +        *(uint32_t *)p = cpu_to_fdt32(addr);
> > +        p += sizeof(uint32_t);
> > +    }
> > +    else if ( addr_cells == 2 )
> > +    {
> > +        *(uint64_t *)p = cpu_to_fdt64(addr);
> > +        p += sizeof(uint64_t);
> > +    }
> > +    else
> > +        return -1;
> > +
> > +    if ( size_cells == 1 )
> > +    {
> > +        *(uint32_t *)p = cpu_to_fdt32(len);
> > +        p += sizeof(uint32_t);
> > +    }
> > +    else if ( size_cells == 2 )
> > +    {
> > +        *(uint64_t *)p = cpu_to_fdt64(len);
> > +        p += sizeof(uint64_t);
> > +    }
> > +    else
> > +        return -1;
> > +
> > +    return(fdt_setprop(fdt, node, "reg", data, p - (void *)data));
> > +}
> > +
> > +static void __init *lookup_fdt_config_table(EFI_SYSTEM_TABLE *sys_table)
> > +{
> > +    const EFI_GUID fdt_guid = DEVICE_TREE_GUID;
> > +    EFI_CONFIGURATION_TABLE *tables;
> > +    void *fdt = NULL;
> > +    int i;
> > +
> > +    tables = sys_table->ConfigurationTable;
> > +    for ( i = 0; i < sys_table->NumberOfTableEntries; i++ )
> > +    {
> > +        if ( match_guid(&tables[i].VendorGuid, &fdt_guid) )
> > +        {
> > +            fdt = tables[i].VendorTable;
> > +            break;
> > +        }
> > +    }
> > +    return fdt;
> > +}
> > +
> > +static EFI_STATUS __init efi_get_memory_map(void **map,
> > +                                            UINTN *mmap_size,
> > +                                            UINTN *desc_size,
> > +                                            UINT32 *desc_ver,
> > +                                            UINTN *key_ptr)
> > +{
> > +    EFI_MEMORY_DESCRIPTOR *m = NULL;
> > +    EFI_STATUS status;
> > +    unsigned long key;
> > +    u32 desc_version;
> > +
> > +    *map = NULL;
> > +    *mmap_size = EFI_PAGE_SIZE;
> > +again:
> > +    *mmap_size += EFI_PAGE_SIZE;  /* Page size is allocation
> granularity */
> > +    status = efi_bs->AllocatePool(EfiLoaderData, *mmap_size, (void
> **)&m);
> > +    if ( status != EFI_SUCCESS )
> > +        return status;
> > +
> > +    *desc_size = 0;
> > +    key = 0;
> > +    status = efi_bs->GetMemoryMap(mmap_size, m, &key, desc_size,
> &desc_version);
> > +    if ( status == EFI_BUFFER_TOO_SMALL )
> > +    {
> > +        efi_bs->FreePool(m);
> > +        goto again;
> > +    }
> > +
> > +    if ( status != EFI_SUCCESS )
> > +    {
> > +        efi_bs->FreePool(m);
> > +        return status;
> > +    }
> > +
> > +    if ( key_ptr && status == EFI_SUCCESS )
> > +        *key_ptr = key;
> > +    if ( desc_ver && status == EFI_SUCCESS )
> > +        *desc_ver = desc_version;
> > +
> > +    *map = m;
> > +    return status;
> > +}
> > +
> > +static EFI_STATUS __init
> efi_process_memory_map_bootinfo(EFI_MEMORY_DESCRIPTOR *map,
> > +                                                UINTN mmap_size,
> > +                                                UINTN desc_size)
> > +{
> > +    int Index;
> > +    int i = 0;
> > +
> > +    EFI_MEMORY_DESCRIPTOR *desc_ptr = map;
> > +
> > +    for ( Index = 0; Index < (mmap_size / desc_size); Index++ )
> > +    {
> > +        if ( desc_ptr->Type == EfiConventionalMemory
> > +             || desc_ptr->Type == EfiBootServicesCode
> > +             || desc_ptr->Type == EfiBootServicesData )
> > +        {
> > +            bootinfo.mem.bank[i].start = desc_ptr->PhysicalStart;
> > +            bootinfo.mem.bank[i].size = desc_ptr->NumberOfPages *
> EFI_PAGE_SIZE;
> > +            if ( ++i >= NR_MEM_BANKS )
> > +            {
> > +                PrintStr(L"Warning: All ");
> > +                DisplayUint(NR_MEM_BANKS, -1);
> > +                PrintStr(L" bootinfo mem banks exhausted.\r\n");
> > +                break;
> > +            }
> > +        }
> > +        desc_ptr = NextMemoryDescriptor(desc_ptr, desc_size);
> > +    }
> > +
> > +    bootinfo.mem.nr_banks = i;
> > +    return EFI_SUCCESS;
> > +
> > +}
> > +
> > +/*
> > + * Add the FDT nodes for the standard EFI information, which consist
> > + * of the System table address, the address of the final EFI memory map,
> > + * and memory map information.
> > + */
> > +EFI_STATUS __init fdt_add_uefi_nodes(EFI_SYSTEM_TABLE *sys_table,
> > +                                            void *fdt,
> > +                                            EFI_MEMORY_DESCRIPTOR
> *memory_map,
> > +                                            UINTN map_size,
> > +                                            UINTN desc_size,
> > +                                            UINT32 desc_ver)
> > +{
> > +    int node;
> > +    int status;
> > +    u32 fdt_val32;
> > +    u64 fdt_val64;
> > +    int prev;
> > +    /*
> > +     * Delete any memory nodes present.  The EFI memory map is the only
> > +     * memory description provided to Xen.
> > +     */
> > +    prev = 0;
> > +    for (;;)
> > +    {
> > +        const char *type;
> > +        int len;
> > +
> > +        node = fdt_next_node(fdt, prev, NULL);
> > +        if ( node < 0 )
> > +            break;
> > +
> > +        type = fdt_getprop(fdt, node, "device_type", &len);
> > +        if ( type && strncmp(type, "memory", len) == 0 )
> > +        {
> > +            fdt_del_node(fdt, node);
> > +            continue;
> > +        }
> > +
> > +        prev = node;
> > +    }
> > +
> > +    /* Add FDT entries for EFI runtime services in chosen node. */
> > +    node = fdt_subnode_offset(fdt, 0, "chosen");
> > +    if ( node < 0 )
> > +    {
> > +        node = fdt_add_subnode(fdt, 0, "chosen");
> > +        if ( node < 0 )
> > +        {
> > +            status = node; /* node is error code when negative */
> > +            goto fdt_set_fail;
> > +        }
> > +    }
>
> setup_chosen_node?
>

Yes, this should be done here as well.  I will add that for the case of
creating
a new FDT.

>
>
> > +    fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)sys_table);
> > +    status = fdt_setprop(fdt, node, "linux,uefi-system-table",
> > +                         &fdt_val64, sizeof(fdt_val64));
> > +    if ( status )
> > +        goto fdt_set_fail;
> > +
> > +    fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)memory_map);
> > +    status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
> > +                         &fdt_val64,  sizeof(fdt_val64));
> > +    if ( status )
> > +        goto fdt_set_fail;
> > +
> > +    fdt_val32 = cpu_to_fdt32(map_size);
> > +    status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
> > +                         &fdt_val32,  sizeof(fdt_val32));
> > +    if ( status )
> > +        goto fdt_set_fail;
> > +
> > +    fdt_val32 = cpu_to_fdt32(desc_size);
> > +    status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
> > +                         &fdt_val32, sizeof(fdt_val32));
> > +    if ( status )
> > +        goto fdt_set_fail;
> > +
> > +    fdt_val32 = cpu_to_fdt32(desc_ver);
> > +    status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
> > +                         &fdt_val32, sizeof(fdt_val32));
> > +    if ( status )
> > +        goto fdt_set_fail;
> > +
> > +    return EFI_SUCCESS;
> > +
> > +fdt_set_fail:
> > +    if ( status == -FDT_ERR_NOSPACE )
> > +        return EFI_BUFFER_TOO_SMALL;
> > +
> > +    return EFI_LOAD_ERROR;
> > +}
> > +
> > +/*
> > + * Allocates new memory for a larger FDT, and frees existing memory if
> > + * struct file size is non-zero.  Updates file struct with new memory
> > + * address/size for later freeing.  If fdtfile.ptr is NULL, an empty FDT
> > + * is created.
> > + */
> > +static void __init *fdt_increase_size(struct file *fdtfile, int
> add_size)
> > +{
> > +    EFI_STATUS status;
> > +    EFI_PHYSICAL_ADDRESS fdt_addr;
> > +    int fdt_size;
> > +    int pages;
> > +    void *new_fdt;
> > +
> > +    if ( fdtfile->ptr )
> > +        fdt_size = fdt_totalsize(fdtfile->ptr);
> > +    else
> > +        fdt_size = 0;
> > +
> > +    pages = PFN_UP(fdt_size) + PFN_UP(add_size);
>
> Shouldn't this be PFN_UP(fdt_size+add_size)?
>
Yup, I will fix this.

>
>
> > +    status = efi_bs->AllocatePages(AllocateAnyPages, EfiLoaderData,
> > +                                   pages, &fdt_addr);
> > +
> > +    if ( status != EFI_SUCCESS )
> > +        return NULL;
> > +
> > +    new_fdt = (void *)fdt_addr;
> > +
> > +    if ( fdt_size )
> > +    {
> > +        if ( fdt_open_into(dtbfile.ptr, new_fdt, pages * EFI_PAGE_SIZE)
> )
> > +            return NULL;
> > +    }
> > +    else
> > +    {
> > +        /*
> > +         * Create an empty FDT if not provided one, which is the
> expected case
> > +         * when booted from the UEFI shell on an ACPI only system.  We
> will use
> > +         * the FDT to pass the EFI information to Xen, as well as nodes
> for
> > +         * any modules the stub loads.  The ACPI tables are part of the
> UEFI
> > +         * system table that is passed in the FDT.
> > +         */
> > +        if ( fdt_create_empty_tree(new_fdt, pages * EFI_PAGE_SIZE) )
> > +            return NULL;
> > +    }
> > +
> > +    /*
> > +     * Now that we have the new FDT allocated and copied, free the
> > +     * original and update the struct file so that the error handling
> > +     * code will free it.  If the original FDT came from a configuration
> > +     * table, we don't own that memory and can't free it.
> > +     */
> > +    if ( dtbfile.size )
> > +        efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
> > +
> > +    /* Update 'file' info for new memory so we clean it up on error
> exits */
> > +    dtbfile.addr = fdt_addr;
> > +    dtbfile.size = pages * EFI_PAGE_SIZE;
> > +    return new_fdt;
> > +}
> > +
> > +static void __init efi_arch_pci(void)
> > +{
> > +}
> > +
> > +static void __init efi_arch_relocate_image(unsigned long delta)
> > +{
> > +}
> > +
> > +static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE
> *SystemTable,
> > +                                               void *map,
> > +                                               UINTN map_size,
> > +                                               UINTN desc_size,
> > +                                               UINT32 desc_ver)
> > +{
> > +    EFI_STATUS status;
> > +
> > +    status = efi_process_memory_map_bootinfo(map, map_size, desc_size);
> > +    if ( EFI_ERROR(status) )
> > +        blexit(L"ERROR processing EFI memory map\r\n");
> > +
> > +    status = fdt_add_uefi_nodes(SystemTable, fdt, map, map_size,
> desc_size,
> > +                                desc_ver);
> > +    if ( EFI_ERROR(status) )
> > +        PrintErrMesg(L"ERROR updating FDT\r\n", status);
> > +}
> > +
> > +static void __init efi_arch_pre_exit_boot(void)
> > +{
> > +}
> > +
> > +static void __init efi_arch_post_exit_boot(void)
> > +{
> > +    efi_xen_start(fdt);
> > +}
> > +
> > +static void __init efi_arch_cfg_file(EFI_FILE_HANDLE dir_handle, char
> *section)
> > +{
> > +    union string name;
> > +    name.s = get_value(&cfg, section, "dtb");
> > +    if ( name.s )
> > +    {
> > +        if ( !read_file(dir_handle, &dtbfile, name.s))
> > +            blexit(NULL);
> > +    }
> > +    fdt = fdt_increase_size(&dtbfile, cfg.size + EFI_PAGE_SIZE);
> > +    if ( !fdt )
> > +        blexit(L"Unable to create new FDT\r\n");
> > +}
> > +
> > +static void __init efi_arch_get_memory_map(UINTN *map_size,
> > +                                             void **map,
> > +                                             UINTN *map_key, UINTN
> *desc_size,
> > +                                             UINT32 *desc_ver)
> > +{
> > +    EFI_STATUS status;
> > +
> > +    status = efi_get_memory_map(map, map_size, desc_size, desc_ver,
> map_key);
> > +    if ( EFI_ERROR(status) )
> > +        blexit(L"ERROR getting EFI memory map.\r\n");
> > +    memmap = *map;
> > +}
> > +
> > +static void __init efi_arch_edd(void)
> > +{
> > +}
> > +
> > +static void __init efi_arch_video(bool_t base_video,
> > +                                  UINTN cols, UINTN rows, UINTN depth,
> > +                                  EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
> > +{
> > +}
> > +
> > +static void __init efi_arch_memory(void)
> > +{
> > +}
> > +
> > +static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
> > +                                           CHAR16 *cmdline_options,
> > +                                           char *cfgfile_options)
> > +{
> > +    union string name;
> > +    char *buf;
> > +    EFI_STATUS status;
> > +    int prop_len;
> > +    int chosen;
> > +
> > +    /* locate chosen node, which is where we add Xen module info. */
> > +    chosen = fdt_subnode_offset(fdt, 0, "chosen");
> > +    if ( chosen < 0 )
> > +        blexit(L"ERROR unable to find chosen node\r\n");
> > +
> > +    status = efi_bs->AllocatePool(EfiBootServicesData, EFI_PAGE_SIZE,
> (void **)&buf);
> > +    if ( EFI_ERROR(status) )
> > +        PrintErrMesg(L"ERROR allocating memory.\r\n", status);
> > +
> > +    if ( image_name )
> > +    {
> > +        name.w = image_name;
> > +        w2s(&name);
> > +    }
> > +    else
> > +        name.s = "xen";
> > +
> > +    prop_len = 0;
> > +    prop_len += snprintf(buf + prop_len,
> > +                           EFI_PAGE_SIZE - prop_len, "%s", name.s);
> > +    if ( prop_len >= EFI_PAGE_SIZE )
> > +        blexit(L"FDT string overflow");
> > +
> > +    if ( cfgfile_options )
> > +    {
> > +        prop_len += snprintf(buf + prop_len,
> > +                               EFI_PAGE_SIZE - prop_len, " %s",
> cfgfile_options);
> > +        if ( prop_len >= EFI_PAGE_SIZE )
> > +            blexit(L"FDT string overflow");
> > +    }
> > +
> > +    if ( cmdline_options )
> > +    {
> > +        name.w = cmdline_options;
> > +        w2s(&name);
> > +    }
> > +    else
> > +        name.s = NULL;
> > +
> > +    if ( name.s )
> > +    {
> > +        prop_len += snprintf(buf + prop_len,
> > +                               EFI_PAGE_SIZE - prop_len, " %s", name.s);
> > +        if ( prop_len >= EFI_PAGE_SIZE )
> > +            blexit(L"FDT string overflow");
> > +    }
> > +
> > +    if ( fdt_setprop_string(fdt, chosen, "xen,xen-bootargs", buf) < 0 )
> > +        blexit(L"unable to set xen,xen-bootargs property.");
> > +
> > +    efi_bs->FreePool(buf);
> > +}
> > +
> > +static void __init efi_arch_handle_module(struct file *file, char *name,
> > +                                          char *options)
> > +{
> > +    int node;
> > +    int chosen;
> > +    int addr_len, size_len;
> > +
> > +    if ( file == &dtbfile )
> > +        return;
> > +    chosen = setup_chosen_node(fdt, &addr_len, &size_len);
> > +    if ( chosen < 0 )
> > +        blexit(L"Unable to setup chosen node\r\n");
> > +
> > +    if ( file == &ramdisk )
> > +    {
> > +        char ramdisk_compat[] = "multiboot,ramdisk\0multiboot,module";
> > +        node = fdt_add_subnode(fdt, chosen, "ramdisk");
> > +        if ( node < 0 )
> > +            blexit(L"Error adding ramdisk FDT node.");
> > +        if ( fdt_setprop(fdt, node, "compatible", ramdisk_compat,
> > +                         sizeof(ramdisk_compat)) < 0 )
> > +            blexit(L"unable to set compatible property.");
> > +        if ( fdt_set_reg(fdt, node, addr_len, size_len, ramdisk.addr,
> > +                    ramdisk.size) < 0 )
> > +            blexit(L"unable to set reg property.");
> > +    }
> > +    else if ( file == &xsm )
> > +    {
> > +        char xsm_compat[] = "xen,xsm-policy\0multiboot,module";
> > +        node = fdt_add_subnode(fdt, chosen, "xsm");
> > +        if ( node < 0 )
> > +            blexit(L"Error adding xsm FDT node.");
> > +        if ( fdt_setprop(fdt, node, "compatible", xsm_compat,
> > +                         sizeof(xsm_compat)) < 0 )
> > +            blexit(L"unable to set compatible property.");
> > +        if ( fdt_set_reg(fdt, node, addr_len, size_len, xsm.addr,
> > +                    xsm.size) < 0 )
> > +            blexit(L"unable to set reg property.");
> > +    }
> > +    else if ( file == &kernel )
> > +    {
> > +        char kernel_compat[] = "multiboot,kernel\0multiboot,module";
> > +        node = fdt_add_subnode(fdt, chosen, "kernel");
> > +        if ( node < 0 )
> > +            blexit(L"Error adding dom0 FDT node.");
> > +        if ( fdt_setprop(fdt, node, "compatible", kernel_compat,
> > +                         sizeof(kernel_compat)) < 0 )
> > +            blexit(L"unable to set compatible property.");
> > +        if ( options && fdt_setprop_string(fdt, node, "bootargs",
> options) < 0 )
> > +            blexit(L"unable to set bootargs property.");
> > +        if ( fdt_set_reg(fdt, node, addr_len, size_len, kernel.addr,
> > +                         kernel.size) < 0 )
> > +            blexit(L"unable to set reg property.");
> > +    }
> > +    else
> > +        blexit(L"Unknown module type\r\n");
> > +}
> > +
> > +static void __init efi_arch_cpu(void)
> > +{
> > +}
> > +
> > +static void __init efi_arch_smbios(void)
> > +{
> > +}
> > +
> > +static void __init efi_arch_blexit(void)
> > +{
> > +    if ( dtbfile.addr && dtbfile.size )
> > +        efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
> > +    if ( memmap )
> > +        efi_bs->FreePool(memmap);
> > +}
> > +
> > +static void __init efi_arch_load_addr_check(EFI_LOADED_IMAGE
> *loaded_image)
> > +{
> > +    if ( (unsigned long)loaded_image->ImageBase & ((1 << 12) - 1) )
> > +        blexit(L"Xen must be loaded at a 4 KByte boundary.");
> > +}
> > +
> > +static void __init efi_arch_runtime_setup(EFI_SYSTEM_TABLE *SystemTable)
> > +{
> > +}
> > +
> > +static __init bool_t efi_arch_use_config_file(EFI_SYSTEM_TABLE
> *SystemTable)
> > +{
> > +    /*
> > +     * For arm, we may get a device tree from GRUB (or other bootloader)
> > +     * that contains modules that have already been loaded into
> memory.  In
> > +     * this case, we do not use a configuration file, and rely on the
> > +     * bootloader to have loaded all required modules and appropriate
> > +     * options.
> > +     */
> > +
> > +    fdt = lookup_fdt_config_table(SystemTable);
> > +    dtbfile.ptr = fdt;
> > +    dtbfile.size = 0;  /* Config table memory can't be freed, so set
> size to 0 */
> > +    if ( !fdt || fdt_node_offset_by_compatible(fdt, 0,
> "multiboot,module") < 0 )
> > +    {
> > +        /*
> > +         * We either have no FDT, or one without modules, so we must
> have a
> > +         * Xen EFI configuration file to specify modules.  (dom0
> required)
> > +         */
> > +        return 1;
> > +    }
> > +    PrintStr(L"Using modules provided by bootloader in FDT\r\n");
> > +    /* We have modules already defined in fdt, just add space. */
> > +    fdt = fdt_increase_size(&dtbfile, EFI_PAGE_SIZE);
> > +    return 0;
> > +}
> > +
> > +/*
> > + * Local variables:
> > + * mode: C
> > + * c-file-style: "BSD"
> > + * c-basic-offset: 4
> > + * indent-tabs-mode: nil
> > + * End:
> > + */
> > diff --git a/xen/include/asm-arm/efi.h b/xen/include/asm-arm/efi.h
> > new file mode 100644
> > index 0000000..aae4716
> > --- /dev/null
> > +++ b/xen/include/asm-arm/efi.h
> > @@ -0,0 +1,29 @@
> > +#include <asm/efibind.h>
> > +#include <efi/efidef.h>
> > +#include <efi/efierr.h>
> > +#include <efi/eficon.h>
> > +#include <efi/efidevp.h>
> > +#include <efi/eficapsule.h>
> > +#include <efi/efiapi.h>
> > +#include <xen/efi.h>
> > +#include <xen/spinlock.h>
> > +#include <asm/page.h>
> > +
> > +extern unsigned int efi_num_ct;
> > +extern EFI_CONFIGURATION_TABLE *efi_ct;
> > +
> > +extern unsigned int efi_version, efi_fw_revision;
> > +extern const CHAR16 *efi_fw_vendor;
> > +
> > +extern EFI_RUNTIME_SERVICES *efi_rs;
> > +
> > +extern UINTN efi_memmap_size, efi_mdesc_size;
> > +extern void *efi_memmap;
> > +
> > +extern const struct efi_pci_rom *efi_pci_roms;
> > +
> > +extern UINT64 efi_boot_max_var_store_size,
> efi_boot_remain_var_store_size,
> > +              efi_boot_max_var_size;
> > +
> > +unsigned long efi_rs_enter(void);
> > +void efi_rs_leave(unsigned long);
> > diff --git a/xen/include/asm-arm/efibind.h
> b/xen/include/asm-arm/efibind.h
> > new file mode 100644
> > index 0000000..09dca7a
> > --- /dev/null
> > +++ b/xen/include/asm-arm/efibind.h
> > @@ -0,0 +1,2 @@
> > +#include <xen/types.h>
> > +#include <asm/arm64/efibind.h>
> > diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
> > index 36e5704..40814e6 100644
> > --- a/xen/include/asm-arm/setup.h
> > +++ b/xen/include/asm-arm/setup.h
> > @@ -3,7 +3,7 @@
> >
> >  #include <public/version.h>
> >
> > -#define NR_MEM_BANKS 8
> > +#define NR_MEM_BANKS 32
>
> Why?
> At the very least you should write it in the commit message.
>
> In the EFI case, we have the EFI memory map which lists all memory by
region and usage  (ie available, boot_services, runtime, etc.)
not the physical memory banks that are provided by FDT.  I am putting the
available memory from the EFI memory map into the memory bank
list, so this requires more entries.  This is somewhat problematic as it is
possible for the EFI memory map to be very fragmented, which could lead
to a great many regions.

Roy



> >  #define MAX_MODULES 5 /* Current maximum useful modules */
> >
> > --
> > 2.1.0.rc1
> >
>

[-- Attachment #1.2: Type: text/html, Size: 58911 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 01/15] move x86 EFI boot code to common/efi
  2014-09-11 17:16     ` Roy Franz
@ 2014-09-12  6:55       ` Jan Beulich
  0 siblings, 0 replies; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  6:55 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

>>> On 11.09.14 at 19:16, <roy.franz@linaro.org> wrote:
> I can move the other file - I think runtime.c would be the only other to 
> move,
> but it is not used by this patchset.  This patchset is limited to EFI
> boot support.
> Runtime services support, ACPI, etc all depend on this functionality,
> but are not
> being addressed in this patchset.
> I can move runtime.c to common/efi, but the only place it will be used
> is x86/efi.

Which is fine as an intermediate state. compat.c, btw, also would
need moving. And considering the comment on a later patch
regarding relocation of the image to the proper VA, the relocation
related files would seem to be needed too. In the end it would be
just check.c and stub.c that are x86-specific.

> This touches on an issue in a number of the following patches - some
> of the things moved to
> the arch specific file are EFI related things that are not truly
> architecture specific, but are not yet
> implemented for ARM and are beyond the scope of this patchset.  My
> intent is for these to be adjusted
> when those features (such as runtime services) are implemented for
> ARM.  There are other non-EFI specific
> things like VGA, which aren't currently in the ARM build, but are
> setup in boot.c, but aren't truly architecture specific.

So you'd end up moving this out and later back in? Please avoid
such unnecessary churn - as a temporary measure here, #ifdef-s
seem like the clearly preferable mechanism to me (with a suitable
"fixme" comment).

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 02/15] Move x86 specific funtions/variables to arch header
  2014-09-11 17:33     ` Roy Franz
@ 2014-09-12  7:04       ` Jan Beulich
  2014-09-12  9:43         ` Ian Campbell
  2014-09-12 16:52         ` Roy Franz
  0 siblings, 2 replies; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  7:04 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

>>> On 11.09.14 at 19:33, <roy.franz@linaro.org> wrote:
> On Thu, Sep 11, 2014 at 7:03 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>>> -/* Using SetVirtualAddressMap() is incompatible with kexec: */
>>> -#undef USE_SET_VIRTUAL_ADDRESS_MAP
>>
>> In which way is this arch-specific?
> The define is only used by the x86 specific code.  I can move it back
> to the common code.

Yes please, as the conflict with kexec is an arch-independent one.

>>> -static void __init place_string(u32 *addr, const char *s)
>>> -{
>>> -    static char *__initdata alloc = start;
>>> -
>>> -    if ( s && *s )
>>> -    {
>>> -        size_t len1 = strlen(s) + 1;
>>> -        const char *old = (char *)(long)*addr;
>>> -        size_t len2 = *addr ? strlen(old) + 1 : 0;
>>> -
>>> -        alloc -= len1 + len2;
>>> -        /*
>>> -         * Insert new string before already existing one. This is needed
>>> -         * for options passed on the command line to override options from
>>> -         * the configuration file.
>>> -         */
>>> -        memcpy(alloc, s, len1);
>>> -        if ( *addr )
>>> -        {
>>> -            alloc[len1 - 1] = ' ';
>>> -            memcpy(alloc + len1, old, len2);
>>> -        }
>>> -    }
>>> -    *addr = (long)alloc;
>>> -}
>>
>> How much of this is really arch-specific?
> 
> This is only used by the x86 code, and this is the x86 specific memory
> management that uses
> memory allocated by the linker script before start.  The ARM boot code
> does not use this.

I.e. the only arch-specific thing here is the initializer of "alloc". Or
are you saying that you don't need a place_string() function in
ARM at all? Is that because to stuff respective information into DT?

>>> -static void __init setup_efi_pci(void)
>>
>> And this doesn't seem arch-specific either (it only depends on
>> HAS_PCI or some such).
> 
> This does scanning of PCI ROMS, which is unlikely to do anything
> useful on ARM platforms.

Why not? Obviously if the ROMs contain x86 code, they're useless,
but in order to, say, do remote boot I suppose you need option
ROMs (with ARM code) on ARM too.

> I also have no way to test this on ARM.
> I can try to pull this back in, but I may run into dependency issues
> such as those with VGA, where I did not
> want to pull in otherwise unused (and likely unusable on ARM)
> drivers/subsystems in order to keep a little more
> code in the common EFI boot path.

The base line should be too keep everything here that is potentially
usable on more than one arch (without limiting our thinking to ARM
and x86). EFI's protocol based approach abstracts this quite nicely
- if something isn't available, you simply won't find th respective
protocol.

>>> --- /dev/null
>>> +++ b/xen/include/asm-x86/efi-boot.h
>>> @@ -0,0 +1,451 @@
>>> +/*
>>> + * Architecture specific implementation for EFI boot code.  This file
>>> + * is intended to be included by XXX _only_, and therefore can define
>>> + * arch specific global variables.
>>> + */
>>> +#include <asm/e820.h>
>>> +#include <asm/edd.h>
>>> +#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
>>> +#include <asm/fixmap.h>
>>> +#undef __ASSEMBLY__
>>> +#include <asm/msr.h>
>>> +#include <asm/processor.h>
>>> +
>>> +static struct file __initdata ucode;
>>> +static multiboot_info_t __initdata mbi = {
>>> +    .flags = MBI_MODULES | MBI_LOADERNAME
>>> +};
>>> +static module_t __initdata mb_modules[3];
>>> +
>>> +static void noreturn blexit(const CHAR16 *str);
>>> +static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
>>
>> What are these two doing here?
> 
> These are forward declarations.  I don't think that I can order
> everything so that I don't need any forward declarations
> anywhere.

I realize you may need forward declarations. But you declare arch-
independent functions in an arch header here.

>>> +void __init efi_init_memory(void)
>>
>> Now that I look at it again, I think a good part of this is arch-
>> independent too.
> By "this" you mean the code in efi_init_memory?

Yes, at least everything up to and including the
SetVirtualAddressMap() call.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 03/15] create arch functions to get and process EFI memory map.
  2014-09-11 17:40     ` Roy Franz
@ 2014-09-12  7:07       ` Jan Beulich
  2014-09-12  9:45         ` Ian Campbell
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  7:07 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

>>> On 11.09.14 at 19:40, <roy.franz@linaro.org> wrote:
> On Thu, Sep 11, 2014 at 7:11 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>>> @@ -1171,67 +1169,12 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
>>>          }
>>>      }
>>>
>>> -    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
>>> -                         &efi_mdesc_size, &mdesc_ver);
>>> -    mbi.mem_upper -= efi_memmap_size;
>>> -    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
>>> -    if ( mbi.mem_upper < xen_phys_start )
>>> -        blexit(L"Out of static memory");
>>> -    efi_memmap = (void *)(long)mbi.mem_upper;
>>> -    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
>>> -                                  &efi_mdesc_size, &mdesc_ver);
>>> -    if ( EFI_ERROR(status) )
>>> -        PrintErrMesg(L"Cannot obtain memory map", status);
>>> +    efi_arch_get_memory_map(&mmap_size, &mmap, &mmap_key,
>>> +                                  &mmap_desc_size, &mmap_desc_ver);
>>
>> The only arch-specific bit here is where to put the map.
> Yes, but the ARM method of allocating the space can make the map
> bigger.  I can re-arrange
> this so that only the memory allocation is in the arch code, but I
> think the current implementation
> is also reasonable.

Hmm, yes, if ARM has no way of avoiding the growth of the map
during allocation (which at a first glance seems suspicious to me),
then yes. Is there a problem allocating a few more entries than the
map's current size, so the possible growth can be accommodated?

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices
  2014-09-11 17:44     ` Roy Franz
@ 2014-09-12  7:08       ` Jan Beulich
  2014-09-12  9:46         ` Ian Campbell
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  7:08 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

>>> On 11.09.14 at 19:44, <roy.franz@linaro.org> wrote:
> On Thu, Sep 11, 2014 at 7:13 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>>>      status = efi_bs->ExitBootServices(ImageHandle, mmap_key);
>>>      if ( EFI_ERROR(status) )
>>>          PrintErrMesg(L"Cannot exit boot services", status);
>>>
>>> -    /* Adjust pointers into EFI. */
>>> -    efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
>>> -#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
>>> -    efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
>>> -#endif
>>> -    efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
>>> -    efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
>>> -
>>> -    efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
>>
>> Up to here I don't see anything arch-specific again.
> This is due to runtime services not being implemented.  The "efi_rs"
> variable is defined in the runtime services
> file runtime.c, which is not yet ported to ARM.
> 
> Short of including ARM runtime service support in the patchset, how
> would you like this handled?

As said before, everything that's generic but not used/usable on
ARM right now should stay here, but get made conditional in one
or another way.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 05/15] Add efi_arch_cfg_file() to handle arch specific cfg file fields
  2014-09-11 18:11     ` Roy Franz
@ 2014-09-12  7:10       ` Jan Beulich
  0 siblings, 0 replies; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  7:10 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

>>> On 11.09.14 at 20:11, <roy.franz@linaro.org> wrote:
> On Thu, Sep 11, 2014 at 7:16 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>>> @@ -752,6 +758,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
> *SystemTable)
>>>      }
>>>      if ( !name.s )
>>>          blexit(L"No Dom0 kernel image specified.");
>>> +
>>> +    efi_arch_cfg_file(dir_handle, section.s);
>>> +
>>>      split_value(name.s);
>>>      read_file(dir_handle, s2w(&name), &kernel);
>>>      efi_bs->FreePool(name.w);
>>> @@ -769,17 +778,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
> *SystemTable)
>>>          efi_bs->FreePool(name.w);
>>>      }
>>>
>>> -    name.s = get_value(&cfg, section.s, "ucode");
>>> -    if ( !name.s )
>>> -        name.s = get_value(&cfg, "global", "ucode");
>>> -    if ( name.s )
>>> -    {
>>> -        microcode_set_module(mbi.mods_count);
>>> -        split_value(name.s);
>>> -        read_file(dir_handle, s2w(&name), &ucode);
>>> -        efi_bs->FreePool(name.w);
>>> -    }
>>> -
>>>      name.s = get_value(&cfg, section.s, "xsm");
>>>      if ( name.s )
>>>      {
>>
>> While the ordering shouldn't matter that much, is it intentional that
>> you move this up ahead of the loading of the kernel? If anything,
>> I'd see this move down after the XSM loading.
>>
> Yes, this is intentional, as in the ARM case the configuration file 
> specifies
> the device tree to use, and the kernel and other modules are added to this,
> so we need this set up before we actually read the other module files.  For 
> x86
> the ordering didn't seem to have any dependencies. I can add a comment
> explaining this.

Thing is that (not just here) I prefer allocating big chunks of
memory before smaller ones (i.e. kernel+initrd before ucode+xsm).
Hence maybe we'd be better of with a pre and a post arch hook
here.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 07/15] Move x86 specific video and disk probing code
  2014-09-11 18:30     ` Roy Franz
@ 2014-09-12  7:12       ` Jan Beulich
  0 siblings, 0 replies; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  7:12 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

>>> On 11.09.14 at 20:30, <roy.franz@linaro.org> wrote:
> On Thu, Sep 11, 2014 at 7:26 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>>> @@ -811,189 +785,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
> *SystemTable)
>>>      cfg.addr = 0;
>>>
>>>      dir_handle->Close(dir_handle);
>>> -
>>> -    if ( gop && !base_video )
>>> -    {
>>> -        for ( i = size = 0; i < gop->Mode->MaxMode; ++i )
>>> -        {
>>> -            unsigned int bpp = 0;
>>> -
>>> -            status = gop->QueryMode(gop, i, &info_size, &mode_info);
>>> -            if ( EFI_ERROR(status) )
>>> -                continue;
>>> -            switch ( mode_info->PixelFormat )
>>> -            {
>>> -            case PixelBitMask:
>>> -                bpp = hweight32(mode_info->PixelInformation.RedMask |
>>> -                                mode_info->PixelInformation.GreenMask |
>>> -                                mode_info->PixelInformation.BlueMask);
>>> -                break;
>>> -            case PixelRedGreenBlueReserved8BitPerColor:
>>> -            case PixelBlueGreenRedReserved8BitPerColor:
>>> -                bpp = 24;
>>> -                break;
>>> -            default:
>>> -                continue;
>>> -            }
>>> -            if ( cols == mode_info->HorizontalResolution &&
>>> -                 rows == mode_info->VerticalResolution &&
>>> -                 (!depth || bpp == depth) )
>>> -            {
>>> -                gop_mode = i;
>>> -                break;
>>> -            }
>>> -            if ( !cols && !rows &&
>>> -                 mode_info->HorizontalResolution *
>>> -                 mode_info->VerticalResolution > size )
>>> -            {
>>> -                size = mode_info->HorizontalResolution *
>>> -                       mode_info->VerticalResolution;
>>> -                gop_mode = i;
>>> -            }
>>> -        }
>>> -    }
>>
>> This together with ...
>>
>>> @@ -1075,77 +867,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
> *SystemTable)
>>>      l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 
> 1)] =
>>>          l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR);
>>>
>>> -    if ( gop )
>>> -    {
>>> -        int bpp = 0;
>>> -
>>> -        /* Set graphics mode. */
>>> -        if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode )
>>> -            gop->SetMode(gop, gop_mode);
>>
>> ... this isn't arch-specific again.
> 
> I'll review the video stuff again, but I only moved what seemed to be
> VGA support specific code to the x86 arch file.
> VGA support is currently not part of the ARM build - the VGA setup
> code in boot.c updates global variables that are
> not present.  I really doubt that VGA support is relevant to ARM so I
> move the code to the x86 specific file rather than
> trying to add VGA support to ARM.

Yes, VGA specific code very likely is x86-specific. But some parts of
this are video related in a fashion broader than VGA, and I don't
think there's no video at all on ARM's EFI (now and forever)?

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 10/15] Add SMBIOS and runtime services setup arch functions.
  2014-09-11 22:03     ` Roy Franz
  2014-09-11 23:41       ` Stefano Stabellini
@ 2014-09-12  7:14       ` Jan Beulich
  2014-09-12 16:24         ` Roy Franz
  1 sibling, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  7:14 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

>>> On 12.09.14 at 00:03, <roy.franz@linaro.org> wrote:
> On Thu, Sep 11, 2014 at 7:44 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
>>> @@ -805,49 +801,13 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
> *SystemTable)
>>>          boot_cpu_data.x86_capability[1] = cpuid_ext_features;
>>>      }
>>>
>>> -    /* Obtain basic table pointers. */
>>> -    for ( i = 0; i < efi_num_ct; ++i )
>>> -    {
>>> -        static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
>>> -        static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
>>> -        static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
>>> -        static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
>>> -
>>> -        if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
>>> -            efi.acpi20 = (long)efi_ct[i].VendorTable;
>>> -        if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
>>> -            efi.acpi = (long)efi_ct[i].VendorTable;
>>> -        if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
>>> -            efi.mps = (long)efi_ct[i].VendorTable;
>>> -        if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
>>> -            efi.smbios = (long)efi_ct[i].VendorTable;
>>> -    }
>>
>> The only arch specific things I can see throughout this entire patch
>> are the specific GUIDs and which fields they go into in the internal
>> structure. The GUIDs can be put in a table, and the fields can be
>> represented e.g. via offsetof(), paired with the respective GUID.
>>
> The efi structure is defined in runtime.c for runtime use, which is
> why I moved it,
> as I am not addressing runtime services in this patchset.  This is an 
> (ab)use of
> the architecture specific head file, using it for features that are
> currently only implemented
> on that architecture, rather than fundamental architectural differences.

So how about you enable building runtime.c on ARM right away and
for now simply #ifdef out everything but the variable definitions there?

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 12/15] Add efi_arch_use_config_file() function to control use of config file
  2014-09-11 23:54     ` Stefano Stabellini
@ 2014-09-12  7:15       ` Jan Beulich
  2014-09-12 16:30         ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  7:15 UTC (permalink / raw)
  To: Stefano.Stabellini, Stefano Stabellini
  Cc: keir, ian.campbell, tim, xen-devel, Roy Franz, fu.wei

>>> On 12.09.14 at 01:54, <stefano.stabellini@eu.citrix.com> wrote:
> On Thu, 11 Sep 2014, Jan Beulich wrote:
>> >>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
>> > -    cols = rows = depth = 0;
>> > -    if ( !base_video )
>> > -    {
>> > -        name.cs = get_value(&cfg, section.s, "video");
>> > -        if ( !name.cs )
>> > -            name.cs = get_value(&cfg, "global", "video");
>> > -        if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
>> > +        cols = rows = depth = 0;
>> > +        if ( !base_video )
>> >          {
>> > -            cols = simple_strtoul(name.cs + 4, &name.cs, 10);
>> > -            if ( *name.cs == 'x' )
>> > -                rows = simple_strtoul(name.cs + 1, &name.cs, 10);
>> > -            if ( *name.cs == 'x' )
>> > -                depth = simple_strtoul(name.cs + 1, &name.cs, 10);
>> > -            if ( *name.cs )
>> > -                cols = rows = depth = 0;
>> > +            name.cs = get_value(&cfg, section.s, "video");
>> > +            if ( !name.cs )
>> > +                name.cs = get_value(&cfg, "global", "video");
>> > +            if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
>> > +            {
>> > +                cols = simple_strtoul(name.cs + 4, &name.cs, 10);
>> > +                if ( *name.cs == 'x' )
>> > +                    rows = simple_strtoul(name.cs + 1, &name.cs, 10);
>> > +                if ( *name.cs == 'x' )
>> > +                    depth = simple_strtoul(name.cs + 1, &name.cs, 10);
>> > +                if ( *name.cs )
>> > +                    cols = rows = depth = 0;
>> > +            }
>> 
>> So how is this video mode selection being represented then without
>> config file? Don't you need to at least add a command line option for
>> that?
> 
> The scenario without config file is the one where Xen is loaded by GRUB.
> Do we actually need to pass a video mode option in that case?
> Wouldn't GRUB take care of changing video mode itself to the value
> specified by the user before booting Xen? Xen can query the current
> video mode afterwards.

Ah, right, that's a good point.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-11 22:26     ` Roy Franz
@ 2014-09-12  7:17       ` Jan Beulich
  0 siblings, 0 replies; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  7:17 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

>>> On 12.09.14 at 00:26, <roy.franz@linaro.org> wrote:
> On Thu, Sep 11, 2014 at 7:53 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
>>> --- a/xen/common/Makefile
>>> +++ b/xen/common/Makefile
>>> @@ -67,4 +67,5 @@ subdir-$(x86_64) += hvm
>>>  subdir-$(coverage) += gcov
>>>
>>>  subdir-y += libelf
>>> +subdir-$(CONFIG_EFI) += efi
>>>  subdir-$(HAS_DEVICE_TREE) += libfdt
>>
>> Hmm, this will suggest to the reader that either x86 doesn't support
>> EFI, or it gets built this way too. Both of which is wrong. I think the
>> symlink mechanism should be used the same way as for x86.
> 
> The common build infrastructure works quite nicely for ARM.  I can
> create an arch/arm/efi, and
> make symlink, etc. like x86, but this seems silly to me.  The x86 EFI
> build is special in the way
> it autodetects toolchain capability, but I don't think that these
> complications (or side effects of these
> x86 specific complications) should be copied for symmetry with x86 as
> the only reason.
> 
> If the Makefile is misleading, I'd rather address that with a comment
> in the Makefile

That's an option, but with the symlinking to be done at build time, I
think doing it universally rather than just for x86 also has benefits.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 02/15] Move x86 specific funtions/variables to arch header
  2014-09-12  7:04       ` Jan Beulich
@ 2014-09-12  9:43         ` Ian Campbell
  2014-09-12  9:53           ` Jan Beulich
  2014-09-12 16:52         ` Roy Franz
  1 sibling, 1 reply; 71+ messages in thread
From: Ian Campbell @ 2014-09-12  9:43 UTC (permalink / raw)
  To: Jan Beulich; +Cc: keir, tim, xen-devel, Roy Franz, Stefano Stabellini, Fu Wei

On Fri, 2014-09-12 at 08:04 +0100, Jan Beulich wrote:
> > This does scanning of PCI ROMS, which is unlikely to do anything
> > useful on ARM platforms.
> 
> Why not? Obviously if the ROMs contain x86 code, they're useless,
> but in order to, say, do remote boot I suppose you need option
> ROMs (with ARM code) on ARM too.

Doesn't that all happen at the UEFI layer, long before Xen gets
involved, even on x86?

Does Xen itself do network boot/loading or does it call some UEFI layer?

> > I also have no way to test this on ARM.
> > I can try to pull this back in, but I may run into dependency issues
> > such as those with VGA, where I did not
> > want to pull in otherwise unused (and likely unusable on ARM)
> > drivers/subsystems in order to keep a little more
> > code in the common EFI boot path.
> 
> The base line should be too keep everything here that is potentially
> usable on more than one arch (without limiting our thinking to ARM
> and x86). EFI's protocol based approach abstracts this quite nicely
> - if something isn't available, you simply won't find th respective
> protocol.

Irrespective of the above this seems like a sensible approach.

Ian.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 03/15] create arch functions to get and process EFI memory map.
  2014-09-12  7:07       ` Jan Beulich
@ 2014-09-12  9:45         ` Ian Campbell
  2014-09-12  9:56           ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Ian Campbell @ 2014-09-12  9:45 UTC (permalink / raw)
  To: Jan Beulich; +Cc: keir, tim, xen-devel, Roy Franz, Stefano Stabellini, Fu Wei

On Fri, 2014-09-12 at 08:07 +0100, Jan Beulich wrote:
> >>> On 11.09.14 at 19:40, <roy.franz@linaro.org> wrote:
> > On Thu, Sep 11, 2014 at 7:11 AM, Jan Beulich <JBeulich@suse.com> wrote:
> >>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> >>> @@ -1171,67 +1169,12 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
> >>>          }
> >>>      }
> >>>
> >>> -    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
> >>> -                         &efi_mdesc_size, &mdesc_ver);
> >>> -    mbi.mem_upper -= efi_memmap_size;
> >>> -    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
> >>> -    if ( mbi.mem_upper < xen_phys_start )
> >>> -        blexit(L"Out of static memory");
> >>> -    efi_memmap = (void *)(long)mbi.mem_upper;
> >>> -    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
> >>> -                                  &efi_mdesc_size, &mdesc_ver);
> >>> -    if ( EFI_ERROR(status) )
> >>> -        PrintErrMesg(L"Cannot obtain memory map", status);
> >>> +    efi_arch_get_memory_map(&mmap_size, &mmap, &mmap_key,
> >>> +                                  &mmap_desc_size, &mmap_desc_ver);
> >>
> >> The only arch-specific bit here is where to put the map.
> > Yes, but the ARM method of allocating the space can make the map
> > bigger.

So something which ARM does can make the result of efi_bs->GetMemoryMap
longer? Or are we talking about the bootinfo.mem array?

>   I can re-arrange
> > this so that only the memory allocation is in the arch code, but I
> > think the current implementation
> > is also reasonable.
> 
> Hmm, yes, if ARM has no way of avoiding the growth of the map
> during allocation (which at a first glance seems suspicious to me),
> then yes. Is there a problem allocating a few more entries than the
> map's current size, so the possible growth can be accommodated?
> 
> Jan
> 

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices
  2014-09-12  7:08       ` Jan Beulich
@ 2014-09-12  9:46         ` Ian Campbell
  2014-09-12  9:58           ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Ian Campbell @ 2014-09-12  9:46 UTC (permalink / raw)
  To: Jan Beulich; +Cc: keir, tim, xen-devel, Roy Franz, Stefano Stabellini, Fu Wei

On Fri, 2014-09-12 at 08:08 +0100, Jan Beulich wrote:
> >>> On 11.09.14 at 19:44, <roy.franz@linaro.org> wrote:
> > On Thu, Sep 11, 2014 at 7:13 AM, Jan Beulich <JBeulich@suse.com> wrote:
> >>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> >>>      status = efi_bs->ExitBootServices(ImageHandle, mmap_key);
> >>>      if ( EFI_ERROR(status) )
> >>>          PrintErrMesg(L"Cannot exit boot services", status);
> >>>
> >>> -    /* Adjust pointers into EFI. */
> >>> -    efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
> >>> -#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
> >>> -    efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
> >>> -#endif
> >>> -    efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
> >>> -    efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
> >>> -
> >>> -    efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
> >>
> >> Up to here I don't see anything arch-specific again.
> > This is due to runtime services not being implemented.  The "efi_rs"
> > variable is defined in the runtime services
> > file runtime.c, which is not yet ported to ARM.
> > 
> > Short of including ARM runtime service support in the patchset, how
> > would you like this handled?
> 
> As said before, everything that's generic but not used/usable on
> ARM right now should stay here, but get made conditional in one
> or another way.

So in this case a HAVE_EFI_RUNTIMESERVICES ifdef would work?

Ian.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 02/15] Move x86 specific funtions/variables to arch header
  2014-09-12  9:43         ` Ian Campbell
@ 2014-09-12  9:53           ` Jan Beulich
  2014-09-12  9:58             ` Ian Campbell
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  9:53 UTC (permalink / raw)
  To: Ian Campbell; +Cc: keir, tim, xen-devel, Roy Franz, Stefano Stabellini, Fu Wei

>>> On 12.09.14 at 11:43, <Ian.Campbell@citrix.com> wrote:
> On Fri, 2014-09-12 at 08:04 +0100, Jan Beulich wrote:
>> > This does scanning of PCI ROMS, which is unlikely to do anything
>> > useful on ARM platforms.
>> 
>> Why not? Obviously if the ROMs contain x86 code, they're useless,
>> but in order to, say, do remote boot I suppose you need option
>> ROMs (with ARM code) on ARM too.
> 
> Doesn't that all happen at the UEFI layer, long before Xen gets
> involved, even on x86?

The purpose of the code here isn't for ourselves, but for onward
reporting to Dom0 (via XEN_FW_EFI_PCI_ROM).

> Does Xen itself do network boot/loading or does it call some UEFI layer?

Iiuc Xen would support remote boot right now only if there was a
file system protocol exposed allowing to read in the necessary
files. Anything requiring explicit awareness of that fact is currently
missing.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 03/15] create arch functions to get and process EFI memory map.
  2014-09-12  9:45         ` Ian Campbell
@ 2014-09-12  9:56           ` Jan Beulich
  2014-09-12 10:23             ` Ian Campbell
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  9:56 UTC (permalink / raw)
  To: Ian Campbell; +Cc: keir, tim, xen-devel, Roy Franz, Stefano Stabellini, Fu Wei

>>> On 12.09.14 at 11:45, <Ian.Campbell@citrix.com> wrote:
> On Fri, 2014-09-12 at 08:07 +0100, Jan Beulich wrote:
>> >>> On 11.09.14 at 19:40, <roy.franz@linaro.org> wrote:
>> > On Thu, Sep 11, 2014 at 7:11 AM, Jan Beulich <JBeulich@suse.com> wrote:
>> >>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>> >>> @@ -1171,67 +1169,12 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
> *SystemTable)
>> >>>          }
>> >>>      }
>> >>>
>> >>> -    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
>> >>> -                         &efi_mdesc_size, &mdesc_ver);
>> >>> -    mbi.mem_upper -= efi_memmap_size;
>> >>> -    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
>> >>> -    if ( mbi.mem_upper < xen_phys_start )
>> >>> -        blexit(L"Out of static memory");
>> >>> -    efi_memmap = (void *)(long)mbi.mem_upper;
>> >>> -    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
>> >>> -                                  &efi_mdesc_size, &mdesc_ver);
>> >>> -    if ( EFI_ERROR(status) )
>> >>> -        PrintErrMesg(L"Cannot obtain memory map", status);
>> >>> +    efi_arch_get_memory_map(&mmap_size, &mmap, &mmap_key,
>> >>> +                                  &mmap_desc_size, &mmap_desc_ver);
>> >>
>> >> The only arch-specific bit here is where to put the map.
>> > Yes, but the ARM method of allocating the space can make the map
>> > bigger.
> 
> So something which ARM does can make the result of efi_bs->GetMemoryMap
> longer? Or are we talking about the bootinfo.mem array?

Not having looked at the code, I suppose the issue is with the
sequence of
- get memory map size
- alloc memory for the map
- get memory map
where the middle step may alter the memory map size. But with any
kind of sane allocator it ought to be reasonable to expect it to not
grow by more than two entries (if the allocator chooses to take the
middle of an existing free block), which could be accounted for up
front.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 02/15] Move x86 specific funtions/variables to arch header
  2014-09-12  9:53           ` Jan Beulich
@ 2014-09-12  9:58             ` Ian Campbell
  0 siblings, 0 replies; 71+ messages in thread
From: Ian Campbell @ 2014-09-12  9:58 UTC (permalink / raw)
  To: Jan Beulich; +Cc: keir, tim, xen-devel, Roy Franz, Stefano Stabellini, Fu Wei

On Fri, 2014-09-12 at 10:53 +0100, Jan Beulich wrote:
> >>> On 12.09.14 at 11:43, <Ian.Campbell@citrix.com> wrote:
> > On Fri, 2014-09-12 at 08:04 +0100, Jan Beulich wrote:
> >> > This does scanning of PCI ROMS, which is unlikely to do anything
> >> > useful on ARM platforms.
> >> 
> >> Why not? Obviously if the ROMs contain x86 code, they're useless,
> >> but in order to, say, do remote boot I suppose you need option
> >> ROMs (with ARM code) on ARM too.
> > 
> > Doesn't that all happen at the UEFI layer, long before Xen gets
> > involved, even on x86?
> 
> The purpose of the code here isn't for ourselves, but for onward
> reporting to Dom0 (via XEN_FW_EFI_PCI_ROM).

Ah, makes sense.

> > Does Xen itself do network boot/loading or does it call some UEFI layer?
> 
> Iiuc Xen would support remote boot right now only if there was a
> file system protocol exposed allowing to read in the necessary
> files. Anything requiring explicit awareness of that fact is currently
> missing.

Right. So behind some UEFI layer.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices
  2014-09-12  9:46         ` Ian Campbell
@ 2014-09-12  9:58           ` Jan Beulich
  2014-09-12 16:57             ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-12  9:58 UTC (permalink / raw)
  To: Ian Campbell; +Cc: keir, tim, xen-devel, Roy Franz, Stefano Stabellini, Fu Wei

>>> On 12.09.14 at 11:46, <Ian.Campbell@citrix.com> wrote:
> On Fri, 2014-09-12 at 08:08 +0100, Jan Beulich wrote:
>> >>> On 11.09.14 at 19:44, <roy.franz@linaro.org> wrote:
>> > On Thu, Sep 11, 2014 at 7:13 AM, Jan Beulich <JBeulich@suse.com> wrote:
>> >>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>> >>>      status = efi_bs->ExitBootServices(ImageHandle, mmap_key);
>> >>>      if ( EFI_ERROR(status) )
>> >>>          PrintErrMesg(L"Cannot exit boot services", status);
>> >>>
>> >>> -    /* Adjust pointers into EFI. */
>> >>> -    efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
>> >>> -#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
>> >>> -    efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
>> >>> -#endif
>> >>> -    efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
>> >>> -    efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
>> >>> -
>> >>> -    efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
>> >>
>> >> Up to here I don't see anything arch-specific again.
>> > This is due to runtime services not being implemented.  The "efi_rs"
>> > variable is defined in the runtime services
>> > file runtime.c, which is not yet ported to ARM.
>> > 
>> > Short of including ARM runtime service support in the patchset, how
>> > would you like this handled?
>> 
>> As said before, everything that's generic but not used/usable on
>> ARM right now should stay here, but get made conditional in one
>> or another way.
> 
> So in this case a HAVE_EFI_RUNTIMESERVICES ifdef would work?

Yes (except that in the case I would use NEED_ or WANT_ instead
of HAVE_). But considering this is intended to be temporary, I'd
even be fine with just using CONFIG_ARM or alike here.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 03/15] create arch functions to get and process EFI memory map.
  2014-09-12  9:56           ` Jan Beulich
@ 2014-09-12 10:23             ` Ian Campbell
  2014-09-12 10:35               ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Ian Campbell @ 2014-09-12 10:23 UTC (permalink / raw)
  To: Jan Beulich; +Cc: keir, tim, xen-devel, Roy Franz, Stefano Stabellini, Fu Wei

On Fri, 2014-09-12 at 10:56 +0100, Jan Beulich wrote:
> >>> On 12.09.14 at 11:45, <Ian.Campbell@citrix.com> wrote:
> > On Fri, 2014-09-12 at 08:07 +0100, Jan Beulich wrote:
> >> >>> On 11.09.14 at 19:40, <roy.franz@linaro.org> wrote:
> >> > On Thu, Sep 11, 2014 at 7:11 AM, Jan Beulich <JBeulich@suse.com> wrote:
> >> >>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> >> >>> @@ -1171,67 +1169,12 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
> > *SystemTable)
> >> >>>          }
> >> >>>      }
> >> >>>
> >> >>> -    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
> >> >>> -                         &efi_mdesc_size, &mdesc_ver);
> >> >>> -    mbi.mem_upper -= efi_memmap_size;
> >> >>> -    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
> >> >>> -    if ( mbi.mem_upper < xen_phys_start )
> >> >>> -        blexit(L"Out of static memory");
> >> >>> -    efi_memmap = (void *)(long)mbi.mem_upper;
> >> >>> -    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
> >> >>> -                                  &efi_mdesc_size, &mdesc_ver);
> >> >>> -    if ( EFI_ERROR(status) )
> >> >>> -        PrintErrMesg(L"Cannot obtain memory map", status);
> >> >>> +    efi_arch_get_memory_map(&mmap_size, &mmap, &mmap_key,
> >> >>> +                                  &mmap_desc_size, &mmap_desc_ver);
> >> >>
> >> >> The only arch-specific bit here is where to put the map.
> >> > Yes, but the ARM method of allocating the space can make the map
> >> > bigger.
> > 
> > So something which ARM does can make the result of efi_bs->GetMemoryMap
> > longer? Or are we talking about the bootinfo.mem array?
> 
> Not having looked at the code, I suppose the issue is with the
> sequence of
> - get memory map size
> - alloc memory for the map
> - get memory map
> where the middle step may alter the memory map size. But with any
> kind of sane allocator it ought to be reasonable to expect it to not
> grow by more than two entries (if the allocator chooses to take the
> middle of an existing free block), which could be accounted for up
> front.

I see, thanks.

Does x86 avoid this by using a static buffer or something? Or by the
"account for it up front" trick which you mention?

Ian.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 03/15] create arch functions to get and process EFI memory map.
  2014-09-12 10:23             ` Ian Campbell
@ 2014-09-12 10:35               ` Jan Beulich
  2014-09-12 17:01                 ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Jan Beulich @ 2014-09-12 10:35 UTC (permalink / raw)
  To: Ian Campbell; +Cc: keir, tim, xen-devel, Roy Franz, Stefano Stabellini, Fu Wei

>>> On 12.09.14 at 12:23, <Ian.Campbell@citrix.com> wrote:
> On Fri, 2014-09-12 at 10:56 +0100, Jan Beulich wrote:
>> >>> On 12.09.14 at 11:45, <Ian.Campbell@citrix.com> wrote:
>> > On Fri, 2014-09-12 at 08:07 +0100, Jan Beulich wrote:
>> >> >>> On 11.09.14 at 19:40, <roy.franz@linaro.org> wrote:
>> >> > On Thu, Sep 11, 2014 at 7:11 AM, Jan Beulich <JBeulich@suse.com> wrote:
>> >> >>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
>> >> >>> @@ -1171,67 +1169,12 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE 
> 
>> > *SystemTable)
>> >> >>>          }
>> >> >>>      }
>> >> >>>
>> >> >>> -    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
>> >> >>> -                         &efi_mdesc_size, &mdesc_ver);
>> >> >>> -    mbi.mem_upper -= efi_memmap_size;
>> >> >>> -    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
>> >> >>> -    if ( mbi.mem_upper < xen_phys_start )
>> >> >>> -        blexit(L"Out of static memory");
>> >> >>> -    efi_memmap = (void *)(long)mbi.mem_upper;
>> >> >>> -    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
>> >> >>> -                                  &efi_mdesc_size, &mdesc_ver);
>> >> >>> -    if ( EFI_ERROR(status) )
>> >> >>> -        PrintErrMesg(L"Cannot obtain memory map", status);
>> >> >>> +    efi_arch_get_memory_map(&mmap_size, &mmap, &mmap_key,
>> >> >>> +                                  &mmap_desc_size, &mmap_desc_ver);
>> >> >>
>> >> >> The only arch-specific bit here is where to put the map.
>> >> > Yes, but the ARM method of allocating the space can make the map
>> >> > bigger.
>> > 
>> > So something which ARM does can make the result of efi_bs->GetMemoryMap
>> > longer? Or are we talking about the bootinfo.mem array?
>> 
>> Not having looked at the code, I suppose the issue is with the
>> sequence of
>> - get memory map size
>> - alloc memory for the map
>> - get memory map
>> where the middle step may alter the memory map size. But with any
>> kind of sane allocator it ought to be reasonable to expect it to not
>> grow by more than two entries (if the allocator chooses to take the
>> middle of an existing free block), which could be accounted for up
>> front.
> 
> I see, thanks.
> 
> Does x86 avoid this by using a static buffer or something? Or by the
> "account for it up front" trick which you mention?

It uses a kind of static buffer.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 10/15] Add SMBIOS and runtime services setup arch functions.
  2014-09-12  7:14       ` Jan Beulich
@ 2014-09-12 16:24         ` Roy Franz
  0 siblings, 0 replies; 71+ messages in thread
From: Roy Franz @ 2014-09-12 16:24 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei


[-- Attachment #1.1: Type: text/plain, Size: 2349 bytes --]

On Fri, Sep 12, 2014 at 12:14 AM, Jan Beulich <JBeulich@suse.com> wrote:

> >>> On 12.09.14 at 00:03, <roy.franz@linaro.org> wrote:
> > On Thu, Sep 11, 2014 at 7:44 AM, Jan Beulich <JBeulich@suse.com> wrote:
> >>>>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
> >>> @@ -805,49 +801,13 @@ efi_start(EFI_HANDLE ImageHandle,
> EFI_SYSTEM_TABLE
> > *SystemTable)
> >>>          boot_cpu_data.x86_capability[1] = cpuid_ext_features;
> >>>      }
> >>>
> >>> -    /* Obtain basic table pointers. */
> >>> -    for ( i = 0; i < efi_num_ct; ++i )
> >>> -    {
> >>> -        static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
> >>> -        static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
> >>> -        static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
> >>> -        static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
> >>> -
> >>> -        if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
> >>> -            efi.acpi20 = (long)efi_ct[i].VendorTable;
> >>> -        if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
> >>> -            efi.acpi = (long)efi_ct[i].VendorTable;
> >>> -        if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
> >>> -            efi.mps = (long)efi_ct[i].VendorTable;
> >>> -        if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
> >>> -            efi.smbios = (long)efi_ct[i].VendorTable;
> >>> -    }
> >>
> >> The only arch specific things I can see throughout this entire patch
> >> are the specific GUIDs and which fields they go into in the internal
> >> structure. The GUIDs can be put in a table, and the fields can be
> >> represented e.g. via offsetof(), paired with the respective GUID.
> >>
> > The efi structure is defined in runtime.c for runtime use, which is
> > why I moved it,
> > as I am not addressing runtime services in this patchset.  This is an
> > (ab)use of
> > the architecture specific head file, using it for features that are
> > currently only implemented
> > on that architecture, rather than fundamental architectural differences.
>
> So how about you enable building runtime.c on ARM right away and
> for now simply #ifdef out everything but the variable definitions there?
>
> Jan
>
> I think this will work pretty well.  I have maybe been overly avoiding
#ifdefs..
I'll move the runtime.c/compat.c files to common/efi as well.

Roy

[-- Attachment #1.2: Type: text/html, Size: 3482 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 12/15] Add efi_arch_use_config_file() function to control use of config file
  2014-09-12  7:15       ` Jan Beulich
@ 2014-09-12 16:30         ` Roy Franz
  0 siblings, 0 replies; 71+ messages in thread
From: Roy Franz @ 2014-09-12 16:30 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, Stefano Stabellini, tim, xen-devel,
	Stefano Stabellini, Fu Wei


[-- Attachment #1.1: Type: text/plain, Size: 2635 bytes --]

On Fri, Sep 12, 2014 at 12:15 AM, Jan Beulich <JBeulich@suse.com> wrote:

> >>> On 12.09.14 at 01:54, <stefano.stabellini@eu.citrix.com> wrote:
> > On Thu, 11 Sep 2014, Jan Beulich wrote:
> >> >>> On 10.09.14 at 02:52, <roy.franz@linaro.org> wrote:
> >> > -    cols = rows = depth = 0;
> >> > -    if ( !base_video )
> >> > -    {
> >> > -        name.cs = get_value(&cfg, section.s, "video");
> >> > -        if ( !name.cs )
> >> > -            name.cs = get_value(&cfg, "global", "video");
> >> > -        if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
> >> > +        cols = rows = depth = 0;
> >> > +        if ( !base_video )
> >> >          {
> >> > -            cols = simple_strtoul(name.cs + 4, &name.cs, 10);
> >> > -            if ( *name.cs == 'x' )
> >> > -                rows = simple_strtoul(name.cs + 1, &name.cs, 10);
> >> > -            if ( *name.cs == 'x' )
> >> > -                depth = simple_strtoul(name.cs + 1, &name.cs, 10);
> >> > -            if ( *name.cs )
> >> > -                cols = rows = depth = 0;
> >> > +            name.cs = get_value(&cfg, section.s, "video");
> >> > +            if ( !name.cs )
> >> > +                name.cs = get_value(&cfg, "global", "video");
> >> > +            if ( name.cs && !strncmp(name.cs, "gfx-", 4) )
> >> > +            {
> >> > +                cols = simple_strtoul(name.cs + 4, &name.cs, 10);
> >> > +                if ( *name.cs == 'x' )
> >> > +                    rows = simple_strtoul(name.cs + 1, &name.cs, 10);
> >> > +                if ( *name.cs == 'x' )
> >> > +                    depth = simple_strtoul(name.cs + 1, &name.cs,
> 10);
> >> > +                if ( *name.cs )
> >> > +                    cols = rows = depth = 0;
> >> > +            }
> >>
> >> So how is this video mode selection being represented then without
> >> config file? Don't you need to at least add a command line option for
> >> that?
> >
> > The scenario without config file is the one where Xen is loaded by GRUB.
> > Do we actually need to pass a video mode option in that case?
> > Wouldn't GRUB take care of changing video mode itself to the value
> > specified by the user before booting Xen? Xen can query the current
> > video mode afterwards.
>
> Ah, right, that's a good point.
>
> Jan
>
> I think we can leave this to GRUB in this case.  It seems to have the
capability to set
video modes use EFI calls so it should be able to take care of this as well
as the EFI boot
portion of XEN.  One of the difficulties with arm64 development right now
is that most of it is being
done on platforms without video, so any video code is rarely used or
tested.

Roy

[-- Attachment #1.2: Type: text/html, Size: 4066 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 02/15] Move x86 specific funtions/variables to arch header
  2014-09-12  7:04       ` Jan Beulich
  2014-09-12  9:43         ` Ian Campbell
@ 2014-09-12 16:52         ` Roy Franz
  1 sibling, 0 replies; 71+ messages in thread
From: Roy Franz @ 2014-09-12 16:52 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei


[-- Attachment #1.1: Type: text/plain, Size: 5066 bytes --]

On Fri, Sep 12, 2014 at 12:04 AM, Jan Beulich <JBeulich@suse.com> wrote:

> >>> On 11.09.14 at 19:33, <roy.franz@linaro.org> wrote:
> > On Thu, Sep 11, 2014 at 7:03 AM, Jan Beulich <JBeulich@suse.com> wrote:
> >>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> >>> -/* Using SetVirtualAddressMap() is incompatible with kexec: */
> >>> -#undef USE_SET_VIRTUAL_ADDRESS_MAP
> >>
> >> In which way is this arch-specific?
> > The define is only used by the x86 specific code.  I can move it back
> > to the common code.
>
> Yes please, as the conflict with kexec is an arch-independent one.
>
> >>> -static void __init place_string(u32 *addr, const char *s)
> >>> -{
> >>> -    static char *__initdata alloc = start;
> >>> -
> >>> -    if ( s && *s )
> >>> -    {
> >>> -        size_t len1 = strlen(s) + 1;
> >>> -        const char *old = (char *)(long)*addr;
> >>> -        size_t len2 = *addr ? strlen(old) + 1 : 0;
> >>> -
> >>> -        alloc -= len1 + len2;
> >>> -        /*
> >>> -         * Insert new string before already existing one. This is
> needed
> >>> -         * for options passed on the command line to override options
> from
> >>> -         * the configuration file.
> >>> -         */
> >>> -        memcpy(alloc, s, len1);
> >>> -        if ( *addr )
> >>> -        {
> >>> -            alloc[len1 - 1] = ' ';
> >>> -            memcpy(alloc + len1, old, len2);
> >>> -        }
> >>> -    }
> >>> -    *addr = (long)alloc;
> >>> -}
> >>
> >> How much of this is really arch-specific?
> >
> > This is only used by the x86 code, and this is the x86 specific memory
> > management that uses
> > memory allocated by the linker script before start.  The ARM boot code
> > does not use this.
>
> I.e. the only arch-specific thing here is the initializer of "alloc". Or
> are you saying that you don't need a place_string() function in
> ARM at all? Is that because to stuff respective information into DT?
>
ARM doesn't use place_string() at all.  All the information is placed into
the DT that has EFI allocated memory for it.


>
> >>> -static void __init setup_efi_pci(void)
> >>
> >> And this doesn't seem arch-specific either (it only depends on
> >> HAS_PCI or some such).
> >
> > This does scanning of PCI ROMS, which is unlikely to do anything
> > useful on ARM platforms.
>
> Why not? Obviously if the ROMs contain x86 code, they're useless,
> but in order to, say, do remote boot I suppose you need option
> ROMs (with ARM code) on ARM too.
>

Yes, something like that may exist someday.  This can get moved back
with the #ifdef'ing of the runtime.c implementation.

>
> > I also have no way to test this on ARM.
> > I can try to pull this back in, but I may run into dependency issues
> > such as those with VGA, where I did not
> > want to pull in otherwise unused (and likely unusable on ARM)
> > drivers/subsystems in order to keep a little more
> > code in the common EFI boot path.
>
> The base line should be too keep everything here that is potentially
> usable on more than one arch (without limiting our thinking to ARM
> and x86). EFI's protocol based approach abstracts this quite nicely
> - if something isn't available, you simply won't find th respective
> protocol.
>

I'll take a look at just factoring out the VGA specific stuff - I agree that
is all that needs to be in the x86 specific file.



>
> >>> --- /dev/null
> >>> +++ b/xen/include/asm-x86/efi-boot.h
> >>> @@ -0,0 +1,451 @@
> >>> +/*
> >>> + * Architecture specific implementation for EFI boot code.  This file
> >>> + * is intended to be included by XXX _only_, and therefore can define
> >>> + * arch specific global variables.
> >>> + */
> >>> +#include <asm/e820.h>
> >>> +#include <asm/edd.h>
> >>> +#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with
> EFI) */
> >>> +#include <asm/fixmap.h>
> >>> +#undef __ASSEMBLY__
> >>> +#include <asm/msr.h>
> >>> +#include <asm/processor.h>
> >>> +
> >>> +static struct file __initdata ucode;
> >>> +static multiboot_info_t __initdata mbi = {
> >>> +    .flags = MBI_MODULES | MBI_LOADERNAME
> >>> +};
> >>> +static module_t __initdata mb_modules[3];
> >>> +
> >>> +static void noreturn blexit(const CHAR16 *str);
> >>> +static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
> >>
> >> What are these two doing here?
> >
> > These are forward declarations.  I don't think that I can order
> > everything so that I don't need any forward declarations
> > anywhere.
>
> I realize you may need forward declarations. But you declare arch-
> independent functions in an arch header here.
>
> >>> +void __init efi_init_memory(void)
> >>
> >> Now that I look at it again, I think a good part of this is arch-
> >> independent too.
> > By "this" you mean the code in efi_init_memory?
>
> Yes, at least everything up to and including the
> SetVirtualAddressMap() call.
>

This is only called from x86/mm.c, so it is currently unused on ARM.
If it causes compile problems on ARM I can #ifdef it, since this will need
to be dealt with as part
of adding runtime service support.

>
> Jan
>

[-- Attachment #1.2: Type: text/html, Size: 7521 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices
  2014-09-12  9:58           ` Jan Beulich
@ 2014-09-12 16:57             ` Roy Franz
  2014-09-15  8:47               ` Jan Beulich
  0 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-12 16:57 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei


[-- Attachment #1.1: Type: text/plain, Size: 2077 bytes --]

On Fri, Sep 12, 2014 at 2:58 AM, Jan Beulich <JBeulich@suse.com> wrote:

> >>> On 12.09.14 at 11:46, <Ian.Campbell@citrix.com> wrote:
> > On Fri, 2014-09-12 at 08:08 +0100, Jan Beulich wrote:
> >> >>> On 11.09.14 at 19:44, <roy.franz@linaro.org> wrote:
> >> > On Thu, Sep 11, 2014 at 7:13 AM, Jan Beulich <JBeulich@suse.com>
> wrote:
> >> >>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> >> >>>      status = efi_bs->ExitBootServices(ImageHandle, mmap_key);
> >> >>>      if ( EFI_ERROR(status) )
> >> >>>          PrintErrMesg(L"Cannot exit boot services", status);
> >> >>>
> >> >>> -    /* Adjust pointers into EFI. */
> >> >>> -    efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
> >> >>> -#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
> >> >>> -    efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
> >> >>> -#endif
> >> >>> -    efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
> >> >>> -    efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START;
> >> >>> -
> >> >>> -    efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
> >> >>
> >> >> Up to here I don't see anything arch-specific again.
> >> > This is due to runtime services not being implemented.  The "efi_rs"
> >> > variable is defined in the runtime services
> >> > file runtime.c, which is not yet ported to ARM.
> >> >
> >> > Short of including ARM runtime service support in the patchset, how
> >> > would you like this handled?
> >>
> >> As said before, everything that's generic but not used/usable on
> >> ARM right now should stay here, but get made conditional in one
> >> or another way.
> >
> > So in this case a HAVE_EFI_RUNTIMESERVICES ifdef would work?
>
> Yes (except that in the case I would use NEED_ or WANT_ instead
> of HAVE_). But considering this is intended to be temporary, I'd
> even be fine with just using CONFIG_ARM or alike here.
>
> Jan
>
> OK, I'll move this back.  Just having the #ifdefs in runtime.c will help a
lot.

Is commenting the #ifef like so acceptable:

#ifndef CONFIG_ARM  /* TODO - disabled until EFI runtime services
implemented */

Thanks,
Roy

[-- Attachment #1.2: Type: text/html, Size: 3310 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 03/15] create arch functions to get and process EFI memory map.
  2014-09-12 10:35               ` Jan Beulich
@ 2014-09-12 17:01                 ` Roy Franz
  0 siblings, 0 replies; 71+ messages in thread
From: Roy Franz @ 2014-09-12 17:01 UTC (permalink / raw)
  To: Jan Beulich
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei


[-- Attachment #1.1: Type: text/plain, Size: 2792 bytes --]

On Fri, Sep 12, 2014 at 3:35 AM, Jan Beulich <JBeulich@suse.com> wrote:

> >>> On 12.09.14 at 12:23, <Ian.Campbell@citrix.com> wrote:
> > On Fri, 2014-09-12 at 10:56 +0100, Jan Beulich wrote:
> >> >>> On 12.09.14 at 11:45, <Ian.Campbell@citrix.com> wrote:
> >> > On Fri, 2014-09-12 at 08:07 +0100, Jan Beulich wrote:
> >> >> >>> On 11.09.14 at 19:40, <roy.franz@linaro.org> wrote:
> >> >> > On Thu, Sep 11, 2014 at 7:11 AM, Jan Beulich <JBeulich@suse.com>
> wrote:
> >> >> >>>>> On 10.09.14 at 02:51, <roy.franz@linaro.org> wrote:
> >> >> >>> @@ -1171,67 +1169,12 @@ efi_start(EFI_HANDLE ImageHandle,
> EFI_SYSTEM_TABLE
> >
> >> > *SystemTable)
> >> >> >>>          }
> >> >> >>>      }
> >> >> >>>
> >> >> >>> -    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
> >> >> >>> -                         &efi_mdesc_size, &mdesc_ver);
> >> >> >>> -    mbi.mem_upper -= efi_memmap_size;
> >> >> >>> -    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
> >> >> >>> -    if ( mbi.mem_upper < xen_phys_start )
> >> >> >>> -        blexit(L"Out of static memory");
> >> >> >>> -    efi_memmap = (void *)(long)mbi.mem_upper;
> >> >> >>> -    status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap,
> &map_key,
> >> >> >>> -                                  &efi_mdesc_size, &mdesc_ver);
> >> >> >>> -    if ( EFI_ERROR(status) )
> >> >> >>> -        PrintErrMesg(L"Cannot obtain memory map", status);
> >> >> >>> +    efi_arch_get_memory_map(&mmap_size, &mmap, &mmap_key,
> >> >> >>> +                                  &mmap_desc_size,
> &mmap_desc_ver);
> >> >> >>
> >> >> >> The only arch-specific bit here is where to put the map.
> >> >> > Yes, but the ARM method of allocating the space can make the map
> >> >> > bigger.
> >> >
> >> > So something which ARM does can make the result of
> efi_bs->GetMemoryMap
> >> > longer? Or are we talking about the bootinfo.mem array?
> >>
> >> Not having looked at the code, I suppose the issue is with the
> >> sequence of
> >> - get memory map size
> >> - alloc memory for the map
> >> - get memory map
> >> where the middle step may alter the memory map size. But with any
> >> kind of sane allocator it ought to be reasonable to expect it to not
> >> grow by more than two entries (if the allocator chooses to take the
> >> middle of an existing free block), which could be accounted for up
> >> front.
> >
> > I see, thanks.
> >
> > Does x86 avoid this by using a static buffer or something? Or by the
> > "account for it up front" trick which you mention?
>
> It uses a kind of static buffer.
>
> Jan
>
> Increasing the buffer size should work.  I will make it a page size
larger, as that is the allocation granularity of the
EFI allocator, and should be generous enough to avoid any problems, while
not being excessively large.

Roy

[-- Attachment #1.2: Type: text/html, Size: 4527 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-12  3:21     ` Roy Franz
@ 2014-09-12 17:41       ` Stefano Stabellini
  2014-09-12 17:50         ` Roy Franz
  0 siblings, 1 reply; 71+ messages in thread
From: Stefano Stabellini @ 2014-09-12 17:41 UTC (permalink / raw)
  To: Roy Franz
  Cc: keir, Ian Campbell, Stefano Stabellini, tim, xen-devel,
	Stefano Stabellini, Jan Beulich, Fu Wei

[-- Attachment #1: Type: text/plain, Size: 14774 bytes --]

Please use plain text in emails, no html.

On Thu, 11 Sep 2014, Roy Franz wrote:
> On Thu, Sep 11, 2014 at 5:49 PM, Stefano Stabellini <stefano.stabellini@eu.citrix.com> wrote:
>       On Tue, 9 Sep 2014, Roy Franz wrote:
>       > This patch adds EFI boot support for ARM based on the previous refactoring of
>       > the x86 EFI boot code.  All ARM specific code is in the ARM efi-boot.h header
>       > file, with the main EFI entry point common/efi/boot.c.  The PE/COFF header is
>       > open-coded in head.S, which allows us to have a single binary be both an EFI
>       > executable and a normal arm64 IMAGE file. There is currently no PE/COFF
>       > toolchain support for arm64, so it is not possible to create the PE/COFF header
>       > in the same manner as on x86.  This also simplifies the build as compared to
>       > x86, as we always build the same executable, whereas x86 builds 2.  An ARM
>       > version of efi-bind.h is added, which is based on the x86_64 version with the
>       > x86 specific portions removed.  The Makefile in common/efi is different for x86
>       > and ARM, as for ARM we always build in EFI support.
>       >
>       > Signed-off-by: Roy Franz <roy.franz@linaro.org>
>       > ---
>       >  config/arm64.mk                     |   1 +
>       >  xen/arch/arm/arm64/head.S           | 150 ++++++++-
>       >  xen/arch/arm/xen.lds.S              |   1 +
>       >  xen/common/Makefile                 |   1 +
>       >  xen/common/efi/Makefile             |   3 +
>       >  xen/include/asm-arm/arm64/efibind.h | 216 +++++++++++++
>       >  xen/include/asm-arm/efi-boot.h      | 630 ++++++++++++++++++++++++++++++++++++
>       >  xen/include/asm-arm/efi.h           |  29 ++
>       >  xen/include/asm-arm/efibind.h       |   2 +
>       >  xen/include/asm-arm/setup.h         |   2 +-
>       >  10 files changed, 1031 insertions(+), 4 deletions(-)
>       >  create mode 100644 xen/common/efi/Makefile
>       >  create mode 100644 xen/include/asm-arm/arm64/efibind.h
>       >  create mode 100644 xen/include/asm-arm/efi-boot.h
>       >  create mode 100644 xen/include/asm-arm/efi.h
>       >  create mode 100644 xen/include/asm-arm/efibind.h
>       >
>       > diff --git a/config/arm64.mk b/config/arm64.mk
>       > index 15b57a4..e6aab0e 100644
>       > --- a/config/arm64.mk
>       > +++ b/config/arm64.mk
>       > @@ -1,6 +1,7 @@
>       >  CONFIG_ARM := y
>       >  CONFIG_ARM_64 := y
>       >  CONFIG_ARM_$(XEN_OS) := y
>       > +CONFIG_EFI := y
>       >
>       >  CONFIG_XEN_INSTALL_SUFFIX :=
>       >
>       > diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
>       > index 43b5e72..158c102 100644
>       > --- a/xen/arch/arm/arm64/head.S
>       > +++ b/xen/arch/arm/arm64/head.S
>       > @@ -24,6 +24,8 @@
>       >  #include <asm/page.h>
>       >  #include <asm/asm_defns.h>
>       >  #include <asm/early_printk.h>
>       > +#include <efi/efierr.h>
>       > +#include <asm/arm64/efibind.h>
>       >
>       >  #define PT_PT     0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
>       >  #define PT_MEM    0xf7d /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=0 P=1 */
>       > @@ -104,8 +106,14 @@ GLOBAL(start)
>       >          /*
>       >           * DO NOT MODIFY. Image header expected by Linux boot-loaders.
>       >           */
>       > -        b       real_start           /* branch to kernel start, magic */
>       > -        .long   0                    /* reserved */
>       > +efi_head:
>       > +        /*
>       > +         * This add instruction has no meaningful effect except that
>       > +         * its opcode forms the magic "MZ" signature of a PE/COFF file
>       > +         * that is required for UEFI applications.
>       > +         */
>       > +        add     x13, x18, #0x16
>       > +        b       real_start           /* branch to kernel start */
>       >          .quad   0                    /* Image load offset from start of RAM */
>       >          .quad   0                    /* reserved */
>       >          .quad   0                    /* reserved */
>       > @@ -116,8 +124,113 @@ GLOBAL(start)
>       >          .byte   0x52
>       >          .byte   0x4d
>       >          .byte   0x64
>       > -        .word   0                    /* reserved */
>       > +        .long   pe_header - efi_head        /* Offset to the PE header. */
>       > +
>       > +        /*
>       > +         * Add the PE/COFF header to the file.  The address of this header
>       > +         * is at offset 0x3c in the file, and is part of Linux "Image"
>       > +         * header.  The arm64 Linux Image format is designed to support
>       > +         * being both an 'Image' format binary and a PE/COFF binary.
>       > +         * The PE/COFF format is defined by Microsoft, and is available
>       > +         * from: http://msdn.microsoft.com/en-us/gg463119.aspx
>       > +         * Version 8.3 adds support for arm64 and UEFI usage.
>       > +         */
>       > +
>       > +        .align  3
>       > +pe_header:
>       > +        .ascii  "PE"
>       > +        .short  0
>       > +coff_header:
>       > +        .short  0xaa64                          /* AArch64 */
>       > +        .short  2                               /* nr_sections */
>       > +        .long   0                               /* TimeDateStamp */
>       > +        .long   0                               /* PointerToSymbolTable */
>       > +        .long   1                               /* NumberOfSymbols */
>       > +        .short  section_table - optional_header /* SizeOfOptionalHeader */
>       > +        .short  0x206                           /* Characteristics. */
>       > +                                                /* IMAGE_FILE_DEBUG_STRIPPED | */
>       > +                                                /* IMAGE_FILE_EXECUTABLE_IMAGE | */
>       > +                                                /* IMAGE_FILE_LINE_NUMS_STRIPPED */
>       > +optional_header:
>       > +        .short  0x20b                           /* PE32+ format */
>       > +        .byte   0x02                            /* MajorLinkerVersion */
>       > +        .byte   0x14                            /* MinorLinkerVersion */
>       > +        .long   _end - real_start               /* SizeOfCode */
>       > +        .long   0                               /* SizeOfInitializedData */
>       > +        .long   0                               /* SizeOfUninitializedData */
>       > +        .long   efi_start - efi_head            /* AddressOfEntryPoint */
>       > +        .long   real_start - efi_head           /* BaseOfCode */
>       > +
>       > +extra_header_fields:
>       > +        .quad   0                               /* ImageBase */
>       > +        .long   0x1000                          /* SectionAlignment (4 KByte) */
>       > +        .long   0x8                             /* FileAlignment */
>       > +        .short  0                               /* MajorOperatingSystemVersion */
>       > +        .short  0                               /* MinorOperatingSystemVersion */
>       > +        .short  0                               /* MajorImageVersion */
>       > +        .short  0                               /* MinorImageVersion */
>       > +        .short  0                               /* MajorSubsystemVersion */
>       > +        .short  0                               /* MinorSubsystemVersion */
>       > +        .long   0                               /* Win32VersionValue */
>       > +
>       > +        .long   _end - efi_head                 /* SizeOfImage */
>       > +
>       > +        /* Everything before the kernel image is considered part of the header */
>       > +        .long   real_start - efi_head           /* SizeOfHeaders */
>       > +        .long   0                               /* CheckSum */
>       > +        .short  0xa                             /* Subsystem (EFI application) */
>       > +        .short  0                               /* DllCharacteristics */
>       > +        .quad   0                               /* SizeOfStackReserve */
>       > +        .quad   0                               /* SizeOfStackCommit */
>       > +        .quad   0                               /* SizeOfHeapReserve */
>       > +        .quad   0                               /* SizeOfHeapCommit */
>       > +        .long   0                               /* LoaderFlags */
>       > +        .long   0x6                             /* NumberOfRvaAndSizes */
>       > +
>       > +        .quad   0                               /* ExportTable */
>       > +        .quad   0                               /* ImportTable */
>       > +        .quad   0                               /* ResourceTable */
>       > +        .quad   0                               /* ExceptionTable */
>       > +        .quad   0                               /* CertificationTable */
>       > +        .quad   0                               /* BaseRelocationTable */
>       > +
>       > +        /* Section table */
>       > +section_table:
>       >
>       > +        /*
>       > +         * The EFI application loader requires a relocation section
>       > +         * because EFI applications must be relocatable.  This is a
>       > +         * dummy section as far as we are concerned.
>       > +         */
>       > +        .ascii  ".reloc"
>       > +        .byte   0
>       > +        .byte   0                               /* end of 0 padding of section name */
>       > +        .long   0
>       > +        .long   0
>       > +        .long   0                               /* SizeOfRawData */
>       > +        .long   0                               /* PointerToRawData */
>       > +        .long   0                               /* PointerToRelocations */
>       > +        .long   0                               /* PointerToLineNumbers */
>       > +        .short  0                               /* NumberOfRelocations */
>       > +        .short  0                               /* NumberOfLineNumbers */
>       > +        .long   0x42100040                      /* Characteristics (section flags) */
>       > +
>       > +
>       > +        .ascii  ".text"
>       > +        .byte   0
>       > +        .byte   0
>       > +        .byte   0                               /* end of 0 padding of section name */
>       > +        .long   _end - real_start               /* VirtualSize */
>       > +        .long   real_start - efi_head           /* VirtualAddress */
>       > +        .long   __init_end_efi - real_start     /* SizeOfRawData */
>       > +        .long   real_start - efi_head           /* PointerToRawData */
>       > +
>       > +        .long   0                /* PointerToRelocations (0 for executables) */
>       > +        .long   0                /* PointerToLineNumbers (0 for executables) */
>       > +        .short  0                /* NumberOfRelocations  (0 for executables) */
>       > +        .short  0                /* NumberOfLineNumbers  (0 for executables) */
>       > +        .long   0xe0500020       /* Characteristics (section flags) */
>       > +        .align  5
>       >  real_start:
>       >          msr   DAIFSet, 0xf           /* Disable all interrupts */
>       >
>       > @@ -617,6 +730,37 @@ putn:   ret
>       >  ENTRY(lookup_processor_type)
>       >          mov  x0, #0
>       >          ret
>       > +/*
>       > + *  Function to transition from EFI loader in C, to Xen entry point.
>       > + *  void noreturn efi_xen_start(void *fdt_ptr);
>       > + */
>       > +ENTRY(efi_xen_start)
>       > +        /*
>       > +         * Turn off cache and MMU as Xen expects. EFI enables them, but also
>       > +         * mandates a 1:1 (unity) VA->PA mapping, so we can turn off the
>       > +         * MMU while executing EFI code before entering Xen.
>       > +         * The EFI loader calls this to start Xen.
>       > +         * Preserve x0 (fdf pointer) across call to __flush_dcache_all,
>       > +         * restore for entry into Xen.
>       > +         */
>       > +        mov   x20, x0
>       > +        bl    __flush_dcache_all
>       > +        ic    ialluis
>       > +
>       > +        /* Turn off Dcache and MMU */
>       > +        mrs   x0, sctlr_el2
>       > +        bic   x0, x0, #1 << 0        /* clear SCTLR.M */
>       > +        bic   x0, x0, #1 << 2        /* clear SCTLR.C */
> 
> dsb?
> 
> The dsb is done at the end of  __flush_dcache_all
 
I think this would be to make sure __flush_dcache_all reads the correct
arguments. We do the same when enabling dcache.

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-12 17:41       ` Stefano Stabellini
@ 2014-09-12 17:50         ` Roy Franz
  2014-09-12 17:55           ` Stefano Stabellini
  0 siblings, 1 reply; 71+ messages in thread
From: Roy Franz @ 2014-09-12 17:50 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini,
	Jan Beulich, Fu Wei

On Fri, Sep 12, 2014 at 10:41 AM, Stefano Stabellini
<stefano.stabellini@eu.citrix.com> wrote:
> Please use plain text in emails, no html.
>
> On Thu, 11 Sep 2014, Roy Franz wrote:
>> On Thu, Sep 11, 2014 at 5:49 PM, Stefano Stabellini <stefano.stabellini@eu.citrix.com> wrote:
>>       On Tue, 9 Sep 2014, Roy Franz wrote:
>>       > This patch adds EFI boot support for ARM based on the previous refactoring of
>>       > the x86 EFI boot code.  All ARM specific code is in the ARM efi-boot.h header
>>       > file, with the main EFI entry point common/efi/boot.c.  The PE/COFF header is
>>       > open-coded in head.S, which allows us to have a single binary be both an EFI
>>       > executable and a normal arm64 IMAGE file. There is currently no PE/COFF
>>       > toolchain support for arm64, so it is not possible to create the PE/COFF header
>>       > in the same manner as on x86.  This also simplifies the build as compared to
>>       > x86, as we always build the same executable, whereas x86 builds 2.  An ARM
>>       > version of efi-bind.h is added, which is based on the x86_64 version with the
>>       > x86 specific portions removed.  The Makefile in common/efi is different for x86
>>       > and ARM, as for ARM we always build in EFI support.
>>       >
>>       > Signed-off-by: Roy Franz <roy.franz@linaro.org>
>>       > ---
>>       >  config/arm64.mk                     |   1 +
>>       >  xen/arch/arm/arm64/head.S           | 150 ++++++++-
>>       >  xen/arch/arm/xen.lds.S              |   1 +
>>       >  xen/common/Makefile                 |   1 +
>>       >  xen/common/efi/Makefile             |   3 +
>>       >  xen/include/asm-arm/arm64/efibind.h | 216 +++++++++++++
>>       >  xen/include/asm-arm/efi-boot.h      | 630 ++++++++++++++++++++++++++++++++++++
>>       >  xen/include/asm-arm/efi.h           |  29 ++
>>       >  xen/include/asm-arm/efibind.h       |   2 +
>>       >  xen/include/asm-arm/setup.h         |   2 +-
>>       >  10 files changed, 1031 insertions(+), 4 deletions(-)
>>       >  create mode 100644 xen/common/efi/Makefile
>>       >  create mode 100644 xen/include/asm-arm/arm64/efibind.h
>>       >  create mode 100644 xen/include/asm-arm/efi-boot.h
>>       >  create mode 100644 xen/include/asm-arm/efi.h
>>       >  create mode 100644 xen/include/asm-arm/efibind.h
>>       >
>>       > diff --git a/config/arm64.mk b/config/arm64.mk
>>       > index 15b57a4..e6aab0e 100644
>>       > --- a/config/arm64.mk
>>       > +++ b/config/arm64.mk
>>       > @@ -1,6 +1,7 @@
>>       >  CONFIG_ARM := y
>>       >  CONFIG_ARM_64 := y
>>       >  CONFIG_ARM_$(XEN_OS) := y
>>       > +CONFIG_EFI := y
>>       >
>>       >  CONFIG_XEN_INSTALL_SUFFIX :=
>>       >
>>       > diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
>>       > index 43b5e72..158c102 100644
>>       > --- a/xen/arch/arm/arm64/head.S
>>       > +++ b/xen/arch/arm/arm64/head.S
>>       > @@ -24,6 +24,8 @@
>>       >  #include <asm/page.h>
>>       >  #include <asm/asm_defns.h>
>>       >  #include <asm/early_printk.h>
>>       > +#include <efi/efierr.h>
>>       > +#include <asm/arm64/efibind.h>
>>       >
>>       >  #define PT_PT     0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
>>       >  #define PT_MEM    0xf7d /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=0 P=1 */
>>       > @@ -104,8 +106,14 @@ GLOBAL(start)
>>       >          /*
>>       >           * DO NOT MODIFY. Image header expected by Linux boot-loaders.
>>       >           */
>>       > -        b       real_start           /* branch to kernel start, magic */
>>       > -        .long   0                    /* reserved */
>>       > +efi_head:
>>       > +        /*
>>       > +         * This add instruction has no meaningful effect except that
>>       > +         * its opcode forms the magic "MZ" signature of a PE/COFF file
>>       > +         * that is required for UEFI applications.
>>       > +         */
>>       > +        add     x13, x18, #0x16
>>       > +        b       real_start           /* branch to kernel start */
>>       >          .quad   0                    /* Image load offset from start of RAM */
>>       >          .quad   0                    /* reserved */
>>       >          .quad   0                    /* reserved */
>>       > @@ -116,8 +124,113 @@ GLOBAL(start)
>>       >          .byte   0x52
>>       >          .byte   0x4d
>>       >          .byte   0x64
>>       > -        .word   0                    /* reserved */
>>       > +        .long   pe_header - efi_head        /* Offset to the PE header. */
>>       > +
>>       > +        /*
>>       > +         * Add the PE/COFF header to the file.  The address of this header
>>       > +         * is at offset 0x3c in the file, and is part of Linux "Image"
>>       > +         * header.  The arm64 Linux Image format is designed to support
>>       > +         * being both an 'Image' format binary and a PE/COFF binary.
>>       > +         * The PE/COFF format is defined by Microsoft, and is available
>>       > +         * from: http://msdn.microsoft.com/en-us/gg463119.aspx
>>       > +         * Version 8.3 adds support for arm64 and UEFI usage.
>>       > +         */
>>       > +
>>       > +        .align  3
>>       > +pe_header:
>>       > +        .ascii  "PE"
>>       > +        .short  0
>>       > +coff_header:
>>       > +        .short  0xaa64                          /* AArch64 */
>>       > +        .short  2                               /* nr_sections */
>>       > +        .long   0                               /* TimeDateStamp */
>>       > +        .long   0                               /* PointerToSymbolTable */
>>       > +        .long   1                               /* NumberOfSymbols */
>>       > +        .short  section_table - optional_header /* SizeOfOptionalHeader */
>>       > +        .short  0x206                           /* Characteristics. */
>>       > +                                                /* IMAGE_FILE_DEBUG_STRIPPED | */
>>       > +                                                /* IMAGE_FILE_EXECUTABLE_IMAGE | */
>>       > +                                                /* IMAGE_FILE_LINE_NUMS_STRIPPED */
>>       > +optional_header:
>>       > +        .short  0x20b                           /* PE32+ format */
>>       > +        .byte   0x02                            /* MajorLinkerVersion */
>>       > +        .byte   0x14                            /* MinorLinkerVersion */
>>       > +        .long   _end - real_start               /* SizeOfCode */
>>       > +        .long   0                               /* SizeOfInitializedData */
>>       > +        .long   0                               /* SizeOfUninitializedData */
>>       > +        .long   efi_start - efi_head            /* AddressOfEntryPoint */
>>       > +        .long   real_start - efi_head           /* BaseOfCode */
>>       > +
>>       > +extra_header_fields:
>>       > +        .quad   0                               /* ImageBase */
>>       > +        .long   0x1000                          /* SectionAlignment (4 KByte) */
>>       > +        .long   0x8                             /* FileAlignment */
>>       > +        .short  0                               /* MajorOperatingSystemVersion */
>>       > +        .short  0                               /* MinorOperatingSystemVersion */
>>       > +        .short  0                               /* MajorImageVersion */
>>       > +        .short  0                               /* MinorImageVersion */
>>       > +        .short  0                               /* MajorSubsystemVersion */
>>       > +        .short  0                               /* MinorSubsystemVersion */
>>       > +        .long   0                               /* Win32VersionValue */
>>       > +
>>       > +        .long   _end - efi_head                 /* SizeOfImage */
>>       > +
>>       > +        /* Everything before the kernel image is considered part of the header */
>>       > +        .long   real_start - efi_head           /* SizeOfHeaders */
>>       > +        .long   0                               /* CheckSum */
>>       > +        .short  0xa                             /* Subsystem (EFI application) */
>>       > +        .short  0                               /* DllCharacteristics */
>>       > +        .quad   0                               /* SizeOfStackReserve */
>>       > +        .quad   0                               /* SizeOfStackCommit */
>>       > +        .quad   0                               /* SizeOfHeapReserve */
>>       > +        .quad   0                               /* SizeOfHeapCommit */
>>       > +        .long   0                               /* LoaderFlags */
>>       > +        .long   0x6                             /* NumberOfRvaAndSizes */
>>       > +
>>       > +        .quad   0                               /* ExportTable */
>>       > +        .quad   0                               /* ImportTable */
>>       > +        .quad   0                               /* ResourceTable */
>>       > +        .quad   0                               /* ExceptionTable */
>>       > +        .quad   0                               /* CertificationTable */
>>       > +        .quad   0                               /* BaseRelocationTable */
>>       > +
>>       > +        /* Section table */
>>       > +section_table:
>>       >
>>       > +        /*
>>       > +         * The EFI application loader requires a relocation section
>>       > +         * because EFI applications must be relocatable.  This is a
>>       > +         * dummy section as far as we are concerned.
>>       > +         */
>>       > +        .ascii  ".reloc"
>>       > +        .byte   0
>>       > +        .byte   0                               /* end of 0 padding of section name */
>>       > +        .long   0
>>       > +        .long   0
>>       > +        .long   0                               /* SizeOfRawData */
>>       > +        .long   0                               /* PointerToRawData */
>>       > +        .long   0                               /* PointerToRelocations */
>>       > +        .long   0                               /* PointerToLineNumbers */
>>       > +        .short  0                               /* NumberOfRelocations */
>>       > +        .short  0                               /* NumberOfLineNumbers */
>>       > +        .long   0x42100040                      /* Characteristics (section flags) */
>>       > +
>>       > +
>>       > +        .ascii  ".text"
>>       > +        .byte   0
>>       > +        .byte   0
>>       > +        .byte   0                               /* end of 0 padding of section name */
>>       > +        .long   _end - real_start               /* VirtualSize */
>>       > +        .long   real_start - efi_head           /* VirtualAddress */
>>       > +        .long   __init_end_efi - real_start     /* SizeOfRawData */
>>       > +        .long   real_start - efi_head           /* PointerToRawData */
>>       > +
>>       > +        .long   0                /* PointerToRelocations (0 for executables) */
>>       > +        .long   0                /* PointerToLineNumbers (0 for executables) */
>>       > +        .short  0                /* NumberOfRelocations  (0 for executables) */
>>       > +        .short  0                /* NumberOfLineNumbers  (0 for executables) */
>>       > +        .long   0xe0500020       /* Characteristics (section flags) */
>>       > +        .align  5
>>       >  real_start:
>>       >          msr   DAIFSet, 0xf           /* Disable all interrupts */
>>       >
>>       > @@ -617,6 +730,37 @@ putn:   ret
>>       >  ENTRY(lookup_processor_type)
>>       >          mov  x0, #0
>>       >          ret
>>       > +/*
>>       > + *  Function to transition from EFI loader in C, to Xen entry point.
>>       > + *  void noreturn efi_xen_start(void *fdt_ptr);
>>       > + */
>>       > +ENTRY(efi_xen_start)
>>       > +        /*
>>       > +         * Turn off cache and MMU as Xen expects. EFI enables them, but also
>>       > +         * mandates a 1:1 (unity) VA->PA mapping, so we can turn off the
>>       > +         * MMU while executing EFI code before entering Xen.
>>       > +         * The EFI loader calls this to start Xen.
>>       > +         * Preserve x0 (fdf pointer) across call to __flush_dcache_all,
>>       > +         * restore for entry into Xen.
>>       > +         */
>>       > +        mov   x20, x0
>>       > +        bl    __flush_dcache_all
>>       > +        ic    ialluis
>>       > +
>>       > +        /* Turn off Dcache and MMU */
>>       > +        mrs   x0, sctlr_el2
>>       > +        bic   x0, x0, #1 << 0        /* clear SCTLR.M */
>>       > +        bic   x0, x0, #1 << 2        /* clear SCTLR.C */
>>
>> dsb?
>>
>> The dsb is done at the end of  __flush_dcache_all
>
> I think this would be to make sure __flush_dcache_all reads the correct
> arguments. We do the same when enabling dcache.

So where exactly are you suggesting the dsb?  Before the call to
__flush_dcache_all?

Roy
sorry about the html... gmail switches it back to html sometines...

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-12 17:50         ` Roy Franz
@ 2014-09-12 17:55           ` Stefano Stabellini
  2014-09-22 11:13             ` Ian Campbell
  0 siblings, 1 reply; 71+ messages in thread
From: Stefano Stabellini @ 2014-09-12 17:55 UTC (permalink / raw)
  To: Roy Franz
  Cc: keir, Ian Campbell, Stefano Stabellini, tim, xen-devel,
	Stefano Stabellini, Jan Beulich, Fu Wei

On Fri, 12 Sep 2014, Roy Franz wrote:
> On Fri, Sep 12, 2014 at 10:41 AM, Stefano Stabellini
> <stefano.stabellini@eu.citrix.com> wrote:
> > Please use plain text in emails, no html.
> >
> > On Thu, 11 Sep 2014, Roy Franz wrote:
> >> On Thu, Sep 11, 2014 at 5:49 PM, Stefano Stabellini <stefano.stabellini@eu.citrix.com> wrote:
> >>       On Tue, 9 Sep 2014, Roy Franz wrote:
> >>       > This patch adds EFI boot support for ARM based on the previous refactoring of
> >>       > the x86 EFI boot code.  All ARM specific code is in the ARM efi-boot.h header
> >>       > file, with the main EFI entry point common/efi/boot.c.  The PE/COFF header is
> >>       > open-coded in head.S, which allows us to have a single binary be both an EFI
> >>       > executable and a normal arm64 IMAGE file. There is currently no PE/COFF
> >>       > toolchain support for arm64, so it is not possible to create the PE/COFF header
> >>       > in the same manner as on x86.  This also simplifies the build as compared to
> >>       > x86, as we always build the same executable, whereas x86 builds 2.  An ARM
> >>       > version of efi-bind.h is added, which is based on the x86_64 version with the
> >>       > x86 specific portions removed.  The Makefile in common/efi is different for x86
> >>       > and ARM, as for ARM we always build in EFI support.
> >>       >
> >>       > Signed-off-by: Roy Franz <roy.franz@linaro.org>
> >>       > ---
> >>       >  config/arm64.mk                     |   1 +
> >>       >  xen/arch/arm/arm64/head.S           | 150 ++++++++-
> >>       >  xen/arch/arm/xen.lds.S              |   1 +
> >>       >  xen/common/Makefile                 |   1 +
> >>       >  xen/common/efi/Makefile             |   3 +
> >>       >  xen/include/asm-arm/arm64/efibind.h | 216 +++++++++++++
> >>       >  xen/include/asm-arm/efi-boot.h      | 630 ++++++++++++++++++++++++++++++++++++
> >>       >  xen/include/asm-arm/efi.h           |  29 ++
> >>       >  xen/include/asm-arm/efibind.h       |   2 +
> >>       >  xen/include/asm-arm/setup.h         |   2 +-
> >>       >  10 files changed, 1031 insertions(+), 4 deletions(-)
> >>       >  create mode 100644 xen/common/efi/Makefile
> >>       >  create mode 100644 xen/include/asm-arm/arm64/efibind.h
> >>       >  create mode 100644 xen/include/asm-arm/efi-boot.h
> >>       >  create mode 100644 xen/include/asm-arm/efi.h
> >>       >  create mode 100644 xen/include/asm-arm/efibind.h
> >>       >
> >>       > diff --git a/config/arm64.mk b/config/arm64.mk
> >>       > index 15b57a4..e6aab0e 100644
> >>       > --- a/config/arm64.mk
> >>       > +++ b/config/arm64.mk
> >>       > @@ -1,6 +1,7 @@
> >>       >  CONFIG_ARM := y
> >>       >  CONFIG_ARM_64 := y
> >>       >  CONFIG_ARM_$(XEN_OS) := y
> >>       > +CONFIG_EFI := y
> >>       >
> >>       >  CONFIG_XEN_INSTALL_SUFFIX :=
> >>       >
> >>       > diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
> >>       > index 43b5e72..158c102 100644
> >>       > --- a/xen/arch/arm/arm64/head.S
> >>       > +++ b/xen/arch/arm/arm64/head.S
> >>       > @@ -24,6 +24,8 @@
> >>       >  #include <asm/page.h>
> >>       >  #include <asm/asm_defns.h>
> >>       >  #include <asm/early_printk.h>
> >>       > +#include <efi/efierr.h>
> >>       > +#include <asm/arm64/efibind.h>
> >>       >
> >>       >  #define PT_PT     0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
> >>       >  #define PT_MEM    0xf7d /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=0 P=1 */
> >>       > @@ -104,8 +106,14 @@ GLOBAL(start)
> >>       >          /*
> >>       >           * DO NOT MODIFY. Image header expected by Linux boot-loaders.
> >>       >           */
> >>       > -        b       real_start           /* branch to kernel start, magic */
> >>       > -        .long   0                    /* reserved */
> >>       > +efi_head:
> >>       > +        /*
> >>       > +         * This add instruction has no meaningful effect except that
> >>       > +         * its opcode forms the magic "MZ" signature of a PE/COFF file
> >>       > +         * that is required for UEFI applications.
> >>       > +         */
> >>       > +        add     x13, x18, #0x16
> >>       > +        b       real_start           /* branch to kernel start */
> >>       >          .quad   0                    /* Image load offset from start of RAM */
> >>       >          .quad   0                    /* reserved */
> >>       >          .quad   0                    /* reserved */
> >>       > @@ -116,8 +124,113 @@ GLOBAL(start)
> >>       >          .byte   0x52
> >>       >          .byte   0x4d
> >>       >          .byte   0x64
> >>       > -        .word   0                    /* reserved */
> >>       > +        .long   pe_header - efi_head        /* Offset to the PE header. */
> >>       > +
> >>       > +        /*
> >>       > +         * Add the PE/COFF header to the file.  The address of this header
> >>       > +         * is at offset 0x3c in the file, and is part of Linux "Image"
> >>       > +         * header.  The arm64 Linux Image format is designed to support
> >>       > +         * being both an 'Image' format binary and a PE/COFF binary.
> >>       > +         * The PE/COFF format is defined by Microsoft, and is available
> >>       > +         * from: http://msdn.microsoft.com/en-us/gg463119.aspx
> >>       > +         * Version 8.3 adds support for arm64 and UEFI usage.
> >>       > +         */
> >>       > +
> >>       > +        .align  3
> >>       > +pe_header:
> >>       > +        .ascii  "PE"
> >>       > +        .short  0
> >>       > +coff_header:
> >>       > +        .short  0xaa64                          /* AArch64 */
> >>       > +        .short  2                               /* nr_sections */
> >>       > +        .long   0                               /* TimeDateStamp */
> >>       > +        .long   0                               /* PointerToSymbolTable */
> >>       > +        .long   1                               /* NumberOfSymbols */
> >>       > +        .short  section_table - optional_header /* SizeOfOptionalHeader */
> >>       > +        .short  0x206                           /* Characteristics. */
> >>       > +                                                /* IMAGE_FILE_DEBUG_STRIPPED | */
> >>       > +                                                /* IMAGE_FILE_EXECUTABLE_IMAGE | */
> >>       > +                                                /* IMAGE_FILE_LINE_NUMS_STRIPPED */
> >>       > +optional_header:
> >>       > +        .short  0x20b                           /* PE32+ format */
> >>       > +        .byte   0x02                            /* MajorLinkerVersion */
> >>       > +        .byte   0x14                            /* MinorLinkerVersion */
> >>       > +        .long   _end - real_start               /* SizeOfCode */
> >>       > +        .long   0                               /* SizeOfInitializedData */
> >>       > +        .long   0                               /* SizeOfUninitializedData */
> >>       > +        .long   efi_start - efi_head            /* AddressOfEntryPoint */
> >>       > +        .long   real_start - efi_head           /* BaseOfCode */
> >>       > +
> >>       > +extra_header_fields:
> >>       > +        .quad   0                               /* ImageBase */
> >>       > +        .long   0x1000                          /* SectionAlignment (4 KByte) */
> >>       > +        .long   0x8                             /* FileAlignment */
> >>       > +        .short  0                               /* MajorOperatingSystemVersion */
> >>       > +        .short  0                               /* MinorOperatingSystemVersion */
> >>       > +        .short  0                               /* MajorImageVersion */
> >>       > +        .short  0                               /* MinorImageVersion */
> >>       > +        .short  0                               /* MajorSubsystemVersion */
> >>       > +        .short  0                               /* MinorSubsystemVersion */
> >>       > +        .long   0                               /* Win32VersionValue */
> >>       > +
> >>       > +        .long   _end - efi_head                 /* SizeOfImage */
> >>       > +
> >>       > +        /* Everything before the kernel image is considered part of the header */
> >>       > +        .long   real_start - efi_head           /* SizeOfHeaders */
> >>       > +        .long   0                               /* CheckSum */
> >>       > +        .short  0xa                             /* Subsystem (EFI application) */
> >>       > +        .short  0                               /* DllCharacteristics */
> >>       > +        .quad   0                               /* SizeOfStackReserve */
> >>       > +        .quad   0                               /* SizeOfStackCommit */
> >>       > +        .quad   0                               /* SizeOfHeapReserve */
> >>       > +        .quad   0                               /* SizeOfHeapCommit */
> >>       > +        .long   0                               /* LoaderFlags */
> >>       > +        .long   0x6                             /* NumberOfRvaAndSizes */
> >>       > +
> >>       > +        .quad   0                               /* ExportTable */
> >>       > +        .quad   0                               /* ImportTable */
> >>       > +        .quad   0                               /* ResourceTable */
> >>       > +        .quad   0                               /* ExceptionTable */
> >>       > +        .quad   0                               /* CertificationTable */
> >>       > +        .quad   0                               /* BaseRelocationTable */
> >>       > +
> >>       > +        /* Section table */
> >>       > +section_table:
> >>       >
> >>       > +        /*
> >>       > +         * The EFI application loader requires a relocation section
> >>       > +         * because EFI applications must be relocatable.  This is a
> >>       > +         * dummy section as far as we are concerned.
> >>       > +         */
> >>       > +        .ascii  ".reloc"
> >>       > +        .byte   0
> >>       > +        .byte   0                               /* end of 0 padding of section name */
> >>       > +        .long   0
> >>       > +        .long   0
> >>       > +        .long   0                               /* SizeOfRawData */
> >>       > +        .long   0                               /* PointerToRawData */
> >>       > +        .long   0                               /* PointerToRelocations */
> >>       > +        .long   0                               /* PointerToLineNumbers */
> >>       > +        .short  0                               /* NumberOfRelocations */
> >>       > +        .short  0                               /* NumberOfLineNumbers */
> >>       > +        .long   0x42100040                      /* Characteristics (section flags) */
> >>       > +
> >>       > +
> >>       > +        .ascii  ".text"
> >>       > +        .byte   0
> >>       > +        .byte   0
> >>       > +        .byte   0                               /* end of 0 padding of section name */
> >>       > +        .long   _end - real_start               /* VirtualSize */
> >>       > +        .long   real_start - efi_head           /* VirtualAddress */
> >>       > +        .long   __init_end_efi - real_start     /* SizeOfRawData */
> >>       > +        .long   real_start - efi_head           /* PointerToRawData */
> >>       > +
> >>       > +        .long   0                /* PointerToRelocations (0 for executables) */
> >>       > +        .long   0                /* PointerToLineNumbers (0 for executables) */
> >>       > +        .short  0                /* NumberOfRelocations  (0 for executables) */
> >>       > +        .short  0                /* NumberOfLineNumbers  (0 for executables) */
> >>       > +        .long   0xe0500020       /* Characteristics (section flags) */
> >>       > +        .align  5
> >>       >  real_start:
> >>       >          msr   DAIFSet, 0xf           /* Disable all interrupts */
> >>       >
> >>       > @@ -617,6 +730,37 @@ putn:   ret
> >>       >  ENTRY(lookup_processor_type)
> >>       >          mov  x0, #0
> >>       >          ret
> >>       > +/*
> >>       > + *  Function to transition from EFI loader in C, to Xen entry point.
> >>       > + *  void noreturn efi_xen_start(void *fdt_ptr);
> >>       > + */
> >>       > +ENTRY(efi_xen_start)
> >>       > +        /*
> >>       > +         * Turn off cache and MMU as Xen expects. EFI enables them, but also
> >>       > +         * mandates a 1:1 (unity) VA->PA mapping, so we can turn off the
> >>       > +         * MMU while executing EFI code before entering Xen.
> >>       > +         * The EFI loader calls this to start Xen.
> >>       > +         * Preserve x0 (fdf pointer) across call to __flush_dcache_all,
> >>       > +         * restore for entry into Xen.
> >>       > +         */
> >>       > +        mov   x20, x0
> >>       > +        bl    __flush_dcache_all
> >>       > +        ic    ialluis
> >>       > +
> >>       > +        /* Turn off Dcache and MMU */
> >>       > +        mrs   x0, sctlr_el2
> >>       > +        bic   x0, x0, #1 << 0        /* clear SCTLR.M */
> >>       > +        bic   x0, x0, #1 << 2        /* clear SCTLR.C */
> >>
> >> dsb?
> >>
> >> The dsb is done at the end of  __flush_dcache_all
> >
> > I think this would be to make sure __flush_dcache_all reads the correct
> > arguments. We do the same when enabling dcache.
> 
> So where exactly are you suggesting the dsb?  Before the call to
> __flush_dcache_all?

Sorry my comment was wrong, not had my coffee yet!
I meant right before:

msr   sctlr_el2, x0

to make sure that ordering and arguments are correct. And yes, we do the
same when enabling dcache see:

        mrs   x0, SCTLR_EL2
        orr   x0, x0, #SCTLR_M       /* Enable MMU */
        orr   x0, x0, #SCTLR_C       /* Enable D-cache */
        dsb   sy                     /* Flush PTE writes and finish reads */
        msr   SCTLR_EL2, x0          /* now paging is enabled */
        isb                          /* Now, flush the icache */

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices
  2014-09-12 16:57             ` Roy Franz
@ 2014-09-15  8:47               ` Jan Beulich
  0 siblings, 0 replies; 71+ messages in thread
From: Jan Beulich @ 2014-09-15  8:47 UTC (permalink / raw)
  To: Roy Franz; +Cc: keir, Ian Campbell, tim, xen-devel, Stefano Stabellini, Fu Wei

>>> On 12.09.14 at 18:57, <roy.franz@linaro.org> wrote:
>> OK, I'll move this back.  Just having the #ifdefs in runtime.c will help a
> lot.
> 
> Is commenting the #ifef like so acceptable:
> 
> #ifndef CONFIG_ARM  /* TODO - disabled until EFI runtime services
> implemented */

Sure.

Jan

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-12 17:55           ` Stefano Stabellini
@ 2014-09-22 11:13             ` Ian Campbell
  2014-09-23 12:39               ` Stefano Stabellini
  0 siblings, 1 reply; 71+ messages in thread
From: Ian Campbell @ 2014-09-22 11:13 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: keir, tim, xen-devel, Roy Franz, Stefano Stabellini, Jan Beulich, Fu Wei

On Fri, 2014-09-12 at 18:55 +0100, Stefano Stabellini wrote:
> On Fri, 12 Sep 2014, Roy Franz wrote:
> > On Fri, Sep 12, 2014 at 10:41 AM, Stefano Stabellini
> > <stefano.stabellini@eu.citrix.com> wrote:
> > >>       > +        /* Turn off Dcache and MMU */
> > >>       > +        mrs   x0, sctlr_el2
> > >>       > +        bic   x0, x0, #1 << 0        /* clear SCTLR.M */
> > >>       > +        bic   x0, x0, #1 << 2        /* clear SCTLR.C */
> > >>
> > >> dsb?
> > >>
> > >> The dsb is done at the end of  __flush_dcache_all
> > >
> > > I think this would be to make sure __flush_dcache_all reads the correct
> > > arguments. We do the same when enabling dcache.
> > 
> > So where exactly are you suggesting the dsb?  Before the call to
> > __flush_dcache_all?
> 
> Sorry my comment was wrong, not had my coffee yet!
> I meant right before:
> 
> msr   sctlr_el2, x0
> 
> to make sure that ordering and arguments are correct. And yes, we do the
> same when enabling dcache see:
> 
>         mrs   x0, SCTLR_EL2
>         orr   x0, x0, #SCTLR_M       /* Enable MMU */
>         orr   x0, x0, #SCTLR_C       /* Enable D-cache */
>         dsb   sy                     /* Flush PTE writes and finish reads */
>         msr   SCTLR_EL2, x0          /* now paging is enabled */
>         isb                          /* Now, flush the icache */

FYI when I asked Will Deacon about this he was of the opinion that the
combination of an msr write to SCTLR_EL2 and an isb was a sufficient
barrier at least in the case I showed him (which was the Linux
equivalent of Roy's code.

The code you quote here is difference because it is enabling the MMU, so
it needs to ensure the previous PTE writes have already occurred, which
is what that barrier does.

Ian.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V4 15/15] Add ARM EFI boot support
  2014-09-22 11:13             ` Ian Campbell
@ 2014-09-23 12:39               ` Stefano Stabellini
  0 siblings, 0 replies; 71+ messages in thread
From: Stefano Stabellini @ 2014-09-23 12:39 UTC (permalink / raw)
  To: Ian Campbell
  Cc: keir, Stefano Stabellini, tim, xen-devel, Roy Franz,
	Stefano Stabellini, Jan Beulich, Fu Wei

On Mon, 22 Sep 2014, Ian Campbell wrote:
> On Fri, 2014-09-12 at 18:55 +0100, Stefano Stabellini wrote:
> > On Fri, 12 Sep 2014, Roy Franz wrote:
> > > On Fri, Sep 12, 2014 at 10:41 AM, Stefano Stabellini
> > > <stefano.stabellini@eu.citrix.com> wrote:
> > > >>       > +        /* Turn off Dcache and MMU */
> > > >>       > +        mrs   x0, sctlr_el2
> > > >>       > +        bic   x0, x0, #1 << 0        /* clear SCTLR.M */
> > > >>       > +        bic   x0, x0, #1 << 2        /* clear SCTLR.C */
> > > >>
> > > >> dsb?
> > > >>
> > > >> The dsb is done at the end of  __flush_dcache_all
> > > >
> > > > I think this would be to make sure __flush_dcache_all reads the correct
> > > > arguments. We do the same when enabling dcache.
> > > 
> > > So where exactly are you suggesting the dsb?  Before the call to
> > > __flush_dcache_all?
> > 
> > Sorry my comment was wrong, not had my coffee yet!
> > I meant right before:
> > 
> > msr   sctlr_el2, x0
> > 
> > to make sure that ordering and arguments are correct. And yes, we do the
> > same when enabling dcache see:
> > 
> >         mrs   x0, SCTLR_EL2
> >         orr   x0, x0, #SCTLR_M       /* Enable MMU */
> >         orr   x0, x0, #SCTLR_C       /* Enable D-cache */
> >         dsb   sy                     /* Flush PTE writes and finish reads */
> >         msr   SCTLR_EL2, x0          /* now paging is enabled */
> >         isb                          /* Now, flush the icache */
> 
> FYI when I asked Will Deacon about this he was of the opinion that the
> combination of an msr write to SCTLR_EL2 and an isb was a sufficient
> barrier at least in the case I showed him (which was the Linux
> equivalent of Roy's code.
> 
> The code you quote here is difference because it is enabling the MMU, so
> it needs to ensure the previous PTE writes have already occurred, which
> is what that barrier does.

OK

^ permalink raw reply	[flat|nested] 71+ messages in thread

end of thread, other threads:[~2014-09-23 12:39 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-10  0:51 [PATCH V4 00/15] arm64 EFI stub Roy Franz
2014-09-10  0:51 ` [PATCH V4 01/15] move x86 EFI boot code to common/efi Roy Franz
2014-09-11 13:50   ` Jan Beulich
2014-09-11 17:16     ` Roy Franz
2014-09-12  6:55       ` Jan Beulich
2014-09-10  0:51 ` [PATCH V4 02/15] Move x86 specific funtions/variables to arch header Roy Franz
2014-09-11 14:03   ` Jan Beulich
2014-09-11 17:33     ` Roy Franz
2014-09-12  7:04       ` Jan Beulich
2014-09-12  9:43         ` Ian Campbell
2014-09-12  9:53           ` Jan Beulich
2014-09-12  9:58             ` Ian Campbell
2014-09-12 16:52         ` Roy Franz
2014-09-10  0:51 ` [PATCH V4 03/15] create arch functions to get and process EFI memory map Roy Franz
2014-09-11 14:11   ` Jan Beulich
2014-09-11 17:40     ` Roy Franz
2014-09-12  7:07       ` Jan Beulich
2014-09-12  9:45         ` Ian Campbell
2014-09-12  9:56           ` Jan Beulich
2014-09-12 10:23             ` Ian Campbell
2014-09-12 10:35               ` Jan Beulich
2014-09-12 17:01                 ` Roy Franz
2014-09-10  0:51 ` [PATCH V4 04/15] Add architecture functions for pre/post ExitBootServices Roy Franz
2014-09-11 14:13   ` Jan Beulich
2014-09-11 17:44     ` Roy Franz
2014-09-12  7:08       ` Jan Beulich
2014-09-12  9:46         ` Ian Campbell
2014-09-12  9:58           ` Jan Beulich
2014-09-12 16:57             ` Roy Franz
2014-09-15  8:47               ` Jan Beulich
2014-09-10  0:51 ` [PATCH V4 05/15] Add efi_arch_cfg_file() to handle arch specific cfg file fields Roy Franz
2014-09-11 14:16   ` Jan Beulich
2014-09-11 18:11     ` Roy Franz
2014-09-12  7:10       ` Jan Beulich
2014-09-10  0:51 ` [PATCH V4 06/15] Add efi_arch_handle_cmdline() for processing commandline Roy Franz
2014-09-11 14:22   ` Jan Beulich
2014-09-11 18:24     ` Roy Franz
2014-09-10  0:51 ` [PATCH V4 07/15] Move x86 specific video and disk probing code Roy Franz
2014-09-11 14:26   ` Jan Beulich
2014-09-11 18:30     ` Roy Franz
2014-09-12  7:12       ` Jan Beulich
2014-09-10  0:51 ` [PATCH V4 08/15] Add efi_arch_memory() for arch specific memory setup Roy Franz
2014-09-11 14:27   ` Jan Beulich
2014-09-10  0:51 ` [PATCH V4 09/15] Add arch specific module handling to read_file() Roy Franz
2014-09-11 14:40   ` Jan Beulich
2014-09-10  0:52 ` [PATCH V4 10/15] Add SMBIOS and runtime services setup arch functions Roy Franz
2014-09-11 14:44   ` Jan Beulich
2014-09-11 22:03     ` Roy Franz
2014-09-11 23:41       ` Stefano Stabellini
2014-09-12  7:14       ` Jan Beulich
2014-09-12 16:24         ` Roy Franz
2014-09-10  0:52 ` [PATCH V4 11/15] Add several misc. arch functions for EFI boot code Roy Franz
2014-09-11 14:45   ` Jan Beulich
2014-09-10  0:52 ` [PATCH V4 12/15] Add efi_arch_use_config_file() function to control use of config file Roy Franz
2014-09-11 14:49   ` Jan Beulich
2014-09-11 23:54     ` Stefano Stabellini
2014-09-12  7:15       ` Jan Beulich
2014-09-12 16:30         ` Roy Franz
2014-09-10  0:52 ` [PATCH V4 13/15] add arm64 cache flushing code from linux v3.16 Roy Franz
2014-09-10  0:52 ` [PATCH V4 14/15] Update libfdt to v1.4.0 Roy Franz
2014-09-10  0:52 ` [PATCH V4 15/15] Add ARM EFI boot support Roy Franz
2014-09-11 14:53   ` Jan Beulich
2014-09-11 22:26     ` Roy Franz
2014-09-12  7:17       ` Jan Beulich
2014-09-12  0:49   ` Stefano Stabellini
2014-09-12  3:21     ` Roy Franz
2014-09-12 17:41       ` Stefano Stabellini
2014-09-12 17:50         ` Roy Franz
2014-09-12 17:55           ` Stefano Stabellini
2014-09-22 11:13             ` Ian Campbell
2014-09-23 12:39               ` Stefano Stabellini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.