/** @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; | |
} |