From 04c94fa6cb783ecbc8ce620222c91599b8d95777 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 17 Nov 2015 10:14:57 -0500 Subject: [PATCH] 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, T420 to use GetNextVariableName in 1-1 mapping mode. Signed-off-by: Konrad Rzeszutek Wilk --- xen/common/efi/boot.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 5 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 53c7452..2e0d4c2 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -836,6 +836,75 @@ 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 void __init efi_variables(void) { EFI_STATUS status; @@ -875,7 +944,7 @@ static void __init efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop efi_arch_video_init(gop, info_size, mode_info); } -static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable, bool_t exitbootservices) { EFI_STATUS status; UINTN info_size = 0, map_key; @@ -903,9 +972,13 @@ static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *Syste efi_arch_pre_exit_boot(); - status = SystemTable->BootServices->ExitBootServices(ImageHandle, - map_key); - efi_bs = NULL; + status = 0; + if ( exitbootservices ) + { + status = SystemTable->BootServices->ExitBootServices(ImageHandle, + map_key); + efi_bs = NULL; + } if ( status != EFI_INVALID_PARAMETER || retry ) break; } @@ -951,8 +1024,10 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL; union string section = { NULL }, name; bool_t base_video = 0; + bool_t query_only = 0; char *option_str; bool_t use_cfg_file; + bool_t exit_boot_services = 1; efi_init(ImageHandle, SystemTable); @@ -990,6 +1065,10 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) base_video = 1; else if ( wstrcmp(ptr + 1, L"mapbs") == 0 ) map_bs = 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 ) @@ -1000,6 +1079,8 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) PrintStr(L"Xen EFI Loader options:\r\n"); PrintStr(L"-basevideo retain current video mode\r\n"); PrintStr(L"-mapbs map EfiBootServices{Code,Data}\r\n"); + PrintStr(L"-noexitboot do not call ExitBootServices\r\n"); + PrintStr(L"-query call GetNextVariableName for up to five times\r\n"); PrintStr(L"-cfg= specify configuration file\r\n"); PrintStr(L"-help, -? display this help\r\n"); blexit(NULL); @@ -1160,12 +1241,15 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) /* Get snapshot of variable store parameters. */ efi_variables(); + if ( efi_getnextvariable(query_only) ) + blexit(L"Could not get next variable"); + efi_arch_memory_setup(); if ( gop ) efi_set_gop_mode(gop, gop_mode); - efi_exit_boot(ImageHandle, SystemTable); + efi_exit_boot(ImageHandle, SystemTable, exit_boot_services); efi_arch_post_exit_boot(); for( ; ; ); /* not reached */ -- 2.1.0