From ffb09e4938021ed47bc7097585dd19a10f2e09de Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 27 Jan 2015 14:04:30 -0500 Subject: [PATCH 3/5] EFI/early: Implement GetNextVariableName and /query and /noexitboot parameters In the early EFI boot we will enumerate up to five EFI variables to make sure it works. The /query will just enumerate them and then quit. Helps in troubleshooting and redirecting the output to a file (xen.efi /query > q). The /noexitboot will inhibit Xen from calling ExitBootServices. This allows on Lenovo ThinkPad x230 to use GetNextVariableName in 1-1 mapping mode. Signed-off-by: Konrad Rzeszutek Wilk --- xen/common/efi/boot.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index b0bbc4b..4ee8f68 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -673,6 +673,74 @@ static void __init setup_efi_pci(void) efi_bs->FreePool(handles); } +static int __init efi_getnextvariable(bool_t query_only) +{ + EFI_GUID guid; + UINTN i, size, idx; + CHAR16 *name; + EFI_STATUS status; + + + status = efi_bs->AllocatePool(EfiLoaderData, 1024, (void *)&name); + if ( EFI_ERROR(status) ) + return status; + + guid.Data1 = 0; + guid.Data2 = 0; + guid.Data3 = 0; + for ( i = 0; i < 8; i++ ) + guid.Data4[i] = 0; + + for ( i = 0 ; i < 1024 / sizeof (CHAR16); i++ ) + name[i] = 0; + + PrintStr(L"GetNextVariableName: "); + PrintStr(name); + PrintStr(newline); + idx = 0; + do { + size = 1024; + efi_rs->GetNextVariableName(&size, name, &guid); + if ( EFI_ERROR(status) ) + { + if ( query_only ) + { + efi_bs->FreePool(name); + PrintErrMesg(L"Failed to GetNextVariableName", status); + } + else + { + PrintStr(L"Warning: GetNextVariableName: "); + DisplayUint(status, 0); + PrintStr(newline); + } + } + else + { + DisplayUint(guid.Data1, 4); + DisplayUint(guid.Data2, 2); + DisplayUint(guid.Data3, 2); + for ( i = 0; i < 8; i++ ) + DisplayUint(guid.Data4[i], 1); + + PrintStr(L":"); + PrintStr(name); + PrintStr(L" "); + DisplayUint(status, 0); + PrintStr(newline); + } + } while ( !EFI_ERROR(status) && idx++ < 5 ); + + efi_bs->FreePool(name); + + if ( query_only ) + return -EINVAL; + + if ( EFI_ERROR(EFI_NOT_FOUND) ) + return 0; + + return status; +} static int __init __maybe_unused set_color(u32 mask, int bpp, u8 *pos, u8 *sz) { if ( bpp < 0 ) @@ -705,8 +773,10 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; union string section = { NULL }, name; bool_t base_video = 0, retry; + bool_t query_only = 0; char *option_str; bool_t use_cfg_file; + bool_t exit_boot_services = 0; efi_ih = ImageHandle; efi_bs = SystemTable->BootServices; @@ -751,6 +821,10 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { if ( wstrcmp(ptr + 1, L"basevideo") == 0 ) base_video = 1; + else if ( wstrcmp(ptr + 1, L"query") == 0 ) + query_only = 1; + else if ( wstrcmp(ptr + 1, L"noexitboot") == 0 ) + exit_boot_services = 0; 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 ) @@ -1031,6 +1105,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) PrintStr(newline); } + if ( efi_getnextvariable(query_only) ) + blexit(L"Could not get next variable"); + efi_arch_memory_setup(); if ( gop ) @@ -1064,7 +1141,11 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) efi_arch_pre_exit_boot(); - status = efi_bs->ExitBootServices(ImageHandle, map_key); + if ( exit_boot_services ) + status = efi_bs->ExitBootServices(ImageHandle, map_key); + else + status = 0; + if ( status != EFI_INVALID_PARAMETER || retry ) break; } -- 2.1.0