mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2026-06-07 09:41:30 +00:00
HV:Acrn-hypvervisor Root Directory Clean-up and create misc/ folder for Acrn daemons, services and tools.
This patch is to clean-up acrn-hypervisor root directory, targt only 5 folders under acrn-hypervisor:1.hypervisor,2.devicemodel,3.misc,4.doc,5.build Tracked-On: #3482 Signed-off-by: Terry Zou <terry.zou@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
502
misc/efi-stub/boot.c
Normal file
502
misc/efi-stub/boot.c
Normal file
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * 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.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* 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 <efi.h>
|
||||
#include <efilib.h>
|
||||
#include "efilinux.h"
|
||||
#include "stdlib.h"
|
||||
#include "boot.h"
|
||||
#include "acrn_common.h"
|
||||
#include "deprivilege_boot.h"
|
||||
#include "MpService.h"
|
||||
|
||||
EFI_SYSTEM_TABLE *sys_table;
|
||||
EFI_BOOT_SERVICES *boot;
|
||||
char *cmdline = NULL;
|
||||
extern const uint64_t guest_entry;
|
||||
static UINT64 hv_hpa;
|
||||
|
||||
static void
|
||||
enable_disable_all_ap(BOOLEAN enable)
|
||||
{
|
||||
EFI_MP_SERVICES_PROTOCOL *mp = NULL;
|
||||
EFI_STATUS err;
|
||||
EFI_GUID mp_guid = EFI_MP_SERVICES_PROTOCOL_GUID;
|
||||
UINTN n_proc, n_enabled_proc, bsp, i;
|
||||
|
||||
err = uefi_call_wrapper(boot->LocateProtocol, 3, &mp_guid, NULL, (void **)&mp);
|
||||
if (err != EFI_SUCCESS) {
|
||||
Print(L"Unable to locate MP service protocol: %r, skip %s all AP\n",
|
||||
err, enable ? "enable" : "disable");
|
||||
return;
|
||||
}
|
||||
|
||||
err = uefi_call_wrapper(mp->GetNumberOfProcessors, 3, mp, &n_proc, &n_enabled_proc);
|
||||
if (err != EFI_SUCCESS) {
|
||||
Print(L"failed to GetNumberOfProcessors: %r\n", err);
|
||||
return;
|
||||
}
|
||||
Print(L"detected %d processes, %d enabled\n", n_proc, n_enabled_proc);
|
||||
|
||||
err = uefi_call_wrapper(mp->WhoAmI, 2, mp, &bsp);
|
||||
if (err != EFI_SUCCESS) {
|
||||
Print(L"failed to WhoAmI: %r\n", err);
|
||||
return;
|
||||
}
|
||||
Print(L"current on process %d\n", bsp);
|
||||
|
||||
for (i = 0; i < n_proc; i++) {
|
||||
if (i == bsp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = uefi_call_wrapper(mp->EnableDisableAP, 4, mp, i, enable, NULL);
|
||||
if (err != EFI_SUCCESS) {
|
||||
Print(L"failed to %s AP%d: %r\n", enable ? "enable" : "disable", i, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hv_jump(EFI_PHYSICAL_ADDRESS hv_start,
|
||||
struct multiboot_info *mbi, struct depri_boot_context *efi_ctx)
|
||||
{
|
||||
hv_func hf;
|
||||
|
||||
efi_ctx->vcpu_regs.rip = (uint64_t)&guest_entry;
|
||||
|
||||
/* The 64-bit entry of acrn hypervisor is 0x200 from the start
|
||||
* address of hv image. But due to there is multiboot header,
|
||||
* so it has to be added with 0x10.
|
||||
*
|
||||
* FIXME: The hardcode value 0x210 should be worked out
|
||||
* from the link address of cpu_primary_start_64 in acrn.out
|
||||
*/
|
||||
hf = (hv_func)(hv_start + 0x210);
|
||||
|
||||
asm volatile ("cli");
|
||||
|
||||
/* jump to acrn hypervisor */
|
||||
hf(MULTIBOOT_INFO_MAGIC, mbi);
|
||||
}
|
||||
|
||||
EFI_STATUS construct_mbi(EFI_PHYSICAL_ADDRESS hv_hpa, struct multiboot_info *mbi,
|
||||
struct multiboot_mmap *mmap)
|
||||
{
|
||||
UINTN map_size, map_key;
|
||||
UINT32 desc_version;
|
||||
UINTN desc_size;
|
||||
EFI_MEMORY_DESCRIPTOR *map_buf;
|
||||
EFI_STATUS err = EFI_SUCCESS;
|
||||
int32_t i, j, mmap_entry_count;
|
||||
|
||||
/* We're just interested in the map's size for now */
|
||||
map_size = 0;
|
||||
err = get_memory_map(&map_size, NULL, NULL, NULL, NULL);
|
||||
if (err != EFI_SUCCESS && err != EFI_BUFFER_TOO_SMALL)
|
||||
goto out;
|
||||
|
||||
again:
|
||||
err = allocate_pool(EfiLoaderData, map_size, (void **) &map_buf);
|
||||
if (err != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Remember! We've already allocated map_buf with emalloc (and
|
||||
* 'map_size' contains its size) which means that it should be
|
||||
* positioned below our allocation for the kernel. Use that
|
||||
* space for the memory map.
|
||||
*/
|
||||
err = get_memory_map(&map_size, map_buf, &map_key,
|
||||
&desc_size, &desc_version);
|
||||
if (err != EFI_SUCCESS) {
|
||||
if (err == EFI_BUFFER_TOO_SMALL) {
|
||||
/*
|
||||
* Argh! The buffer that we allocated further
|
||||
* up wasn't large enough which means we need
|
||||
* to allocate them again, but this time
|
||||
* larger. 'map_size' has been updated by the
|
||||
* call to memory_map().
|
||||
*/
|
||||
free_pool(map_buf);
|
||||
goto again;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
mmap_entry_count = map_size / desc_size;
|
||||
/*
|
||||
* Convert the EFI memory map to E820.
|
||||
*/
|
||||
for (i = 0, j = 0; i < mmap_entry_count && j < MBOOT_MMAP_NUMS - 1; i++) {
|
||||
EFI_MEMORY_DESCRIPTOR *d;
|
||||
uint32_t e820_type = 0;
|
||||
|
||||
d = (EFI_MEMORY_DESCRIPTOR *)((uint64_t)map_buf + (i * desc_size));
|
||||
switch(d->Type) {
|
||||
case EfiReservedMemoryType:
|
||||
case EfiRuntimeServicesCode:
|
||||
case EfiRuntimeServicesData:
|
||||
case EfiMemoryMappedIO:
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
case EfiPalCode:
|
||||
e820_type = E820_RESERVED;
|
||||
break;
|
||||
|
||||
case EfiUnusableMemory:
|
||||
e820_type = E820_UNUSABLE;
|
||||
break;
|
||||
|
||||
case EfiACPIReclaimMemory:
|
||||
e820_type = E820_ACPI;
|
||||
break;
|
||||
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory:
|
||||
e820_type = E820_RAM;
|
||||
break;
|
||||
|
||||
case EfiACPIMemoryNVS:
|
||||
e820_type = E820_NVS;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((j != 0) && mmap[j-1].mm_type == e820_type &&
|
||||
(mmap[j-1].mm_base_addr + mmap[j-1].mm_length)
|
||||
== d->PhysicalStart) {
|
||||
mmap[j-1].mm_length += d->NumberOfPages << EFI_PAGE_SHIFT;
|
||||
} else {
|
||||
mmap[j].mm_base_addr = d->PhysicalStart;
|
||||
mmap[j].mm_length = d->NumberOfPages << EFI_PAGE_SHIFT;
|
||||
mmap[j].mm_type = e820_type;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if we haven't gone through all the mmap table entries,
|
||||
* there must be a memory overwrite if we continue,
|
||||
* so just abort anyway.
|
||||
*/
|
||||
if (i < mmap_entry_count) {
|
||||
Print(L": bios provides %d mmap entries which is beyond limitation[%d]\n",
|
||||
mmap_entry_count, MBOOT_MMAP_NUMS-1);
|
||||
err = EFI_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* switch hv memory region(0x20000000 ~ 0x22000000) to
|
||||
* available RAM in e820 table
|
||||
*/
|
||||
mmap[j].mm_base_addr = hv_hpa;
|
||||
mmap[j].mm_length = CONFIG_HV_RAM_SIZE;
|
||||
mmap[j].mm_type = E820_RAM;
|
||||
j++;
|
||||
|
||||
mbi->mi_cmdline = (UINTN)cmdline;
|
||||
mbi->mi_mmap_addr = (UINTN)mmap;
|
||||
mbi->mi_mmap_length = j*sizeof(struct multiboot_mmap);
|
||||
mbi->mi_flags |= MULTIBOOT_INFO_HAS_MMAP | MULTIBOOT_INFO_HAS_CMDLINE;
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static EFI_STATUS
|
||||
switch_to_guest_mode(EFI_HANDLE image, EFI_PHYSICAL_ADDRESS hv_hpa)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS addr;
|
||||
EFI_STATUS err;
|
||||
struct multiboot_mmap *mmap;
|
||||
struct multiboot_info *mbi;
|
||||
struct depri_boot_context *efi_ctx;
|
||||
struct acpi_table_rsdp *rsdp = NULL;
|
||||
int32_t i;
|
||||
EFI_CONFIGURATION_TABLE *config_table;
|
||||
char *uefi_boot_loader_name;
|
||||
const char loader_name[BOOT_LOADER_NAME_SIZE] = UEFI_BOOT_LOADER_NAME;
|
||||
|
||||
err = allocate_pool(EfiLoaderData, EFI_BOOT_MEM_SIZE, (VOID *)&addr);
|
||||
if (err != EFI_SUCCESS) {
|
||||
Print(L"Failed to allocate memory for EFI boot\n");
|
||||
goto out;
|
||||
}
|
||||
(void)memset((void *)addr, 0x0, EFI_BOOT_MEM_SIZE);
|
||||
|
||||
mmap = MBOOT_MMAP_PTR(addr);
|
||||
mbi = MBOOT_INFO_PTR(addr);
|
||||
efi_ctx = BOOT_CTX_PTR(addr);
|
||||
|
||||
uefi_boot_loader_name = BOOT_LOADER_NAME_PTR(addr);
|
||||
memcpy(uefi_boot_loader_name, loader_name, BOOT_LOADER_NAME_SIZE);
|
||||
|
||||
/* reserve secondary memory region for CPU trampoline code */
|
||||
err = emalloc_reserved_mem(&addr, CONFIG_LOW_RAM_SIZE, MEM_ADDR_1MB);
|
||||
if (err != EFI_SUCCESS)
|
||||
goto out;
|
||||
if (addr < 4096)
|
||||
Print(L"Warning: CPU trampoline code buf occupied zero-page\n");
|
||||
|
||||
efi_ctx->ap_trampoline_buf = addr;
|
||||
|
||||
config_table = sys_table->ConfigurationTable;
|
||||
|
||||
for (i = 0; i < sys_table->NumberOfTableEntries; i++) {
|
||||
EFI_GUID acpi_20_table_guid = ACPI_20_TABLE_GUID;
|
||||
EFI_GUID acpi_table_guid = ACPI_TABLE_GUID;
|
||||
|
||||
if (CompareGuid(&acpi_20_table_guid,
|
||||
&config_table->VendorGuid) == 0) {
|
||||
rsdp = config_table->VendorTable;
|
||||
break;
|
||||
}
|
||||
|
||||
if (CompareGuid(&acpi_table_guid,
|
||||
&config_table->VendorGuid) == 0)
|
||||
rsdp = config_table->VendorTable;
|
||||
|
||||
config_table++;
|
||||
}
|
||||
|
||||
if (rsdp == NULL) {
|
||||
Print(L"unable to find RSDP\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
efi_ctx->rsdp = rsdp;
|
||||
|
||||
/* construct multiboot info and deliver it to hypervisor */
|
||||
err = construct_mbi(hv_hpa, mbi, mmap);
|
||||
if (err != EFI_SUCCESS)
|
||||
goto out;
|
||||
|
||||
mbi->mi_flags |= MULTIBOOT_INFO_HAS_DRIVES;
|
||||
mbi->mi_drives_addr = (UINT32)(UINTN)efi_ctx;
|
||||
|
||||
/* Set boot loader name in the multiboot header of UEFI, this name is used by hypervisor;
|
||||
* The host physical start address of boot loader name is stored in multiboot header.
|
||||
*/
|
||||
mbi->mi_flags |= MULTIBOOT_INFO_HAS_LOADER_NAME;
|
||||
mbi->mi_loader_name = (UINT32)uefi_boot_loader_name;
|
||||
|
||||
asm volatile ("pushf\n\t"
|
||||
"pop %0\n\t"
|
||||
: "=r"(efi_ctx->vcpu_regs.rflags)
|
||||
: );
|
||||
asm volatile ("movq %%rax, %0" : "=r"(efi_ctx->vcpu_regs.gprs.rax));
|
||||
asm volatile ("movq %%rbx, %0" : "=r"(efi_ctx->vcpu_regs.gprs.rbx));
|
||||
asm volatile ("movq %%rcx, %0" : "=r"(efi_ctx->vcpu_regs.gprs.rcx));
|
||||
asm volatile ("movq %%rdx, %0" : "=r"(efi_ctx->vcpu_regs.gprs.rdx));
|
||||
asm volatile ("movq %%rdi, %0" : "=r"(efi_ctx->vcpu_regs.gprs.rdi));
|
||||
asm volatile ("movq %%rsi, %0" : "=r"(efi_ctx->vcpu_regs.gprs.rsi));
|
||||
asm volatile ("movq %%rsp, %0" : "=r"(efi_ctx->vcpu_regs.gprs.rsp));
|
||||
asm volatile ("movq %%rbp, %0" : "=r"(efi_ctx->vcpu_regs.gprs.rbp));
|
||||
asm volatile ("movq %%r8, %0" : "=r"(efi_ctx->vcpu_regs.gprs.r8));
|
||||
asm volatile ("movq %%r9, %0" : "=r"(efi_ctx->vcpu_regs.gprs.r9));
|
||||
asm volatile ("movq %%r10, %0" : "=r"(efi_ctx->vcpu_regs.gprs.r10));
|
||||
asm volatile ("movq %%r11, %0" : "=r"(efi_ctx->vcpu_regs.gprs.r11));
|
||||
asm volatile ("movq %%r12, %0" : "=r"(efi_ctx->vcpu_regs.gprs.r12));
|
||||
asm volatile ("movq %%r13, %0" : "=r"(efi_ctx->vcpu_regs.gprs.r13));
|
||||
asm volatile ("movq %%r14, %0" : "=r"(efi_ctx->vcpu_regs.gprs.r14));
|
||||
asm volatile ("movq %%r15, %0" : "=r"(efi_ctx->vcpu_regs.gprs.r15));
|
||||
|
||||
hv_jump(hv_hpa, mbi, efi_ctx);
|
||||
asm volatile (".global guest_entry\n\t"
|
||||
"guest_entry:\n\t");
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline EFI_STATUS isspace(CHAR8 ch)
|
||||
{
|
||||
return ((uint8_t)ch <= ' ');
|
||||
}
|
||||
|
||||
#define DEFAULT_UEFI_OS_LOADER_NAME L"\\EFI\\org.clearlinux\\bootloaderx64.efi"
|
||||
/**
|
||||
* efi_main - The entry point for the OS loader image.
|
||||
* @image: firmware-allocated handle that identifies the image
|
||||
* @sys_table: EFI system table
|
||||
*/
|
||||
EFI_STATUS
|
||||
efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *_table)
|
||||
{
|
||||
WCHAR *error_buf;
|
||||
EFI_STATUS err;
|
||||
EFI_LOADED_IMAGE *info;
|
||||
UINTN sec_addr;
|
||||
UINTN sec_size;
|
||||
char *section;
|
||||
EFI_DEVICE_PATH *path;
|
||||
|
||||
INTN i, index;
|
||||
CHAR16 *bootloader_name = NULL;
|
||||
CHAR16 bootloader_param[] = L"bootloader=";
|
||||
EFI_HANDLE bootloader_image;
|
||||
CHAR16 *options = NULL;
|
||||
UINT32 options_size = 0;
|
||||
CHAR16 *cmdline16, *n;
|
||||
|
||||
InitializeLib(image, _table);
|
||||
sys_table = _table;
|
||||
boot = sys_table->BootServices;
|
||||
|
||||
if (CheckCrc(sys_table->Hdr.HeaderSize, &sys_table->Hdr) != TRUE)
|
||||
return EFI_LOAD_ERROR;
|
||||
|
||||
/* make sure only bsp is enable before entering hv */
|
||||
enable_disable_all_ap(FALSE);
|
||||
|
||||
err = handle_protocol(image, &LoadedImageProtocol, (void **)&info);
|
||||
if (err != EFI_SUCCESS)
|
||||
goto failed;
|
||||
|
||||
/* get the options */
|
||||
options = info->LoadOptions;
|
||||
options_size = info->LoadOptionsSize;
|
||||
|
||||
/* convert the options to cmdline */
|
||||
if (options_size > 0)
|
||||
cmdline = ch16_2_ch8(options, StrnLen(options, options_size));
|
||||
|
||||
/* First check if we were given a bootloader name
|
||||
* E.g.: "bootloader=\EFI\org.clearlinux\bootloaderx64.efi"
|
||||
*/
|
||||
cmdline16 = StrDuplicate(options);
|
||||
bootloader_name = strstr_16(cmdline16, bootloader_param, StrLen(bootloader_param));
|
||||
if (bootloader_name) {
|
||||
bootloader_name = bootloader_name + StrLen(bootloader_param);
|
||||
n = bootloader_name;
|
||||
i = 0;
|
||||
while (*n && !isspace((CHAR8)*n) && (*n < 0xff)) {
|
||||
n++; i++;
|
||||
}
|
||||
*n++ = '\0';
|
||||
} else {
|
||||
/*
|
||||
* If we reach this point, it means we did not receive a specific
|
||||
* bootloader name to be used. Fall back to the default bootloader
|
||||
* as specified in config.h
|
||||
*/
|
||||
bootloader_name = DEFAULT_UEFI_OS_LOADER_NAME;
|
||||
}
|
||||
|
||||
section = ".hv";
|
||||
err = get_pe_section(info->ImageBase, section, strlen(section), &sec_addr, &sec_size);
|
||||
if (EFI_ERROR(err)) {
|
||||
Print(L"Unable to locate section of ACRNHV %r ", err);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* without relocateion enabled, hypervisor binary need to reside in
|
||||
* fixed memory address starting from CONFIG_HV_RAM_START, make a call
|
||||
* to emalloc_fixed_addr for that case. With CONFIG_RELOC enabled,
|
||||
* hypervisor is able to do relocation, the only requirement is that
|
||||
* it need to reside in memory below 4GB, call emalloc_reserved_mem()
|
||||
* instead.
|
||||
*/
|
||||
#ifdef CONFIG_RELOC
|
||||
err = emalloc_reserved_aligned(&hv_hpa, CONFIG_HV_RAM_SIZE, 1 << 21, MEM_ADDR_4GB);
|
||||
#else
|
||||
err = emalloc_fixed_addr(&hv_hpa, CONFIG_HV_RAM_SIZE, CONFIG_HV_RAM_START);
|
||||
#endif
|
||||
if (err != EFI_SUCCESS)
|
||||
goto failed;
|
||||
|
||||
memcpy((char *)hv_hpa, info->ImageBase + sec_addr, sec_size);
|
||||
|
||||
/* load hypervisor and begin to run on it */
|
||||
err = switch_to_guest_mode(image, hv_hpa);
|
||||
if (err != EFI_SUCCESS)
|
||||
goto failed;
|
||||
|
||||
/*
|
||||
* enable all AP here will reset all APs,
|
||||
* so acrn can handle their ctx from now on.
|
||||
*/
|
||||
enable_disable_all_ap(TRUE);
|
||||
|
||||
/* load and start the default bootloader */
|
||||
path = FileDevicePath(info->DeviceHandle, bootloader_name);
|
||||
if (!path)
|
||||
goto free_args;
|
||||
|
||||
FreePool(bootloader_name);
|
||||
|
||||
err = uefi_call_wrapper(boot->LoadImage, 6, FALSE, image,
|
||||
path, NULL, 0, &bootloader_image);
|
||||
if (EFI_ERROR(err)) {
|
||||
uefi_call_wrapper(boot->Stall, 1, 3 * 1000 * 1000);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
err = uefi_call_wrapper(boot->StartImage, 3, bootloader_image,
|
||||
NULL, NULL);
|
||||
if (EFI_ERROR(err)) {
|
||||
uefi_call_wrapper(boot->Stall, 1, 3 * 1000 * 1000);
|
||||
goto failed;
|
||||
}
|
||||
uefi_call_wrapper(boot->UnloadImage, 1, bootloader_image);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
free_args:
|
||||
FreePool(bootloader_name);
|
||||
failed:
|
||||
/*
|
||||
* We need to be careful not to trash 'err' here. If we fail
|
||||
* to allocate enough memory to hold the error string fallback
|
||||
* to returning 'err'.
|
||||
*/
|
||||
if (allocate_pool(EfiLoaderData, ERROR_STRING_LENGTH,
|
||||
(void **)&error_buf) != EFI_SUCCESS) {
|
||||
Print(L"Couldn't allocate pages for error string\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
StatusToString(error_buf, err);
|
||||
Print(L": %s\n", error_buf);
|
||||
|
||||
/* If we don't wait for user input, (s)he will not see the error message */
|
||||
uefi_call_wrapper(sys_table->ConOut->OutputString, 2, sys_table->ConOut, \
|
||||
L"\r\n\r\n\r\nHit any key to exit\r\n");
|
||||
uefi_call_wrapper(sys_table->BootServices->WaitForEvent, 3, 1, \
|
||||
&sys_table->ConIn->WaitForKey, &index);
|
||||
|
||||
return exit(image, err, ERROR_STRING_LENGTH, error_buf);
|
||||
}
|
||||
Reference in New Issue
Block a user