diff --git a/xen/arch/x86/efi/boot.c b/xen/arch/x86/efi/boot.c
index edbdb8a..348e237 100644
--- a/xen/arch/x86/efi/boot.c
+++ b/xen/arch/x86/efi/boot.c
@@ -7,7 +7,6 @@
 #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>
@@ -91,55 +90,6 @@ static void __init noreturn blexit(const CHAR16 *str)
     unreachable(); /* not reached */
 }
 
-/* generic routine for printing error messages */
-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;
-    }
-}
 
 /* generic routine for printing error messages */
 static void __init PrintErrMesgExit(const CHAR16 *mesg, EFI_STATUS ErrCode)
@@ -174,311 +124,6 @@ static void __init place_string(u32 *addr, const char *s)
     *addr = (long)alloc;
 }
 
-static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
-                                    CHAR16 *cmdline, UINTN cmdsize,
-                                    CHAR16 **cmdline_remain)
-{
-    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 )
-            {
-                --argv;
-                if (**cmdline_remain)
-                    *cmdline_remain = cmdline;
-                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);
-            return NULL;
-        }
-        ret = fio->OpenVolume(fio, &dir_handle);
-    } while ( ret == EFI_MEDIA_CHANGED );
-    if ( ret != EFI_SUCCESS )
-    {
-        PrintErrMesg(L"OpenVolume failure", ret);
-        return NULL;
-    }
-
-#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 )
-        {
-            PrintErr(L"Unsupported device path component");
-            return NULL;
-        }
-
-        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);
-                return NULL;
-            }
-            dir_handle->Close(dir_handle);
-            dir_handle = new_handle;
-        }
-        fp = (void *)dp;
-        if ( BUFFERSIZE < DevicePathNodeLength(dp) -
-                          sizeof(*dp) + sizeof(*buffer) )
-        {
-            PrintErr(L"Increase BUFFERSIZE");
-            return NULL;
-        }
-        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);
-                return NULL;
-            }
-            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_PHYSICAL_ADDRESS max_addr)
-{
-    EFI_FILE_HANDLE FileHandle = NULL;
-    UINT64 size;
-    EFI_STATUS ret;
-    CHAR16 *what = NULL;
-
-    if ( !name )
-    {
-        PrintErrMesg(L"No Filename", EFI_OUT_OF_RESOURCES);
-        return 0;
-    }
-
-    ret = dir_handle->Open(dir_handle, &FileHandle, name,
-                           EFI_FILE_MODE_READ, 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 = max_addr;
-        ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
-                                    PFN_UP(size), &file->addr);
-    }
-    if ( EFI_ERROR(ret) )
-    {
-        file->addr = 0;
-        what = what ?: L"Allocation";
-    }
-    else
-    {
-
-        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 = what ?: L"Read";
-            efi_bs->FreePages(file->addr, PFN_UP(file->size));
-            file->addr = 0;
-        }
-    }
-
-    if ( FileHandle )
-        FileHandle->Close(FileHandle);
-
-    if ( what )
-    {
-        PrintErrMesg(what, ret);
-        PrintErr(L"Unable to load file");
-        return 0;
-    }
-    else
-    {
-        PrintStr(name);
-        PrintStr(L": ");
-        DisplayUint(file->addr, 2 * sizeof(file->addr));
-        PrintStr(L"-");
-        DisplayUint(file->addr + file->size, 2 * sizeof(file->addr));
-        PrintStr(newline);
-        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] == '=' )
-            {
-                ptr += ilen + 1;
-                /* strip off any leading spaces */
-                while ( *ptr && isspace(*ptr) )
-                    ptr++;
-                return ptr;
-            }
-            break;
-        }
-        ptr += strlen(ptr);
-    }
-    return NULL;
-}
 /* Only call with non-config files. */
 bool_t __init load_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
                                struct file *file)
@@ -495,85 +140,6 @@ bool_t __init load_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
     return 0;
 }
 
-/* Truncate string at first space, and return pointer
- * to remainder of string.
- */
-char * __init truncate_string(char *s)
-{
-    while ( *s && !isspace(*s) )
-        ++s;
-    if (*s)
-    {
-        *s = 0;
-        return(s + 1);
-    }
-    return(NULL);
-}
-
-bool_t __init read_config_file(EFI_FILE_HANDLE *cfg_dir_handle,
-                             struct file *cfg, CHAR16 *cfg_file_name,
-                             union string *section,
-                             CHAR16 *xen_file_name)
-{
-    /*
-     * This allocation is internal to the EFI stub, so any address is
-     * fine.
-     */
-    EFI_PHYSICAL_ADDRESS max = ~0;
-
-    /* Read and parse the config file. */
-    if ( !cfg_file_name )
-    {
-        CHAR16 *tail;
-
-        while ( (tail = point_tail(xen_file_name)) != NULL )
-        {
-            wstrcpy(tail, L".cfg");
-            if ( read_file(*cfg_dir_handle, xen_file_name, cfg, max) )
-                break;
-            *tail = 0;
-        }
-        if ( !tail )
-            return 0;
-        PrintStr(L"Using configuration file '");
-        PrintStr(xen_file_name);
-        PrintStr(L"'\r\n");
-    }
-    else if ( !read_file(*cfg_dir_handle, cfg_file_name, cfg, max) )
-        return 0;
-    pre_parse(cfg);
-
-    if ( section->w )
-        w2s(section);
-    else
-        section->s = get_value(cfg, "global", "default");
-
-
-    for ( ; ; )
-    {
-        union string dom0_kernel_name;
-        dom0_kernel_name.s = get_value(cfg, section->s, "kernel");
-        if ( dom0_kernel_name.s )
-            break;
-        dom0_kernel_name.s = get_value(cfg, "global", "chain");
-        if ( !dom0_kernel_name.s )
-            break;
-        efi_bs->FreePages(cfg->addr, PFN_UP(cfg->size));
-        cfg->addr = 0;
-        if ( !read_file(*cfg_dir_handle, s2w(&dom0_kernel_name), cfg, max) )
-        {
-            PrintStr(L"Chained configuration file '");
-            PrintStr(dom0_kernel_name.w);
-            efi_bs->FreePool(dom0_kernel_name.w);
-            PrintStr(L"'not found.");
-            return 0;
-        }
-        pre_parse(cfg);
-        efi_bs->FreePool(dom0_kernel_name.w);
-    }
-    return 1;
-}
-
 static void __init edd_put_string(u8 *dst, size_t n, const char *src)
 {
     while ( n-- && *src )
@@ -745,73 +311,6 @@ static void __init relocate_image(unsigned long delta)
 }
 
 
-bool_t __init handle_cmdline(EFI_LOADED_IMAGE *loaded_image,
-                           CHAR16 **cfg_file_name, bool_t *base_video,
-                           CHAR16 **image_name, CHAR16 **section_name,
-                           CHAR16 **cmdline_remain)
-{
-
-    unsigned int i, argc;
-    CHAR16 **argv;
-
-
-    if ( !cfg_file_name || !base_video || !image_name )
-    {
-        PrintStr(L"Invalid args to handle_cmdline\r\n");
-        return 0;
-    }
-
-    argc = get_argv(0, NULL, loaded_image->LoadOptions,
-                    loaded_image->LoadOptionsSize, NULL);
-    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, cmdline_remain);
-    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");
-                return 0;
-            }
-            else
-            {
-                PrintStr(L"WARNING: Unknown command line option '");
-                PrintStr(ptr);
-                PrintStr(L"' ignored\r\n");
-            }
-        }
-        else
-            *section_name = ptr;
-    }
-
-    if ( argc )
-        *image_name = *argv;
-
-    return 1;
-}
 
 extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
 extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
diff --git a/xen/common/efi/efi-shared.c b/xen/common/efi/efi-shared.c
index b990292..835121d 100644
--- a/xen/common/efi/efi-shared.c
+++ b/xen/common/efi/efi-shared.c
@@ -19,6 +19,11 @@
 #include <xen/ctype.h>
 #include <xen/init.h>
 #include <asm/processor.h>
+#include <xen/keyhandler.h>
+#include <xen/pfn.h>
+#if EFI_PAGE_SIZE != PAGE_SIZE
+# error Cannot use xen/pfn.h here!
+#endif
 
 
 SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdOut;
@@ -131,6 +136,507 @@ bool_t __init match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2)
 }
 
 
+/* generic routine for printing error messages */
+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;
+    }
+}
+
+
+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);
+            return NULL;
+        }
+        ret = fio->OpenVolume(fio, &dir_handle);
+    } while ( ret == EFI_MEDIA_CHANGED );
+    if ( ret != EFI_SUCCESS )
+    {
+        PrintErrMesg(L"OpenVolume failure", ret);
+        return NULL;
+    }
+
+#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 )
+        {
+            PrintErr(L"Unsupported device path component");
+            return NULL;
+        }
+
+        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);
+                return NULL;
+            }
+            dir_handle->Close(dir_handle);
+            dir_handle = new_handle;
+        }
+        fp = (void *)dp;
+        if ( BUFFERSIZE < DevicePathNodeLength(dp) -
+                          sizeof(*dp) + sizeof(*buffer) )
+        {
+            PrintErr(L"Increase BUFFERSIZE");
+            return NULL;
+        }
+        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);
+                return NULL;
+            }
+            dir_handle->Close(dir_handle);
+            dir_handle = new_handle;
+        }
+    }
+    else
+        *leaf = buffer;
+#undef BUFFERSIZE
+#undef buffer
+
+    return dir_handle;
+}
+
+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;
+        }
+}
+
+bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
+                               struct file *file, EFI_PHYSICAL_ADDRESS max_addr)
+{
+    EFI_FILE_HANDLE FileHandle = NULL;
+    UINT64 size;
+    EFI_STATUS ret;
+    CHAR16 *what = NULL;
+
+    if ( !name )
+    {
+        PrintErrMesg(L"No Filename", EFI_OUT_OF_RESOURCES);
+        return 0;
+    }
+
+    ret = dir_handle->Open(dir_handle, &FileHandle, name,
+                           EFI_FILE_MODE_READ, 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 = max_addr;
+        ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
+                                    PFN_UP(size), &file->addr);
+    }
+    if ( EFI_ERROR(ret) )
+    {
+        file->addr = 0;
+        what = what ?: L"Allocation";
+    }
+    else
+    {
+
+        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 = what ?: L"Read";
+            efi_bs->FreePages(file->addr, PFN_UP(file->size));
+            file->addr = 0;
+        }
+    }
+
+    if ( FileHandle )
+        FileHandle->Close(FileHandle);
+
+    if ( what )
+    {
+        PrintErrMesg(what, ret);
+        PrintErr(L"Unable to load file");
+        return 0;
+    }
+    else
+    {
+        PrintStr(name);
+        PrintStr(L": ");
+        DisplayUint(file->addr, 2 * sizeof(file->addr));
+        PrintStr(L"-");
+        DisplayUint(file->addr + file->size, 2 * sizeof(file->addr));
+        PrintStr(newline);
+        return 1;
+    }
+
+}
+
+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");
+}
+
+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] == '=' )
+            {
+                ptr += ilen + 1;
+                /* strip off any leading spaces */
+                while ( *ptr && isspace(*ptr) )
+                    ptr++;
+                return ptr;
+            }
+            break;
+        }
+        ptr += strlen(ptr);
+    }
+    return NULL;
+}
+
+/* Truncate string at first space, and return pointer
+ * to remainder of string.
+ */
+char * __init truncate_string(char *s)
+{
+    while ( *s && !isspace(*s) )
+        ++s;
+    if (*s)
+    {
+        *s = 0;
+        return(s + 1);
+    }
+    return(NULL);
+}
+
+unsigned int __init get_argv(unsigned int argc, CHAR16 **argv, CHAR16 *cmdline,
+                             UINTN cmdsize, CHAR16 **cmdline_remain)
+{
+    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 )
+            {
+                --argv;
+                if (**cmdline_remain)
+                    *cmdline_remain = cmdline;
+                break;
+            }
+            else
+            {
+                *argv++ = prev = ptr;
+                *ptr = *cmdline;
+                *++ptr = 0;
+            }
+        }
+        prev_sep = cur_sep;
+    }
+    if ( argv )
+        *argv = NULL;
+    return argc;
+}
+
+bool_t __init read_config_file(EFI_FILE_HANDLE *cfg_dir_handle,
+                             struct file *cfg, CHAR16 *cfg_file_name,
+                             union string *section,
+                             CHAR16 *xen_file_name)
+{
+    /*
+     * This allocation is internal to the EFI stub, so any address is
+     * fine.
+     */
+    EFI_PHYSICAL_ADDRESS max = ~0;
+
+    /* Read and parse the config file. */
+    if ( !cfg_file_name )
+    {
+        CHAR16 *tail;
+
+        while ( (tail = point_tail(xen_file_name)) != NULL )
+        {
+            wstrcpy(tail, L".cfg");
+            if ( read_file(*cfg_dir_handle, xen_file_name, cfg, max) )
+                break;
+            *tail = 0;
+        }
+        if ( !tail )
+            return 0;
+        PrintStr(L"Using configuration file '");
+        PrintStr(xen_file_name);
+        PrintStr(L"'\r\n");
+    }
+    else if ( !read_file(*cfg_dir_handle, cfg_file_name, cfg, max) )
+        return 0;
+    pre_parse(cfg);
+
+    if ( section->w )
+        w2s(section);
+    else
+        section->s = get_value(cfg, "global", "default");
+
+
+    for ( ; ; )
+    {
+        union string dom0_kernel_name;
+        dom0_kernel_name.s = get_value(cfg, section->s, "kernel");
+        if ( dom0_kernel_name.s )
+            break;
+        dom0_kernel_name.s = get_value(cfg, "global", "chain");
+        if ( !dom0_kernel_name.s )
+            break;
+        efi_bs->FreePages(cfg->addr, PFN_UP(cfg->size));
+        cfg->addr = 0;
+        if ( !read_file(*cfg_dir_handle, s2w(&dom0_kernel_name), cfg, max) )
+        {
+            PrintStr(L"Chained configuration file '");
+            PrintStr(dom0_kernel_name.w);
+            efi_bs->FreePool(dom0_kernel_name.w);
+            PrintStr(L"'not found.");
+            return 0;
+        }
+        pre_parse(cfg);
+        efi_bs->FreePool(dom0_kernel_name.w);
+    }
+    return 1;
+}
+bool_t __init handle_cmdline(EFI_LOADED_IMAGE *loaded_image,
+                           CHAR16 **cfg_file_name, bool_t *base_video,
+                           CHAR16 **image_name, CHAR16 **section_name,
+                           CHAR16 **cmdline_remain)
+{
+
+    unsigned int i, argc;
+    CHAR16 **argv;
+
+
+    if ( !cfg_file_name || !base_video || !image_name )
+    {
+        PrintStr(L"Invalid args to handle_cmdline\r\n");
+        return 0;
+    }
+
+    argc = get_argv(0, NULL, loaded_image->LoadOptions,
+                    loaded_image->LoadOptionsSize, NULL);
+    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, cmdline_remain);
+    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");
+                return 0;
+            }
+            else
+            {
+                PrintStr(L"WARNING: Unknown command line option '");
+                PrintStr(ptr);
+                PrintStr(L"' ignored\r\n");
+            }
+        }
+        else
+            *section_name = ptr;
+    }
+
+    if ( argc )
+        *image_name = *argv;
+
+    return 1;
+}
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/efi/efi-shared.h b/xen/include/efi/efi-shared.h
index 38f8f39..e559bca 100644
--- a/xen/include/efi/efi-shared.h
+++ b/xen/include/efi/efi-shared.h
@@ -36,6 +36,28 @@ CHAR16 *__init s2w(union string *str);
 char *__init w2s(const union string *str);
 bool_t __init match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2);
 
+void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode);
+EFI_FILE_HANDLE __init get_parent_handle(EFI_LOADED_IMAGE *loaded_image,
+                                         CHAR16 **leaf);
+CHAR16 *__init point_tail(CHAR16 *fn);
+bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
+                               struct file *file, EFI_PHYSICAL_ADDRESS max_addr);
+void __init pre_parse(const struct file *cfg);
+char *__init get_value(const struct file *cfg, const char *section,
+                       const char *item);
+
+char * __init truncate_string(char *s);
+
+bool_t __init read_config_file(EFI_FILE_HANDLE *cfg_dir_handle,
+                             struct file *cfg, CHAR16 *cfg_file_name,
+                             union string *section,
+                             CHAR16 *xen_file_name);
+unsigned int __init get_argv(unsigned int argc, CHAR16 **argv, CHAR16 *cmdline,
+                             UINTN cmdsize, CHAR16 **cmdline_remain);
+bool_t __init handle_cmdline(EFI_LOADED_IMAGE *loaded_image,
+                           CHAR16 **cfg_file_name, bool_t *base_video,
+                           CHAR16 **image_name, CHAR16 **section_name,
+                           CHAR16 **cmdline_remain);
 #endif
 
 
