mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-05-10 01:16:06 +00:00
ACRN EFI application based on the legacy efi-stub code provides booting method of HV on UEFI-BIOS without using the GRUB Bootloader. It is supposed to be used for secure booting on certain platform. By means of that users can boot HV, Service VM kernel, pre-launched VM kernel and its ACPI table binary packed in the Slim Bootloader container boot image file format. ACRN EFI application has additional dependencies to compile which are not listed in the existing ACRN GSG doc. Since this is an optional feature but not all users need, it does not get compiled by default to avoid causing any confusion for existing users. README for how to use the feature will come later in a separated commit. This patch adds barebone implementation of this efi-stub. The following files are reused from a previous version of efi-stub without changes: efilinux.h, pe.c, stdlib.h Other files contains stubbed functions, whose implementation will come in coming patches. Tracked-On: #6241 Signed-off-by: Toshiki Nishioka <toshiki.nishioka@intel.com> Signed-off-by: Yifan Liu <yifan1.liu@intel.com> Co-developed-by: Yifan Liu <yifan1.liu@intel.com>
174 lines
5.3 KiB
C
174 lines
5.3 KiB
C
/*
|
|
* Copyright (c) 2011 - 2021, 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.
|
|
*
|
|
* This file contains some wrappers around the gnu-efi functions. As
|
|
* we're not going through uefi_call_wrapper() directly, this allows
|
|
* us to get some type-safety for function call arguments and for the
|
|
* compiler to check that the number of function call arguments is
|
|
* correct.
|
|
*
|
|
* It's also a good place to document the EFI interface.
|
|
*/
|
|
|
|
#include <efi.h>
|
|
#include <efilib.h>
|
|
#include "stdlib.h"
|
|
|
|
#define DOS_FILE_MAGIC_NUMBER 0x5A4D /* "MZ" */
|
|
struct DosFileHeader {
|
|
uint16_t mMagic;
|
|
uint16_t LastSize;
|
|
uint16_t nBlocks;
|
|
uint16_t nReloc;
|
|
uint16_t HdrSize;
|
|
uint16_t MinAlloc;
|
|
uint16_t MaxAlloc;
|
|
uint16_t ss;
|
|
uint16_t sp;
|
|
uint16_t Checksum;
|
|
uint16_t ip;
|
|
uint16_t cs;
|
|
uint16_t RelocPos;
|
|
uint16_t nOverlay;
|
|
uint16_t reserved[4];
|
|
uint16_t OEMId;
|
|
uint16_t OEMInfo;
|
|
uint16_t reserved2[10];
|
|
uint32_t ExeHeader;
|
|
} __attribute__((packed));
|
|
|
|
#define IMAGE_FILE_MACHINE_I386 0x14c
|
|
#define IMAGE_FILE_MACHINE_AMD64 0x8664
|
|
#define PE_FILE_MAGIC_NUMBER 0x00004550 /* "PE\0\0" */
|
|
struct PeHeader {
|
|
uint32_t mMagic;
|
|
uint16_t mMachine;
|
|
uint16_t mNumberOfSections;
|
|
uint32_t mTimeDateStamp;
|
|
uint32_t mPointerToSymbolTable;
|
|
uint32_t mNumberOfSymbols;
|
|
uint16_t mSizeOfOptionalHeader;
|
|
uint16_t mCharacteristics;
|
|
} __attribute__((packed));
|
|
|
|
struct OptionHeader {
|
|
uint16_t Format;
|
|
uint8_t MajorLinkVer;
|
|
uint8_t MinorLinkVer;
|
|
uint32_t CodeSize;
|
|
uint32_t InitializedDataSize;
|
|
uint32_t UninitializedDataSize;
|
|
uint32_t EntryPoint;
|
|
uint32_t BaseOfCode;
|
|
uint32_t BaseOfDate;
|
|
} __attribute__((packed));
|
|
|
|
|
|
struct PeSectionHeader {
|
|
char mName[8];
|
|
uint32_t mVirtualSize;
|
|
uint32_t mVirtualAddress;
|
|
uint32_t mSizeOfRawData;
|
|
uint32_t mPointerToRawData;
|
|
uint32_t mPointerToRealocations;
|
|
uint32_t mPointerToLinenumbers;
|
|
uint16_t mNumberOfRealocations;
|
|
uint16_t mNumberOfLinenumbers;
|
|
uint32_t mCharacteristics;
|
|
} __attribute__((packed));
|
|
|
|
|
|
EFI_STATUS get_pe_section(CHAR8 *base, char *section_name,
|
|
UINTN section_name_len, UINTN *vaddr, UINTN *size)
|
|
{
|
|
struct PeSectionHeader *ph;
|
|
struct DosFileHeader *dh;
|
|
struct PeHeader *pe;
|
|
UINTN i;
|
|
UINTN offset;
|
|
|
|
dh = (struct DosFileHeader *)base;
|
|
|
|
if (dh->mMagic != DOS_FILE_MAGIC_NUMBER)
|
|
return EFI_LOAD_ERROR;
|
|
|
|
pe = (struct PeHeader *)&base[dh->ExeHeader];
|
|
if (pe->mMagic != PE_FILE_MAGIC_NUMBER)
|
|
return EFI_LOAD_ERROR;
|
|
|
|
if ((pe->mMachine != IMAGE_FILE_MACHINE_AMD64)
|
|
&& (pe->mMachine != IMAGE_FILE_MACHINE_I386))
|
|
return EFI_LOAD_ERROR;
|
|
|
|
offset = dh->ExeHeader + sizeof(*pe) + pe->mSizeOfOptionalHeader;
|
|
|
|
for (i = 0; i < pe->mNumberOfSections; i++) {
|
|
ph = (struct PeSectionHeader *)&base[offset];
|
|
if (CompareMem(ph->mName, section_name, section_name_len) == 0) {
|
|
*vaddr = (UINTN)ph->mVirtualAddress;
|
|
*size = (UINTN)ph->mVirtualSize;
|
|
break;
|
|
}
|
|
|
|
offset += sizeof(*ph);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
EFI_IMAGE_ENTRY_POINT get_pe_entry(CHAR8 *base)
|
|
{
|
|
struct DosFileHeader* dh;
|
|
struct PeHeader* pe;
|
|
struct OptionHeader* oh;
|
|
UINTN offset;
|
|
|
|
dh = (struct DosFileHeader *)base;
|
|
|
|
if (dh->mMagic != DOS_FILE_MAGIC_NUMBER)
|
|
return NULL;
|
|
|
|
pe = (struct PeHeader *)&base[dh->ExeHeader];
|
|
if (pe->mMagic != PE_FILE_MAGIC_NUMBER)
|
|
return NULL;
|
|
|
|
if ((pe->mMachine != IMAGE_FILE_MACHINE_AMD64)
|
|
&& (pe->mMachine != IMAGE_FILE_MACHINE_I386))
|
|
return NULL;
|
|
|
|
offset = dh->ExeHeader + sizeof(*pe);
|
|
oh = (struct OptionHeader*)&base[offset];
|
|
|
|
return (EFI_IMAGE_ENTRY_POINT)((UINT64)base + oh->EntryPoint);
|
|
}
|