ArmPlatformPkg/ArmShellCmdRunAxf: Added 'runaxf' cmd to shell

Use the command to load and start a ARM Executable File from mass storage.
This is basically just an ELF file. The program is copied to memory and
the Entrypoint is called. Control is not expected to return back to the
Shell. This has only been tested on AArch64 with a limited set of AXF
binaries.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Harry Liebel <Harry.Liebel@arm.com>
Reviewed-By: Olivier Martin <olivier.martin@arm.com>



git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16247 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Harry Liebel 2014-10-27 10:52:11 +00:00 committed by oliviermartin
parent 53ae06f50d
commit ced216f8b9
17 changed files with 2920 additions and 1 deletions

View File

@ -114,6 +114,13 @@
BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf
FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
# RunAxf support via Dynamic Shell Command protocol
# It uses the Shell libraries.
ArmShellCmdRunAxfLib|ArmPlatformPkg/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf
ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf
[LibraryClasses.common.SEC]
ArmPlatformSecExtraActionLib|ArmPlatformPkg/Library/DebugSecExtraActionLib/DebugSecExtraActionLib.inf
ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Sec/SecArmPlatformGlobalVariableLib.inf
@ -362,6 +369,12 @@
gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenPcAnsi()"
gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|10
# RunAxf support via Dynamic Shell Command protocol
# We want to use the Shell Libraries but don't want it to initialise
# automatically. We initialise the libraries when the command is called by the
# Shell.
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
[Components.common]
# Versatile Express FileSystem
ArmPlatformPkg/FileSystem/BootMonFs/BootMonFs.inf

View File

@ -16,6 +16,7 @@
#include <Library/VirtioMmioDeviceLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/ArmShellCmdLib.h>
#define ARM_FVP_BASE_VIRTIO_BLOCK_BASE 0x1c130000
@ -71,5 +72,11 @@ ArmFvpInitialise (
DEBUG ((EFI_D_ERROR, "ArmFvpDxe: Failed to install Virtio block device\n"));
}
// Install dynamic Shell command to run baremetal binaries.
Status = ShellDynCmdRunAxfInstall (ImageHandle);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "ArmFvpDxe: Failed to install ShellDynCmdRunAxf\n"));
}
return Status;
}

View File

@ -29,6 +29,7 @@
OvmfPkg/OvmfPkg.dec
[LibraryClasses]
ArmShellCmdRunAxfLib
UefiDriverEntryPoint
UefiBootServicesTableLib
VirtioMmioDeviceLib

View File

@ -13,6 +13,8 @@
**/
#include <Library/UefiLib.h>
#include <Library/DebugLib.h>
#include <Library/ArmShellCmdLib.h>
EFI_STATUS
EFIAPI
@ -21,5 +23,13 @@ ArmHwInitialise (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return EFI_SUCCESS;
EFI_STATUS Status;
// Install dynamic Shell command to run baremetal binaries.
Status = ShellDynCmdRunAxfInstall (ImageHandle);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "ArmHwDxe: Failed to install ShellDynCmdRunAxf\n"));
}
return Status;
}

View File

@ -28,4 +28,5 @@
ArmPlatformPkg/ArmPlatformPkg.dec
[LibraryClasses]
ArmShellCmdRunAxfLib
UefiDriverEntryPoint

View File

@ -0,0 +1,57 @@
/** @file
*
* Definitions for the Dynamic Shell command library
*
* Copyright (C) 2014, ARM Ltd
*
* This program and the accompanying materials are licensed and made available
* under the terms and conditions of the BSD License which accompanies this
* distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
* WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#ifndef _ARM_SHELL_CMD_LIB_H_
#define _ARM_SHELL_CMD_LIB_H_
/**
Initialize and Install EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL for RunAxf command.
@param[in] ImageHandle Handle the protocol should be attached to.
@retval EFI_SUCCESS The command has been installed successfully.
@retval EFI_UNSUPPORTED Help for the command failed to initialise.
@return Status code returned by InstallProtocolInterface
Boot Service function.
**/
EFI_STATUS
ShellDynCmdRunAxfInstall (
IN EFI_HANDLE ImageHandle
);
/**
Uninstall the RunAxf Command
@param[in] ImageHandle Handle of the device where the protocol should have
been installed.
@retval EFI_SUCCESS The device has been un-initialized successfully.
@return Status code returned by UninstallProtocolInterface
Boot Service function.
**/
EFI_STATUS
ShellDynCmdRunAxfUninstall (
IN EFI_HANDLE ImageHandle
);
#endif // _ARM_SHELL_CMD_LIB_H_

View File

@ -0,0 +1,95 @@
/** @file
*
* Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
*
* This program and the accompanying materials are licensed and made available
* under the terms and conditions of the BSD License which accompanies this
* distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/ArmShellCmdLib.h>
#include "ArmShellCmdRunAxf.h"
EFI_HANDLE gRunAxfHiiHandle = NULL;
#define RUNAXF_HII_GUID \
{ \
0xf5a6413b, 0x78d5, 0x448e, { 0xa2, 0x15, 0x22, 0x82, 0x8e, 0xbc, 0x61, 0x61 } \
}
EFI_GUID gRunAxfHiiGuid = RUNAXF_HII_GUID;
static EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolRunAxf = {
L"runaxf", // *CommandName
ShellDynCmdRunAxfHandler, // Handler
ShellDynCmdRunAxfGetHelp // GetHelp
};
EFI_STATUS
ShellDynCmdRunAxfInstall (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
// Register our shell command
Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
&gEfiShellDynamicCommandProtocolGuid,
&mShellDynCmdProtocolRunAxf,
NULL);
if (EFI_ERROR (Status)) {
return Status;
}
// Load the manual page for our command
//
// 3rd parameter 'HII strings array' must be name of .uni strings file
// followed by 'Strings', e.g. mycommands.uni must be specified as
// 'mycommandsStrings' because the build Autogen process defines this as a
// string array for the strings in your .uni file. Examine your Build folder
// under your package's DEBUG folder and you will find it defined in a
// xxxStrDefs.h file.
//
gRunAxfHiiHandle = HiiAddPackages (&gRunAxfHiiGuid, ImageHandle,
ArmShellCmdRunAxfStrings, NULL);
if (gRunAxfHiiHandle == NULL) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
EFI_STATUS
ShellDynCmdRunAxfUninstall (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
if (gRunAxfHiiHandle != NULL) {
HiiRemovePackages (gRunAxfHiiHandle);
}
Status = gBS->UninstallMultipleProtocolInterfaces (ImageHandle,
&gEfiShellDynamicCommandProtocolGuid,
&mShellDynCmdProtocolRunAxf,
NULL);
if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,85 @@
/** @file
*
* Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
*
* This program and the accompanying materials are licensed and made available
* under the terms and conditions of the BSD License which accompanies this
* distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#ifndef __ARM_SHELL_CMD_RUNAXF__
#define __ARM_SHELL_CMD_RUNAXF__
#include <ShellBase.h>
#include <Protocol/EfiShell.h>
#include <Protocol/EfiShellDynamicCommand.h>
#include <Library/HiiLib.h>
#include <Library/ShellLib.h>
#include <Library/UefiBootServicesTableLib.h>
extern EFI_GUID gRunAxfHiiGuid;
extern EFI_HANDLE gRunAxfHiiHandle;
extern EFI_HANDLE gRunAxfImageHandle;
// List of data segments to load to memory from AXF/ELF file.
typedef struct {
LIST_ENTRY Link; // This attribute must be the first entry of this
// structure (to avoid pointer computation)
UINTN MemOffset; // Where the data should go, Dest
UINTN FileOffset; // Where the data is from, Src
BOOLEAN Zeroes; // A section of Zeroes. Like .bss in ELF
UINTN Length; // Number of bytes.
} RUNAXF_LOAD_LIST;
/**
This is the shell command handler function pointer callback type. This
function handles the command when it is invoked in the shell.
@param[in] This The instance of the
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
@param[in] SystemTable The pointer to the system table.
@param[in] ShellParameters The parameters associated with the command.
@param[in] Shell The instance of the shell protocol used in the
context of processing this command.
@return EFI_SUCCESS The operation was successful.
@return other The operation failed.
**/
SHELL_STATUS
EFIAPI
ShellDynCmdRunAxfHandler (
IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
IN EFI_SYSTEM_TABLE *SystemTable,
IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
IN EFI_SHELL_PROTOCOL *Shell
);
/**
This is the command help handler function pointer callback type. This
function is responsible for displaying help information for the associated
command.
@param[in] This The instance of the
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
@param[in] Language The pointer to the language string to use.
@return string Pool allocated help string, must be freed by
caller.
**/
CHAR16*
EFIAPI
ShellDynCmdRunAxfGetHelp (
IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
IN CONST CHAR8 *Language
);
#endif //__ARM_SHELL_CMD_RUNAXF__

View File

@ -0,0 +1,54 @@
## @file
#
# Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010006
BASE_NAME = ArmShellCmdRunAxf
FILE_GUID = 1f78349d-7fba-4686-8098-fa017eda35fb
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = ArmShellCmdRunAxfLib
[Sources.common]
ArmShellCmdRunAxf.c
ArmShellCmdRunAxf.uni
RunAxf.c
BootMonFsLoader.h
BootMonFsLoader.c
ElfLoader.h
ElfLoader.c
# ELF definitions taken from BaseTools
elf32.h
elf64.h
elf_common.h
[Packages]
ArmPkg/ArmPkg.dec
ArmPlatformPkg/ArmPlatformPkg.dec
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
ArmLib
BaseLib
DebugLib
HiiLib
ShellLib
[Protocols]
gEfiShellDynamicCommandProtocolGuid
[Guids]
gArmBootMonFsFileInfoGuid

View File

@ -0,0 +1,154 @@
/** @file
*
* Copyright (c) 2014, ARM Ltd. All rights reserved.
*
* This program and the accompanying materials are licensed and made available
* under the terms and conditions of the BSD License which accompanies this
* distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
* WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Guid/BootMonFsFileInfo.h>
#include <Protocol/SimpleFileSystem.h> // EFI_FILE_HANDLE
#include "ArmShellCmdRunAxf.h"
#include "BootMonFsLoader.h"
/**
Check that loading the file is supported.
Not all information is checked, only the properties that matters to us in
our simplified loader.
BootMonFS file properties is not in a file header but in the file-system
metadata, so we need to pass a handle to the file to allow access to the
information.
@param[in] FileHandle Handle of the file to check.
@retval EFI_SUCCESS on success.
@retval EFI_INVALID_PARAMETER if the header is invalid.
@retval EFI_UNSUPPORTED if the file type/platform is not supported.
**/
EFI_STATUS
BootMonFsCheckFile (
IN CONST EFI_FILE_HANDLE FileHandle
)
{
EFI_STATUS Status;
BOOTMON_FS_FILE_INFO Info;
UINTN InfoSize;
UINTN Index;
ASSERT (FileHandle != NULL);
// Try to load the file information as BootMonFS executable.
InfoSize = sizeof (Info);
// Get BootMon File info and see if it gives us what we need to load the file.
Status = FileHandle->GetInfo (FileHandle, &gArmBootMonFsFileInfoGuid,
&InfoSize, &Info);
if (!EFI_ERROR (Status)) {
// Check the values return to see if they look reasonable.
// Do we have a good entrypoint and at least one good load region?
// We assume here that we cannot load to address 0x0.
if ((Info.Size == 0) || (Info.EntryPoint == 0) || (Info.RegionCount == 0) ||
(Info.RegionCount > BOOTMONFS_IMAGE_DESCRIPTION_REGION_MAX)) {
// The file does not seem to be of the right type.
Status = EFI_UNSUPPORTED;
} else {
// Check load regions. We just check for valid numbers, we dont do the
// checksums. Info.Offset can be zero if it loads from the start of the
// file.
for (Index = 0; Index < Info.RegionCount; Index++) {
if ((Info.Region[Index].LoadAddress == 0) || (Info.Region[Index].Size == 0)) {
Status = EFI_UNSUPPORTED;
break;
}
}
}
}
return Status;
}
/**
Load a binary file from BootMonFS.
@param[in] FileHandle Handle of the file to load.
@param[in] FileData Address of the file data in memory.
@param[out] EntryPoint Will be filled with the ELF entry point address.
@param[out] ImageSize Will be filled with the file size in memory. This
will effectively be equal to the sum of the load
region sizes.
This function assumes the file is valid and supported as checked with
BootMonFsCheckFile().
@retval EFI_SUCCESS on success.
@retval EFI_INVALID_PARAMETER if the file is invalid.
**/
EFI_STATUS
BootMonFsLoadFile (
IN CONST EFI_FILE_HANDLE FileHandle,
IN CONST VOID *FileData,
OUT VOID **EntryPoint,
OUT LIST_ENTRY *LoadList
)
{
EFI_STATUS Status;
BOOTMON_FS_FILE_INFO Info;
UINTN InfoSize;
UINTN Index;
UINTN ImageSize;
RUNAXF_LOAD_LIST *LoadNode;
ASSERT (FileHandle != NULL);
ASSERT (FileData != NULL);
ASSERT (EntryPoint != NULL);
ASSERT (LoadList != NULL);
ImageSize = 0;
InfoSize = sizeof (Info);
Status = FileHandle->GetInfo (FileHandle, &gArmBootMonFsFileInfoGuid,
&InfoSize, &Info);
if (!EFI_ERROR (Status)) {
*EntryPoint = (VOID*)((UINTN)Info.EntryPoint);
// Load all the regions to run-time memory
for (Index = 0; Index < Info.RegionCount; Index++) {
LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST));
if (LoadNode == NULL) {
Status = EFI_OUT_OF_RESOURCES;
break;
}
LoadNode->MemOffset = (UINTN)Info.Region[Index].LoadAddress;
LoadNode->FileOffset = (UINTN)FileData + Info.Region[Index].Offset;
LoadNode->Length = (UINTN)Info.Region[Index].Size;
InsertTailList (LoadList, &LoadNode->Link);
ImageSize += LoadNode->Length;
}
}
if ((!EFI_ERROR (Status)) && (ImageSize == 0)) {
Status = EFI_INVALID_PARAMETER;
}
return Status;
}

View File

@ -0,0 +1,66 @@
/** @file
*
* Copyright (c) 2014, ARM Ltd. All rights reserved.
*
* This program and the accompanying materials are licensed and made available
* under the terms and conditions of the BSD License which accompanies this
* distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
* WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#ifndef __BOOTMONFS_LOADER_H__
#define __BOOTMONFS_LOADER_H__
/**
Check that loading the file is supported.
Not all information is checked, only the properties that matters to us in
our simplified loader.
BootMonFS file properties is not in a file header but in the file-system
metadata, so we need to pass a handle to the file to allow access to the
information.
@param[in] FileHandle Handle of the file to check.
@retval EFI_SUCCESS on success.
@retval EFI_INVALID_PARAMETER if the header is invalid.
@retval EFI_UNSUPPORTED if the file type/platform is not supported.
**/
EFI_STATUS
BootMonFsCheckFile (
IN CONST EFI_FILE_HANDLE FileHandle
);
/**
Load a binary file from BootMonFS.
@param[in] FileHandle Handle of the file to load.
@param[in] FileData Address of the file data in memory.
@param[out] EntryPoint Will be filled with the ELF entry point address.
@param[out] ImageSize Will be filled with the file size in memory. This
will effectively be equal to the sum of the load
region sizes.
This function assumes the file is valid and supported as checked with
BootMonFsCheckFile().
@retval EFI_SUCCESS on success.
@retval EFI_INVALID_PARAMETER if the file is invalid.
**/
EFI_STATUS
BootMonFsLoadFile (
IN CONST EFI_FILE_HANDLE FileHandle,
IN CONST VOID *FileData,
OUT VOID **EntryPoint,
OUT LIST_ENTRY *LoadList
);
#endif // __BOOTMONFS_LOADER_H__

View File

@ -0,0 +1,340 @@
/** @file
*
* Copyright (c) 2014, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include "ArmShellCmdRunAxf.h"
#include "ElfLoader.h"
#include "elf_common.h"
#include "elf32.h"
#include "elf64.h"
// Put the functions the #ifdef. We only use the appropriate one for the platform.
// This prevents 'defined but not used' compiler warning.
#ifdef MDE_CPU_ARM
STATIC
BOOLEAN
IsArmElf (
IN CONST VOID *Buf
)
{
Elf32_Ehdr *Hdr = (Elf32_Ehdr*)Buf;
if (Hdr->e_ident[EI_CLASS] != ELFCLASS32) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGCLASS_32), gRunAxfHiiHandle);
return FALSE;
}
if (Hdr->e_machine != EM_ARM) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGMACH_32), gRunAxfHiiHandle);
return FALSE;
}
// We don't currently check endianness of ELF data (hdr->e_ident[EI_DATA])
return TRUE;
}
#elif defined(MDE_CPU_AARCH64)
STATIC
BOOLEAN
IsAarch64Elf (
IN CONST VOID *Buf
)
{
Elf64_Ehdr *Hdr = (Elf64_Ehdr*)Buf;
if (Hdr->e_ident[EI_CLASS] != ELFCLASS64) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGCLASS_64), gRunAxfHiiHandle);
return FALSE;
}
if (Hdr->e_machine != EM_AARCH64) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGMACH_64), gRunAxfHiiHandle);
return FALSE;
}
// We don't currently check endianness of ELF data (hdr->e_ident[EI_DATA])
return TRUE;
}
#endif // MDE_CPU_ARM , MDE_CPU_AARCH64
/**
Support checking 32 and 64bit as the header could be valid, we might just
not support loading it.
**/
STATIC
EFI_STATUS
ElfCheckHeader (
IN CONST VOID *Buf
)
{
Elf32_Ehdr *Hdr32 = (Elf32_Ehdr*)Buf;
if (!IS_ELF (*Hdr32)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFMAGIC), gRunAxfHiiHandle);
return EFI_INVALID_PARAMETER;
}
if (Hdr32->e_type != ET_EXEC) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOTEXEC), gRunAxfHiiHandle);
return EFI_INVALID_PARAMETER;
}
if (Hdr32->e_ident[EI_CLASS] == ELFCLASS32) {
if ((Hdr32->e_phoff == 0) || (Hdr32->e_phentsize == 0) || (Hdr32->e_phnum == 0)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOPROG), gRunAxfHiiHandle);
return EFI_INVALID_PARAMETER;
}
if (Hdr32->e_flags != 0) {
DEBUG ((EFI_D_INFO, "Warning: Wrong processor-specific flags, expected 0.\n"));
}
DEBUG ((EFI_D_INFO, "Entry point addr: 0x%lx\n", Hdr32->e_entry));
DEBUG ((EFI_D_INFO, "Start of program headers: 0x%lx\n", Hdr32->e_phoff));
DEBUG ((EFI_D_INFO, "Size of 1 program header: %d\n", Hdr32->e_phentsize));
DEBUG ((EFI_D_INFO, "Number of program headers: %d\n", Hdr32->e_phnum));
} else if (Hdr32->e_ident[EI_CLASS] == ELFCLASS64) {
Elf64_Ehdr *Hdr64 = (Elf64_Ehdr*)Buf;
if ((Hdr64->e_phoff == 0) || (Hdr64->e_phentsize == 0) || (Hdr64->e_phnum == 0)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOPROG), gRunAxfHiiHandle);
return EFI_INVALID_PARAMETER;
}
if (Hdr64->e_flags != 0) {
DEBUG ((EFI_D_INFO, "Warning: Wrong processor-specific flags, expected 0.\n"));
}
DEBUG ((EFI_D_INFO, "Entry point addr: 0x%lx\n", Hdr64->e_entry));
DEBUG ((EFI_D_INFO, "Start of program headers: 0x%lx\n", Hdr64->e_phoff));
DEBUG ((EFI_D_INFO, "Size of 1 program header: %d\n", Hdr64->e_phentsize));
DEBUG ((EFI_D_INFO, "Number of program headers: %d\n", Hdr64->e_phnum));
} else {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGCLASS), gRunAxfHiiHandle);
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
/**
Load an ELF segment into memory.
This function assumes the ELF file is valid.
This function is meant to be called for PT_LOAD type segments only.
**/
STATIC
EFI_STATUS
ElfLoadSegment (
IN CONST VOID *ElfImage,
IN CONST VOID *PHdr,
IN LIST_ENTRY *LoadList
)
{
VOID *FileSegment;
VOID *MemSegment;
UINTN ExtraZeroes;
UINTN ExtraZeroesCount;
RUNAXF_LOAD_LIST *LoadNode;
#ifdef MDE_CPU_ARM
Elf32_Phdr *ProgramHdr;
ProgramHdr = (Elf32_Phdr *)PHdr;
#elif defined(MDE_CPU_AARCH64)
Elf64_Phdr *ProgramHdr;
ProgramHdr = (Elf64_Phdr *)PHdr;
#endif
ASSERT (ElfImage != NULL);
ASSERT (ProgramHdr != NULL);
FileSegment = (VOID *)((UINTN)ElfImage + ProgramHdr->p_offset);
MemSegment = (VOID *)ProgramHdr->p_vaddr;
// If the segment's memory size p_memsz is larger than the file size p_filesz,
// the "extra" bytes are defined to hold the value 0 and to follow the
// segment's initialised area.
// This is typically the case for the .bss segment.
// The file size may not be larger than the memory size.
if (ProgramHdr->p_filesz > ProgramHdr->p_memsz) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFBADFORMAT), gRunAxfHiiHandle);
return EFI_INVALID_PARAMETER;
}
// Load the segment in memory.
if (ProgramHdr->p_filesz != 0) {
DEBUG ((EFI_D_INFO, "Loading segment from 0x%lx to 0x%lx (size = %ld)\n",
FileSegment, MemSegment, ProgramHdr->p_filesz));
LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST));
if (LoadNode == NULL) {
return EFI_OUT_OF_RESOURCES;
}
LoadNode->MemOffset = (UINTN)MemSegment;
LoadNode->FileOffset = (UINTN)FileSegment;
LoadNode->Length = (UINTN)ProgramHdr->p_filesz;
InsertTailList (LoadList, &LoadNode->Link);
}
ExtraZeroes = ((UINTN)MemSegment + ProgramHdr->p_filesz);
ExtraZeroesCount = ProgramHdr->p_memsz - ProgramHdr->p_filesz;
DEBUG ((EFI_D_INFO, "Completing segment with %d zero bytes.\n", ExtraZeroesCount));
if (ExtraZeroesCount > 0) {
// Extra Node to add the Zeroes.
LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST));
if (LoadNode == NULL) {
return EFI_OUT_OF_RESOURCES;
}
LoadNode->MemOffset = (UINTN)ExtraZeroes;
LoadNode->Zeroes = TRUE;
LoadNode->Length = ExtraZeroesCount;
InsertTailList (LoadList, &LoadNode->Link);
}
return EFI_SUCCESS;
}
/**
Check that the ELF File Header is valid and Machine type supported.
Not all information is checked in the ELF header, only the stuff that
matters to us in our simplified ELF loader.
@param[in] ElfImage Address of the ELF file to check.
@retval EFI_SUCCESS on success.
@retval EFI_INVALID_PARAMETER if the header is invalid.
@retval EFI_UNSUPPORTED if the file type/platform is not supported.
**/
EFI_STATUS
ElfCheckFile (
IN CONST VOID *ElfImage
)
{
EFI_STATUS Status;
ASSERT (ElfImage != NULL);
// Check that the ELF header is valid.
Status = ElfCheckHeader (ElfImage);
if (EFI_ERROR(Status)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFBADHEADER), gRunAxfHiiHandle);
return EFI_INVALID_PARAMETER;
}
#ifdef MDE_CPU_ARM
if (IsArmElf (ElfImage)) {
return EFI_SUCCESS;
}
#elif defined(MDE_CPU_AARCH64)
if (IsAarch64Elf (ElfImage)) {
return EFI_SUCCESS;
}
#endif
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_BAD_ARCH), gRunAxfHiiHandle);
return EFI_UNSUPPORTED;
}
/**
Load a ELF file.
@param[in] ElfImage Address of the ELF file in memory.
@param[out] EntryPoint Will be filled with the ELF entry point address.
@param[out] ImageSize Will be filled with the ELF size in memory. This will
effectively be equal to the sum of the segments sizes.
This functon assumes the header is valid and supported as checked with
ElfCheckFile().
@retval EFI_SUCCESS on success.
@retval EFI_INVALID_PARAMETER if the ELF file is invalid.
**/
EFI_STATUS
ElfLoadFile (
IN CONST VOID *ElfImage,
OUT VOID **EntryPoint,
OUT LIST_ENTRY *LoadList
)
{
EFI_STATUS Status;
UINT8 *ProgramHdr;
UINTN Index;
UINTN ImageSize;
#ifdef MDE_CPU_ARM
Elf32_Ehdr *ElfHdr;
Elf32_Phdr *ProgramHdrPtr;
ElfHdr = (Elf32_Ehdr*)ElfImage;
#elif defined(MDE_CPU_AARCH64)
Elf64_Ehdr *ElfHdr;
Elf64_Phdr *ProgramHdrPtr;
ElfHdr = (Elf64_Ehdr*)ElfImage;
#endif
ASSERT (ElfImage != NULL);
ASSERT (EntryPoint != NULL);
ASSERT (LoadList != NULL);
ProgramHdr = (UINT8*)ElfImage + ElfHdr->e_phoff;
DEBUG ((EFI_D_INFO, "ELF program header entry : 0x%lx\n", ProgramHdr));
ImageSize = 0;
// Load every loadable ELF segment into memory.
for (Index = 0; Index < ElfHdr->e_phnum; ++Index) {
#ifdef MDE_CPU_ARM
ProgramHdrPtr = (Elf32_Phdr*)ProgramHdr;
#elif defined(MDE_CPU_AARCH64)
ProgramHdrPtr = (Elf64_Phdr*)ProgramHdr;
#endif
// Only consider PT_LOAD type segments, ignore others.
if (ProgramHdrPtr->p_type == PT_LOAD) {
Status = ElfLoadSegment (ElfImage, (VOID *)ProgramHdrPtr, LoadList);
if (EFI_ERROR (Status)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFFAILSEG), gRunAxfHiiHandle);
return EFI_INVALID_PARAMETER;
}
ImageSize += ProgramHdrPtr->p_memsz;
}
ProgramHdr += ElfHdr->e_phentsize;
}
if (ImageSize == 0) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOSEG), gRunAxfHiiHandle);
return EFI_INVALID_PARAMETER;
}
// Return the entry point specified in the ELF header.
*EntryPoint = (void*)ElfHdr->e_entry;
return EFI_SUCCESS;
}

View File

@ -0,0 +1,64 @@
/** @file
*
* Copyright (c) 2014, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#ifndef ELF_LOADER_H
#define ELF_LOADER_H
/**
Check that the ELF File Header is valid and Machine type supported.
Not all information is checked in the ELF header, only the stuff that
matters to us in our simplified ELF loader.
@param[in] ElfImage Address of the ELF file to check.
@retval EFI_SUCCESS on success.
@retval EFI_INVALID_PARAMETER if the header is invalid.
@retval EFI_UNSUPPORTED if the file type/platform is not supported.
**/
EFI_STATUS
ElfCheckFile (
IN CONST VOID *ElfImage
);
/**
Load a ELF file.
@param[in] ElfImage Address of the ELF file in memory.
@param[out] EntryPoint Will be filled with the ELF entry point address.
@param[out] ImageSize Will be filled with the ELF size in memory. This will
effectively be equal to the sum of the segments sizes.
This function assumes the header is valid and supported as checked with
ElfCheckFile().
NOTE:
- We don't currently take the segment permissions into account (indicated by
the program headers). It can be used to allocate pages with the right
read/write/exec permissions.
@retval EFI_SUCCESS on success.
@retval EFI_INVALID_PARAMETER if the ELF file is invalid.
**/
EFI_STATUS
ElfLoadFile (
IN CONST VOID *ElfImage,
OUT VOID **EntryPoint,
OUT LIST_ENTRY *LoadList
);
#endif // ELF_LOADER_H

View File

@ -0,0 +1,395 @@
/** @file
*
* Shell command for launching AXF files.
*
* Copyright (c) 2014, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#include <Guid/GlobalVariable.h>
#include <Library/PrintLib.h>
#include <Library/HandleParsingLib.h>
#include <Library/DevicePathLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/ArmLib.h>
#include "ArmShellCmdRunAxf.h"
#include "ElfLoader.h"
#include "BootMonFsLoader.h"
// Provide arguments to AXF?
typedef VOID (*ELF_ENTRYPOINT)(UINTN arg0, UINTN arg1,
UINTN arg2, UINTN arg3);
STATIC
EFI_STATUS
ShutdownUefiBootServices (
VOID
)
{
EFI_STATUS Status;
UINTN MemoryMapSize;
EFI_MEMORY_DESCRIPTOR *MemoryMap;
UINTN MapKey;
UINTN DescriptorSize;
UINT32 DescriptorVersion;
UINTN Pages;
MemoryMap = NULL;
MemoryMapSize = 0;
Pages = 0;
do {
Status = gBS->GetMemoryMap (
&MemoryMapSize,
MemoryMap,
&MapKey,
&DescriptorSize,
&DescriptorVersion
);
if (Status == EFI_BUFFER_TOO_SMALL) {
Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
MemoryMap = AllocatePages (Pages);
//
// Get System MemoryMap
//
Status = gBS->GetMemoryMap (
&MemoryMapSize,
MemoryMap,
&MapKey,
&DescriptorSize,
&DescriptorVersion
);
}
// Don't do anything between the GetMemoryMap() and ExitBootServices()
if (!EFI_ERROR (Status)) {
Status = gBS->ExitBootServices (gImageHandle, MapKey);
if (EFI_ERROR (Status)) {
FreePages (MemoryMap, Pages);
MemoryMap = NULL;
MemoryMapSize = 0;
}
}
} while (EFI_ERROR (Status));
return Status;
}
STATIC
EFI_STATUS
PreparePlatformHardware (
VOID
)
{
//Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called.
// Clean before Disable else the Stack gets corrupted with old data.
ArmCleanDataCache ();
ArmDisableDataCache ();
// Invalidate all the entries that might have snuck in.
ArmInvalidateDataCache ();
// Disable and invalidate the instruction cache
ArmDisableInstructionCache ();
ArmInvalidateInstructionCache ();
// Turn off MMU
ArmDisableMmu();
return EFI_SUCCESS;
}
// Process arguments to pass to AXF?
STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
{NULL, TypeMax}
};
/**
This is the shell command handler function pointer callback type. This
function handles the command when it is invoked in the shell.
@param[in] This The instance of the
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
@param[in] SystemTable The pointer to the system table.
@param[in] ShellParameters The parameters associated with the command.
@param[in] Shell The instance of the shell protocol used in the
context of processing this command.
@return EFI_SUCCESS The operation was successful.
@return other The operation failed.
**/
SHELL_STATUS
EFIAPI
ShellDynCmdRunAxfHandler (
IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
IN EFI_SYSTEM_TABLE *SystemTable,
IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
IN EFI_SHELL_PROTOCOL *Shell
)
{
LIST_ENTRY *ParamPackage;
EFI_STATUS Status;
SHELL_STATUS ShellStatus;
SHELL_FILE_HANDLE FileHandle;
ELF_ENTRYPOINT StartElf;
CONST CHAR16 *FileName;
EFI_FILE_INFO *Info;
UINTN FileSize;
VOID *FileData;
VOID *Entrypoint;
LIST_ENTRY LoadList;
LIST_ENTRY *Node;
LIST_ENTRY *NextNode;
RUNAXF_LOAD_LIST *LoadNode;
CHAR16 *TmpFileName;
CHAR16 *TmpChar16;
ShellStatus = SHELL_SUCCESS;
FileHandle = NULL;
FileData = NULL;
InitializeListHead (&LoadList);
// Only install if they are not there yet? First time or every time?
// These can change if the shell exits and start again.
Status = gBS->InstallMultipleProtocolInterfaces (&gImageHandle,
&gEfiShellProtocolGuid, Shell,
&gEfiShellParametersProtocolGuid, ShellParameters,
NULL);
if (EFI_ERROR (Status)) {
return SHELL_DEVICE_ERROR;
}
// Update the protocols for the application library
Status = ShellInitialize ();
ASSERT_EFI_ERROR (Status);
// Add support to load AXF with optipnal args?
//
// Process Command Line arguments
//
Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);
if (EFI_ERROR (Status)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_INVALID_ARG), gRunAxfHiiHandle);
ShellStatus = SHELL_INVALID_PARAMETER;
} else {
//
// Check for "-?"
//
if ((ShellCommandLineGetFlag (ParamPackage, L"-?")) ||
(ShellCommandLineGetRawValue (ParamPackage, 1) == NULL)) {
//
// We didn't get a file to load
//
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_INVALID_ARG), gRunAxfHiiHandle);
ShellStatus = SHELL_INVALID_PARAMETER;
} else {
// For the moment we assume we only ever get one file to load with no arguments.
FileName = ShellCommandLineGetRawValue (ParamPackage, 1);
Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
if (EFI_ERROR (Status)) {
// BootMonFS supports file extensions, but they are stripped by default
// when the NOR is programmed.
// Remove the file extension and try to open again.
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_FILE_NOT_FOUND),
gRunAxfHiiHandle, FileName);
// Go through the filename and remove file extension. Preserve the
// original name.
TmpFileName = AllocateCopyPool (StrSize (FileName), (VOID *)FileName);
if (TmpFileName != NULL) {
TmpChar16 = StrStr (TmpFileName, L".");
if (TmpChar16 != NULL) {
*TmpChar16 = '\0';
DEBUG((EFI_D_ERROR, "Trying to open file: %s\n", TmpFileName));
Status = ShellOpenFileByName (TmpFileName, &FileHandle,
EFI_FILE_MODE_READ, 0);
}
FreePool (TmpFileName);
}
// Do we now have an open file after trying again?
if (EFI_ERROR (Status)) {
ShellStatus = SHELL_INVALID_PARAMETER;
FileHandle = NULL;
}
}
if (FileHandle != NULL) {
Info = ShellGetFileInfo (FileHandle);
FileSize = (UINTN) Info->FileSize;
FreePool (Info);
//
// Allocate buffer to read file. 'Runtime' so we can access it after
// ExitBootServices().
//
FileData = AllocateRuntimeZeroPool (FileSize);
if (FileData == NULL) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_NO_MEM), gRunAxfHiiHandle);
ShellStatus = SHELL_OUT_OF_RESOURCES;
} else {
//
// Read file into Buffer
//
Status = ShellReadFile (FileHandle, &FileSize, FileData);
if (EFI_ERROR (Status)) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_READ_FAIL), gRunAxfHiiHandle);
SHELL_FREE_NON_NULL (FileData);
FileData = NULL;
ShellStatus = SHELL_DEVICE_ERROR;
}
}
}
}
//
// Free the command line package
//
ShellCommandLineFreeVarList (ParamPackage);
}
// We have a file in memory. Try to work out if we can use it.
// It can either be in ELF format or BootMonFS format.
if (FileData != NULL) {
// Do some validation on the file before we try to load it. The file can
// either be an proper ELF file or one processed by the FlashLoader.
// Since the data might need to go to various locations in memory we cannot
// load the data directly while UEFI is running. We use the file loaders to
// populate a linked list of data and load addresses. This is processed and
// data copied to where it needs to go after calling ExitBootServices. At
// that stage we've reached the point of no return, so overwriting UEFI code
// does not make a difference.
Status = ElfCheckFile (FileData);
if (!EFI_ERROR (Status)) {
// Load program into memory
Status = ElfLoadFile ((VOID*)FileData, &Entrypoint, &LoadList);
} else {
// Try to see if it is a BootMonFs executable
Status = BootMonFsCheckFile ((EFI_FILE_HANDLE)FileHandle);
if (!EFI_ERROR (Status)) {
// Load program into memory
Status = BootMonFsLoadFile ((EFI_FILE_HANDLE)FileHandle,
(VOID*)FileData, &Entrypoint, &LoadList);
} else {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_BAD_FILE),
gRunAxfHiiHandle);
SHELL_FREE_NON_NULL (FileData);
ShellStatus = SHELL_UNSUPPORTED;
}
}
}
// Program load list created.
// Shutdown UEFI, copy and jump to code.
if (!IsListEmpty (&LoadList) && !EFI_ERROR (Status)) {
// Exit boot services here. This means we cannot return and cannot assume to
// have access to UEFI functions.
Status = ShutdownUefiBootServices ();
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR,"Can not shutdown UEFI boot services. Status=0x%X\n",
Status));
} else {
// Process linked list. Copy data to Memory.
Node = GetFirstNode (&LoadList);
while (!IsNull (&LoadList, Node)) {
LoadNode = (RUNAXF_LOAD_LIST *)Node;
// Do we have data to copy or do we need to set Zeroes (.bss)?
if (LoadNode->Zeroes) {
ZeroMem ((VOID*)LoadNode->MemOffset, LoadNode->Length);
} else {
CopyMem ((VOID *)LoadNode->MemOffset, (VOID *)LoadNode->FileOffset,
LoadNode->Length);
}
Node = GetNextNode (&LoadList, Node);
}
//
// Switch off interrupts, caches, mmu, etc
//
Status = PreparePlatformHardware ();
ASSERT_EFI_ERROR (Status);
StartElf = (ELF_ENTRYPOINT)Entrypoint;
StartElf (0,0,0,0);
// We should never get here.. But if we do, spin..
ASSERT (FALSE);
while (1);
}
}
// Free file related information as we are returning to UEFI.
Node = GetFirstNode (&LoadList);
while (!IsNull (&LoadList, Node)) {
NextNode = RemoveEntryList (Node);
FreePool (Node);
Node = NextNode;
}
SHELL_FREE_NON_NULL (FileData);
if (FileHandle != NULL) {
ShellCloseFile (&FileHandle);
}
// Uninstall protocols as we don't know if they will change.
// If the shell exits and come in again these mappings may be different
// and cause a crash.
Status = gBS->UninstallMultipleProtocolInterfaces (gImageHandle,
&gEfiShellProtocolGuid, Shell,
&gEfiShellParametersProtocolGuid, ShellParameters,
NULL);
if (EFI_ERROR (Status) && ShellStatus == SHELL_SUCCESS) {
ShellStatus = SHELL_DEVICE_ERROR;
}
return ShellStatus;
}
/**
This is the command help handler function pointer callback type. This
function is responsible for displaying help information for the associated
command.
@param[in] This The instance of the
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
@param[in] Language The pointer to the language string to use.
@return string Pool allocated help string, must be freed by
caller.
**/
CHAR16*
EFIAPI
ShellDynCmdRunAxfGetHelp (
IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
IN CONST CHAR8 *Language
)
{
CHAR16 *HelpText;
ASSERT (gRunAxfHiiHandle != NULL);
// This allocates memory. The caller is responsoible to free.
HelpText = HiiGetString (gRunAxfHiiHandle, STRING_TOKEN (STR_GET_HELP_RUNAXF),
Language);
return HelpText;
}

View File

@ -0,0 +1,258 @@
/** @file
Ported ELF include files from FreeBSD
Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
/*-
* Copyright (c) 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.2 2007/12/03 21:30:36 marius Exp $
*/
#ifndef _SYS_ELF32_H_
#define _SYS_ELF32_H_ 1
/*
* ELF definitions common to all 32-bit architectures.
*/
typedef UINT32 Elf32_Addr;
typedef UINT16 Elf32_Half;
typedef UINT32 Elf32_Off;
typedef INT32 Elf32_Sword;
typedef UINT32 Elf32_Word;
typedef UINT64 Elf32_Lword;
typedef Elf32_Word Elf32_Hashelt;
/* Non-standard class-dependent datatype used for abstraction. */
typedef Elf32_Word Elf32_Size;
typedef Elf32_Sword Elf32_Ssize;
/*
* ELF header.
*/
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* File identification. */
Elf32_Half e_type; /* File type. */
Elf32_Half e_machine; /* Machine architecture. */
Elf32_Word e_version; /* ELF format version. */
Elf32_Addr e_entry; /* Entry point. */
Elf32_Off e_phoff; /* Program header file offset. */
Elf32_Off e_shoff; /* Section header file offset. */
Elf32_Word e_flags; /* Architecture-specific flags. */
Elf32_Half e_ehsize; /* Size of ELF header in bytes. */
Elf32_Half e_phentsize; /* Size of program header entry. */
Elf32_Half e_phnum; /* Number of program header entries. */
Elf32_Half e_shentsize; /* Size of section header entry. */
Elf32_Half e_shnum; /* Number of section header entries. */
Elf32_Half e_shstrndx; /* Section name strings section. */
} Elf32_Ehdr;
/*
* Section header.
*/
typedef struct {
Elf32_Word sh_name; /* Section name (index into the
section header string table). */
Elf32_Word sh_type; /* Section type. */
Elf32_Word sh_flags; /* Section flags. */
Elf32_Addr sh_addr; /* Address in memory image. */
Elf32_Off sh_offset; /* Offset in file. */
Elf32_Word sh_size; /* Size in bytes. */
Elf32_Word sh_link; /* Index of a related section. */
Elf32_Word sh_info; /* Depends on section type. */
Elf32_Word sh_addralign; /* Alignment in bytes. */
Elf32_Word sh_entsize; /* Size of each entry in section. */
} Elf32_Shdr;
/*
* Program header.
*/
typedef struct {
Elf32_Word p_type; /* Entry type. */
Elf32_Off p_offset; /* File offset of contents. */
Elf32_Addr p_vaddr; /* Virtual address in memory image. */
Elf32_Addr p_paddr; /* Physical address (not used). */
Elf32_Word p_filesz; /* Size of contents in file. */
Elf32_Word p_memsz; /* Size of contents in memory. */
Elf32_Word p_flags; /* Access permission flags. */
Elf32_Word p_align; /* Alignment in memory and file. */
} Elf32_Phdr;
/*
* Dynamic structure. The ".dynamic" section contains an array of them.
*/
typedef struct {
Elf32_Sword d_tag; /* Entry type. */
union {
Elf32_Word d_val; /* Integer value. */
Elf32_Addr d_ptr; /* Address value. */
} d_un;
} Elf32_Dyn;
/*
* Relocation entries.
*/
/* Relocations that don't need an addend field. */
typedef struct {
Elf32_Addr r_offset; /* Location to be relocated. */
Elf32_Word r_info; /* Relocation type and symbol index. */
} Elf32_Rel;
/* Relocations that need an addend field. */
typedef struct {
Elf32_Addr r_offset; /* Location to be relocated. */
Elf32_Word r_info; /* Relocation type and symbol index. */
Elf32_Sword r_addend; /* Addend. */
} Elf32_Rela;
/* Macros for accessing the fields of r_info. */
#define ELF32_R_SYM(info) ((info) >> 8)
#define ELF32_R_TYPE(info) ((unsigned char)(info))
/* Macro for constructing r_info from field values. */
#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type))
/*
* Note entry header
*/
typedef Elf_Note Elf32_Nhdr;
/*
* Move entry
*/
typedef struct {
Elf32_Lword m_value; /* symbol value */
Elf32_Word m_info; /* size + index */
Elf32_Word m_poffset; /* symbol offset */
Elf32_Half m_repeat; /* repeat count */
Elf32_Half m_stride; /* stride info */
} Elf32_Move;
/*
* The macros compose and decompose values for Move.r_info
*
* sym = ELF32_M_SYM(M.m_info)
* size = ELF32_M_SIZE(M.m_info)
* M.m_info = ELF32_M_INFO(sym, size)
*/
#define ELF32_M_SYM(info) ((info)>>8)
#define ELF32_M_SIZE(info) ((unsigned char)(info))
#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
/*
* Hardware/Software capabilities entry
*/
typedef struct {
Elf32_Word c_tag; /* how to interpret value */
union {
Elf32_Word c_val;
Elf32_Addr c_ptr;
} c_un;
} Elf32_Cap;
/*
* Symbol table entries.
*/
typedef struct {
Elf32_Word st_name; /* String table index of name. */
Elf32_Addr st_value; /* Symbol value. */
Elf32_Word st_size; /* Size of associated object. */
unsigned char st_info; /* Type and binding information. */
unsigned char st_other; /* Reserved (not used). */
Elf32_Half st_shndx; /* Section index of symbol. */
} Elf32_Sym;
/* Macros for accessing the fields of st_info. */
#define ELF32_ST_BIND(info) ((info) >> 4)
#define ELF32_ST_TYPE(info) ((info) & 0xf)
/* Macro for constructing st_info from field values. */
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
/* Macro for accessing the fields of st_other. */
#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3)
/* Structures used by Sun & GNU symbol versioning. */
typedef struct
{
Elf32_Half vd_version;
Elf32_Half vd_flags;
Elf32_Half vd_ndx;
Elf32_Half vd_cnt;
Elf32_Word vd_hash;
Elf32_Word vd_aux;
Elf32_Word vd_next;
} Elf32_Verdef;
typedef struct
{
Elf32_Word vda_name;
Elf32_Word vda_next;
} Elf32_Verdaux;
typedef struct
{
Elf32_Half vn_version;
Elf32_Half vn_cnt;
Elf32_Word vn_file;
Elf32_Word vn_aux;
Elf32_Word vn_next;
} Elf32_Verneed;
typedef struct
{
Elf32_Word vna_hash;
Elf32_Half vna_flags;
Elf32_Half vna_other;
Elf32_Word vna_name;
Elf32_Word vna_next;
} Elf32_Vernaux;
typedef Elf32_Half Elf32_Versym;
typedef struct {
Elf32_Half si_boundto; /* direct bindings - symbol bound to */
Elf32_Half si_flags; /* per symbol flags */
} Elf32_Syminfo;
#endif /* !_SYS_ELF32_H_ */

View File

@ -0,0 +1,260 @@
/** @file
Ported ELF include files from FreeBSD
Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
/*-
* Copyright (c) 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.2 2007/12/03 21:30:36 marius Exp $
*/
#ifndef _SYS_ELF64_H_
#define _SYS_ELF64_H_ 1
/*
* ELF definitions common to all 64-bit architectures.
*/
typedef UINT64 Elf64_Addr;
typedef UINT16 Elf64_Half;
typedef UINT64 Elf64_Off;
typedef INT32 Elf64_Sword;
typedef INT64 Elf64_Sxword;
typedef UINT32 Elf64_Word;
typedef UINT64 Elf64_Lword;
typedef UINT64 Elf64_Xword;
/*
* Types of dynamic symbol hash table bucket and chain elements.
*
* This is inconsistent among 64 bit architectures, so a machine dependent
* typedef is required.
*/
typedef Elf64_Word Elf64_Hashelt;
/* Non-standard class-dependent datatype used for abstraction. */
typedef Elf64_Xword Elf64_Size;
typedef Elf64_Sxword Elf64_Ssize;
/*
* ELF header.
*/
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* File identification. */
Elf64_Half e_type; /* File type. */
Elf64_Half e_machine; /* Machine architecture. */
Elf64_Word e_version; /* ELF format version. */
Elf64_Addr e_entry; /* Entry point. */
Elf64_Off e_phoff; /* Program header file offset. */
Elf64_Off e_shoff; /* Section header file offset. */
Elf64_Word e_flags; /* Architecture-specific flags. */
Elf64_Half e_ehsize; /* Size of ELF header in bytes. */
Elf64_Half e_phentsize; /* Size of program header entry. */
Elf64_Half e_phnum; /* Number of program header entries. */
Elf64_Half e_shentsize; /* Size of section header entry. */
Elf64_Half e_shnum; /* Number of section header entries. */
Elf64_Half e_shstrndx; /* Section name strings section. */
} Elf64_Ehdr;
/*
* Section header.
*/
typedef struct {
Elf64_Word sh_name; /* Section name (index into the
section header string table). */
Elf64_Word sh_type; /* Section type. */
Elf64_Xword sh_flags; /* Section flags. */
Elf64_Addr sh_addr; /* Address in memory image. */
Elf64_Off sh_offset; /* Offset in file. */
Elf64_Xword sh_size; /* Size in bytes. */
Elf64_Word sh_link; /* Index of a related section. */
Elf64_Word sh_info; /* Depends on section type. */
Elf64_Xword sh_addralign; /* Alignment in bytes. */
Elf64_Xword sh_entsize; /* Size of each entry in section. */
} Elf64_Shdr;
/*
* Program header.
*/
typedef struct {
Elf64_Word p_type; /* Entry type. */
Elf64_Word p_flags; /* Access permission flags. */
Elf64_Off p_offset; /* File offset of contents. */
Elf64_Addr p_vaddr; /* Virtual address in memory image. */
Elf64_Addr p_paddr; /* Physical address (not used). */
Elf64_Xword p_filesz; /* Size of contents in file. */
Elf64_Xword p_memsz; /* Size of contents in memory. */
Elf64_Xword p_align; /* Alignment in memory and file. */
} Elf64_Phdr;
/*
* Dynamic structure. The ".dynamic" section contains an array of them.
*/
typedef struct {
Elf64_Sxword d_tag; /* Entry type. */
union {
Elf64_Xword d_val; /* Integer value. */
Elf64_Addr d_ptr; /* Address value. */
} d_un;
} Elf64_Dyn;
/*
* Relocation entries.
*/
/* Relocations that don't need an addend field. */
typedef struct {
Elf64_Addr r_offset; /* Location to be relocated. */
Elf64_Xword r_info; /* Relocation type and symbol index. */
} Elf64_Rel;
/* Relocations that need an addend field. */
typedef struct {
Elf64_Addr r_offset; /* Location to be relocated. */
Elf64_Xword r_info; /* Relocation type and symbol index. */
Elf64_Sxword r_addend; /* Addend. */
} Elf64_Rela;
/* Macros for accessing the fields of r_info. */
#define ELF64_R_SYM(info) ((info) >> 32)
#define ELF64_R_TYPE(info) ((info) & 0xffffffffL)
/* Macro for constructing r_info from field values. */
#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL))
#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40)
#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56)
#define ELF64_R_TYPE_INFO(data, type) \
(((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type))
/*
* Note entry header
*/
typedef Elf_Note Elf64_Nhdr;
/*
* Move entry
*/
typedef struct {
Elf64_Lword m_value; /* symbol value */
Elf64_Xword m_info; /* size + index */
Elf64_Xword m_poffset; /* symbol offset */
Elf64_Half m_repeat; /* repeat count */
Elf64_Half m_stride; /* stride info */
} Elf64_Move;
#define ELF64_M_SYM(info) ((info)>>8)
#define ELF64_M_SIZE(info) ((unsigned char)(info))
#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
/*
* Hardware/Software capabilities entry
*/
typedef struct {
Elf64_Xword c_tag; /* how to interpret value */
union {
Elf64_Xword c_val;
Elf64_Addr c_ptr;
} c_un;
} Elf64_Cap;
/*
* Symbol table entries.
*/
typedef struct {
Elf64_Word st_name; /* String table index of name. */
unsigned char st_info; /* Type and binding information. */
unsigned char st_other; /* Reserved (not used). */
Elf64_Half st_shndx; /* Section index of symbol. */
Elf64_Addr st_value; /* Symbol value. */
Elf64_Xword st_size; /* Size of associated object. */
} Elf64_Sym;
/* Macros for accessing the fields of st_info. */
#define ELF64_ST_BIND(info) ((info) >> 4)
#define ELF64_ST_TYPE(info) ((info) & 0xf)
/* Macro for constructing st_info from field values. */
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
/* Macro for accessing the fields of st_other. */
#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3)
/* Structures used by Sun & GNU-style symbol versioning. */
typedef struct {
Elf64_Half vd_version;
Elf64_Half vd_flags;
Elf64_Half vd_ndx;
Elf64_Half vd_cnt;
Elf64_Word vd_hash;
Elf64_Word vd_aux;
Elf64_Word vd_next;
} Elf64_Verdef;
typedef struct {
Elf64_Word vda_name;
Elf64_Word vda_next;
} Elf64_Verdaux;
typedef struct {
Elf64_Half vn_version;
Elf64_Half vn_cnt;
Elf64_Word vn_file;
Elf64_Word vn_aux;
Elf64_Word vn_next;
} Elf64_Verneed;
typedef struct {
Elf64_Word vna_hash;
Elf64_Half vna_flags;
Elf64_Half vna_other;
Elf64_Word vna_name;
Elf64_Word vna_next;
} Elf64_Vernaux;
typedef Elf64_Half Elf64_Versym;
typedef struct {
Elf64_Half si_boundto; /* direct bindings - symbol bound to */
Elf64_Half si_flags; /* per symbol flags */
} Elf64_Syminfo;
#endif /* !_SYS_ELF64_H_ */

File diff suppressed because it is too large Load Diff