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:
@ -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
Reference in New Issue
Block a user