From patchwork Tue Jul 22 00:43:32 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roy Franz X-Patchwork-Id: 34012 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f72.google.com (mail-oa0-f72.google.com [209.85.219.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id E281020492 for ; Tue, 22 Jul 2014 00:45:42 +0000 (UTC) Received: by mail-oa0-f72.google.com with SMTP id m1sf45133146oag.11 for ; Mon, 21 Jul 2014 17:45:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:cc:subject:precedence:list-id:list-unsubscribe:list-post :list-help:list-subscribe:mime-version:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list :list-archive:content-type:content-transfer-encoding; bh=FYfuhbXAqjs9+wCDhUTKoW1uqO/hLZPoJeJnu3C58WE=; b=fjUvXfnFDRn8o+7JPehxWRtwjHK28PFxUocm2NtWSm9zZW06V2W3zf+zPCZPHrzKsg xAzD4oFT0SuiVRgbPK+ts3H/doOteOXLFl2kSVQF/OeReK13NDEhfMNfMewQcsiXthYY Wy6U9TFn9mD1HkeKciPq9FjhzpHrn3YyIMaeU8KbN3/10zAS1+3Ws3LmxQdxDY9VcTOa TsEW4kEe7PLBhIIAAdjeB6byOIpx1Wn9ZHsGPIlnvv4y9sVYWprGhay1zKBWzUPjbXGE UE8YRH10eh5KvbV9/CF/2GW3MZ2/fx2VAQ1OR93gweITRyIh+KUpz0PzGtLjEFQhi43t tRpw== X-Gm-Message-State: ALoCoQntf77CPeyUP/XvoEEHncoGo+mlk8KKxw7ORNewFIvQYVqWiqq9UO2HVQGkH7yVdB/OEJi/ X-Received: by 10.182.130.169 with SMTP id of9mr15331789obb.27.1405989942210; Mon, 21 Jul 2014 17:45:42 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.41.231 with SMTP id z94ls2224001qgz.63.gmail; Mon, 21 Jul 2014 17:45:42 -0700 (PDT) X-Received: by 10.220.110.77 with SMTP id m13mr7390195vcp.73.1405989942048; Mon, 21 Jul 2014 17:45:42 -0700 (PDT) Received: from mail-vc0-f181.google.com (mail-vc0-f181.google.com [209.85.220.181]) by mx.google.com with ESMTPS id cb8si12862723vcb.36.2014.07.21.17.45.42 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 21 Jul 2014 17:45:42 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.181 as permitted sender) client-ip=209.85.220.181; Received: by mail-vc0-f181.google.com with SMTP id lf12so13172540vcb.26 for ; Mon, 21 Jul 2014 17:45:42 -0700 (PDT) X-Received: by 10.221.47.9 with SMTP id uq9mr17426341vcb.48.1405989941933; Mon, 21 Jul 2014 17:45:41 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp154125vcb; Mon, 21 Jul 2014 17:45:40 -0700 (PDT) X-Received: by 10.42.50.82 with SMTP id z18mr17111360icf.47.1405989940549; Mon, 21 Jul 2014 17:45:40 -0700 (PDT) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id z8si32942750igl.40.2014.07.21.17.45.40 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 21 Jul 2014 17:45:40 -0700 (PDT) Received-SPF: none (google.com: xen-devel-bounces@lists.xen.org does not designate permitted sender hosts) client-ip=50.57.142.19; Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1X9OBn-0000Bv-Mw; Tue, 22 Jul 2014 00:44:19 +0000 Received: from mail6.bemta4.messagelabs.com ([85.158.143.247]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1X9OBm-0000B3-ML for xen-devel@lists.xen.org; Tue, 22 Jul 2014 00:44:18 +0000 Received: from [85.158.143.35:7625] by server-2.bemta-4.messagelabs.com id 28/6A-26128-2E3BDC35; Tue, 22 Jul 2014 00:44:18 +0000 X-Env-Sender: roy.franz@linaro.org X-Msg-Ref: server-5.tower-21.messagelabs.com!1405989854!19143697!1 X-Originating-IP: [209.85.220.50] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 6.11.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 24105 invoked from network); 22 Jul 2014 00:44:16 -0000 Received: from mail-pa0-f50.google.com (HELO mail-pa0-f50.google.com) (209.85.220.50) by server-5.tower-21.messagelabs.com with RC4-SHA encrypted SMTP; 22 Jul 2014 00:44:16 -0000 Received: by mail-pa0-f50.google.com with SMTP id et14so10825066pad.37 for ; Mon, 21 Jul 2014 17:44:14 -0700 (PDT) X-Received: by 10.70.140.13 with SMTP id rc13mr7833409pdb.127.1405989854423; Mon, 21 Jul 2014 17:44:14 -0700 (PDT) Received: from rfranz-t520.local (c-24-10-97-91.hsd1.ca.comcast.net. [24.10.97.91]) by mx.google.com with ESMTPSA id fl3sm15417298pbc.35.2014.07.21.17.44.13 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 21 Jul 2014 17:44:13 -0700 (PDT) From: Roy Franz To: xen-devel@lists.xen.org, ian.campbell@citrix.com, stefano.stabellini@citrix.com, tim@xen.org, jbeulich@suse.com, keir@xen.org Date: Mon, 21 Jul 2014 17:43:32 -0700 Message-Id: <1405989815-25236-10-git-send-email-roy.franz@linaro.org> X-Mailer: git-send-email 2.0.0 In-Reply-To: <1405989815-25236-1-git-send-email-roy.franz@linaro.org> References: <1405989815-25236-1-git-send-email-roy.franz@linaro.org> Cc: Roy Franz , fu.wei@linaro.org, linaro-uefi@lists.linaro.org Subject: [Xen-devel] [PATCH V2 09/12] Move shared EFI functions to efi-shared.c X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: List-Unsubscribe: , List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: roy.franz@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.181 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Archive: Move all of the shareable functions from boot.c to the the shared EFI code. These functions will be used by the arm64 EFI stub. Signed-off-by: Roy Franz --- xen/arch/x86/efi/boot.c | 501 ------------------------------------------ xen/common/efi/efi-shared.c | 506 +++++++++++++++++++++++++++++++++++++++++++ xen/include/efi/efi-shared.h | 22 ++ 3 files changed, 528 insertions(+), 501 deletions(-) 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 #include #include -#include #include #include #include @@ -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= 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 #include #include +#include +#include +#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= 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