ArmPlatformPkg: remove BootMonFs and ArmShellCmdRunAxf

These modules have been imported into edk2-platforms where they belong
so remove them from the main EDK2 branch.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
This commit is contained in:
Ard Biesheuvel 2017-11-15 16:21:53 +00:00
parent bc52af3bf3
commit de4940885a
24 changed files with 0 additions and 6215 deletions

View File

@ -1,61 +0,0 @@
#/** @file
# Support for ARM Boot Monitor File System
#
# Copyright (c) 2012-2015, 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 = 0x00010005
BASE_NAME = BootMonFs
FILE_GUID = 7abbc454-f737-4322-931c-b1bb62a01d6f
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = BootMonFsEntryPoint
[Sources]
BootMonFsEntryPoint.c
BootMonFsOpenClose.c
BootMonFsDir.c
BootMonFsImages.c
BootMonFsReadWrite.c
BootMonFsUnsupported.c
[Packages]
ArmPlatformPkg/ArmPlatformPkg.dec
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
BaseLib
DevicePathLib
MemoryAllocationLib
PrintLib
UefiDriverEntryPoint
UefiLib
[Guids]
gArmBootMonFsFileInfoGuid
gEfiFileSystemInfoGuid
gEfiFileInfoGuid
gEfiFileSystemVolumeLabelInfoIdGuid
[Pcd]
gArmPlatformTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths
[Protocols]
gEfiDiskIoProtocolGuid
gEfiBlockIoProtocolGuid
gEfiSimpleFileSystemProtocolGuid
gEfiDevicePathProtocolGuid
gEfiDevicePathFromTextProtocolGuid

View File

@ -1,388 +0,0 @@
/** @file
*
* Copyright (c) 2012-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 __BOOTMON_FS_API_H
#define __BOOTMON_FS_API_H
#include <Protocol/SimpleFileSystem.h>
EFI_STATUS
BootMonFsInitialize (
IN BOOTMON_FS_INSTANCE *Instance
);
UINT32
BootMonFsChecksum (
IN VOID *Data,
IN UINT32 Size
);
EFI_STATUS
BootMonFsComputeFooterChecksum (
IN OUT HW_IMAGE_DESCRIPTION *Footer
);
EFIAPI
EFI_STATUS
OpenBootMonFsOpenVolume (
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **Root
);
UINT32
BootMonFsGetImageLength (
IN BOOTMON_FS_FILE *File
);
UINTN
BootMonFsGetPhysicalSize (
IN BOOTMON_FS_FILE* File
);
EFI_STATUS
BootMonFsCreateFile (
IN BOOTMON_FS_INSTANCE *Instance,
OUT BOOTMON_FS_FILE **File
);
EFIAPI
EFI_STATUS
BootMonFsGetInfo (
IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
);
EFIAPI
EFI_STATUS
BootMonFsReadDirectory (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
);
EFIAPI
EFI_STATUS
BootMonFsFlushDirectory (
IN EFI_FILE_PROTOCOL *This
);
/**
Flush all modified data associated with a file to a device.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the
file handle to flush.
@retval EFI_SUCCESS The data was flushed.
@retval EFI_ACCESS_DENIED The file was opened read-only.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_VOLUME_FULL The volume is full.
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to flush the data.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsFlushFile (
IN EFI_FILE_PROTOCOL *This
);
/**
Close a specified file handle.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
handle to close.
@retval EFI_SUCCESS The file was closed.
@retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open
file handle.
**/
EFIAPI
EFI_STATUS
BootMonFsCloseFile (
IN EFI_FILE_PROTOCOL *This
);
/**
Open a file on the boot monitor file system.
The boot monitor file system does not allow for sub-directories. There is only
one directory, the root one. On any attempt to create a directory, the function
returns in error with the EFI_WRITE_PROTECTED error code.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
the file handle to source location.
@param[out] NewHandle A pointer to the location to return the opened
handle for the new file.
@param[in] FileName The Null-terminated string of the name of the file
to be opened.
@param[in] OpenMode The mode to open the file : Read or Read/Write or
Read/Write/Create
@param[in] Attributes Attributes of the file in case of a file creation
@retval EFI_SUCCESS The file was open.
@retval EFI_NOT_FOUND The specified file could not be found or the specified
directory in which to create a file could not be found.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible
with the Boot Monitor file system.
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsOpenFile (
IN EFI_FILE_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
);
/**
Read data from an open file.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
is the file handle to read data from.
@param[in out] BufferSize On input, the size of the Buffer. On output, the
amount of data returned in Buffer. In both cases,
the size is measured in bytes.
@param[out] Buffer The buffer into which the data is read.
@retval EFI_SUCCESS The data was read.
@retval EFI_DEVICE_ERROR On entry, the current file position is
beyond the end of the file, or the device
reported an error while performing the read
operation.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsReadFile (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
);
EFIAPI
EFI_STATUS
BootMonFsSetDirPosition (
IN EFI_FILE_PROTOCOL *This,
IN UINT64 Position
);
EFIAPI
EFI_STATUS
BootMonFsGetPosition (
IN EFI_FILE_PROTOCOL *This,
OUT UINT64 *Position
);
/**
Write data to an open file.
The data is not written to the flash yet. It will be written when the file
will be either read, closed or flushed.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
is the file handle to write data to.
@param[in out] BufferSize On input, the size of the Buffer. On output, the
size of the data actually written. In both cases,
the size is measured in bytes.
@param[in] Buffer The buffer of data to write.
@retval EFI_SUCCESS The data was written.
@retval EFI_ACCESS_DENIED The file was opened read only.
@retval EFI_OUT_OF_RESOURCES Unable to allocate the buffer to store the
data to write.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsWriteFile (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
);
EFIAPI
EFI_STATUS
BootMonFsDeleteFail (
IN EFI_FILE_PROTOCOL *This
);
/**
Close and delete a file from the boot monitor file system.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
handle to delete.
@retval EFI_SUCCESS The file was closed and deleted.
@retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open
file handle.
@retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted.
**/
EFIAPI
EFI_STATUS
BootMonFsDelete (
IN EFI_FILE_PROTOCOL *This
);
/**
Set a file's current position.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
the file handle to set the requested position on.
@param[in] Position The byte position from the start of the file to set.
@retval EFI_SUCCESS The position was set.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsSetPosition (
IN EFI_FILE_PROTOCOL *This,
IN UINT64 Position
);
/**
Return a file's current position.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
the file handle to get the current position on.
@param[out] Position The address to return the file's current position value.
@retval EFI_SUCCESS The position was returned.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsGetPosition(
IN EFI_FILE_PROTOCOL *This,
OUT UINT64 *Position
);
//
// UNSUPPORTED OPERATIONS
//
EFIAPI
EFI_STATUS
BootMonFsGetPositionUnsupported (
IN EFI_FILE_PROTOCOL *This,
OUT UINT64 *Position
);
/**
Set information about a file or a volume.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
is the file handle the information is for.
@param[in] InformationType The type identifier for the information being set :
EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or
EFI_FILE_SYSTEM_VOLUME_LABEL_ID
@param[in] BufferSize The size, in bytes, of Buffer.
@param[in] Buffer A pointer to the data buffer to write. The type of the
data inside the buffer is indicated by InformationType.
@retval EFI_SUCCESS The information was set.
@retval EFI_UNSUPPORTED The InformationType is not known.
@retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.
@retval EFI_ACCESS_DENIED An attempt is made to change the name of a file
to a file that is already present.
@retval EFI_ACCESS_DENIED An attempt is being made to change the
EFI_FILE_DIRECTORY Attribute.
@retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and
the file was opened in read-only mode and an
attempt is being made to modify a field other
than Attribute.
@retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only
attribute.
@retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by
the data inside the buffer.
@retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsSetInfo (
IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType,
IN UINTN BufferSize,
IN VOID *Buffer
);
//
// Directory API
//
EFI_STATUS
BootMonFsOpenDirectory (
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName,
IN BOOTMON_FS_INSTANCE *Volume
);
//
// Internal API
//
/**
Search for a file given its name coded in Ascii.
When searching through the files of the volume, if a file is currently not
open, its name was written on the media and is kept in RAM in the
"HwDescription.Footer.Filename[]" field of the file's description.
If a file is currently open, its name might not have been written on the
media yet, and as the "HwDescription" is a mirror in RAM of what is on the
media the "HwDescription.Footer.Filename[]" might be outdated. In that case,
the up to date name of the file is stored in the "Info" field of the file's
description.
@param[in] Instance Pointer to the description of the volume in which
the file has to be search for.
@param[in] AsciiFileName Name of the file.
@param[out] File Pointer to the description of the file if the
file was found.
@retval EFI_SUCCESS The file was found.
@retval EFI_NOT_FOUND The file was not found.
**/
EFI_STATUS
BootMonGetFileFromAsciiFileName (
IN BOOTMON_FS_INSTANCE *Instance,
IN CHAR8* AsciiFileName,
OUT BOOTMON_FS_FILE **File
);
EFI_STATUS
BootMonGetFileFromPosition (
IN BOOTMON_FS_INSTANCE *Instance,
IN UINTN Position,
OUT BOOTMON_FS_FILE **File
);
#endif

View File

@ -1,766 +0,0 @@
/** @file
*
* Copyright (c) 2012-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 "BootMonFsInternal.h"
EFIAPI
EFI_STATUS
OpenBootMonFsOpenVolume (
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **Root
)
{
BOOTMON_FS_INSTANCE *Instance;
Instance = BOOTMON_FS_FROM_FS_THIS (This);
if (Instance == NULL) {
return EFI_DEVICE_ERROR;
}
Instance->RootFile->Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
*Root = &Instance->RootFile->File;
return EFI_SUCCESS;
}
UINT32
BootMonFsGetImageLength (
IN BOOTMON_FS_FILE *File
)
{
UINT32 Index;
UINT32 FileSize;
LIST_ENTRY *RegionToFlushLink;
BOOTMON_FS_FILE_REGION *Region;
FileSize = 0;
// Look at all Flash areas to determine file size
for (Index = 0; Index < HW_IMAGE_DESCRIPTION_REGION_MAX; Index++) {
FileSize += File->HwDescription.Region[Index].Size;
}
// Add the regions that have not been flushed yet
for (RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
!IsNull (&File->RegionToFlushLink, RegionToFlushLink);
RegionToFlushLink = GetNextNode (&File->RegionToFlushLink, RegionToFlushLink)
)
{
Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
if (Region->Offset + Region->Size > FileSize) {
FileSize += Region->Offset + Region->Size;
}
}
return FileSize;
}
UINTN
BootMonFsGetPhysicalSize (
IN BOOTMON_FS_FILE* File
)
{
// Return 0 for files that haven't yet been flushed to media
if (File->HwDescription.RegionCount == 0) {
return 0;
}
return ((File->HwDescription.BlockEnd - File->HwDescription.BlockStart) + 1 )
* File->Instance->Media->BlockSize;
}
EFIAPI
EFI_STATUS
BootMonFsSetDirPosition (
IN EFI_FILE_PROTOCOL *This,
IN UINT64 Position
)
{
BOOTMON_FS_FILE *File;
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (File == NULL) {
return EFI_INVALID_PARAMETER;
}
// UEFI Spec section 12.5:
// "The seek request for nonzero is not valid on open directories."
if (Position != 0) {
return EFI_UNSUPPORTED;
}
File->Position = Position;
return EFI_SUCCESS;
}
EFI_STATUS
BootMonFsOpenDirectory (
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName,
IN BOOTMON_FS_INSTANCE *Volume
)
{
ASSERT(0);
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
GetFileSystemVolumeLabelInfo (
IN BOOTMON_FS_INSTANCE *Instance,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
UINTN Size;
EFI_FILE_SYSTEM_VOLUME_LABEL *Label;
EFI_STATUS Status;
Label = Buffer;
// Value returned by StrSize includes null terminator.
Size = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL
+ StrSize (Instance->FsInfo.VolumeLabel);
if (*BufferSize >= Size) {
CopyMem (&Label->VolumeLabel, &Instance->FsInfo.VolumeLabel, Size);
Status = EFI_SUCCESS;
} else {
Status = EFI_BUFFER_TOO_SMALL;
}
*BufferSize = Size;
return Status;
}
// Helper function that calculates a rough "free space" by:
// - Taking the media size
// - Subtracting the sum of all file sizes
// - Subtracting the block size times the number of files
// (To account for the blocks containing the HW_IMAGE_INFO
STATIC
UINT64
ComputeFreeSpace (
IN BOOTMON_FS_INSTANCE *Instance
)
{
LIST_ENTRY *FileLink;
UINT64 FileSizeSum;
UINT64 MediaSize;
UINTN NumFiles;
EFI_BLOCK_IO_MEDIA *Media;
BOOTMON_FS_FILE *File;
Media = Instance->BlockIo->Media;
MediaSize = Media->BlockSize * (Media->LastBlock + 1);
NumFiles = 0;
FileSizeSum = 0;
for (FileLink = GetFirstNode (&Instance->RootFile->Link);
!IsNull (&Instance->RootFile->Link, FileLink);
FileLink = GetNextNode (&Instance->RootFile->Link, FileLink)
)
{
File = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink);
FileSizeSum += BootMonFsGetImageLength (File);
NumFiles++;
}
return MediaSize - (FileSizeSum + (Media->BlockSize + NumFiles));
}
STATIC
EFI_STATUS
GetFilesystemInfo (
IN BOOTMON_FS_INSTANCE *Instance,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
EFI_STATUS Status;
if (*BufferSize >= Instance->FsInfo.Size) {
Instance->FsInfo.FreeSpace = ComputeFreeSpace (Instance);
CopyMem (Buffer, &Instance->FsInfo, Instance->FsInfo.Size);
Status = EFI_SUCCESS;
} else {
Status = EFI_BUFFER_TOO_SMALL;
}
*BufferSize = Instance->FsInfo.Size;
return Status;
}
STATIC
EFI_STATUS
GetFileInfo (
IN BOOTMON_FS_INSTANCE *Instance,
IN BOOTMON_FS_FILE *File,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
EFI_FILE_INFO *Info;
UINTN ResultSize;
ResultSize = SIZE_OF_EFI_FILE_INFO + StrSize (File->Info->FileName);
if (*BufferSize < ResultSize) {
*BufferSize = ResultSize;
return EFI_BUFFER_TOO_SMALL;
}
Info = Buffer;
CopyMem (Info, File->Info, ResultSize);
// Size of the information
Info->Size = ResultSize;
*BufferSize = ResultSize;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
GetBootMonFsFileInfo (
IN BOOTMON_FS_INSTANCE *Instance,
IN BOOTMON_FS_FILE *File,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
EFI_STATUS Status;
BOOTMON_FS_FILE_INFO *Info;
UINTN ResultSize;
UINTN Index;
if (File == Instance->RootFile) {
Status = EFI_UNSUPPORTED;
} else {
ResultSize = SIZE_OF_BOOTMON_FS_FILE_INFO;
if (*BufferSize < ResultSize) {
*BufferSize = ResultSize;
Status = EFI_BUFFER_TOO_SMALL;
} else {
Info = Buffer;
// Zero out the structure
ZeroMem (Info, ResultSize);
// Fill in the structure
Info->Size = ResultSize;
Info->EntryPoint = File->HwDescription.EntryPoint;
Info->RegionCount = File->HwDescription.RegionCount;
for (Index = 0; Index < File->HwDescription.RegionCount; Index++) {
Info->Region[Index].LoadAddress = File->HwDescription.Region[Index].LoadAddress;
Info->Region[Index].Size = File->HwDescription.Region[Index].Size;
Info->Region[Index].Offset = File->HwDescription.Region[Index].Offset;
Info->Region[Index].Checksum = File->HwDescription.Region[Index].Checksum;
}
*BufferSize = ResultSize;
Status = EFI_SUCCESS;
}
}
return Status;
}
/**
Set the name of a file.
This is a helper function for SetFileInfo().
@param[in] Instance A pointer to the description of the volume
the file belongs to.
@param[in] File A pointer to the description of the file.
@param[in] FileName A pointer to the new name of the file.
@retval EFI_SUCCESS The name was set.
@retval EFI_ACCESS_DENIED An attempt is made to change the name of a file
to a file that is already present.
**/
STATIC
EFI_STATUS
SetFileName (
IN BOOTMON_FS_INSTANCE *Instance,
IN BOOTMON_FS_FILE *File,
IN CONST CHAR16 *FileName
)
{
CHAR8 AsciiFileName[MAX_NAME_LENGTH];
BOOTMON_FS_FILE *SameFile;
// If the file path start with a \ strip it. The EFI Shell may
// insert a \ in front of the file name.
if (FileName[0] == L'\\') {
FileName++;
}
UnicodeStrToAsciiStrS (FileName, AsciiFileName, MAX_NAME_LENGTH);
if (BootMonGetFileFromAsciiFileName (
File->Instance,
AsciiFileName,
&SameFile
) != EFI_NOT_FOUND) {
// A file with that name already exists.
return EFI_ACCESS_DENIED;
} else {
// OK, change the filename.
AsciiStrToUnicodeStrS (AsciiFileName, File->Info->FileName,
(File->Info->Size - SIZE_OF_EFI_FILE_INFO) / sizeof (CHAR16));
return EFI_SUCCESS;
}
}
/**
Set the size of a file.
This is a helper function for SetFileInfo().
@param[in] Instance A pointer to the description of the volume
the file belongs to.
@param[in] File A pointer to the description of the file.
@param[in] NewSize The requested new size for the file.
@retval EFI_SUCCESS The size was set.
@retval EFI_OUT_OF_RESOURCES An allocation needed to process the request failed.
**/
STATIC
EFI_STATUS
SetFileSize (
IN BOOTMON_FS_INSTANCE *Instance,
IN BOOTMON_FS_FILE *BootMonFsFile,
IN UINTN NewSize
)
{
EFI_STATUS Status;
UINT32 OldSize;
LIST_ENTRY *RegionToFlushLink;
LIST_ENTRY *NextRegionToFlushLink;
BOOTMON_FS_FILE_REGION *Region;
EFI_FILE_PROTOCOL *File;
CHAR8 *Buffer;
UINTN BufferSize;
UINT64 StoredPosition;
OldSize = BootMonFsFile->Info->FileSize;
//
// In case of file truncation, force the regions waiting for writing to
// not overflow the new size of the file.
//
if (NewSize < OldSize) {
for (RegionToFlushLink = GetFirstNode (&BootMonFsFile->RegionToFlushLink);
!IsNull (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink);
)
{
NextRegionToFlushLink = GetNextNode (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink);
Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
if (Region->Offset > NewSize) {
RemoveEntryList (RegionToFlushLink);
FreePool (Region->Buffer);
FreePool (Region);
} else {
Region->Size = MIN (Region->Size, NewSize - Region->Offset);
}
RegionToFlushLink = NextRegionToFlushLink;
}
} else if (NewSize > OldSize) {
// Increasing a file's size is potentially complicated as it may require
// moving the image description on media. The simplest way to do it is to
// seek past the end of the file (which is valid in UEFI) and perform a
// Write.
File = &BootMonFsFile->File;
// Save position
Status = File->GetPosition (File, &StoredPosition);
if (EFI_ERROR (Status)) {
return Status;
}
// Set position at the end of the file
Status = File->SetPosition (File, OldSize);
if (EFI_ERROR (Status)) {
return Status;
}
BufferSize = NewSize - OldSize;
Buffer = AllocateZeroPool (BufferSize);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = File->Write (File, &BufferSize, Buffer);
FreePool (Buffer);
if (EFI_ERROR (Status)) {
return Status;
}
// Restore saved position
Status = File->SetPosition (File, StoredPosition);
if (EFI_ERROR (Status)) {
return Status;
}
}
BootMonFsFile->Info->FileSize = NewSize;
return EFI_SUCCESS;
}
/**
Set information about a file.
@param[in] Instance A pointer to the description of the volume
the file belongs to.
@param[in] File A pointer to the description of the file.
@param[in] Info A pointer to the file information to write.
@retval EFI_SUCCESS The information was set.
@retval EFI_ACCESS_DENIED An attempt is being made to change the
EFI_FILE_DIRECTORY Attribute.
@retval EFI_ACCESS_DENIED The file was opened in read-only mode and an
attempt is being made to modify a field other
than Attribute.
@retval EFI_ACCESS_DENIED An attempt is made to change the name of a file
to a file that is already present.
@retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only
attribute.
@retval EFI_OUT_OF_RESOURCES An allocation needed to process the request
failed.
**/
STATIC
EFI_STATUS
SetFileInfo (
IN BOOTMON_FS_INSTANCE *Instance,
IN BOOTMON_FS_FILE *File,
IN EFI_FILE_INFO *Info
)
{
EFI_STATUS Status;
BOOLEAN FileSizeIsDifferent;
BOOLEAN FileNameIsDifferent;
BOOLEAN TimeIsDifferent;
//
// A directory can not be changed to a file and a file can
// not be changed to a directory.
//
if ((Info->Attribute & EFI_FILE_DIRECTORY) !=
(File->Info->Attribute & EFI_FILE_DIRECTORY) ) {
return EFI_ACCESS_DENIED;
}
FileSizeIsDifferent = (Info->FileSize != File->Info->FileSize);
FileNameIsDifferent = (StrnCmp (
Info->FileName,
File->Info->FileName,
MAX_NAME_LENGTH - 1
) != 0);
//
// Check if the CreateTime, LastAccess or ModificationTime
// have been changed. The file system does not support file
// timestamps thus the three times in "File->Info" are
// always equal to zero. The following comparison actually
// checks if all three times are still equal to 0 or not.
//
TimeIsDifferent = CompareMem (
&Info->CreateTime,
&File->Info->CreateTime,
3 * sizeof (EFI_TIME)
) != 0;
//
// For a file opened in read-only mode, only the Attribute field can be
// modified. The root directory open mode is forced to read-only at opening
// thus the following test protects the root directory to be somehow modified.
//
if (File->OpenMode == EFI_FILE_MODE_READ) {
if (FileSizeIsDifferent || FileNameIsDifferent || TimeIsDifferent) {
return EFI_ACCESS_DENIED;
}
}
if (TimeIsDifferent) {
return EFI_WRITE_PROTECTED;
}
if (FileSizeIsDifferent) {
Status = SetFileSize (Instance, File, Info->FileSize);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Note down in RAM the Attribute field but we can not
// ask to store it in flash for the time being.
//
File->Info->Attribute = Info->Attribute;
if (FileNameIsDifferent) {
Status = SetFileName (Instance, File, Info->FileName);
if (EFI_ERROR (Status)) {
return Status;
}
}
return EFI_SUCCESS;
}
EFIAPI
EFI_STATUS
BootMonFsGetInfo (
IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
EFI_STATUS Status;
BOOTMON_FS_FILE *File;
BOOTMON_FS_INSTANCE *Instance;
if ((This == NULL) ||
(InformationType == NULL) ||
(BufferSize == NULL) ||
((Buffer == NULL) && (*BufferSize > 0)) ) {
return EFI_INVALID_PARAMETER;
}
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (File->Info == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = File->Instance;
// If the instance has not been initialized yet then do it ...
if (!Instance->Initialized) {
Status = BootMonFsInitialize (Instance);
} else {
Status = EFI_SUCCESS;
}
if (!EFI_ERROR (Status)) {
if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)
!= 0) {
Status = GetFileSystemVolumeLabelInfo (Instance, BufferSize, Buffer);
} else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {
Status = GetFilesystemInfo (Instance, BufferSize, Buffer);
} else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {
Status = GetFileInfo (Instance, File, BufferSize, Buffer);
} else if (CompareGuid (InformationType, &gArmBootMonFsFileInfoGuid) != 0) {
Status = GetBootMonFsFileInfo (Instance, File, BufferSize, Buffer);
} else {
Status = EFI_UNSUPPORTED;
}
}
return Status;
}
/**
Set information about a file or a volume.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
is the file handle the information is for.
@param[in] InformationType The type identifier for the information being set :
EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or
EFI_FILE_SYSTEM_VOLUME_LABEL_ID
@param[in] BufferSize The size, in bytes, of Buffer.
@param[in] Buffer A pointer to the data buffer to write. The type of the
data inside the buffer is indicated by InformationType.
@retval EFI_SUCCESS The information was set.
@retval EFI_UNSUPPORTED The InformationType is not known.
@retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.
@retval EFI_ACCESS_DENIED An attempt is made to change the name of a file
to a file that is already present.
@retval EFI_ACCESS_DENIED An attempt is being made to change the
EFI_FILE_DIRECTORY Attribute.
@retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and
the file was opened in read-only mode and an
attempt is being made to modify a field other
than Attribute.
@retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only
attribute.
@retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by
the data inside the buffer.
@retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsSetInfo (
IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType,
IN UINTN BufferSize,
IN VOID *Buffer
)
{
BOOTMON_FS_FILE *File;
EFI_FILE_INFO *Info;
EFI_FILE_SYSTEM_INFO *SystemInfo;
if ((This == NULL) ||
(InformationType == NULL) ||
(Buffer == NULL) ) {
return EFI_INVALID_PARAMETER;
}
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (File->Info == NULL) {
return EFI_INVALID_PARAMETER;
}
if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
Info = Buffer;
if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) {
return EFI_INVALID_PARAMETER;
}
if (BufferSize < Info->Size) {
return EFI_BAD_BUFFER_SIZE;
}
return (SetFileInfo (File->Instance, File, Info));
}
//
// The only writable field in the other two information types
// (i.e. EFI_FILE_SYSTEM_INFO and EFI_FILE_SYSTEM_VOLUME_LABEL) is the
// filesystem volume label. This can be retrieved with GetInfo, but it is
// hard-coded into this driver, not stored on media.
//
if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
SystemInfo = Buffer;
if (SystemInfo->Size <
(SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (SystemInfo->VolumeLabel))) {
return EFI_INVALID_PARAMETER;
}
if (BufferSize < SystemInfo->Size) {
return EFI_BAD_BUFFER_SIZE;
}
return EFI_WRITE_PROTECTED;
}
if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
return EFI_WRITE_PROTECTED;
}
return EFI_UNSUPPORTED;
}
EFIAPI
EFI_STATUS
BootMonFsReadDirectory (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
BOOTMON_FS_INSTANCE *Instance;
BOOTMON_FS_FILE *RootFile;
BOOTMON_FS_FILE *File;
EFI_FILE_INFO *Info;
UINTN NameSize;
UINTN ResultSize;
EFI_STATUS Status;
UINTN Index;
RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (RootFile == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = RootFile->Instance;
Status = BootMonGetFileFromPosition (Instance, RootFile->Position, &File);
if (EFI_ERROR (Status)) {
// No more file
*BufferSize = 0;
return EFI_SUCCESS;
}
NameSize = AsciiStrLen (File->HwDescription.Footer.Filename) + 1;
ResultSize = SIZE_OF_EFI_FILE_INFO + (NameSize * sizeof (CHAR16));
if (*BufferSize < ResultSize) {
*BufferSize = ResultSize;
return EFI_BUFFER_TOO_SMALL;
}
// Zero out the structure
Info = Buffer;
ZeroMem (Info, ResultSize);
// Fill in the structure
Info->Size = ResultSize;
Info->FileSize = BootMonFsGetImageLength (File);
Info->PhysicalSize = BootMonFsGetPhysicalSize (File);
for (Index = 0; Index < NameSize; Index++) {
Info->FileName[Index] = File->HwDescription.Footer.Filename[Index];
}
*BufferSize = ResultSize;
RootFile->Position++;
return EFI_SUCCESS;
}
EFIAPI
EFI_STATUS
BootMonFsFlushDirectory (
IN EFI_FILE_PROTOCOL *This
)
{
BOOTMON_FS_FILE *RootFile;
LIST_ENTRY *ListFiles;
LIST_ENTRY *Link;
BOOTMON_FS_FILE *File;
RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (RootFile == NULL) {
return EFI_INVALID_PARAMETER;
}
ListFiles = &RootFile->Link;
if (IsListEmpty (ListFiles)) {
return EFI_SUCCESS;
}
//
// Flush all the files that need to be flushed
//
// Go through all the list of files to flush them
for (Link = GetFirstNode (ListFiles);
!IsNull (ListFiles, Link);
Link = GetNextNode (ListFiles, Link)
)
{
File = BOOTMON_FS_FILE_FROM_LINK_THIS (Link);
File->File.Flush (&File->File);
}
return EFI_SUCCESS;
}

View File

@ -1,529 +0,0 @@
/** @file
*
* Copyright (c) 2012-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/BaseMemoryLib.h>
#include <Library/DevicePathLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/DevicePathFromText.h>
#include <Protocol/DriverBinding.h>
#include "BootMonFsInternal.h"
EFI_DEVICE_PATH* mBootMonFsSupportedDevicePaths;
LIST_ENTRY mInstances;
EFI_FILE_PROTOCOL mBootMonFsRootTemplate = {
EFI_FILE_PROTOCOL_REVISION,
BootMonFsOpenFile,
BootMonFsCloseFile,
BootMonFsDeleteFail,
BootMonFsReadDirectory,
BootMonFsWriteFile,
BootMonFsGetPositionUnsupported, // UEFI Spec: GetPosition not valid on dirs
BootMonFsSetDirPosition,
BootMonFsGetInfo,
BootMonFsSetInfo,
BootMonFsFlushDirectory
};
EFI_FILE_PROTOCOL mBootMonFsFileTemplate = {
EFI_FILE_PROTOCOL_REVISION,
BootMonFsOpenFile,
BootMonFsCloseFile,
BootMonFsDelete,
BootMonFsReadFile,
BootMonFsWriteFile,
BootMonFsGetPosition,
BootMonFsSetPosition,
BootMonFsGetInfo,
BootMonFsSetInfo,
BootMonFsFlushFile
};
/**
Search for a file given its name coded in Ascii.
When searching through the files of the volume, if a file is currently not
open, its name was written on the media and is kept in RAM in the
"HwDescription.Footer.Filename[]" field of the file's description.
If a file is currently open, its name might not have been written on the
media yet, and as the "HwDescription" is a mirror in RAM of what is on the
media the "HwDescription.Footer.Filename[]" might be outdated. In that case,
the up to date name of the file is stored in the "Info" field of the file's
description.
@param[in] Instance Pointer to the description of the volume in which
the file has to be search for.
@param[in] AsciiFileName Name of the file.
@param[out] File Pointer to the description of the file if the
file was found.
@retval EFI_SUCCESS The file was found.
@retval EFI_NOT_FOUND The file was not found.
**/
EFI_STATUS
BootMonGetFileFromAsciiFileName (
IN BOOTMON_FS_INSTANCE *Instance,
IN CHAR8* AsciiFileName,
OUT BOOTMON_FS_FILE **File
)
{
LIST_ENTRY *Entry;
BOOTMON_FS_FILE *FileEntry;
CHAR8 OpenFileAsciiFileName[MAX_NAME_LENGTH];
CHAR8 *AsciiFileNameToCompare;
// Go through all the files in the list and return the file handle
for (Entry = GetFirstNode (&Instance->RootFile->Link);
!IsNull (&Instance->RootFile->Link, Entry);
Entry = GetNextNode (&Instance->RootFile->Link, Entry)
)
{
FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry);
if (FileEntry->Info != NULL) {
UnicodeStrToAsciiStrS (FileEntry->Info->FileName, OpenFileAsciiFileName,
MAX_NAME_LENGTH);
AsciiFileNameToCompare = OpenFileAsciiFileName;
} else {
AsciiFileNameToCompare = FileEntry->HwDescription.Footer.Filename;
}
if (AsciiStrCmp (AsciiFileNameToCompare, AsciiFileName) == 0) {
*File = FileEntry;
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
EFI_STATUS
BootMonGetFileFromPosition (
IN BOOTMON_FS_INSTANCE *Instance,
IN UINTN Position,
OUT BOOTMON_FS_FILE **File
)
{
LIST_ENTRY *Entry;
BOOTMON_FS_FILE *FileEntry;
// Go through all the files in the list and return the file handle
for (Entry = GetFirstNode (&Instance->RootFile->Link);
!IsNull (&Instance->RootFile->Link, Entry) && (&Instance->RootFile->Link != Entry);
Entry = GetNextNode (&Instance->RootFile->Link, Entry)
)
{
if (Position == 0) {
FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry);
*File = FileEntry;
return EFI_SUCCESS;
}
Position--;
}
return EFI_NOT_FOUND;
}
EFI_STATUS
BootMonFsCreateFile (
IN BOOTMON_FS_INSTANCE *Instance,
OUT BOOTMON_FS_FILE **File
)
{
BOOTMON_FS_FILE *NewFile;
NewFile = (BOOTMON_FS_FILE*)AllocateZeroPool (sizeof (BOOTMON_FS_FILE));
if (NewFile == NULL) {
return EFI_OUT_OF_RESOURCES;
}
NewFile->Signature = BOOTMON_FS_FILE_SIGNATURE;
InitializeListHead (&NewFile->Link);
InitializeListHead (&NewFile->RegionToFlushLink);
NewFile->Instance = Instance;
// If the created file is the root file then create a directory EFI_FILE_PROTOCOL
if (Instance->RootFile == *File) {
CopyMem (&NewFile->File, &mBootMonFsRootTemplate, sizeof (mBootMonFsRootTemplate));
} else {
CopyMem (&NewFile->File, &mBootMonFsFileTemplate, sizeof (mBootMonFsFileTemplate));
}
*File = NewFile;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
SupportedDevicePathsInit (
VOID
)
{
EFI_STATUS Status;
CHAR16* DevicePathListStr;
CHAR16* DevicePathStr;
CHAR16* NextDevicePathStr;
EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
EFI_DEVICE_PATH_PROTOCOL *Instance;
Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
ASSERT_EFI_ERROR (Status);
// Initialize Variable
DevicePathListStr = (CHAR16*)PcdGetPtr (PcdBootMonFsSupportedDevicePaths);
mBootMonFsSupportedDevicePaths = NULL;
// Extract the Device Path instances from the multi-device path string
while ((DevicePathListStr != NULL) && (DevicePathListStr[0] != L'\0')) {
NextDevicePathStr = StrStr (DevicePathListStr, L";");
if (NextDevicePathStr == NULL) {
DevicePathStr = DevicePathListStr;
DevicePathListStr = NULL;
} else {
DevicePathStr = (CHAR16*)AllocateCopyPool ((NextDevicePathStr - DevicePathListStr + 1) * sizeof (CHAR16), DevicePathListStr);
if (DevicePathStr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
*(DevicePathStr + (NextDevicePathStr - DevicePathListStr)) = L'\0';
DevicePathListStr = NextDevicePathStr;
if (DevicePathListStr[0] == L';') {
DevicePathListStr++;
}
}
Instance = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DevicePathStr);
ASSERT (Instance != NULL);
mBootMonFsSupportedDevicePaths = AppendDevicePathInstance (mBootMonFsSupportedDevicePaths, Instance);
if (NextDevicePathStr != NULL) {
FreePool (DevicePathStr);
}
FreePool (Instance);
}
if (mBootMonFsSupportedDevicePaths == NULL) {
return EFI_UNSUPPORTED;
} else {
return EFI_SUCCESS;
}
}
EFI_STATUS
EFIAPI
BootMonFsDriverSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL
)
{
EFI_DISK_IO_PROTOCOL *DiskIo;
EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol;
EFI_DEVICE_PATH_PROTOCOL *SupportedDevicePath;
EFI_DEVICE_PATH_PROTOCOL *SupportedDevicePaths;
EFI_STATUS Status;
UINTN Size1;
UINTN Size2;
//
// Open the IO Abstraction(s) needed to perform the supported test
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDiskIoProtocolGuid,
(VOID **) &DiskIo,
gImageHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Close the I/O Abstraction(s) used to perform the supported test
//
gBS->CloseProtocol (
ControllerHandle,
&gEfiDiskIoProtocolGuid,
gImageHandle,
ControllerHandle
);
// Check that BlockIo protocol instance exists
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiBlockIoProtocolGuid,
NULL,
gImageHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
// Check if a DevicePath is attached to the handle
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDevicePathProtocolGuid,
(VOID **)&DevicePathProtocol,
gImageHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
// Check if the Device Path is the one which contains the Boot Monitor File System
Size1 = GetDevicePathSize (DevicePathProtocol);
// Go through the list of Device Path Instances
Status = EFI_UNSUPPORTED;
SupportedDevicePaths = mBootMonFsSupportedDevicePaths;
while (SupportedDevicePaths != NULL) {
SupportedDevicePath = GetNextDevicePathInstance (&SupportedDevicePaths, &Size2);
if ((Size1 == Size2) && (CompareMem (DevicePathProtocol, SupportedDevicePath, Size1) == 0)) {
// The Device Path is supported
Status = EFI_SUCCESS;
break;
}
}
gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, gImageHandle, ControllerHandle);
return Status;
}
EFI_STATUS
EFIAPI
BootMonFsDriverStart (
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL
)
{
BOOTMON_FS_INSTANCE *Instance;
EFI_STATUS Status;
UINTN VolumeNameSize;
EFI_FILE_INFO *Info;
Instance = AllocateZeroPool (sizeof (BOOTMON_FS_INSTANCE));
if (Instance == NULL) {
return EFI_OUT_OF_RESOURCES;
}
// Initialize the BlockIo of the Instance
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiBlockIoProtocolGuid,
(VOID **)&(Instance->BlockIo),
gImageHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
goto Error;
}
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDiskIoProtocolGuid,
(VOID **)&(Instance->DiskIo),
gImageHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto Error;
}
//
// Initialize the attributes of the Instance
//
Instance->Signature = BOOTMON_FS_SIGNATURE;
Instance->ControllerHandle = ControllerHandle;
Instance->Media = Instance->BlockIo->Media;
Instance->Binding = DriverBinding;
// Initialize the Simple File System Protocol
Instance->Fs.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
Instance->Fs.OpenVolume = OpenBootMonFsOpenVolume;
// Volume name + L' ' + '2' digit number
VolumeNameSize = StrSize (BOOTMON_FS_VOLUME_LABEL) + (3 * sizeof (CHAR16));
// Initialize FileSystem Information
Instance->FsInfo.Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + VolumeNameSize;
Instance->FsInfo.BlockSize = Instance->Media->BlockSize;
Instance->FsInfo.ReadOnly = FALSE;
Instance->FsInfo.VolumeSize =
Instance->Media->BlockSize * (Instance->Media->LastBlock - Instance->Media->LowestAlignedLba);
CopyMem (Instance->FsInfo.VolumeLabel, BOOTMON_FS_VOLUME_LABEL, StrSize (BOOTMON_FS_VOLUME_LABEL));
// Initialize the root file
Status = BootMonFsCreateFile (Instance, &Instance->RootFile);
if (EFI_ERROR (Status)) {
goto Error;
}
Info = AllocateZeroPool (sizeof (EFI_FILE_INFO));
if (Info == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
Instance->RootFile->Info = Info;
// Initialize the DevicePath of the Instance
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDevicePathProtocolGuid,
(VOID **)&(Instance->DevicePath),
gImageHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
goto Error;
}
//
// Install the Simple File System Protocol
//
Status = gBS->InstallMultipleProtocolInterfaces (
&ControllerHandle,
&gEfiSimpleFileSystemProtocolGuid, &Instance->Fs,
NULL
);
if (EFI_ERROR (Status)) {
goto Error;
}
InsertTailList (&mInstances, &Instance->Link);
return EFI_SUCCESS;
Error:
if (Instance->RootFile != NULL) {
if (Instance->RootFile->Info != NULL) {
FreePool (Instance->RootFile->Info);
}
FreePool (Instance->RootFile);
}
FreePool (Instance);
return Status;
}
EFI_STATUS
EFIAPI
BootMonFsDriverStop (
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
)
{
BOOTMON_FS_INSTANCE *Instance;
LIST_ENTRY *Link;
EFI_STATUS Status;
BOOLEAN InstanceFound;
// Find instance from ControllerHandle.
Instance = NULL;
InstanceFound = FALSE;
// For each instance in mInstances:
for (Link = GetFirstNode (&mInstances); !IsNull (&mInstances, Link); Link = GetNextNode (&mInstances, Link)) {
Instance = BOOTMON_FS_FROM_LINK (Link);
if (Instance->ControllerHandle == ControllerHandle) {
InstanceFound = TRUE;
break;
}
}
ASSERT (InstanceFound == TRUE);
gBS->CloseProtocol (
ControllerHandle,
&gEfiDevicePathProtocolGuid,
DriverBinding->ImageHandle,
ControllerHandle);
gBS->CloseProtocol (
ControllerHandle,
&gEfiDiskIoProtocolGuid,
DriverBinding->ImageHandle,
ControllerHandle);
gBS->CloseProtocol (
ControllerHandle,
&gEfiBlockIoProtocolGuid,
DriverBinding->ImageHandle,
ControllerHandle);
Status = gBS->UninstallMultipleProtocolInterfaces (
&ControllerHandle,
&gEfiSimpleFileSystemProtocolGuid, &Instance->Fs,
NULL);
FreePool (Instance->RootFile->Info);
FreePool (Instance->RootFile);
FreePool (Instance);
return Status;
}
//
// Simple Network Protocol Driver Global Variables
//
EFI_DRIVER_BINDING_PROTOCOL mBootMonFsDriverBinding = {
BootMonFsDriverSupported,
BootMonFsDriverStart,
BootMonFsDriverStop,
0xa,
NULL,
NULL
};
EFI_STATUS
EFIAPI
BootMonFsEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
InitializeListHead (&mInstances);
// Initialize the list of Device Paths that could support BootMonFs
Status = SupportedDevicePathsInit ();
if (!EFI_ERROR (Status)) {
Status = gBS->InstallMultipleProtocolInterfaces (
&ImageHandle,
&gEfiDriverBindingProtocolGuid, &mBootMonFsDriverBinding,
NULL
);
ASSERT_EFI_ERROR (Status);
} else {
DEBUG((EFI_D_ERROR,"Warning: No Device Paths supporting BootMonFs have been defined in the PCD.\n"));
}
return Status;
}

View File

@ -1,57 +0,0 @@
/** @file
*
* Copyright (c) 2012-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 __BOOTMON_FS_HW_H__
#define __BOOTMON_FS_HW_H__
#define MAX_NAME_LENGTH 32
#define HW_IMAGE_FOOTER_SIGNATURE_1 0x464C5348
#define HW_IMAGE_FOOTER_SIGNATURE_2 0x464F4F54
#define HW_IMAGE_FOOTER_VERSION 1
#define HW_IMAGE_FOOTER_OFFSET 92
#define HW_IMAGE_FOOTER_VERSION2 2
#define HW_IMAGE_FOOTER_OFFSET2 96
typedef struct {
CHAR8 Filename[MAX_NAME_LENGTH];
UINT32 Offset;
UINT32 Version;
UINT32 FooterSignature1;
UINT32 FooterSignature2;
} HW_IMAGE_FOOTER;
#define HW_IMAGE_DESCRIPTION_REGION_MAX 4
// This structure is located at the end of a block when a file is present
typedef struct {
UINT32 EntryPoint;
UINT32 Attributes;
UINT32 RegionCount;
struct {
UINT32 LoadAddress;
UINT32 Size;
UINT32 Offset;
UINT32 Checksum;
} Region[HW_IMAGE_DESCRIPTION_REGION_MAX];
UINT32 BlockStart;
UINT32 BlockEnd;
UINT32 FooterChecksum;
HW_IMAGE_FOOTER Footer;
} HW_IMAGE_DESCRIPTION;
#endif

View File

@ -1,222 +0,0 @@
/** @file
*
* Copyright (c) 2012-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/IoLib.h>
#include <Library/NorFlashPlatformLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Protocol/SimpleFileSystem.h>
#include "BootMonFsInternal.h"
UINT32
BootMonFsChecksum (
IN VOID *Data,
IN UINT32 Size
)
{
UINT32 *Ptr;
UINT32 Word;
UINT32 Checksum;
ASSERT (Size % 4 == 0);
Checksum = 0;
Ptr = (UINT32*)Data;
while (Size > 0) {
Word = *Ptr++;
Size -= 4;
if (Word > ~Checksum) {
Checksum++;
}
Checksum += Word;
}
return ~Checksum;
}
EFI_STATUS
BootMonFsComputeFooterChecksum (
IN OUT HW_IMAGE_DESCRIPTION *Footer
)
{
HW_IMAGE_DESCRIPTION *Description;
UINT32 Index;
Footer->Attributes = 1;
Description = AllocateZeroPool (sizeof (HW_IMAGE_DESCRIPTION));
if (Description == NULL) {
DEBUG ((DEBUG_ERROR, "BootMonFsComputeFooterChecksum: Unable to allocate memory.\n"));
return EFI_OUT_OF_RESOURCES;
}
// Copy over to temporary shim
CopyMem (Description, Footer, sizeof (HW_IMAGE_DESCRIPTION));
// BootMon doesn't checksum the previous checksum
Description->FooterChecksum = 0;
// Blank out regions which aren't being used.
for (Index = Footer->RegionCount; Index < HW_IMAGE_DESCRIPTION_REGION_MAX; Index++) {
Description->Region[Index].Checksum = 0;
Description->Region[Index].LoadAddress = 0;
Description->Region[Index].Offset = 0;
Description->Region[Index].Size = 0;
}
// Compute the checksum
Footer->FooterChecksum = BootMonFsChecksum (Description, sizeof (HW_IMAGE_DESCRIPTION));
FreePool (Description);
return EFI_SUCCESS;
}
BOOLEAN
BootMonFsIsImageValid (
IN HW_IMAGE_DESCRIPTION *Desc,
IN EFI_LBA Lba
)
{
EFI_STATUS Status;
HW_IMAGE_FOOTER *Footer;
UINT32 Checksum;
Footer = &Desc->Footer;
// Check that the verification bytes are present
if ((Footer->FooterSignature1 != HW_IMAGE_FOOTER_SIGNATURE_1) ||
(Footer->FooterSignature2 != HW_IMAGE_FOOTER_SIGNATURE_2)) {
return FALSE;
}
if (Footer->Version == HW_IMAGE_FOOTER_VERSION) {
if (Footer->Offset != HW_IMAGE_FOOTER_OFFSET) {
return FALSE;
}
} else if (Footer->Version == HW_IMAGE_FOOTER_VERSION2) {
if (Footer->Offset != HW_IMAGE_FOOTER_OFFSET2) {
return FALSE;
}
} else {
return FALSE;
}
Checksum = Desc->FooterChecksum;
Status = BootMonFsComputeFooterChecksum (Desc);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Warning: failed to compute checksum for image '%a'\n", Desc->Footer.Filename));
}
if (Desc->FooterChecksum != Checksum) {
DEBUG ((DEBUG_ERROR, "Warning: image '%a' checksum mismatch.\n", Desc->Footer.Filename));
}
if ((Desc->BlockEnd != Lba) || (Desc->BlockStart > Desc->BlockEnd)) {
return FALSE;
}
return TRUE;
}
STATIC
EFI_STATUS
BootMonFsDiscoverNextImage (
IN BOOTMON_FS_INSTANCE *Instance,
IN OUT EFI_LBA *LbaStart,
IN OUT BOOTMON_FS_FILE *File
)
{
EFI_DISK_IO_PROTOCOL *DiskIo;
EFI_LBA CurrentLba;
UINT64 DescOffset;
EFI_STATUS Status;
DiskIo = Instance->DiskIo;
CurrentLba = *LbaStart;
// Look for images in the rest of this block
while (CurrentLba <= Instance->Media->LastBlock) {
// Work out the byte offset into media of the image description in this block
// If present, the image description is at the very end of the block.
DescOffset = ((CurrentLba + 1) * Instance->Media->BlockSize) - sizeof (HW_IMAGE_DESCRIPTION);
// Read the image description from media
Status = DiskIo->ReadDisk (DiskIo,
Instance->Media->MediaId,
DescOffset,
sizeof (HW_IMAGE_DESCRIPTION),
&File->HwDescription
);
if (EFI_ERROR (Status)) {
return Status;
}
// If we found a valid image description...
if (BootMonFsIsImageValid (&File->HwDescription, (CurrentLba - Instance->Media->LowestAlignedLba))) {
DEBUG ((EFI_D_ERROR, "Found image: %a in block %d.\n",
&(File->HwDescription.Footer.Filename),
(UINTN)(CurrentLba - Instance->Media->LowestAlignedLba)
));
File->HwDescAddress = DescOffset;
*LbaStart = CurrentLba + 1;
return EFI_SUCCESS;
} else {
CurrentLba++;
}
}
*LbaStart = CurrentLba;
return EFI_NOT_FOUND;
}
EFI_STATUS
BootMonFsInitialize (
IN BOOTMON_FS_INSTANCE *Instance
)
{
EFI_STATUS Status;
EFI_LBA Lba;
UINT32 ImageCount;
BOOTMON_FS_FILE *NewFile;
ImageCount = 0;
Lba = 0;
while (1) {
Status = BootMonFsCreateFile (Instance, &NewFile);
if (EFI_ERROR (Status)) {
return Status;
}
Status = BootMonFsDiscoverNextImage (Instance, &Lba, NewFile);
if (EFI_ERROR (Status)) {
// Free NewFile allocated by BootMonFsCreateFile ()
FreePool (NewFile);
break;
}
InsertTailList (&Instance->RootFile->Link, &NewFile->Link);
ImageCount++;
}
Instance->Initialized = TRUE;
return EFI_SUCCESS;
}

View File

@ -1,101 +0,0 @@
/** @file
*
* Copyright (c) 2012-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 __BOOTMONFS_INTERNAL_H__
#define __BOOTMONFS_INTERNAL_H__
#include <PiDxe.h>
#include <Library/UefiLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Protocol/BlockIo.h>
#include <Protocol/DiskIo.h>
#include <Protocol/FirmwareVolumeBlock.h>
#include <Protocol/SimpleFileSystem.h>
#include <Guid/BootMonFsFileInfo.h>
#include <Guid/FileInfo.h>
#include <Guid/FileSystemInfo.h>
#include <Guid/FileSystemVolumeLabelInfo.h>
#include "BootMonFsHw.h"
#define BOOTMON_FS_VOLUME_LABEL L"NOR Flash"
typedef struct _BOOTMON_FS_INSTANCE BOOTMON_FS_INSTANCE;
typedef struct {
LIST_ENTRY Link;
VOID* Buffer;
UINTN Size;
UINT64 Offset; // Offset from the start of the file
} BOOTMON_FS_FILE_REGION;
typedef struct {
UINT32 Signature;
LIST_ENTRY Link;
BOOTMON_FS_INSTANCE *Instance;
UINTN HwDescAddress;
HW_IMAGE_DESCRIPTION HwDescription;
EFI_FILE_PROTOCOL File;
//
// The following fields are relevant only if the file is open.
//
EFI_FILE_INFO *Info;
UINT64 Position;
// If the file needs to be flushed then this list contain the memory
// buffer that creates this file
LIST_ENTRY RegionToFlushLink;
UINT64 OpenMode;
} BOOTMON_FS_FILE;
#define BOOTMON_FS_FILE_SIGNATURE SIGNATURE_32('b', 'o', 't', 'f')
#define BOOTMON_FS_FILE_FROM_FILE_THIS(a) CR (a, BOOTMON_FS_FILE, File, BOOTMON_FS_FILE_SIGNATURE)
#define BOOTMON_FS_FILE_FROM_LINK_THIS(a) CR (a, BOOTMON_FS_FILE, Link, BOOTMON_FS_FILE_SIGNATURE)
struct _BOOTMON_FS_INSTANCE {
UINT32 Signature;
EFI_HANDLE ControllerHandle;
LIST_ENTRY Link;
EFI_DRIVER_BINDING_PROTOCOL *Binding;
EFI_DISK_IO_PROTOCOL *DiskIo;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
EFI_BLOCK_IO_MEDIA *Media;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL Fs;
EFI_FILE_SYSTEM_INFO FsInfo;
CHAR16 Label[20];
BOOTMON_FS_FILE *RootFile; // All the other files are linked to this root
BOOLEAN Initialized;
};
#define BOOTMON_FS_SIGNATURE SIGNATURE_32('b', 'o', 't', 'm')
#define BOOTMON_FS_FROM_FS_THIS(a) CR (a, BOOTMON_FS_INSTANCE, Fs, BOOTMON_FS_SIGNATURE)
#define BOOTMON_FS_FROM_LINK(a) CR (a, BOOTMON_FS_INSTANCE, Link, BOOTMON_FS_SIGNATURE)
#include "BootMonFsApi.h"
#endif

View File

@ -1,795 +0,0 @@
/** @file
*
* Copyright (c) 2012-2015, 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 "BootMonFsInternal.h"
// Clear a file's image description on storage media:
// UEFI allows you to seek past the end of a file, a subsequent write will grow
// the file. It does not specify how space between the former end of the file
// and the beginning of the write should be filled. It's therefore possible that
// BootMonFs metadata, that comes after the end of a file, could be left there
// and wrongly detected by BootMonFsImageInBlock.
STATIC
EFI_STATUS
InvalidateImageDescription (
IN BOOTMON_FS_FILE *File
)
{
EFI_DISK_IO_PROTOCOL *DiskIo;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
UINT32 MediaId;
VOID *Buffer;
EFI_STATUS Status;
DiskIo = File->Instance->DiskIo;
BlockIo = File->Instance->BlockIo;
MediaId = BlockIo->Media->MediaId;
Buffer = AllocateZeroPool (sizeof (HW_IMAGE_DESCRIPTION));
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = DiskIo->WriteDisk (DiskIo,
MediaId,
File->HwDescAddress,
sizeof (HW_IMAGE_DESCRIPTION),
Buffer
);
FreePool(Buffer);
return Status;
}
/**
Write the description of a file to storage media.
This function uses DiskIo to write to the media, so call BlockIo->FlushBlocks()
after calling it to ensure the data are written on the media.
@param[in] File Description of the file whose description on the
storage media has to be updated.
@param[in] FileName Name of the file. Its length is assumed to be
lower than MAX_NAME_LENGTH.
@param[in] DataSize Number of data bytes of the file.
@param[in] FileStart File's starting position on media. FileStart must
be aligned to the media's block size.
@retval EFI_WRITE_PROTECTED The device cannot be written to.
@retval EFI_DEVICE_ERROR The device reported an error while performing
the write operation.
**/
STATIC
EFI_STATUS
WriteFileDescription (
IN BOOTMON_FS_FILE *File,
IN CHAR8 *FileName,
IN UINT32 DataSize,
IN UINT64 FileStart
)
{
EFI_STATUS Status;
EFI_DISK_IO_PROTOCOL *DiskIo;
UINTN BlockSize;
UINT32 FileSize;
HW_IMAGE_DESCRIPTION *Description;
DiskIo = File->Instance->DiskIo;
BlockSize = File->Instance->BlockIo->Media->BlockSize;
ASSERT (FileStart % BlockSize == 0);
//
// Construct the file description
//
FileSize = DataSize + sizeof (HW_IMAGE_DESCRIPTION);
Description = &File->HwDescription;
Description->Attributes = 1;
Description->BlockStart = FileStart / BlockSize;
Description->BlockEnd = Description->BlockStart + (FileSize / BlockSize);
AsciiStrCpyS (Description->Footer.Filename,
sizeof Description->Footer.Filename, FileName);
#ifdef MDE_CPU_ARM
Description->Footer.Offset = HW_IMAGE_FOOTER_OFFSET;
Description->Footer.Version = HW_IMAGE_FOOTER_VERSION;
#else
Description->Footer.Offset = HW_IMAGE_FOOTER_OFFSET2;
Description->Footer.Version = HW_IMAGE_FOOTER_VERSION2;
#endif
Description->Footer.FooterSignature1 = HW_IMAGE_FOOTER_SIGNATURE_1;
Description->Footer.FooterSignature2 = HW_IMAGE_FOOTER_SIGNATURE_2;
Description->RegionCount = 1;
Description->Region[0].Checksum = 0;
Description->Region[0].Offset = Description->BlockStart * BlockSize;
Description->Region[0].Size = DataSize;
Status = BootMonFsComputeFooterChecksum (Description);
if (EFI_ERROR (Status)) {
return Status;
}
File->HwDescAddress = ((Description->BlockEnd + 1) * BlockSize) - sizeof (HW_IMAGE_DESCRIPTION);
// Update the file description on the media
Status = DiskIo->WriteDisk (
DiskIo,
File->Instance->Media->MediaId,
File->HwDescAddress,
sizeof (HW_IMAGE_DESCRIPTION),
Description
);
ASSERT_EFI_ERROR (Status);
return Status;
}
// Find a space on media for a file that has not yet been flushed to disk.
// Just returns the first space that's big enough.
// This function could easily be adapted to:
// - Find space for moving an existing file that has outgrown its space
// (We do not currently move files, just return EFI_VOLUME_FULL)
// - Find space for a fragment of a file that has outgrown its space
// (We do not currently fragment files - it's not clear whether fragmentation
// is actually part of BootMonFs as there is no spec)
// - Be more clever about finding space (choosing the largest or smallest
// suitable space)
// Parameters:
// File - the new (not yet flushed) file for which we need to find space.
// FileStart - the position on media of the file (in bytes).
STATIC
EFI_STATUS
BootMonFsFindSpaceForNewFile (
IN BOOTMON_FS_FILE *File,
IN UINT64 FileSize,
OUT UINT64 *FileStart
)
{
LIST_ENTRY *FileLink;
BOOTMON_FS_FILE *RootFile;
BOOTMON_FS_FILE *FileEntry;
UINTN BlockSize;
EFI_BLOCK_IO_MEDIA *Media;
Media = File->Instance->BlockIo->Media;
BlockSize = Media->BlockSize;
RootFile = File->Instance->RootFile;
// This function must only be called for file which has not been flushed into
// Flash yet
ASSERT (File->HwDescription.RegionCount == 0);
*FileStart = 0;
// Go through all the files in the list
for (FileLink = GetFirstNode (&RootFile->Link);
!IsNull (&RootFile->Link, FileLink);
FileLink = GetNextNode (&RootFile->Link, FileLink)
)
{
FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink);
// Skip files that aren't on disk yet
if (FileEntry->HwDescription.RegionCount == 0) {
continue;
}
// If the free space preceding the file is big enough to contain the new
// file then use it!
if (((FileEntry->HwDescription.BlockStart * BlockSize) - *FileStart)
>= FileSize) {
// The file list must be in disk-order
RemoveEntryList (&File->Link);
File->Link.BackLink = FileLink->BackLink;
File->Link.ForwardLink = FileLink;
FileLink->BackLink->ForwardLink = &File->Link;
FileLink->BackLink = &File->Link;
return EFI_SUCCESS;
} else {
*FileStart = (FileEntry->HwDescription.BlockEnd + 1) * BlockSize;
}
}
// See if there's space after the last file
if ((((Media->LastBlock + 1) * BlockSize) - *FileStart) >= FileSize) {
return EFI_SUCCESS;
} else {
return EFI_VOLUME_FULL;
}
}
// Free the resources in the file's Region list.
STATIC
VOID
FreeFileRegions (
IN BOOTMON_FS_FILE *File
)
{
LIST_ENTRY *RegionToFlushLink;
BOOTMON_FS_FILE_REGION *Region;
RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
while (!IsNull (&File->RegionToFlushLink, RegionToFlushLink)) {
// Repeatedly remove the first node from the list and free its resources.
Region = (BOOTMON_FS_FILE_REGION *) RegionToFlushLink;
RemoveEntryList (RegionToFlushLink);
FreePool (Region->Buffer);
FreePool (Region);
RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
}
}
/**
Flush all modified data associated with a file to a device.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the
file handle to flush.
@retval EFI_SUCCESS The data was flushed.
@retval EFI_ACCESS_DENIED The file was opened read-only.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_VOLUME_FULL The volume is full.
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to flush the data.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsFlushFile (
IN EFI_FILE_PROTOCOL *This
)
{
EFI_STATUS Status;
BOOTMON_FS_INSTANCE *Instance;
EFI_FILE_INFO *Info;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
EFI_BLOCK_IO_MEDIA *Media;
EFI_DISK_IO_PROTOCOL *DiskIo;
UINTN BlockSize;
CHAR8 AsciiFileName[MAX_NAME_LENGTH];
LIST_ENTRY *RegionToFlushLink;
BOOTMON_FS_FILE *File;
BOOTMON_FS_FILE *NextFile;
BOOTMON_FS_FILE_REGION *Region;
LIST_ENTRY *FileLink;
UINTN CurrentPhysicalSize;
UINT64 FileStart;
UINT64 FileEnd;
UINT64 RegionStart;
UINT64 RegionEnd;
UINT64 NewDataSize;
UINT64 NewFileSize;
UINT64 EndOfAppendSpace;
BOOLEAN HasSpace;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (File->Info == NULL) {
return EFI_INVALID_PARAMETER;
}
if (File->OpenMode == EFI_FILE_MODE_READ) {
return EFI_ACCESS_DENIED;
}
Instance = File->Instance;
Info = File->Info;
BlockIo = Instance->BlockIo;
Media = BlockIo->Media;
DiskIo = Instance->DiskIo;
BlockSize = Media->BlockSize;
UnicodeStrToAsciiStrS (Info->FileName, AsciiFileName, MAX_NAME_LENGTH);
// If the file doesn't exist then find a space for it
if (File->HwDescription.RegionCount == 0) {
Status = BootMonFsFindSpaceForNewFile (
File,
Info->FileSize + sizeof (HW_IMAGE_DESCRIPTION),
&FileStart
);
if (EFI_ERROR (Status)) {
return Status;
}
} else {
FileStart = File->HwDescription.BlockStart * BlockSize;
}
// FileEnd is the current NOR address of the end of the file's data
FileEnd = FileStart + File->HwDescription.Region[0].Size;
for (RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
!IsNull (&File->RegionToFlushLink, RegionToFlushLink);
RegionToFlushLink = GetNextNode (&File->RegionToFlushLink, RegionToFlushLink)
)
{
Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
if (Region->Size == 0) {
continue;
}
// RegionStart and RegionEnd are the the intended NOR address of the
// start and end of the region
RegionStart = FileStart + Region->Offset;
RegionEnd = RegionStart + Region->Size;
if (RegionEnd < FileEnd) {
// Handle regions representing edits to existing portions of the file
// Write the region data straight into the file
Status = DiskIo->WriteDisk (DiskIo,
Media->MediaId,
RegionStart,
Region->Size,
Region->Buffer
);
if (EFI_ERROR (Status)) {
return Status;
}
} else {
// Handle regions representing appends to the file
//
// Note: Since seeking past the end of the file with SetPosition() is
// valid, it's possible there will be a gap between the current end of
// the file and the beginning of the new region. Since the UEFI spec
// says nothing about this case (except "a subsequent write would grow
// the file"), we just leave garbage in the gap.
// Check if there is space to append the new region
HasSpace = FALSE;
NewDataSize = RegionEnd - FileStart;
NewFileSize = NewDataSize + sizeof (HW_IMAGE_DESCRIPTION);
CurrentPhysicalSize = BootMonFsGetPhysicalSize (File);
if (NewFileSize <= CurrentPhysicalSize) {
HasSpace = TRUE;
} else {
// Get the File Description for the next file
FileLink = GetNextNode (&Instance->RootFile->Link, &File->Link);
if (!IsNull (&Instance->RootFile->Link, FileLink)) {
NextFile = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink);
// If there is space between the beginning of the current file and the
// beginning of the next file then use it
EndOfAppendSpace = NextFile->HwDescription.BlockStart * BlockSize;
} else {
// We are flushing the last file.
EndOfAppendSpace = (Media->LastBlock + 1) * BlockSize;
}
if (EndOfAppendSpace - FileStart >= NewFileSize) {
HasSpace = TRUE;
}
}
if (HasSpace == TRUE) {
// Invalidate the current image description of the file if any.
if (File->HwDescAddress != 0) {
Status = InvalidateImageDescription (File);
if (EFI_ERROR (Status)) {
return Status;
}
}
// Write the new file data
Status = DiskIo->WriteDisk (
DiskIo,
Media->MediaId,
RegionStart,
Region->Size,
Region->Buffer
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = WriteFileDescription (File, AsciiFileName, NewDataSize, FileStart);
if (EFI_ERROR (Status)) {
return Status;
}
} else {
// There isn't a space for the file.
// Options here are to move the file or fragment it. However as files
// may represent boot images at fixed positions, these options will
// break booting if the bootloader doesn't use BootMonFs to find the
// image.
return EFI_VOLUME_FULL;
}
}
}
FreeFileRegions (File);
Info->PhysicalSize = BootMonFsGetPhysicalSize (File);
if ((AsciiStrCmp (AsciiFileName, File->HwDescription.Footer.Filename) != 0) ||
(Info->FileSize != File->HwDescription.Region[0].Size) ) {
Status = WriteFileDescription (File, AsciiFileName, Info->FileSize, FileStart);
if (EFI_ERROR (Status)) {
return Status;
}
}
// Flush DiskIo Buffers (see UEFI Spec 12.7 - DiskIo buffers are flushed by
// calling FlushBlocks on the same device's BlockIo).
BlockIo->FlushBlocks (BlockIo);
return EFI_SUCCESS;
}
/**
Close a specified file handle.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
handle to close.
@retval EFI_SUCCESS The file was closed.
@retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open
file handle.
**/
EFIAPI
EFI_STATUS
BootMonFsCloseFile (
IN EFI_FILE_PROTOCOL *This
)
{
BOOTMON_FS_FILE *File;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (File->Info == NULL) {
return EFI_INVALID_PARAMETER;
}
// In the case of a file and not the root directory
if (This != &File->Instance->RootFile->File) {
This->Flush (This);
FreePool (File->Info);
File->Info = NULL;
}
return EFI_SUCCESS;
}
/**
Open a file on the boot monitor file system.
The boot monitor file system does not allow for sub-directories. There is only
one directory, the root one. On any attempt to create a directory, the function
returns in error with the EFI_WRITE_PROTECTED error code.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
the file handle to source location.
@param[out] NewHandle A pointer to the location to return the opened
handle for the new file.
@param[in] FileName The Null-terminated string of the name of the file
to be opened.
@param[in] OpenMode The mode to open the file : Read or Read/Write or
Read/Write/Create
@param[in] Attributes Attributes of the file in case of a file creation
@retval EFI_SUCCESS The file was open.
@retval EFI_NOT_FOUND The specified file could not be found or the specified
directory in which to create a file could not be found.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible
with the Boot Monitor file system.
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsOpenFile (
IN EFI_FILE_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
)
{
EFI_STATUS Status;
BOOTMON_FS_FILE *Directory;
BOOTMON_FS_FILE *File;
BOOTMON_FS_INSTANCE *Instance;
CHAR8 *Buf;
CHAR16 *Path;
CHAR16 *Separator;
CHAR8 *AsciiFileName;
EFI_FILE_INFO *Info;
UINTN AsciiFileNameSize;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Directory = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (Directory->Info == NULL) {
return EFI_INVALID_PARAMETER;
}
if ((FileName == NULL) || (NewHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// The only valid modes are read, read/write, and read/write/create
//
if ( (OpenMode != EFI_FILE_MODE_READ) &&
(OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE)) &&
(OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE)) ) {
return EFI_INVALID_PARAMETER;
}
Instance = Directory->Instance;
//
// If the instance has not been initialized yet then do it ...
//
if (!Instance->Initialized) {
Status = BootMonFsInitialize (Instance);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Copy the file path to be able to work on it. We do not want to
// modify the input file name string "FileName".
//
Buf = AllocateCopyPool (StrSize (FileName), FileName);
if (Buf == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Path = (CHAR16*)Buf;
AsciiFileName = NULL;
Info = NULL;
//
// Handle single periods, double periods and convert forward slashes '/'
// to backward '\' ones. Does not handle a '.' at the beginning of the
// path for the time being.
//
if (PathCleanUpDirectories (Path) == NULL) {
Status = EFI_INVALID_PARAMETER;
goto Error;
}
//
// Detect if the first component of the path refers to a directory.
// This is done to return the correct error code when trying to
// access or create a directory other than the root directory.
//
//
// Search for the '\\' sequence and if found return in error
// with the EFI_INVALID_PARAMETER error code. ere in the path.
//
if (StrStr (Path, L"\\\\") != NULL) {
Status = EFI_INVALID_PARAMETER;
goto Error;
}
//
// Get rid of the leading '\' if any.
//
Path += (Path[0] == L'\\');
//
// Look for a '\' in the file path. If one is found then
// the first component of the path refers to a directory
// that is not the root directory.
//
Separator = StrStr (Path, L"\\");
if (Separator != NULL) {
//
// In the case '<dir name>\' and a creation, return
// EFI_WRITE_PROTECTED if this is for a directory
// creation, EFI_INVALID_PARAMETER otherwise.
//
if ((*(Separator + 1) == '\0') && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) {
if (Attributes & EFI_FILE_DIRECTORY) {
Status = EFI_WRITE_PROTECTED;
} else {
Status = EFI_INVALID_PARAMETER;
}
} else {
//
// Attempt to open a file or a directory that is not in the
// root directory or to open without creation a directory
// located in the root directory, returns EFI_NOT_FOUND.
//
Status = EFI_NOT_FOUND;
}
goto Error;
}
//
// BootMonFs interface requires ASCII filenames
//
AsciiFileNameSize = StrLen (Path) + 1;
if (AsciiFileNameSize > MAX_NAME_LENGTH) {
AsciiFileNameSize = MAX_NAME_LENGTH;
}
AsciiFileName = AllocatePool (AsciiFileNameSize);
if (AsciiFileName == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
UnicodeStrToAsciiStrS (Path, AsciiFileName, AsciiFileNameSize);
if ((AsciiFileName[0] == '\0') ||
(AsciiFileName[0] == '.' ) ) {
//
// Opening the root directory
//
*NewHandle = &Instance->RootFile->File;
Instance->RootFile->Position = 0;
Status = EFI_SUCCESS;
} else {
if ((OpenMode & EFI_FILE_MODE_CREATE) &&
(Attributes & EFI_FILE_DIRECTORY) ) {
Status = EFI_WRITE_PROTECTED;
goto Error;
}
//
// Allocate a buffer to store the characteristics of the file while the
// file is open. We allocate the maximum size to not have to reallocate
// if the file name is changed.
//
Info = AllocateZeroPool (
SIZE_OF_EFI_FILE_INFO + (sizeof (CHAR16) * MAX_NAME_LENGTH));
if (Info == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
//
// Open or create a file in the root directory.
//
Status = BootMonGetFileFromAsciiFileName (Instance, AsciiFileName, &File);
if (Status == EFI_NOT_FOUND) {
if ((OpenMode & EFI_FILE_MODE_CREATE) == 0) {
goto Error;
}
Status = BootMonFsCreateFile (Instance, &File);
if (EFI_ERROR (Status)) {
goto Error;
}
InsertHeadList (&Instance->RootFile->Link, &File->Link);
Info->Attribute = Attributes;
} else {
//
// File already open, not supported yet.
//
if (File->Info != NULL) {
Status = EFI_UNSUPPORTED;
goto Error;
}
}
Info->FileSize = BootMonFsGetImageLength (File);
Info->PhysicalSize = BootMonFsGetPhysicalSize (File);
AsciiStrToUnicodeStrS (AsciiFileName, Info->FileName, MAX_NAME_LENGTH);
File->Info = Info;
Info = NULL;
File->Position = 0;
File->OpenMode = OpenMode;
*NewHandle = &File->File;
}
Error:
FreePool (Buf);
if (AsciiFileName != NULL) {
FreePool (AsciiFileName);
}
if (Info != NULL) {
FreePool (Info);
}
return Status;
}
// Delete() for the root directory's EFI_FILE_PROTOCOL instance
EFIAPI
EFI_STATUS
BootMonFsDeleteFail (
IN EFI_FILE_PROTOCOL *This
)
{
This->Close(This);
// You can't delete the root directory
return EFI_WARN_DELETE_FAILURE;
}
/**
Close and delete a file from the boot monitor file system.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
handle to delete.
@retval EFI_SUCCESS The file was closed and deleted.
@retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open
file handle.
@retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted.
**/
EFIAPI
EFI_STATUS
BootMonFsDelete (
IN EFI_FILE_PROTOCOL *This
)
{
EFI_STATUS Status;
BOOTMON_FS_FILE *File;
LIST_ENTRY *RegionToFlushLink;
BOOTMON_FS_FILE_REGION *Region;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (File->Info == NULL) {
return EFI_INVALID_PARAMETER;
}
if (!IsListEmpty (&File->RegionToFlushLink)) {
// Free the entries from the Buffer List
RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
do {
Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
//
// Get next element of the list before deleting the region description
// that contain the LIST_ENTRY structure.
//
RegionToFlushLink = RemoveEntryList (RegionToFlushLink);
// Free the buffers
FreePool (Region->Buffer);
FreePool (Region);
} while (!IsListEmpty (&File->RegionToFlushLink));
}
// If (RegionCount is greater than 0) then the file already exists
if (File->HwDescription.RegionCount > 0) {
// Invalidate the last Block
Status = InvalidateImageDescription (File);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
return EFI_WARN_DELETE_FAILURE;
}
}
// Remove the entry from the list
RemoveEntryList (&File->Link);
FreePool (File->Info);
FreePool (File);
return EFI_SUCCESS;
}

View File

@ -1,259 +0,0 @@
/** @file
*
* Copyright (c) 2012-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 <Protocol/SimpleFileSystem.h>
#include <Library/UefiLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include "BootMonFsInternal.h"
/**
Read data from an open file.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
is the file handle to read data from.
@param[in out] BufferSize On input, the size of the Buffer. On output, the
amount of data returned in Buffer. In both cases,
the size is measured in bytes.
@param[out] Buffer The buffer into which the data is read.
@retval EFI_SUCCESS The data was read.
@retval EFI_DEVICE_ERROR On entry, the current file position is
beyond the end of the file, or the device
reported an error while performing the read
operation.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsReadFile (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
BOOTMON_FS_INSTANCE *Instance;
BOOTMON_FS_FILE *File;
EFI_DISK_IO_PROTOCOL *DiskIo;
EFI_BLOCK_IO_MEDIA *Media;
UINT64 FileStart;
EFI_STATUS Status;
UINTN RemainingFileSize;
if ((This == NULL) ||
(BufferSize == NULL) ||
(Buffer == NULL) ) {
return EFI_INVALID_PARAMETER;
}
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (File->Info == NULL) {
return EFI_INVALID_PARAMETER;
}
// Ensure the file has been written in Flash before reading it.
// This keeps the code simple and avoids having to manage a non-flushed file.
BootMonFsFlushFile (This);
Instance = File->Instance;
DiskIo = Instance->DiskIo;
Media = Instance->Media;
FileStart = (Media->LowestAlignedLba + File->HwDescription.BlockStart) * Media->BlockSize;
if (File->Position >= File->Info->FileSize) {
// The entire file has been read or the position has been
// set past the end of the file.
*BufferSize = 0;
if (File->Position > File->Info->FileSize) {
return EFI_DEVICE_ERROR;
} else {
return EFI_SUCCESS;
}
}
// This driver assumes that the entire file is in region 0.
RemainingFileSize = File->Info->FileSize - File->Position;
// If read would go past end of file, truncate the read
if (*BufferSize > RemainingFileSize) {
*BufferSize = RemainingFileSize;
}
Status = DiskIo->ReadDisk (
DiskIo,
Media->MediaId,
FileStart + File->Position,
*BufferSize,
Buffer
);
if (EFI_ERROR (Status)) {
*BufferSize = 0;
}
File->Position += *BufferSize;
return Status;
}
/**
Write data to an open file.
The data is not written to the flash yet. It will be written when the file
will be either read, closed or flushed.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
is the file handle to write data to.
@param[in out] BufferSize On input, the size of the Buffer. On output, the
size of the data actually written. In both cases,
the size is measured in bytes.
@param[in] Buffer The buffer of data to write.
@retval EFI_SUCCESS The data was written.
@retval EFI_ACCESS_DENIED The file was opened read only.
@retval EFI_OUT_OF_RESOURCES Unable to allocate the buffer to store the
data to write.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsWriteFile (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
)
{
BOOTMON_FS_FILE *File;
BOOTMON_FS_FILE_REGION *Region;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (File->Info == NULL) {
return EFI_INVALID_PARAMETER;
}
if (File->OpenMode == EFI_FILE_MODE_READ) {
return EFI_ACCESS_DENIED;
}
// Allocate and initialize the memory region
Region = (BOOTMON_FS_FILE_REGION*)AllocateZeroPool (sizeof (BOOTMON_FS_FILE_REGION));
if (Region == NULL) {
*BufferSize = 0;
return EFI_OUT_OF_RESOURCES;
}
Region->Buffer = AllocateCopyPool (*BufferSize, Buffer);
if (Region->Buffer == NULL) {
*BufferSize = 0;
FreePool (Region);
return EFI_OUT_OF_RESOURCES;
}
Region->Size = *BufferSize;
Region->Offset = File->Position;
InsertTailList (&File->RegionToFlushLink, &Region->Link);
File->Position += *BufferSize;
if (File->Position > File->Info->FileSize) {
File->Info->FileSize = File->Position;
}
return EFI_SUCCESS;
}
/**
Set a file's current position.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
the file handle to set the requested position on.
@param[in] Position The byte position from the start of the file to set.
@retval EFI_SUCCESS The position was set.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsSetPosition (
IN EFI_FILE_PROTOCOL *This,
IN UINT64 Position
)
{
BOOTMON_FS_FILE *File;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (File->Info == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// UEFI Spec section 12.5:
// "Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to
// be set to the end of the file."
//
if (Position == 0xFFFFFFFFFFFFFFFF) {
Position = File->Info->FileSize;
}
File->Position = Position;
return EFI_SUCCESS;
}
/**
Return a file's current position.
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
the file handle to get the current position on.
@param[out] Position The address to return the file's current position value.
@retval EFI_SUCCESS The position was returned.
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
**/
EFIAPI
EFI_STATUS
BootMonFsGetPosition (
IN EFI_FILE_PROTOCOL *This,
OUT UINT64 *Position
)
{
BOOTMON_FS_FILE *File;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
if (File->Info == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Position == NULL) {
return EFI_INVALID_PARAMETER;
}
*Position = File->Position;
return EFI_SUCCESS;
}

View File

@ -1,37 +0,0 @@
/** @file
*
* Copyright (c) 2012-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 "BootMonFsInternal.h"
EFIAPI
EFI_STATUS
BootMonFsSetPositionUnsupported (
IN EFI_FILE_PROTOCOL *This,
IN UINT64 Position
)
{
ASSERT(0);
return EFI_UNSUPPORTED;
}
EFIAPI
EFI_STATUS
BootMonFsGetPositionUnsupported (
IN EFI_FILE_PROTOCOL *This,
OUT UINT64 *Position
)
{
ASSERT(0);
return EFI_UNSUPPORTED;
}

View File

@ -1,47 +0,0 @@
/** @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 __BOOTMON_FS_FILE_INFO_H__
#define __BOOTMON_FS_FILE_INFO_H__
#define BOOTMON_FS_FILE_INFO_ID \
{ \
0x41e26b9c, 0xada6, 0x45b3, {0x80, 0x8e, 0x23, 0x57, 0xa3, 0x5b, 0x60, 0xd6 } \
}
// From BootMonFS header file
#define BOOTMONFS_IMAGE_DESCRIPTION_REGION_MAX 4
typedef struct {
// The size of the structure.
UINT64 Size;
// Subset of properties stored in the file meta-data.
UINT32 EntryPoint;
UINT32 RegionCount;
struct {
UINT32 LoadAddress;
UINT32 Size;
UINT32 Offset;
UINT32 Checksum;
} Region[BOOTMONFS_IMAGE_DESCRIPTION_REGION_MAX];
} BOOTMON_FS_FILE_INFO;
#define SIZE_OF_BOOTMON_FS_FILE_INFO \
OFFSET_OF (BOOTMON_FS_FILE_INFO, Region[BOOTMONFS_IMAGE_DESCRIPTION_REGION_MAX - 1].Checksum)
extern EFI_GUID gArmBootMonFsFileInfoGuid;
#endif // __BOOTMON_FS_FILE_INFO_H__

View File

@ -1,57 +0,0 @@
/** @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

@ -1,95 +0,0 @@
/** @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

@ -1,83 +0,0 @@
/** @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 <Protocol/Shell.h>
#include <Protocol/ShellDynamicCommand.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

@ -1,54 +0,0 @@
## @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

@ -1,68 +0,0 @@
// *++
//
// 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.
//
//
// Module Name:
//
// RunAxfStrings.uni
//
// Abstract:
//
// String definitions for the Shell 'runaxf' command
//
// Revision History:
//
// --*/
/=#
#langdef en-US "English"
#string STR_RUNAXF_BAD_FILE #language en-US "File type not supported\n"
#string STR_RUNAXF_BAD_ARCH #language en-US "Architecture not supported\n"
#string STR_RUNAXF_INVALID_ARG #language en-US "Invalid argument(s)\n"
#string STR_RUNAXF_FILE_NOT_FOUND #language en-US "File not found : %s\n"
#string STR_RUNAXF_NO_MEM #language en-US "Out of Memory\n"
#string STR_RUNAXF_READ_FAIL #language en-US "Failed to read file\n"
#string STR_RUNAXF_ELFMAGIC #language en-US "Wrong magic number. The file is either not an ELF binary or it is corrupted.\n"
#string STR_RUNAXF_ELFNOTEXEC #language en-US "Wrong ELF file type, expected an executable file.\n"
#string STR_RUNAXF_ELFNOPROG #language en-US "No program header table found in ELF file.\n"
#string STR_RUNAXF_ELFWRONGCLASS #language en-US "Invalid ELF Class type.\n"
#string STR_RUNAXF_ELFBADFORMAT #language en-US "ELF file format is incorrect (filesize > memorysize).\n"
#string STR_RUNAXF_ELFBADHEADER #language en-US "Invalid ELF header.\n"
#string STR_RUNAXF_ELFFAILSEG #language en-US "Failed to load segment from ELF file.\n
#string STR_RUNAXF_ELFNOSEG #language en-US "The ELF file must have at least 1 loadable segment.\n"
#string STR_RUNAXF_ELFWRONGCLASS_32 #language en-US "Wrong file class, expected 32-bit ELF file.\n"
#string STR_RUNAXF_ELFWRONGCLASS_64 #language en-US "Wrong file class, expected 64-bit ELF file.\n"
#string STR_RUNAXF_ELFWRONGMACH_32 #language en-US "Wrong machine type, expected ARM.\n"
#string STR_RUNAXF_ELFWRONGMACH_64 #language en-US "Wrong machine type, expected AARCH64.\n"
#string STR_GET_HELP_RUNAXF #language en-US ""
".TH runaxf 0 "load and execute AXF binary"\r\n"
".SH NAME\r\n"
"Loads and executes ARM Executable File (AXF).\r\n"
".SH SYNOPSIS\r\n"
"runaxf file\r\n"
".SH OPTIONS\r\n"
"file AXF binary to load and execute.\r\n"
".SH DESCRIPTION\r\n"
"Loads and executes ARM Executable File (AXF). This function is not expected to return.\r\n"
".SH RETURNVALUES\r\n"
"SHELL_DEVICE_ERROR The operation failed to complete.\r\n"
"SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly formatted or its value was out of bounds.\r\n"
"SHELL_UNSUPPORTED The action as requested was unsupported.\r\n"
"SHELL_OUT_OF_RESOURCES There was insufficient free space for the request to be completed.\r\n"
".SH EXAMPLES\r\n"
" fs0:\> runaxf file.axf\r\n"

View File

@ -1,154 +0,0 @@
/** @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

@ -1,66 +0,0 @@
/** @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

@ -1,340 +0,0 @@
/** @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

@ -1,64 +0,0 @@
/** @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

@ -1,395 +0,0 @@
/** @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

@ -1,258 +0,0 @@
/** @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

@ -1,260 +0,0 @@
/** @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