mirror of https://github.com/acidanthera/audk.git
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:
parent
bc52af3bf3
commit
de4940885a
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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__
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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__
|
|
@ -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
|
|
@ -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"
|
|
@ -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;
|
||||
}
|
|
@ -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__
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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
Loading…
Reference in New Issue