diff mbox series

[edk2,v3,edk2-platforms,2/2] Platform/ARM: import BootMonFs and ArmShellCmdRunAxf from EDK2

Message ID 20171204221235.11807-3-ard.biesheuvel@linaro.org
State New
Headers show
Series Move ArmPlatformPkg stuff into edk2-platforms | expand

Commit Message

Ard Biesheuvel Dec. 4, 2017, 10:12 p.m. UTC
BootMonFs and ArmShellCmdRunAxf are only used on development boards
manufactured by ARM itself, so let's keep it under Platform/ARM where
it belongs.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>

---
 Platform/ARM/ARM.dec                                         |   25 +
 Platform/ARM/Drivers/BootMonFs/BootMonFs.dec                 |   26 +
 Platform/ARM/Drivers/BootMonFs/BootMonFs.inf                 |   63 ++
 Platform/ARM/Drivers/BootMonFs/BootMonFsApi.h                |  388 +++++++
 Platform/ARM/Drivers/BootMonFs/BootMonFsDir.c                |  766 ++++++++++++++
 Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c         |  529 ++++++++++
 Platform/ARM/Drivers/BootMonFs/BootMonFsHw.h                 |   57 ++
 Platform/ARM/Drivers/BootMonFs/BootMonFsImages.c             |  222 ++++
 Platform/ARM/Drivers/BootMonFs/BootMonFsInternal.h           |  101 ++
 Platform/ARM/Drivers/BootMonFs/BootMonFsOpenClose.c          |  795 +++++++++++++++
 Platform/ARM/Drivers/BootMonFs/BootMonFsReadWrite.c          |  259 +++++
 Platform/ARM/Drivers/BootMonFs/BootMonFsUnsupported.c        |   37 +
 Platform/ARM/Include/Guid/BootMonFsFileInfo.h                |   47 +
 Platform/ARM/Include/Library/ArmShellCmdLib.h                |   57 ++
 Platform/ARM/JunoPkg/ArmJuno.dsc                             |    2 +-
 Platform/ARM/JunoPkg/ArmJuno.fdf                             |    2 +-
 Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf       |    1 +
 Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.c   |   95 ++
 Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.h   |   83 ++
 Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf |   54 +
 Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.uni |   68 ++
 Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.c     |  154 +++
 Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.h     |   66 ++
 Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.c           |  340 +++++++
 Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.h           |   64 ++
 Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c              |  395 ++++++++
 Platform/ARM/Library/ArmShellCmdRunAxf/elf32.h               |  258 +++++
 Platform/ARM/Library/ArmShellCmdRunAxf/elf64.h               |  260 +++++
 Platform/ARM/Library/ArmShellCmdRunAxf/elf_common.h          | 1059 ++++++++++++++++++++
 Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf            |    2 +-
 Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc                 |    6 +-
 Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf |    1 +
 32 files changed, 6276 insertions(+), 6 deletions(-)

-- 
2.11.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
diff mbox series

Patch

diff --git a/Platform/ARM/ARM.dec b/Platform/ARM/ARM.dec
new file mode 100644
index 000000000000..f9bf3294a0ca
--- /dev/null
+++ b/Platform/ARM/ARM.dec
@@ -0,0 +1,25 @@ 
+#/** @file
+#
+#  Copyright (c) 2011-2017, 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.
+#
+#**/
+
+[Defines]
+  DEC_SPECIFICATION              = 0x0001001A
+  PACKAGE_NAME                   = ARM
+  PACKAGE_GUID                   = 2a905d2b-30c9-4408-86a2-c0b328876aee
+  PACKAGE_VERSION                = 0.1
+
+[Includes]
+  Include                        # Root include for the package
+
+[Guids]
+  gArmBootMonFsFileInfoGuid   = { 0x41e26b9c, 0xada6, 0x45b3, { 0x80, 0x8e, 0x23, 0x57, 0xa3, 0x5b, 0x60, 0xd6 } }
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFs.dec b/Platform/ARM/Drivers/BootMonFs/BootMonFs.dec
new file mode 100644
index 000000000000..533dee3b616c
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFs.dec
@@ -0,0 +1,26 @@ 
+#/** @file
+#
+#  Copyright (c) 2011-2017, 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.
+#
+#**/
+
+[Defines]
+  DEC_SPECIFICATION              = 0x0001001A
+  PACKAGE_NAME                   = BootMonFs
+  PACKAGE_GUID                   = 41f14aba-452f-4204-a435-25242973c5b1
+  PACKAGE_VERSION                = 0.1
+
+[Guids.common]
+  gArmBootMonFsTokenSpaceGuid = { 0xeb76a201, 0x69b4, 0x491f, { 0x9b, 0xde, 0xbf, 0x30, 0xbd, 0x03, 0x82, 0xb4 } }
+
+[PcdsFixedAtBuild.common]
+  # Boot Monitor FileSystem
+  gArmBootMonFsTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L""|VOID*|0x0000003A
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFs.inf b/Platform/ARM/Drivers/BootMonFs/BootMonFs.inf
new file mode 100644
index 000000000000..5b9353f0ee21
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFs.inf
@@ -0,0 +1,63 @@ 
+#/** @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
+  Platform/ARM/ARM.dec
+  Platform/ARM/Drivers/BootMonFs/BootMonFs.dec
+
+[LibraryClasses]
+  BaseLib
+  DevicePathLib
+  MemoryAllocationLib
+  PrintLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Guids]
+  gArmBootMonFsFileInfoGuid
+  gEfiFileSystemInfoGuid
+  gEfiFileInfoGuid
+  gEfiFileSystemVolumeLabelInfoIdGuid
+
+[Pcd]
+  gArmBootMonFsTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths
+
+[Protocols]
+  gEfiDiskIoProtocolGuid
+  gEfiBlockIoProtocolGuid
+  gEfiSimpleFileSystemProtocolGuid
+  gEfiDevicePathProtocolGuid
+  gEfiDevicePathFromTextProtocolGuid
+
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsApi.h b/Platform/ARM/Drivers/BootMonFs/BootMonFsApi.h
new file mode 100644
index 000000000000..d690520a0f67
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsApi.h
@@ -0,0 +1,388 @@ 
+/** @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
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsDir.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsDir.c
new file mode 100644
index 000000000000..64ea0ec68048
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsDir.c
@@ -0,0 +1,766 @@ 
+/** @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;
+}
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c
new file mode 100644
index 000000000000..a1150856f6ba
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c
@@ -0,0 +1,529 @@ 
+/** @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;
+}
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsHw.h b/Platform/ARM/Drivers/BootMonFs/BootMonFsHw.h
new file mode 100644
index 000000000000..c1bef755aea0
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsHw.h
@@ -0,0 +1,57 @@ 
+/** @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
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsImages.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsImages.c
new file mode 100644
index 000000000000..346c360292eb
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsImages.c
@@ -0,0 +1,222 @@ 
+/** @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;
+}
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsInternal.h b/Platform/ARM/Drivers/BootMonFs/BootMonFsInternal.h
new file mode 100644
index 000000000000..c0c6599cb707
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsInternal.h
@@ -0,0 +1,101 @@ 
+/** @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
+
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsOpenClose.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsOpenClose.c
new file mode 100644
index 000000000000..ae10055255ff
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsOpenClose.c
@@ -0,0 +1,795 @@ 
+/** @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;
+}
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsReadWrite.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsReadWrite.c
new file mode 100644
index 000000000000..f8124e95ac0c
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsReadWrite.c
@@ -0,0 +1,259 @@ 
+/** @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;
+}
diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsUnsupported.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsUnsupported.c
new file mode 100644
index 000000000000..4ecc4ea008ea
--- /dev/null
+++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsUnsupported.c
@@ -0,0 +1,37 @@ 
+/** @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;
+}
diff --git a/Platform/ARM/Include/Guid/BootMonFsFileInfo.h b/Platform/ARM/Include/Guid/BootMonFsFileInfo.h
new file mode 100644
index 000000000000..c4d805c14f0e
--- /dev/null
+++ b/Platform/ARM/Include/Guid/BootMonFsFileInfo.h
@@ -0,0 +1,47 @@ 
+/** @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__
diff --git a/Platform/ARM/Include/Library/ArmShellCmdLib.h b/Platform/ARM/Include/Library/ArmShellCmdLib.h
new file mode 100644
index 000000000000..eb31cd405338
--- /dev/null
+++ b/Platform/ARM/Include/Library/ArmShellCmdLib.h
@@ -0,0 +1,57 @@ 
+/** @file
+*
+*  Definitions for the Dynamic Shell command library
+*
+*  Copyright (C) 2014, ARM Ltd
+*
+*  This program and the accompanying materials are licensed and made available
+*  under the terms and conditions of the BSD License which accompanies this
+*  distribution. The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+*  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _ARM_SHELL_CMD_LIB_H_
+#define _ARM_SHELL_CMD_LIB_H_
+
+/**
+
+  Initialize and Install EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL for RunAxf command.
+
+  @param[in] ImageHandle        Handle the protocol should be attached to.
+
+  @retval EFI_SUCCESS           The command has been installed successfully.
+
+  @retval EFI_UNSUPPORTED       Help for the command failed to initialise.
+
+  @return                       Status code returned by InstallProtocolInterface
+                                Boot Service function.
+
+**/
+EFI_STATUS
+ShellDynCmdRunAxfInstall (
+  IN EFI_HANDLE             ImageHandle
+  );
+
+/**
+
+  Uninstall the RunAxf Command
+
+  @param[in] ImageHandle  Handle of the device where the protocol should have
+                          been installed.
+
+  @retval EFI_SUCCESS     The device has been un-initialized successfully.
+
+  @return                 Status code returned by UninstallProtocolInterface
+                          Boot Service function.
+
+**/
+EFI_STATUS
+ShellDynCmdRunAxfUninstall (
+  IN EFI_HANDLE             ImageHandle
+  );
+
+#endif // _ARM_SHELL_CMD_LIB_H_
diff --git a/Platform/ARM/JunoPkg/ArmJuno.dsc b/Platform/ARM/JunoPkg/ArmJuno.dsc
index 2844c91813d4..e7cb280ff381 100644
--- a/Platform/ARM/JunoPkg/ArmJuno.dsc
+++ b/Platform/ARM/JunoPkg/ArmJuno.dsc
@@ -157,7 +157,7 @@  [PcdsFixedAtBuild.common]
   gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|24
 
   # List of Device Paths that support BootMonFs
-  gArmPlatformTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)"
+  gArmBootMonFsTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)"
 
   #
   # ARM OS Loader
diff --git a/Platform/ARM/JunoPkg/ArmJuno.fdf b/Platform/ARM/JunoPkg/ArmJuno.fdf
index 72771b1170b0..ee9d0e7f4f6e 100644
--- a/Platform/ARM/JunoPkg/ArmJuno.fdf
+++ b/Platform/ARM/JunoPkg/ArmJuno.fdf
@@ -135,7 +135,7 @@  [FV.FvMain]
   INF ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
 
   # Versatile Express FileSystem
-  INF ArmPlatformPkg/FileSystem/BootMonFs/BootMonFs.inf
+  INF Platform/ARM/Drivers/BootMonFs/BootMonFs.inf
 
   #
   # FAT filesystem + GPT/MBR partitioning
diff --git a/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
index 0e53a49ee2fc..7da336fbd8e7 100644
--- a/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
+++ b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
@@ -28,6 +28,7 @@  [Packages]
   EmbeddedPkg/EmbeddedPkg.dec
   MdePkg/MdePkg.dec
   MdeModulePkg/MdeModulePkg.dec
+  Platform/ARM/ARM.dec
   Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.dec
   Platform/ARM/JunoPkg/ArmJuno.dec
 
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.c b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.c
new file mode 100644
index 000000000000..67bbb9e86334
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.c
@@ -0,0 +1,95 @@ 
+/** @file
+*
+*  Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
+*
+*  This program and the accompanying materials are licensed and made available
+*  under the terms and conditions of the BSD License which accompanies this
+*  distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/ArmShellCmdLib.h>
+
+#include "ArmShellCmdRunAxf.h"
+
+EFI_HANDLE gRunAxfHiiHandle = NULL;
+
+#define RUNAXF_HII_GUID \
+  { \
+  0xf5a6413b, 0x78d5, 0x448e, { 0xa2, 0x15, 0x22, 0x82, 0x8e, 0xbc, 0x61, 0x61 } \
+  }
+
+EFI_GUID gRunAxfHiiGuid = RUNAXF_HII_GUID;
+
+static EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolRunAxf = {
+    L"runaxf",                             // *CommandName
+    ShellDynCmdRunAxfHandler,              // Handler
+    ShellDynCmdRunAxfGetHelp               // GetHelp
+};
+
+EFI_STATUS
+ShellDynCmdRunAxfInstall (
+  IN EFI_HANDLE             ImageHandle
+  )
+{
+  EFI_STATUS Status;
+
+  // Register our shell command
+  Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
+                 &gEfiShellDynamicCommandProtocolGuid,
+                 &mShellDynCmdProtocolRunAxf,
+                 NULL);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Load the manual page for our command
+  //
+  // 3rd parameter 'HII strings array' must be name of .uni strings file
+  // followed by 'Strings', e.g. mycommands.uni must be specified as
+  // 'mycommandsStrings' because the build Autogen process defines this as a
+  // string array for the strings in your .uni file.  Examine your Build folder
+  // under your package's DEBUG folder and you will find it defined in a
+  // xxxStrDefs.h file.
+  //
+  gRunAxfHiiHandle = HiiAddPackages (&gRunAxfHiiGuid, ImageHandle,
+                                     ArmShellCmdRunAxfStrings, NULL);
+  if (gRunAxfHiiHandle == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+ShellDynCmdRunAxfUninstall (
+  IN EFI_HANDLE             ImageHandle
+  )
+{
+
+  EFI_STATUS Status;
+
+  if (gRunAxfHiiHandle != NULL) {
+    HiiRemovePackages (gRunAxfHiiHandle);
+  }
+
+  Status = gBS->UninstallMultipleProtocolInterfaces (ImageHandle,
+                 &gEfiShellDynamicCommandProtocolGuid,
+                 &mShellDynCmdProtocolRunAxf,
+                 NULL);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.h b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.h
new file mode 100644
index 000000000000..2708b53cc172
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.h
@@ -0,0 +1,83 @@ 
+/** @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__
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf
new file mode 100644
index 000000000000..8473b0fa90d2
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf
@@ -0,0 +1,54 @@ 
+## @file
+#
+#  Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
+#
+#  This program and the accompanying materials are licensed and made available
+#  under the terms and conditions of the BSD License which accompanies this
+#  distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = ArmShellCmdRunAxf
+  FILE_GUID                      = 676a0e7c-2e16-43e8-b49c-d82a1f9e24df
+  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
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Platform/ARM/ARM.dec
+  ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+  ArmLib
+  BaseLib
+  DebugLib
+  HiiLib
+  ShellLib
+
+[Protocols]
+  gEfiShellDynamicCommandProtocolGuid
+
+[Guids]
+  gArmBootMonFsFileInfoGuid
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.uni b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.uni
new file mode 100644
index 000000000000..6b7296079175
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.uni
@@ -0,0 +1,68 @@ 
+// *++
+//
+// 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"
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.c b/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.c
new file mode 100644
index 000000000000..0bce037dcb08
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.c
@@ -0,0 +1,154 @@ 
+/** @file
+*
+*  Copyright (c) 2014, ARM Ltd. All rights reserved.
+*
+*  This program and the accompanying materials are licensed and made available
+*  under the terms and conditions of the BSD License which accompanies this
+*  distribution. The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+*  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+
+#include <Guid/BootMonFsFileInfo.h>
+#include <Protocol/SimpleFileSystem.h> // EFI_FILE_HANDLE
+
+#include "ArmShellCmdRunAxf.h"
+#include "BootMonFsLoader.h"
+
+/**
+  Check that loading the file is supported.
+
+  Not all information is checked, only the properties that matters to us in
+  our simplified loader.
+
+  BootMonFS file properties is not in a file header but in the file-system
+  metadata, so we need to pass a handle to the file to allow access to the
+  information.
+
+  @param[in] FileHandle  Handle of the file to check.
+
+  @retval EFI_SUCCESS on success.
+  @retval EFI_INVALID_PARAMETER if the header is invalid.
+  @retval EFI_UNSUPPORTED if the file type/platform is not supported.
+**/
+EFI_STATUS
+BootMonFsCheckFile (
+  IN  CONST EFI_FILE_HANDLE  FileHandle
+  )
+{
+  EFI_STATUS           Status;
+  BOOTMON_FS_FILE_INFO Info;
+  UINTN                InfoSize;
+  UINTN                Index;
+
+  ASSERT (FileHandle != NULL);
+
+  // Try to load the file information as BootMonFS executable.
+  InfoSize = sizeof (Info);
+  // Get BootMon File info and see if it gives us what we need to load the file.
+  Status = FileHandle->GetInfo (FileHandle, &gArmBootMonFsFileInfoGuid,
+                               &InfoSize, &Info);
+
+  if (!EFI_ERROR (Status)) {
+    // Check the values return to see if they look reasonable.
+    // Do we have a good entrypoint and at least one good load region?
+    // We assume here that we cannot load to address 0x0.
+    if ((Info.Size == 0) || (Info.EntryPoint == 0) || (Info.RegionCount == 0) ||
+        (Info.RegionCount > BOOTMONFS_IMAGE_DESCRIPTION_REGION_MAX)) {
+      // The file does not seem to be of the right type.
+      Status = EFI_UNSUPPORTED;
+    } else {
+      // Check load regions. We just check for valid numbers, we dont do the
+      // checksums. Info.Offset can be zero if it loads from the start of the
+      // file.
+      for (Index = 0; Index < Info.RegionCount; Index++) {
+        if ((Info.Region[Index].LoadAddress == 0) || (Info.Region[Index].Size == 0)) {
+          Status = EFI_UNSUPPORTED;
+          break;
+        }
+      }
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Load a binary file from BootMonFS.
+
+  @param[in]  FileHandle    Handle of the file to load.
+
+  @param[in]  FileData      Address  of the file data in memory.
+
+  @param[out] EntryPoint    Will be filled with the ELF entry point address.
+
+  @param[out] ImageSize     Will be filled with the file size in memory. This
+                            will effectively be equal to the sum of the load
+                            region sizes.
+
+  This function assumes the file is valid and supported as checked with
+  BootMonFsCheckFile().
+
+  @retval EFI_SUCCESS on success.
+  @retval EFI_INVALID_PARAMETER if the file is invalid.
+**/
+EFI_STATUS
+BootMonFsLoadFile (
+  IN  CONST EFI_FILE_HANDLE   FileHandle,
+  IN  CONST VOID             *FileData,
+  OUT VOID                  **EntryPoint,
+  OUT LIST_ENTRY             *LoadList
+  )
+{
+  EFI_STATUS            Status;
+  BOOTMON_FS_FILE_INFO  Info;
+  UINTN                 InfoSize;
+  UINTN                 Index;
+  UINTN                 ImageSize;
+  RUNAXF_LOAD_LIST     *LoadNode;
+
+  ASSERT (FileHandle != NULL);
+  ASSERT (FileData   != NULL);
+  ASSERT (EntryPoint != NULL);
+  ASSERT (LoadList   != NULL);
+
+  ImageSize = 0;
+
+  InfoSize = sizeof (Info);
+  Status = FileHandle->GetInfo (FileHandle, &gArmBootMonFsFileInfoGuid,
+                               &InfoSize, &Info);
+
+  if (!EFI_ERROR (Status)) {
+    *EntryPoint = (VOID*)((UINTN)Info.EntryPoint);
+    // Load all the regions to run-time memory
+    for (Index = 0; Index < Info.RegionCount; Index++) {
+      LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST));
+      if (LoadNode == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        break;
+      }
+
+      LoadNode->MemOffset  = (UINTN)Info.Region[Index].LoadAddress;
+      LoadNode->FileOffset = (UINTN)FileData + Info.Region[Index].Offset;
+      LoadNode->Length     = (UINTN)Info.Region[Index].Size;
+      InsertTailList (LoadList, &LoadNode->Link);
+
+      ImageSize += LoadNode->Length;
+    }
+  }
+
+  if ((!EFI_ERROR (Status)) && (ImageSize == 0)) {
+    Status = EFI_INVALID_PARAMETER;
+  }
+
+  return Status;
+}
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.h b/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.h
new file mode 100644
index 000000000000..de3c0adcd11f
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.h
@@ -0,0 +1,66 @@ 
+/** @file
+*
+*  Copyright (c) 2014, ARM Ltd. All rights reserved.
+*
+*  This program and the accompanying materials are licensed and made available
+*  under the terms and conditions of the BSD License which accompanies this
+*  distribution. The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+*  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __BOOTMONFS_LOADER_H__
+#define __BOOTMONFS_LOADER_H__
+
+/**
+  Check that loading the file is supported.
+
+  Not all information is checked, only the properties that matters to us in
+  our simplified loader.
+
+  BootMonFS file properties is not in a file header but in the file-system
+  metadata, so we need to pass a handle to the file to allow access to the
+  information.
+
+  @param[in] FileHandle  Handle of the file to check.
+
+  @retval EFI_SUCCESS on success.
+  @retval EFI_INVALID_PARAMETER if the header is invalid.
+  @retval EFI_UNSUPPORTED if the file type/platform is not supported.
+**/
+EFI_STATUS
+BootMonFsCheckFile (
+  IN  CONST EFI_FILE_HANDLE  FileHandle
+  );
+
+/**
+  Load a binary file from BootMonFS.
+
+  @param[in]  FileHandle    Handle of the file to load.
+
+  @param[in]  FileData      Address  of the file data in memory.
+
+  @param[out] EntryPoint    Will be filled with the ELF entry point address.
+
+  @param[out] ImageSize     Will be filled with the file size in memory. This
+                            will effectively be equal to the sum of the load
+                            region sizes.
+
+  This function assumes the file is valid and supported as checked with
+  BootMonFsCheckFile().
+
+  @retval EFI_SUCCESS on success.
+  @retval EFI_INVALID_PARAMETER if the file is invalid.
+**/
+EFI_STATUS
+BootMonFsLoadFile (
+  IN  CONST EFI_FILE_HANDLE   FileHandle,
+  IN  CONST VOID             *FileData,
+  OUT VOID                  **EntryPoint,
+  OUT LIST_ENTRY             *LoadList
+  );
+
+#endif // __BOOTMONFS_LOADER_H__
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.c b/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.c
new file mode 100644
index 000000000000..6bb0d22de2fd
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.c
@@ -0,0 +1,340 @@ 
+/** @file
+*
+*  Copyright (c) 2014, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+
+#include "ArmShellCmdRunAxf.h"
+#include "ElfLoader.h"
+#include "elf_common.h"
+#include "elf32.h"
+#include "elf64.h"
+
+
+// Put the functions the #ifdef. We only use the appropriate one for the platform.
+// This prevents 'defined but not used' compiler warning.
+#ifdef MDE_CPU_ARM
+STATIC
+BOOLEAN
+IsArmElf (
+  IN  CONST VOID *Buf
+  )
+{
+  Elf32_Ehdr *Hdr = (Elf32_Ehdr*)Buf;
+
+  if (Hdr->e_ident[EI_CLASS] != ELFCLASS32) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGCLASS_32), gRunAxfHiiHandle);
+    return FALSE;
+  }
+
+  if (Hdr->e_machine != EM_ARM) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGMACH_32), gRunAxfHiiHandle);
+    return FALSE;
+  }
+
+  // We don't currently check endianness of ELF data (hdr->e_ident[EI_DATA])
+
+  return TRUE;
+}
+#elif defined(MDE_CPU_AARCH64)
+STATIC
+BOOLEAN
+IsAarch64Elf (
+  IN  CONST VOID *Buf
+  )
+{
+  Elf64_Ehdr *Hdr = (Elf64_Ehdr*)Buf;
+
+  if (Hdr->e_ident[EI_CLASS] != ELFCLASS64) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGCLASS_64), gRunAxfHiiHandle);
+    return FALSE;
+  }
+
+  if (Hdr->e_machine != EM_AARCH64) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGMACH_64), gRunAxfHiiHandle);
+    return FALSE;
+  }
+
+  // We don't currently check endianness of ELF data (hdr->e_ident[EI_DATA])
+
+  return TRUE;
+}
+#endif // MDE_CPU_ARM , MDE_CPU_AARCH64
+
+
+/**
+ Support checking 32 and 64bit as the header could be valid, we might just
+ not support loading it.
+**/
+STATIC
+EFI_STATUS
+ElfCheckHeader (
+  IN  CONST VOID *Buf
+  )
+{
+  Elf32_Ehdr *Hdr32 = (Elf32_Ehdr*)Buf;
+
+  if (!IS_ELF (*Hdr32)) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFMAGIC), gRunAxfHiiHandle);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Hdr32->e_type != ET_EXEC) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOTEXEC), gRunAxfHiiHandle);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Hdr32->e_ident[EI_CLASS] == ELFCLASS32) {
+    if ((Hdr32->e_phoff == 0) || (Hdr32->e_phentsize == 0) || (Hdr32->e_phnum == 0)) {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOPROG), gRunAxfHiiHandle);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (Hdr32->e_flags != 0) {
+      DEBUG ((EFI_D_INFO, "Warning: Wrong processor-specific flags, expected 0.\n"));
+    }
+
+    DEBUG ((EFI_D_INFO, "Entry point addr: 0x%lx\n", Hdr32->e_entry));
+    DEBUG ((EFI_D_INFO, "Start of program headers: 0x%lx\n", Hdr32->e_phoff));
+    DEBUG ((EFI_D_INFO, "Size of 1 program header: %d\n", Hdr32->e_phentsize));
+    DEBUG ((EFI_D_INFO, "Number of program headers: %d\n", Hdr32->e_phnum));
+  } else if (Hdr32->e_ident[EI_CLASS] == ELFCLASS64) {
+      Elf64_Ehdr *Hdr64 = (Elf64_Ehdr*)Buf;
+
+    if ((Hdr64->e_phoff == 0) || (Hdr64->e_phentsize == 0) || (Hdr64->e_phnum == 0)) {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOPROG), gRunAxfHiiHandle);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (Hdr64->e_flags != 0) {
+      DEBUG ((EFI_D_INFO, "Warning: Wrong processor-specific flags, expected 0.\n"));
+    }
+
+    DEBUG ((EFI_D_INFO, "Entry point addr: 0x%lx\n", Hdr64->e_entry));
+    DEBUG ((EFI_D_INFO, "Start of program headers: 0x%lx\n", Hdr64->e_phoff));
+    DEBUG ((EFI_D_INFO, "Size of 1 program header: %d\n", Hdr64->e_phentsize));
+    DEBUG ((EFI_D_INFO, "Number of program headers: %d\n", Hdr64->e_phnum));
+  } else {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGCLASS), gRunAxfHiiHandle);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+ Load an ELF segment into memory.
+
+ This function assumes the ELF file is valid.
+ This function is meant to be called for PT_LOAD type segments only.
+**/
+STATIC
+EFI_STATUS
+ElfLoadSegment (
+  IN  CONST VOID  *ElfImage,
+  IN  CONST VOID  *PHdr,
+  IN  LIST_ENTRY  *LoadList
+  )
+{
+  VOID             *FileSegment;
+  VOID             *MemSegment;
+  UINTN             ExtraZeroes;
+  UINTN             ExtraZeroesCount;
+  RUNAXF_LOAD_LIST *LoadNode;
+
+#ifdef MDE_CPU_ARM
+  Elf32_Phdr  *ProgramHdr;
+  ProgramHdr = (Elf32_Phdr *)PHdr;
+#elif defined(MDE_CPU_AARCH64)
+  Elf64_Phdr  *ProgramHdr;
+  ProgramHdr = (Elf64_Phdr *)PHdr;
+#endif
+
+  ASSERT (ElfImage != NULL);
+  ASSERT (ProgramHdr != NULL);
+
+  FileSegment = (VOID *)((UINTN)ElfImage + ProgramHdr->p_offset);
+  MemSegment = (VOID *)ProgramHdr->p_vaddr;
+
+  // If the segment's memory size p_memsz is larger than the file size p_filesz,
+  // the "extra" bytes are defined to hold the value 0 and to follow the
+  // segment's initialised area.
+  // This is typically the case for the .bss segment.
+  // The file size may not be larger than the memory size.
+  if (ProgramHdr->p_filesz > ProgramHdr->p_memsz) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFBADFORMAT), gRunAxfHiiHandle);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Load the segment in memory.
+  if (ProgramHdr->p_filesz != 0) {
+    DEBUG ((EFI_D_INFO, "Loading segment from 0x%lx to 0x%lx (size = %ld)\n",
+                 FileSegment, MemSegment, ProgramHdr->p_filesz));
+
+    LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST));
+    if (LoadNode == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    LoadNode->MemOffset  = (UINTN)MemSegment;
+    LoadNode->FileOffset = (UINTN)FileSegment;
+    LoadNode->Length     = (UINTN)ProgramHdr->p_filesz;
+    InsertTailList (LoadList, &LoadNode->Link);
+  }
+
+  ExtraZeroes = ((UINTN)MemSegment + ProgramHdr->p_filesz);
+  ExtraZeroesCount = ProgramHdr->p_memsz - ProgramHdr->p_filesz;
+  DEBUG ((EFI_D_INFO, "Completing segment with %d zero bytes.\n", ExtraZeroesCount));
+  if (ExtraZeroesCount > 0) {
+    // Extra Node to add the Zeroes.
+    LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST));
+    if (LoadNode == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    LoadNode->MemOffset  = (UINTN)ExtraZeroes;
+    LoadNode->Zeroes     = TRUE;
+    LoadNode->Length     = ExtraZeroesCount;
+    InsertTailList (LoadList, &LoadNode->Link);
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+ Check that the ELF File Header is valid and Machine type supported.
+
+ Not all information is checked in the ELF header, only the stuff that
+ matters to us in our simplified ELF loader.
+
+ @param[in] ElfImage  Address of the ELF file to check.
+
+ @retval EFI_SUCCESS on success.
+ @retval EFI_INVALID_PARAMETER if the header is invalid.
+ @retval EFI_UNSUPPORTED if the file type/platform is not supported.
+**/
+EFI_STATUS
+ElfCheckFile (
+  IN  CONST VOID *ElfImage
+  )
+{
+  EFI_STATUS Status;
+
+  ASSERT (ElfImage != NULL);
+
+  // Check that the ELF header is valid.
+  Status = ElfCheckHeader (ElfImage);
+  if (EFI_ERROR(Status)) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFBADHEADER), gRunAxfHiiHandle);
+    return EFI_INVALID_PARAMETER;
+  }
+
+#ifdef MDE_CPU_ARM
+  if (IsArmElf (ElfImage)) {
+    return EFI_SUCCESS;
+  }
+#elif defined(MDE_CPU_AARCH64)
+  if (IsAarch64Elf (ElfImage)) {
+    return EFI_SUCCESS;
+  }
+#endif
+
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_BAD_ARCH), gRunAxfHiiHandle);
+  return EFI_UNSUPPORTED;
+}
+
+
+/**
+  Load a ELF file.
+
+  @param[in] ElfImage       Address of the ELF file in memory.
+
+  @param[out] EntryPoint    Will be filled with the ELF entry point address.
+
+  @param[out] ImageSize     Will be filled with the ELF size in memory. This will
+                            effectively be equal to the sum of the segments sizes.
+
+  This functon assumes the header is valid and supported as checked with
+  ElfCheckFile().
+
+  @retval EFI_SUCCESS on success.
+  @retval EFI_INVALID_PARAMETER if the ELF file is invalid.
+**/
+EFI_STATUS
+ElfLoadFile (
+  IN  CONST VOID   *ElfImage,
+  OUT VOID        **EntryPoint,
+  OUT LIST_ENTRY   *LoadList
+  )
+{
+  EFI_STATUS    Status;
+  UINT8        *ProgramHdr;
+  UINTN         Index;
+  UINTN         ImageSize;
+
+#ifdef MDE_CPU_ARM
+  Elf32_Ehdr   *ElfHdr;
+  Elf32_Phdr   *ProgramHdrPtr;
+
+  ElfHdr = (Elf32_Ehdr*)ElfImage;
+#elif defined(MDE_CPU_AARCH64)
+  Elf64_Ehdr   *ElfHdr;
+  Elf64_Phdr   *ProgramHdrPtr;
+
+  ElfHdr = (Elf64_Ehdr*)ElfImage;
+#endif
+
+  ASSERT (ElfImage   != NULL);
+  ASSERT (EntryPoint != NULL);
+  ASSERT (LoadList   != NULL);
+
+  ProgramHdr = (UINT8*)ElfImage + ElfHdr->e_phoff;
+  DEBUG ((EFI_D_INFO, "ELF program header entry : 0x%lx\n", ProgramHdr));
+
+  ImageSize = 0;
+
+  // Load every loadable ELF segment into memory.
+  for (Index = 0; Index < ElfHdr->e_phnum; ++Index) {
+
+#ifdef MDE_CPU_ARM
+    ProgramHdrPtr = (Elf32_Phdr*)ProgramHdr;
+#elif defined(MDE_CPU_AARCH64)
+    ProgramHdrPtr = (Elf64_Phdr*)ProgramHdr;
+#endif
+
+    // Only consider PT_LOAD type segments, ignore others.
+    if (ProgramHdrPtr->p_type == PT_LOAD) {
+      Status = ElfLoadSegment (ElfImage, (VOID *)ProgramHdrPtr, LoadList);
+      if (EFI_ERROR (Status)) {
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFFAILSEG), gRunAxfHiiHandle);
+        return EFI_INVALID_PARAMETER;
+      }
+      ImageSize += ProgramHdrPtr->p_memsz;
+    }
+    ProgramHdr += ElfHdr->e_phentsize;
+  }
+
+  if (ImageSize == 0) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOSEG), gRunAxfHiiHandle);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Return the entry point specified in the ELF header.
+  *EntryPoint = (void*)ElfHdr->e_entry;
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.h b/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.h
new file mode 100644
index 000000000000..7020a6c4e726
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.h
@@ -0,0 +1,64 @@ 
+/** @file
+*
+*  Copyright (c) 2014, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef ELF_LOADER_H
+#define ELF_LOADER_H
+
+/**
+  Check that the ELF File Header is valid and Machine type supported.
+
+  Not all information is checked in the ELF header, only the stuff that
+  matters to us in our simplified ELF loader.
+
+  @param[in] ElfImage  Address of the ELF file to check.
+
+  @retval EFI_SUCCESS on success.
+  @retval EFI_INVALID_PARAMETER if the header is invalid.
+  @retval EFI_UNSUPPORTED if the file type/platform is not supported.
+**/
+EFI_STATUS
+ElfCheckFile (
+  IN  CONST VOID *ElfImage
+  );
+
+
+/**
+  Load a ELF file.
+
+  @param[in]  ElfImage      Address of the ELF file in memory.
+
+  @param[out] EntryPoint    Will be filled with the ELF entry point address.
+
+  @param[out] ImageSize     Will be filled with the ELF size in memory. This will
+                            effectively be equal to the sum of the segments sizes.
+
+  This function assumes the header is valid and supported as checked with
+  ElfCheckFile().
+
+  NOTE:
+   - We don't currently take the segment permissions into account (indicated by
+     the program headers). It can be used to allocate pages with the right
+     read/write/exec permissions.
+
+  @retval EFI_SUCCESS on success.
+  @retval EFI_INVALID_PARAMETER if the ELF file is invalid.
+**/
+EFI_STATUS
+ElfLoadFile (
+  IN  CONST VOID   *ElfImage,
+  OUT VOID        **EntryPoint,
+  OUT LIST_ENTRY   *LoadList
+  );
+
+#endif // ELF_LOADER_H
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c b/Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c
new file mode 100644
index 000000000000..9f4fc780307d
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c
@@ -0,0 +1,395 @@ 
+/** @file
+*
+*  Shell command for launching AXF files.
+*
+*  Copyright (c) 2014, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Guid/GlobalVariable.h>
+
+#include <Library/PrintLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+
+#include <Library/ArmLib.h>
+
+#include "ArmShellCmdRunAxf.h"
+#include "ElfLoader.h"
+#include "BootMonFsLoader.h"
+
+// Provide arguments to AXF?
+typedef VOID (*ELF_ENTRYPOINT)(UINTN arg0, UINTN arg1,
+                               UINTN arg2, UINTN arg3);
+
+STATIC
+EFI_STATUS
+ShutdownUefiBootServices (
+  VOID
+  )
+{
+  EFI_STATUS              Status;
+  UINTN                   MemoryMapSize;
+  EFI_MEMORY_DESCRIPTOR   *MemoryMap;
+  UINTN                   MapKey;
+  UINTN                   DescriptorSize;
+  UINT32                  DescriptorVersion;
+  UINTN                   Pages;
+
+  MemoryMap = NULL;
+  MemoryMapSize = 0;
+  Pages = 0;
+
+  do {
+    Status = gBS->GetMemoryMap (
+                    &MemoryMapSize,
+                    MemoryMap,
+                    &MapKey,
+                    &DescriptorSize,
+                    &DescriptorVersion
+                    );
+    if (Status == EFI_BUFFER_TOO_SMALL) {
+
+      Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
+      MemoryMap = AllocatePages (Pages);
+
+      //
+      // Get System MemoryMap
+      //
+      Status = gBS->GetMemoryMap (
+                      &MemoryMapSize,
+                      MemoryMap,
+                      &MapKey,
+                      &DescriptorSize,
+                      &DescriptorVersion
+                      );
+    }
+
+    // Don't do anything between the GetMemoryMap() and ExitBootServices()
+    if (!EFI_ERROR(Status)) {
+      Status = gBS->ExitBootServices (gImageHandle, MapKey);
+      if (EFI_ERROR(Status)) {
+        FreePages (MemoryMap, Pages);
+        MemoryMap = NULL;
+        MemoryMapSize = 0;
+      }
+    }
+  } while (EFI_ERROR(Status));
+
+  return Status;
+}
+
+
+STATIC
+EFI_STATUS
+PreparePlatformHardware (
+  VOID
+  )
+{
+  //Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called.
+
+  // Clean before Disable else the Stack gets corrupted with old data.
+  ArmCleanDataCache ();
+  ArmDisableDataCache ();
+  // Invalidate all the entries that might have snuck in.
+  ArmInvalidateDataCache ();
+
+  // Disable and invalidate the instruction cache
+  ArmDisableInstructionCache ();
+  ArmInvalidateInstructionCache ();
+
+  // Turn off MMU
+  ArmDisableMmu();
+
+  return EFI_SUCCESS;
+}
+
+// Process arguments to pass to AXF?
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+  {NULL, TypeMax}
+};
+
+
+/**
+  This is the shell command handler function pointer callback type. This
+  function handles the command when it is invoked in the shell.
+
+  @param[in] This             The instance of the
+                              EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
+  @param[in] SystemTable      The pointer to the system table.
+  @param[in] ShellParameters  The parameters associated with the command.
+  @param[in] Shell            The instance of the shell protocol used in the
+                              context of processing this command.
+
+  @return EFI_SUCCESS         The operation was successful.
+  @return other               The operation failed.
+**/
+SHELL_STATUS
+EFIAPI
+ShellDynCmdRunAxfHandler (
+  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL    *This,
+  IN EFI_SYSTEM_TABLE                      *SystemTable,
+  IN EFI_SHELL_PARAMETERS_PROTOCOL         *ShellParameters,
+  IN EFI_SHELL_PROTOCOL                    *Shell
+  )
+{
+  LIST_ENTRY        *ParamPackage;
+  EFI_STATUS         Status;
+  SHELL_STATUS       ShellStatus;
+  SHELL_FILE_HANDLE  FileHandle;
+  ELF_ENTRYPOINT     StartElf;
+  CONST CHAR16      *FileName;
+  EFI_FILE_INFO     *Info;
+  UINTN              FileSize;
+  VOID              *FileData;
+  VOID              *Entrypoint;
+  LIST_ENTRY         LoadList;
+  LIST_ENTRY        *Node;
+  LIST_ENTRY        *NextNode;
+  RUNAXF_LOAD_LIST  *LoadNode;
+  CHAR16            *TmpFileName;
+  CHAR16            *TmpChar16;
+
+
+  ShellStatus = SHELL_SUCCESS;
+  FileHandle = NULL;
+  FileData = NULL;
+  InitializeListHead (&LoadList);
+
+  // Only install if they are not there yet? First time or every time?
+  // These can change if the shell exits and start again.
+  Status = gBS->InstallMultipleProtocolInterfaces (&gImageHandle,
+                &gEfiShellProtocolGuid, Shell,
+                &gEfiShellParametersProtocolGuid, ShellParameters,
+                NULL);
+
+  if (EFI_ERROR (Status)) {
+    return SHELL_DEVICE_ERROR;
+  }
+
+  // Update the protocols for the application library
+  Status = ShellInitialize ();
+  ASSERT_EFI_ERROR (Status);
+  // Add support to load AXF with optipnal args?
+
+  //
+  // Process Command Line arguments
+  //
+  Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);
+  if (EFI_ERROR (Status)) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_INVALID_ARG), gRunAxfHiiHandle);
+    ShellStatus = SHELL_INVALID_PARAMETER;
+  } else {
+    //
+    // Check for "-?"
+    //
+    if ((ShellCommandLineGetFlag (ParamPackage, L"-?")) ||
+        (ShellCommandLineGetRawValue (ParamPackage, 1) == NULL)) {
+      //
+      // We didn't get a file to load
+      //
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_INVALID_ARG), gRunAxfHiiHandle);
+      ShellStatus = SHELL_INVALID_PARAMETER;
+    } else {
+      // For the moment we assume we only ever get one file to load with no arguments.
+      FileName = ShellCommandLineGetRawValue (ParamPackage, 1);
+      Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+      if (EFI_ERROR (Status)) {
+        // BootMonFS supports file extensions, but they are stripped by default
+        // when the NOR is programmed.
+        // Remove the file extension and try to open again.
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_FILE_NOT_FOUND),
+                         gRunAxfHiiHandle, FileName);
+        // Go through the filename and remove file extension. Preserve the
+        // original name.
+        TmpFileName = AllocateCopyPool (StrSize (FileName), (VOID *)FileName);
+        if (TmpFileName != NULL) {
+          TmpChar16 = StrStr (TmpFileName, L".");
+          if (TmpChar16 != NULL) {
+            *TmpChar16 = '\0';
+            DEBUG((EFI_D_ERROR, "Trying to open file: %s\n", TmpFileName));
+            Status = ShellOpenFileByName (TmpFileName, &FileHandle,
+                                          EFI_FILE_MODE_READ, 0);
+          }
+          FreePool (TmpFileName);
+        }
+        // Do we now have an open file after trying again?
+        if (EFI_ERROR (Status)) {
+          ShellStatus = SHELL_INVALID_PARAMETER;
+          FileHandle = NULL;
+        }
+      }
+
+      if (FileHandle != NULL) {
+        Info = ShellGetFileInfo (FileHandle);
+        FileSize = (UINTN) Info->FileSize;
+        FreePool (Info);
+
+        //
+        // Allocate buffer to read file. 'Runtime' so we can access it after
+        // ExitBootServices().
+        //
+        FileData = AllocateRuntimeZeroPool (FileSize);
+        if (FileData == NULL) {
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_NO_MEM), gRunAxfHiiHandle);
+          ShellStatus = SHELL_OUT_OF_RESOURCES;
+        } else {
+          //
+          // Read file into Buffer
+          //
+          Status = ShellReadFile (FileHandle, &FileSize, FileData);
+          if (EFI_ERROR (Status)) {
+            ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_READ_FAIL), gRunAxfHiiHandle);
+            SHELL_FREE_NON_NULL (FileData);
+            FileData = NULL;
+            ShellStatus = SHELL_DEVICE_ERROR;
+          }
+        }
+      }
+    }
+
+    //
+    // Free the command line package
+    //
+    ShellCommandLineFreeVarList (ParamPackage);
+  }
+
+  // We have a file in memory. Try to work out if we can use it.
+  // It can either be in ELF format or BootMonFS format.
+  if (FileData != NULL) {
+    // Do some validation on the file before we try to load it. The file can
+    // either be an proper ELF file or one processed by the FlashLoader.
+    // Since the data might need to go to various locations in memory we cannot
+    // load the data directly while UEFI is running. We use the file loaders to
+    // populate a linked list of data and load addresses. This is processed and
+    // data copied to where it needs to go after calling ExitBootServices. At
+    // that stage we've reached the point of no return, so overwriting UEFI code
+    // does not make a difference.
+    Status = ElfCheckFile (FileData);
+    if (!EFI_ERROR (Status)) {
+      // Load program into memory
+      Status = ElfLoadFile ((VOID*)FileData, &Entrypoint, &LoadList);
+    } else {
+      // Try to see if it is a BootMonFs executable
+      Status = BootMonFsCheckFile ((EFI_FILE_HANDLE)FileHandle);
+      if (!EFI_ERROR (Status)) {
+        // Load program into memory
+        Status = BootMonFsLoadFile ((EFI_FILE_HANDLE)FileHandle,
+                                    (VOID*)FileData, &Entrypoint, &LoadList);
+      } else {
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_BAD_FILE),
+                         gRunAxfHiiHandle);
+        SHELL_FREE_NON_NULL (FileData);
+        ShellStatus = SHELL_UNSUPPORTED;
+      }
+    }
+  }
+
+  // Program load list created.
+  // Shutdown UEFI, copy and jump to code.
+  if (!IsListEmpty (&LoadList) && !EFI_ERROR (Status)) {
+    // Exit boot services here. This means we cannot return and cannot assume to
+    // have access to UEFI functions.
+    Status = ShutdownUefiBootServices ();
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR,"Can not shutdown UEFI boot services. Status=0x%X\n",
+              Status));
+    } else {
+      // Process linked list. Copy data to Memory.
+      Node = GetFirstNode (&LoadList);
+      while (!IsNull (&LoadList, Node)) {
+        LoadNode = (RUNAXF_LOAD_LIST *)Node;
+        // Do we have data to copy or do we need to set Zeroes (.bss)?
+        if (LoadNode->Zeroes) {
+          ZeroMem ((VOID*)LoadNode->MemOffset, LoadNode->Length);
+        } else {
+          CopyMem ((VOID *)LoadNode->MemOffset, (VOID *)LoadNode->FileOffset,
+                   LoadNode->Length);
+        }
+        Node = GetNextNode (&LoadList, Node);
+      }
+
+      //
+      // Switch off interrupts, caches, mmu, etc
+      //
+      Status = PreparePlatformHardware ();
+      ASSERT_EFI_ERROR (Status);
+
+      StartElf = (ELF_ENTRYPOINT)Entrypoint;
+      StartElf (0,0,0,0);
+
+      // We should never get here.. But if we do, spin..
+      ASSERT (FALSE);
+      while (1);
+    }
+  }
+
+  // Free file related information as we are returning to UEFI.
+  Node = GetFirstNode (&LoadList);
+  while (!IsNull (&LoadList, Node)) {
+    NextNode = RemoveEntryList (Node);
+    FreePool (Node);
+    Node = NextNode;
+  }
+  SHELL_FREE_NON_NULL (FileData);
+  if (FileHandle != NULL) {
+    ShellCloseFile (&FileHandle);
+  }
+
+  // Uninstall protocols as we don't know if they will change.
+  // If the shell exits and come in again these mappings may be different
+  // and cause a crash.
+  Status = gBS->UninstallMultipleProtocolInterfaces (gImageHandle,
+                &gEfiShellProtocolGuid, Shell,
+                &gEfiShellParametersProtocolGuid, ShellParameters,
+                NULL);
+
+  if (EFI_ERROR (Status) && ShellStatus == SHELL_SUCCESS) {
+    ShellStatus = SHELL_DEVICE_ERROR;
+  }
+
+  return ShellStatus;
+}
+
+
+/**
+  This is the command help handler function pointer callback type. This
+  function is responsible for displaying help information for the associated
+  command.
+
+  @param[in] This             The instance of the
+                              EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
+  @param[in] Language         The pointer to the language string to use.
+
+  @return string              Pool allocated help string, must be freed by
+                              caller.
+**/
+CHAR16*
+EFIAPI
+ShellDynCmdRunAxfGetHelp (
+  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL    *This,
+  IN CONST CHAR8                           *Language
+  )
+{
+  CHAR16 *HelpText;
+
+  ASSERT (gRunAxfHiiHandle != NULL);
+
+  // This allocates memory. The caller is responsoible to free.
+  HelpText = HiiGetString (gRunAxfHiiHandle, STRING_TOKEN (STR_GET_HELP_RUNAXF),
+                           Language);
+
+  return HelpText;
+}
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/elf32.h b/Platform/ARM/Library/ArmShellCmdRunAxf/elf32.h
new file mode 100644
index 000000000000..3951444a3085
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/elf32.h
@@ -0,0 +1,258 @@ 
+/** @file
+Ported ELF include files from FreeBSD
+
+Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+/*-
+ * Copyright (c) 1996-1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.2 2007/12/03 21:30:36 marius Exp $
+ */
+
+#ifndef _SYS_ELF32_H_
+#define _SYS_ELF32_H_ 1
+
+
+/*
+ * ELF definitions common to all 32-bit architectures.
+ */
+
+typedef UINT32  Elf32_Addr;
+typedef UINT16  Elf32_Half;
+typedef UINT32  Elf32_Off;
+typedef INT32   Elf32_Sword;
+typedef UINT32  Elf32_Word;
+typedef UINT64  Elf32_Lword;
+
+typedef Elf32_Word      Elf32_Hashelt;
+
+/* Non-standard class-dependent datatype used for abstraction. */
+typedef Elf32_Word      Elf32_Size;
+typedef Elf32_Sword     Elf32_Ssize;
+
+/*
+ * ELF header.
+ */
+
+typedef struct {
+  unsigned char   e_ident[EI_NIDENT]; /* File identification. */
+  Elf32_Half      e_type;             /* File type. */
+  Elf32_Half      e_machine;          /* Machine architecture. */
+  Elf32_Word      e_version;          /* ELF format version. */
+  Elf32_Addr      e_entry;            /* Entry point. */
+  Elf32_Off       e_phoff;            /* Program header file offset. */
+  Elf32_Off       e_shoff;            /* Section header file offset. */
+  Elf32_Word      e_flags;            /* Architecture-specific flags. */
+  Elf32_Half      e_ehsize;           /* Size of ELF header in bytes. */
+  Elf32_Half      e_phentsize;        /* Size of program header entry. */
+  Elf32_Half      e_phnum;            /* Number of program header entries. */
+  Elf32_Half      e_shentsize;        /* Size of section header entry. */
+  Elf32_Half      e_shnum;            /* Number of section header entries. */
+  Elf32_Half      e_shstrndx;         /* Section name strings section. */
+} Elf32_Ehdr;
+
+/*
+ * Section header.
+ */
+
+typedef struct {
+  Elf32_Word      sh_name;        /* Section name (index into the
+                                     section header string table). */
+  Elf32_Word      sh_type;        /* Section type. */
+  Elf32_Word      sh_flags;       /* Section flags. */
+  Elf32_Addr      sh_addr;        /* Address in memory image. */
+  Elf32_Off       sh_offset;      /* Offset in file. */
+  Elf32_Word      sh_size;        /* Size in bytes. */
+  Elf32_Word      sh_link;        /* Index of a related section. */
+  Elf32_Word      sh_info;        /* Depends on section type. */
+  Elf32_Word      sh_addralign;   /* Alignment in bytes. */
+  Elf32_Word      sh_entsize;     /* Size of each entry in section. */
+} Elf32_Shdr;
+
+/*
+ * Program header.
+ */
+
+typedef struct {
+  Elf32_Word      p_type;         /* Entry type. */
+  Elf32_Off       p_offset;       /* File offset of contents. */
+  Elf32_Addr      p_vaddr;        /* Virtual address in memory image. */
+  Elf32_Addr      p_paddr;        /* Physical address (not used). */
+  Elf32_Word      p_filesz;       /* Size of contents in file. */
+  Elf32_Word      p_memsz;        /* Size of contents in memory. */
+  Elf32_Word      p_flags;        /* Access permission flags. */
+  Elf32_Word      p_align;        /* Alignment in memory and file. */
+} Elf32_Phdr;
+
+/*
+ * Dynamic structure.  The ".dynamic" section contains an array of them.
+ */
+
+typedef struct {
+  Elf32_Sword     d_tag;          /* Entry type. */
+  union {
+    Elf32_Word      d_val;  /* Integer value. */
+    Elf32_Addr      d_ptr;  /* Address value. */
+  } d_un;
+} Elf32_Dyn;
+
+/*
+ * Relocation entries.
+ */
+
+/* Relocations that don't need an addend field. */
+typedef struct {
+  Elf32_Addr      r_offset;       /* Location to be relocated. */
+  Elf32_Word      r_info;         /* Relocation type and symbol index. */
+} Elf32_Rel;
+
+/* Relocations that need an addend field. */
+typedef struct {
+  Elf32_Addr      r_offset;       /* Location to be relocated. */
+  Elf32_Word      r_info;         /* Relocation type and symbol index. */
+  Elf32_Sword     r_addend;       /* Addend. */
+} Elf32_Rela;
+
+/* Macros for accessing the fields of r_info. */
+#define ELF32_R_SYM(info)       ((info) >> 8)
+#define ELF32_R_TYPE(info)      ((unsigned char)(info))
+
+/* Macro for constructing r_info from field values. */
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type))
+
+/*
+ *      Note entry header
+ */
+typedef Elf_Note Elf32_Nhdr;
+
+/*
+ *      Move entry
+ */
+typedef struct {
+  Elf32_Lword     m_value;        /* symbol value */
+  Elf32_Word      m_info;         /* size + index */
+  Elf32_Word      m_poffset;      /* symbol offset */
+  Elf32_Half      m_repeat;       /* repeat count */
+  Elf32_Half      m_stride;       /* stride info */
+} Elf32_Move;
+
+/*
+ *      The macros compose and decompose values for Move.r_info
+ *
+ *      sym = ELF32_M_SYM(M.m_info)
+ *      size = ELF32_M_SIZE(M.m_info)
+ *      M.m_info = ELF32_M_INFO(sym, size)
+ */
+#define ELF32_M_SYM(info)       ((info)>>8)
+#define ELF32_M_SIZE(info)      ((unsigned char)(info))
+#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
+
+/*
+ *      Hardware/Software capabilities entry
+ */
+typedef struct {
+  Elf32_Word      c_tag;          /* how to interpret value */
+  union {
+    Elf32_Word      c_val;
+    Elf32_Addr      c_ptr;
+  } c_un;
+} Elf32_Cap;
+
+/*
+ * Symbol table entries.
+ */
+
+typedef struct {
+  Elf32_Word      st_name;        /* String table index of name. */
+  Elf32_Addr      st_value;       /* Symbol value. */
+  Elf32_Word      st_size;        /* Size of associated object. */
+  unsigned char   st_info;        /* Type and binding information. */
+  unsigned char   st_other;       /* Reserved (not used). */
+  Elf32_Half      st_shndx;       /* Section index of symbol. */
+} Elf32_Sym;
+
+/* Macros for accessing the fields of st_info. */
+#define ELF32_ST_BIND(info)             ((info) >> 4)
+#define ELF32_ST_TYPE(info)             ((info) & 0xf)
+
+/* Macro for constructing st_info from field values. */
+#define ELF32_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
+
+/* Macro for accessing the fields of st_other. */
+#define ELF32_ST_VISIBILITY(oth)        ((oth) & 0x3)
+
+/* Structures used by Sun & GNU symbol versioning. */
+typedef struct
+{
+  Elf32_Half      vd_version;
+  Elf32_Half      vd_flags;
+  Elf32_Half      vd_ndx;
+  Elf32_Half      vd_cnt;
+  Elf32_Word      vd_hash;
+  Elf32_Word      vd_aux;
+  Elf32_Word      vd_next;
+} Elf32_Verdef;
+
+typedef struct
+{
+  Elf32_Word      vda_name;
+  Elf32_Word      vda_next;
+} Elf32_Verdaux;
+
+typedef struct
+{
+  Elf32_Half      vn_version;
+  Elf32_Half      vn_cnt;
+  Elf32_Word      vn_file;
+  Elf32_Word      vn_aux;
+  Elf32_Word      vn_next;
+} Elf32_Verneed;
+
+typedef struct
+{
+  Elf32_Word      vna_hash;
+  Elf32_Half      vna_flags;
+  Elf32_Half      vna_other;
+  Elf32_Word      vna_name;
+  Elf32_Word      vna_next;
+} Elf32_Vernaux;
+
+typedef Elf32_Half Elf32_Versym;
+
+typedef struct {
+  Elf32_Half      si_boundto;     /* direct bindings - symbol bound to */
+  Elf32_Half      si_flags;       /* per symbol flags */
+} Elf32_Syminfo;
+
+#endif /* !_SYS_ELF32_H_ */
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/elf64.h b/Platform/ARM/Library/ArmShellCmdRunAxf/elf64.h
new file mode 100644
index 000000000000..1cfe0c9539aa
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/elf64.h
@@ -0,0 +1,260 @@ 
+/** @file
+Ported ELF include files from FreeBSD
+
+Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+/*-
+ * Copyright (c) 1996-1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.2 2007/12/03 21:30:36 marius Exp $
+ */
+
+#ifndef _SYS_ELF64_H_
+#define _SYS_ELF64_H_ 1
+
+
+/*
+ * ELF definitions common to all 64-bit architectures.
+ */
+
+typedef UINT64  Elf64_Addr;
+typedef UINT16  Elf64_Half;
+typedef UINT64  Elf64_Off;
+typedef INT32   Elf64_Sword;
+typedef INT64   Elf64_Sxword;
+typedef UINT32  Elf64_Word;
+typedef UINT64  Elf64_Lword;
+typedef UINT64  Elf64_Xword;
+
+/*
+ * Types of dynamic symbol hash table bucket and chain elements.
+ *
+ * This is inconsistent among 64 bit architectures, so a machine dependent
+ * typedef is required.
+ */
+
+typedef Elf64_Word      Elf64_Hashelt;
+
+/* Non-standard class-dependent datatype used for abstraction. */
+typedef Elf64_Xword     Elf64_Size;
+typedef Elf64_Sxword    Elf64_Ssize;
+
+/*
+ * ELF header.
+ */
+
+typedef struct {
+  unsigned char   e_ident[EI_NIDENT]; /* File identification. */
+  Elf64_Half      e_type;             /* File type. */
+  Elf64_Half      e_machine;          /* Machine architecture. */
+  Elf64_Word      e_version;          /* ELF format version. */
+  Elf64_Addr      e_entry;            /* Entry point. */
+  Elf64_Off       e_phoff;            /* Program header file offset. */
+  Elf64_Off       e_shoff;            /* Section header file offset. */
+  Elf64_Word      e_flags;            /* Architecture-specific flags. */
+  Elf64_Half      e_ehsize;           /* Size of ELF header in bytes. */
+  Elf64_Half      e_phentsize;        /* Size of program header entry. */
+  Elf64_Half      e_phnum;            /* Number of program header entries. */
+  Elf64_Half      e_shentsize;        /* Size of section header entry. */
+  Elf64_Half      e_shnum;            /* Number of section header entries. */
+  Elf64_Half      e_shstrndx;         /* Section name strings section. */
+} Elf64_Ehdr;
+
+/*
+ * Section header.
+ */
+
+typedef struct {
+  Elf64_Word      sh_name;        /* Section name (index into the
+                                     section header string table). */
+  Elf64_Word      sh_type;        /* Section type. */
+  Elf64_Xword     sh_flags;       /* Section flags. */
+  Elf64_Addr      sh_addr;        /* Address in memory image. */
+  Elf64_Off       sh_offset;      /* Offset in file. */
+  Elf64_Xword     sh_size;        /* Size in bytes. */
+  Elf64_Word      sh_link;        /* Index of a related section. */
+  Elf64_Word      sh_info;        /* Depends on section type. */
+  Elf64_Xword     sh_addralign;   /* Alignment in bytes. */
+  Elf64_Xword     sh_entsize;     /* Size of each entry in section. */
+} Elf64_Shdr;
+
+/*
+ * Program header.
+ */
+
+typedef struct {
+  Elf64_Word      p_type;         /* Entry type. */
+  Elf64_Word      p_flags;        /* Access permission flags. */
+  Elf64_Off       p_offset;       /* File offset of contents. */
+  Elf64_Addr      p_vaddr;        /* Virtual address in memory image. */
+  Elf64_Addr      p_paddr;        /* Physical address (not used). */
+  Elf64_Xword     p_filesz;       /* Size of contents in file. */
+  Elf64_Xword     p_memsz;        /* Size of contents in memory. */
+  Elf64_Xword     p_align;        /* Alignment in memory and file. */
+} Elf64_Phdr;
+
+/*
+ * Dynamic structure.  The ".dynamic" section contains an array of them.
+ */
+
+typedef struct {
+  Elf64_Sxword    d_tag;          /* Entry type. */
+  union {
+    Elf64_Xword     d_val;  /* Integer value. */
+    Elf64_Addr      d_ptr;  /* Address value. */
+  } d_un;
+} Elf64_Dyn;
+
+/*
+ * Relocation entries.
+ */
+
+/* Relocations that don't need an addend field. */
+typedef struct {
+  Elf64_Addr      r_offset;       /* Location to be relocated. */
+  Elf64_Xword     r_info;         /* Relocation type and symbol index. */
+} Elf64_Rel;
+
+/* Relocations that need an addend field. */
+typedef struct {
+  Elf64_Addr      r_offset;       /* Location to be relocated. */
+  Elf64_Xword     r_info;         /* Relocation type and symbol index. */
+  Elf64_Sxword    r_addend;       /* Addend. */
+} Elf64_Rela;
+
+/* Macros for accessing the fields of r_info. */
+#define ELF64_R_SYM(info)       ((info) >> 32)
+#define ELF64_R_TYPE(info)      ((info) & 0xffffffffL)
+
+/* Macro for constructing r_info from field values. */
+#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL))
+
+#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40)
+#define ELF64_R_TYPE_ID(info)   (((Elf64_Xword)(info)<<56)>>56)
+#define ELF64_R_TYPE_INFO(data, type)   \
+                (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type))
+
+/*
+ *      Note entry header
+ */
+typedef Elf_Note Elf64_Nhdr;
+
+/*
+ *      Move entry
+ */
+typedef struct {
+  Elf64_Lword     m_value;        /* symbol value */
+  Elf64_Xword     m_info;         /* size + index */
+  Elf64_Xword     m_poffset;      /* symbol offset */
+  Elf64_Half      m_repeat;       /* repeat count */
+  Elf64_Half      m_stride;       /* stride info */
+} Elf64_Move;
+
+#define ELF64_M_SYM(info)       ((info)>>8)
+#define ELF64_M_SIZE(info)      ((unsigned char)(info))
+#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
+
+/*
+ *      Hardware/Software capabilities entry
+ */
+typedef struct {
+  Elf64_Xword     c_tag;          /* how to interpret value */
+  union {
+    Elf64_Xword     c_val;
+    Elf64_Addr      c_ptr;
+  } c_un;
+} Elf64_Cap;
+
+/*
+ * Symbol table entries.
+ */
+
+typedef struct {
+  Elf64_Word      st_name;        /* String table index of name. */
+  unsigned char   st_info;        /* Type and binding information. */
+  unsigned char   st_other;       /* Reserved (not used). */
+  Elf64_Half      st_shndx;       /* Section index of symbol. */
+  Elf64_Addr      st_value;       /* Symbol value. */
+  Elf64_Xword     st_size;        /* Size of associated object. */
+} Elf64_Sym;
+
+/* Macros for accessing the fields of st_info. */
+#define ELF64_ST_BIND(info)             ((info) >> 4)
+#define ELF64_ST_TYPE(info)             ((info) & 0xf)
+
+/* Macro for constructing st_info from field values. */
+#define ELF64_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
+
+/* Macro for accessing the fields of st_other. */
+#define ELF64_ST_VISIBILITY(oth)        ((oth) & 0x3)
+
+/* Structures used by Sun & GNU-style symbol versioning. */
+typedef struct {
+  Elf64_Half      vd_version;
+  Elf64_Half      vd_flags;
+  Elf64_Half      vd_ndx;
+  Elf64_Half      vd_cnt;
+  Elf64_Word      vd_hash;
+  Elf64_Word      vd_aux;
+  Elf64_Word      vd_next;
+} Elf64_Verdef;
+
+typedef struct {
+  Elf64_Word      vda_name;
+  Elf64_Word      vda_next;
+} Elf64_Verdaux;
+
+typedef struct {
+  Elf64_Half      vn_version;
+  Elf64_Half      vn_cnt;
+  Elf64_Word      vn_file;
+  Elf64_Word      vn_aux;
+  Elf64_Word      vn_next;
+} Elf64_Verneed;
+
+typedef struct {
+  Elf64_Word      vna_hash;
+  Elf64_Half      vna_flags;
+  Elf64_Half      vna_other;
+  Elf64_Word      vna_name;
+  Elf64_Word      vna_next;
+} Elf64_Vernaux;
+
+typedef Elf64_Half Elf64_Versym;
+
+typedef struct {
+  Elf64_Half      si_boundto;     /* direct bindings - symbol bound to */
+  Elf64_Half      si_flags;       /* per symbol flags */
+} Elf64_Syminfo;
+
+#endif /* !_SYS_ELF64_H_ */
diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/elf_common.h b/Platform/ARM/Library/ArmShellCmdRunAxf/elf_common.h
new file mode 100644
index 000000000000..ed3cedc1b076
--- /dev/null
+++ b/Platform/ARM/Library/ArmShellCmdRunAxf/elf_common.h
@@ -0,0 +1,1059 @@ 
+/** @file
+Ported ELF include files from FreeBSD
+
+Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
+Portions Copyright (c) 2011 - 2013, 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.
+
+
+**/
+/*-
+ * Copyright (c) 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/elf_common.h,v 1.15.8.2 2007/12/03 21:30:36 marius Exp $
+ */
+
+#ifndef _SYS_ELF_COMMON_H_
+#define _SYS_ELF_COMMON_H_ 1
+
+/*
+ * ELF definitions that are independent of architecture or word size.
+ */
+
+/*
+ * Note header.  The ".note" section contains an array of notes.  Each
+ * begins with this header, aligned to a word boundary.  Immediately
+ * following the note header is n_namesz bytes of name, padded to the
+ * next word boundary.  Then comes n_descsz bytes of descriptor, again
+ * padded to a word boundary.  The values of n_namesz and n_descsz do
+ * not include the padding.
+ */
+
+typedef struct {
+        UINT32  n_namesz;       /* Length of name. */
+        UINT32  n_descsz;       /* Length of descriptor. */
+        UINT32  n_type;         /* Type of this note. */
+} Elf_Note;
+
+/* Indexes into the e_ident array.  Keep synced with
+   http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
+#define EI_MAG0         0       /* Magic number, byte 0. */
+#define EI_MAG1         1       /* Magic number, byte 1. */
+#define EI_MAG2         2       /* Magic number, byte 2. */
+#define EI_MAG3         3       /* Magic number, byte 3. */
+#define EI_CLASS        4       /* Class of machine. */
+#define EI_DATA         5       /* Data format. */
+#define EI_VERSION      6       /* ELF format version. */
+#define EI_OSABI        7       /* Operating system / ABI identification */
+#define EI_ABIVERSION   8       /* ABI version */
+#define OLD_EI_BRAND    8       /* Start of architecture identification. */
+#define EI_PAD          9       /* Start of padding (per SVR4 ABI). */
+#define EI_NIDENT       16      /* Size of e_ident array. */
+
+/* Values for the magic number bytes. */
+#define ELFMAG0         0x7f
+#define ELFMAG1         'E'
+#define ELFMAG2         'L'
+#define ELFMAG3         'F'
+#define ELFMAG          "\177ELF"       /* magic string */
+#define SELFMAG         4               /* magic string size */
+
+/* Values for e_ident[EI_VERSION] and e_version. */
+#define EV_NONE         0
+#define EV_CURRENT      1
+
+/* Values for e_ident[EI_CLASS]. */
+#define ELFCLASSNONE    0       /* Unknown class. */
+#define ELFCLASS32      1       /* 32-bit architecture. */
+#define ELFCLASS64      2       /* 64-bit architecture. */
+
+/* Values for e_ident[EI_DATA]. */
+#define ELFDATANONE     0       /* Unknown data format. */
+#define ELFDATA2LSB     1       /* 2's complement little-endian. */
+#define ELFDATA2MSB     2       /* 2's complement big-endian. */
+
+/* Values for e_ident[EI_OSABI]. */
+#define ELFOSABI_NONE           0       /* UNIX System V ABI */
+#define ELFOSABI_HPUX           1       /* HP-UX operating system */
+#define ELFOSABI_NETBSD         2       /* NetBSD */
+#define ELFOSABI_LINUX          3       /* GNU/Linux */
+#define ELFOSABI_HURD           4       /* GNU/Hurd */
+#define ELFOSABI_86OPEN         5       /* 86Open common IA32 ABI */
+#define ELFOSABI_SOLARIS        6       /* Solaris */
+#define ELFOSABI_AIX            7       /* AIX */
+#define ELFOSABI_IRIX           8       /* IRIX */
+#define ELFOSABI_FREEBSD        9       /* FreeBSD */
+#define ELFOSABI_TRU64          10      /* TRU64 UNIX */
+#define ELFOSABI_MODESTO        11      /* Novell Modesto */
+#define ELFOSABI_OPENBSD        12      /* OpenBSD */
+#define ELFOSABI_OPENVMS        13      /* Open VMS */
+#define ELFOSABI_NSK            14      /* HP Non-Stop Kernel */
+#define ELFOSABI_ARM            97      /* ARM */
+#define ELFOSABI_STANDALONE     255     /* Standalone (embedded) application */
+
+#define ELFOSABI_SYSV           ELFOSABI_NONE   /* symbol used in old spec */
+#define ELFOSABI_MONTEREY       ELFOSABI_AIX    /* Monterey */
+
+/* e_ident */
+#define IS_ELF(ehdr)    ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
+                         (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
+                         (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
+                         (ehdr).e_ident[EI_MAG3] == ELFMAG3)
+
+/* Values for e_type. */
+#define ET_NONE         0       /* Unknown type. */
+#define ET_REL          1       /* Relocatable. */
+#define ET_EXEC         2       /* Executable. */
+#define ET_DYN          3       /* Shared object. */
+#define ET_CORE         4       /* Core file. */
+#define ET_LOOS         0xfe00  /* First operating system specific. */
+#define ET_HIOS         0xfeff  /* Last operating system-specific. */
+#define ET_LOPROC       0xff00  /* First processor-specific. */
+#define ET_HIPROC       0xffff  /* Last processor-specific. */
+
+/* Values for e_machine. */
+#define EM_NONE         0       /* Unknown machine. */
+#define EM_M32          1       /* AT&T WE32100. */
+#define EM_SPARC        2       /* Sun SPARC. */
+#define EM_386          3       /* Intel i386. */
+#define EM_68K          4       /* Motorola 68000. */
+#define EM_88K          5       /* Motorola 88000. */
+#define EM_860          7       /* Intel i860. */
+#define EM_MIPS         8       /* MIPS R3000 Big-Endian only. */
+#define EM_S370         9       /* IBM System/370. */
+#define EM_MIPS_RS3_LE  10      /* MIPS R3000 Little-Endian. */
+#define EM_PARISC       15      /* HP PA-RISC. */
+#define EM_VPP500       17      /* Fujitsu VPP500. */
+#define EM_SPARC32PLUS  18      /* SPARC v8plus. */
+#define EM_960          19      /* Intel 80960. */
+#define EM_PPC          20      /* PowerPC 32-bit. */
+#define EM_PPC64        21      /* PowerPC 64-bit. */
+#define EM_S390         22      /* IBM System/390. */
+#define EM_V800         36      /* NEC V800. */
+#define EM_FR20         37      /* Fujitsu FR20. */
+#define EM_RH32         38      /* TRW RH-32. */
+#define EM_RCE          39      /* Motorola RCE. */
+#define EM_ARM          40      /* ARM. */
+#define EM_SH           42      /* Hitachi SH. */
+#define EM_SPARCV9      43      /* SPARC v9 64-bit. */
+#define EM_TRICORE      44      /* Siemens TriCore embedded processor. */
+#define EM_ARC          45      /* Argonaut RISC Core. */
+#define EM_H8_300       46      /* Hitachi H8/300. */
+#define EM_H8_300H      47      /* Hitachi H8/300H. */
+#define EM_H8S          48      /* Hitachi H8S. */
+#define EM_H8_500       49      /* Hitachi H8/500. */
+#define EM_IA_64        50      /* Intel IA-64 Processor. */
+#define EM_MIPS_X       51      /* Stanford MIPS-X. */
+#define EM_COLDFIRE     52      /* Motorola ColdFire. */
+#define EM_68HC12       53      /* Motorola M68HC12. */
+#define EM_MMA          54      /* Fujitsu MMA. */
+#define EM_PCP          55      /* Siemens PCP. */
+#define EM_NCPU         56      /* Sony nCPU. */
+#define EM_NDR1         57      /* Denso NDR1 microprocessor. */
+#define EM_STARCORE     58      /* Motorola Star*Core processor. */
+#define EM_ME16         59      /* Toyota ME16 processor. */
+#define EM_ST100        60      /* STMicroelectronics ST100 processor. */
+#define EM_TINYJ        61      /* Advanced Logic Corp. TinyJ processor. */
+#define EM_X86_64       62      /* Advanced Micro Devices x86-64 */
+#define EM_AMD64        EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */
+#define EM_AARCH64      183     /* ARM 64bit Architecture */
+
+/* Non-standard or deprecated. */
+#define EM_486          6       /* Intel i486. */
+#define EM_MIPS_RS4_BE  10      /* MIPS R4000 Big-Endian */
+#define EM_ALPHA_STD    41      /* Digital Alpha (standard value). */
+#define EM_ALPHA        0x9026  /* Alpha (written in the absence of an ABI) */
+
+/* Special section indexes. */
+#define SHN_UNDEF            0          /* Undefined, missing, irrelevant. */
+#define SHN_LORESERVE   0xff00          /* First of reserved range. */
+#define SHN_LOPROC      0xff00          /* First processor-specific. */
+#define SHN_HIPROC      0xff1f          /* Last processor-specific. */
+#define SHN_LOOS        0xff20          /* First operating system-specific. */
+#define SHN_HIOS        0xff3f          /* Last operating system-specific. */
+#define SHN_ABS         0xfff1          /* Absolute values. */
+#define SHN_COMMON      0xfff2          /* Common data. */
+#define SHN_XINDEX      0xffff          /* Escape -- index stored elsewhere. */
+#define SHN_HIRESERVE   0xffff          /* Last of reserved range. */
+
+/* sh_type */
+#define SHT_NULL                0       /* inactive */
+#define SHT_PROGBITS            1       /* program defined information */
+#define SHT_SYMTAB              2       /* symbol table section */
+#define SHT_STRTAB              3       /* string table section */
+#define SHT_RELA                4       /* relocation section with addends */
+#define SHT_HASH                5       /* symbol hash table section */
+#define SHT_DYNAMIC             6       /* dynamic section */
+#define SHT_NOTE                7       /* note section */
+#define SHT_NOBITS              8       /* no space section */
+#define SHT_REL                 9       /* relocation section - no addends */
+#define SHT_SHLIB               10      /* reserved - purpose unknown */
+#define SHT_DYNSYM              11      /* dynamic symbol table section */
+#define SHT_INIT_ARRAY          14      /* Initialization function pointers. */
+#define SHT_FINI_ARRAY          15      /* Termination function pointers. */
+#define SHT_PREINIT_ARRAY       16      /* Pre-initialization function ptrs. */
+#define SHT_GROUP               17      /* Section group. */
+#define SHT_SYMTAB_SHNDX        18      /* Section indexes (see SHN_XINDEX). */
+#define SHT_LOOS                0x60000000      /* First of OS specific semantics */
+#define SHT_LOSUNW              0x6ffffff4
+#define SHT_SUNW_dof            0x6ffffff4
+#define SHT_SUNW_cap            0x6ffffff5
+#define SHT_SUNW_SIGNATURE      0x6ffffff6
+#define SHT_SUNW_ANNOTATE       0x6ffffff7
+#define SHT_SUNW_DEBUGSTR       0x6ffffff8
+#define SHT_SUNW_DEBUG          0x6ffffff9
+#define SHT_SUNW_move           0x6ffffffa
+#define SHT_SUNW_COMDAT         0x6ffffffb
+#define SHT_SUNW_syminfo        0x6ffffffc
+#define SHT_SUNW_verdef         0x6ffffffd
+#define SHT_GNU_verdef          0x6ffffffd      /* Symbol versions provided */
+#define SHT_SUNW_verneed        0x6ffffffe
+#define SHT_GNU_verneed         0x6ffffffe      /* Symbol versions required */
+#define SHT_SUNW_versym         0x6fffffff
+#define SHT_GNU_versym          0x6fffffff      /* Symbol version table */
+#define SHT_HISUNW              0x6fffffff
+#define SHT_HIOS                0x6fffffff      /* Last of OS specific semantics */
+#define SHT_LOPROC              0x70000000      /* reserved range for processor */
+#define SHT_AMD64_UNWIND        0x70000001      /* unwind information */
+#define SHT_HIPROC              0x7fffffff      /* specific section header types */
+#define SHT_LOUSER              0x80000000      /* reserved range for application */
+#define SHT_HIUSER              0xffffffff      /* specific indexes */
+
+/* Flags for sh_flags. */
+#define SHF_WRITE               0x1     /* Section contains writable data. */
+#define SHF_ALLOC               0x2     /* Section occupies memory. */
+#define SHF_EXECINSTR           0x4     /* Section contains instructions. */
+#define SHF_MERGE               0x10    /* Section may be merged. */
+#define SHF_STRINGS             0x20    /* Section contains strings. */
+#define SHF_INFO_LINK           0x40    /* sh_info holds section index. */
+#define SHF_LINK_ORDER          0x80    /* Special ordering requirements. */
+#define SHF_OS_NONCONFORMING    0x100   /* OS-specific processing required. */
+#define SHF_GROUP               0x200   /* Member of section group. */
+#define SHF_TLS                 0x400   /* Section contains TLS data. */
+#define SHF_MASKOS      0x0ff00000      /* OS-specific semantics. */
+#define SHF_MASKPROC    0xf0000000      /* Processor-specific semantics. */
+
+/* Values for p_type. */
+#define PT_NULL         0       /* Unused entry. */
+#define PT_LOAD         1       /* Loadable segment. */
+#define PT_DYNAMIC      2       /* Dynamic linking information segment. */
+#define PT_INTERP       3       /* Pathname of interpreter. */
+#define PT_NOTE         4       /* Auxiliary information. */
+#define PT_SHLIB        5       /* Reserved (not used). */
+#define PT_PHDR         6       /* Location of program header itself. */
+#define PT_TLS          7       /* Thread local storage segment */
+#define PT_LOOS         0x60000000      /* First OS-specific. */
+#define PT_SUNW_UNWIND  0x6464e550      /* amd64 UNWIND program header */
+#define PT_GNU_EH_FRAME 0x6474e550
+#define PT_LOSUNW       0x6ffffffa
+#define PT_SUNWBSS      0x6ffffffa      /* Sun Specific segment */
+#define PT_SUNWSTACK    0x6ffffffb      /* describes the stack segment */
+#define PT_SUNWDTRACE   0x6ffffffc      /* private */
+#define PT_SUNWCAP      0x6ffffffd      /* hard/soft capabilities segment */
+#define PT_HISUNW       0x6fffffff
+#define PT_HIOS         0x6fffffff      /* Last OS-specific. */
+#define PT_LOPROC       0x70000000      /* First processor-specific type. */
+#define PT_HIPROC       0x7fffffff      /* Last processor-specific type. */
+
+/* Values for p_flags. */
+#define PF_X            0x1             /* Executable. */
+#define PF_W            0x2             /* Writable. */
+#define PF_R            0x4             /* Readable. */
+#define PF_MASKOS       0x0ff00000      /* Operating system-specific. */
+#define PF_MASKPROC     0xf0000000      /* Processor-specific. */
+
+/* Extended program header index. */
+#define PN_XNUM         0xffff
+
+/* Values for d_tag. */
+#define DT_NULL         0       /* Terminating entry. */
+#define DT_NEEDED       1       /* String table offset of a needed shared
+                                   library. */
+#define DT_PLTRELSZ     2       /* Total size in bytes of PLT relocations. */
+#define DT_PLTGOT       3       /* Processor-dependent address. */
+#define DT_HASH         4       /* Address of symbol hash table. */
+#define DT_STRTAB       5       /* Address of string table. */
+#define DT_SYMTAB       6       /* Address of symbol table. */
+#define DT_RELA         7       /* Address of ElfNN_Rela relocations. */
+#define DT_RELASZ       8       /* Total size of ElfNN_Rela relocations. */
+#define DT_RELAENT      9       /* Size of each ElfNN_Rela relocation entry. */
+#define DT_STRSZ        10      /* Size of string table. */
+#define DT_SYMENT       11      /* Size of each symbol table entry. */
+#define DT_INIT         12      /* Address of initialization function. */
+#define DT_FINI         13      /* Address of finalization function. */
+#define DT_SONAME       14      /* String table offset of shared object
+                                   name. */
+#define DT_RPATH        15      /* String table offset of library path. [sup] */
+#define DT_SYMBOLIC     16      /* Indicates "symbolic" linking. [sup] */
+#define DT_REL          17      /* Address of ElfNN_Rel relocations. */
+#define DT_RELSZ        18      /* Total size of ElfNN_Rel relocations. */
+#define DT_RELENT       19      /* Size of each ElfNN_Rel relocation. */
+#define DT_PLTREL       20      /* Type of relocation used for PLT. */
+#define DT_DEBUG        21      /* Reserved (not used). */
+#define DT_TEXTREL      22      /* Indicates there may be relocations in
+                                   non-writable segments. [sup] */
+#define DT_JMPREL       23      /* Address of PLT relocations. */
+#define DT_BIND_NOW     24      /* [sup] */
+#define DT_INIT_ARRAY   25      /* Address of the array of pointers to
+                                   initialization functions */
+#define DT_FINI_ARRAY   26      /* Address of the array of pointers to
+                                   termination functions */
+#define DT_INIT_ARRAYSZ 27      /* Size in bytes of the array of
+                                   initialization functions. */
+#define DT_FINI_ARRAYSZ 28      /* Size in bytes of the array of
+                                   terminationfunctions. */
+#define DT_RUNPATH      29      /* String table offset of a null-terminated
+                                   library search path string. */
+#define DT_FLAGS        30      /* Object specific flag values. */
+#define DT_ENCODING     32      /* Values greater than or equal to DT_ENCODING
+                                   and less than DT_LOOS follow the rules for
+                                   the interpretation of the d_un union
+                                   as follows: even == 'd_ptr', even == 'd_val'
+                                   or none */
+#define DT_PREINIT_ARRAY   32   /* Address of the array of pointers to
+                                   pre-initialization functions. */
+#define DT_PREINIT_ARRAYSZ 33   /* Size in bytes of the array of
+                                   pre-initialization functions. */
+#define DT_MAXPOSTAGS      34   /* number of positive tags */
+#define DT_LOOS            0x6000000d      /* First OS-specific */
+#define DT_SUNW_AUXILIARY  0x6000000d      /* symbol auxiliary name */
+#define DT_SUNW_RTLDINF    0x6000000e      /* ld.so.1 info (private) */
+#define DT_SUNW_FILTER     0x6000000f      /* symbol filter name */
+#define DT_SUNW_CAP        0x60000010      /* hardware/software */
+#define DT_HIOS            0x6ffff000      /* Last OS-specific */
+
+/*
+ * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+ * Dyn.d_un.d_val field of the Elf*_Dyn structure.
+ */
+#define DT_VALRNGLO     0x6ffffd00
+#define DT_CHECKSUM     0x6ffffdf8      /* elf checksum */
+#define DT_PLTPADSZ     0x6ffffdf9      /* pltpadding size */
+#define DT_MOVEENT      0x6ffffdfa      /* move table entry size */
+#define DT_MOVESZ       0x6ffffdfb      /* move table size */
+#define DT_FEATURE_1    0x6ffffdfc      /* feature holder */
+#define DT_POSFLAG_1    0x6ffffdfd      /* flags for DT_* entries, effecting */
+                                        /*      the following DT_* entry. */
+                                        /*      See DF_P1_* definitions */
+#define DT_SYMINSZ      0x6ffffdfe      /* syminfo table size (in bytes) */
+#define DT_SYMINENT     0x6ffffdff      /* syminfo entry size (in bytes) */
+#define DT_VALRNGHI     0x6ffffdff
+
+/*
+ * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+ * Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+ *
+ * If any adjustment is made to the ELF object after it has been
+ * built, these entries will need to be adjusted.
+ */
+#define DT_ADDRRNGLO    0x6ffffe00
+#define DT_CONFIG       0x6ffffefa      /* configuration information */
+#define DT_DEPAUDIT     0x6ffffefb      /* dependency auditing */
+#define DT_AUDIT        0x6ffffefc      /* object auditing */
+#define DT_PLTPAD       0x6ffffefd      /* pltpadding (sparcv9) */
+#define DT_MOVETAB      0x6ffffefe      /* move table */
+#define DT_SYMINFO      0x6ffffeff      /* syminfo table */
+#define DT_ADDRRNGHI    0x6ffffeff
+
+#define DT_VERSYM       0x6ffffff0      /* Address of versym section. */
+#define DT_RELACOUNT    0x6ffffff9      /* number of RELATIVE relocations */
+#define DT_RELCOUNT     0x6ffffffa      /* number of RELATIVE relocations */
+#define DT_FLAGS_1      0x6ffffffb      /* state flags - see DF_1_* defs */
+#define DT_VERDEF       0x6ffffffc      /* Address of verdef section. */
+#define DT_VERDEFNUM    0x6ffffffd      /* Number of elems in verdef section */
+#define DT_VERNEED      0x6ffffffe      /* Address of verneed section. */
+#define DT_VERNEEDNUM   0x6fffffff      /* Number of elems in verneed section */
+
+#define DT_LOPROC       0x70000000      /* First processor-specific type. */
+#define DT_DEPRECATED_SPARC_REGISTER    0x7000001
+#define DT_AUXILIARY    0x7ffffffd      /* shared library auxiliary name */
+#define DT_USED         0x7ffffffe      /* ignored - same as needed */
+#define DT_FILTER       0x7fffffff      /* shared library filter name */
+#define DT_HIPROC       0x7fffffff      /* Last processor-specific type. */
+
+/* Values for DT_FLAGS */
+#define DF_ORIGIN       0x0001  /* Indicates that the object being loaded may
+                                   make reference to the $ORIGIN substitution
+                                   string */
+#define DF_SYMBOLIC     0x0002  /* Indicates "symbolic" linking. */
+#define DF_TEXTREL      0x0004  /* Indicates there may be relocations in
+                                   non-writable segments. */
+#define DF_BIND_NOW     0x0008  /* Indicates that the dynamic linker should
+                                   process all relocations for the object
+                                   containing this entry before transferring
+                                   control to the program. */
+#define DF_STATIC_TLS   0x0010  /* Indicates that the shared object or
+                                   executable contains code using a static
+                                   thread-local storage scheme. */
+
+/* Values for n_type.  Used in core files. */
+#define NT_PRSTATUS     1       /* Process status. */
+#define NT_FPREGSET     2       /* Floating point registers. */
+#define NT_PRPSINFO     3       /* Process state info. */
+
+/* Symbol Binding - ELFNN_ST_BIND - st_info */
+#define STB_LOCAL       0       /* Local symbol */
+#define STB_GLOBAL      1       /* Global symbol */
+#define STB_WEAK        2       /* like global - lower precedence */
+#define STB_LOOS        10      /* Reserved range for operating system */
+#define STB_HIOS        12      /*   specific semantics. */
+#define STB_LOPROC      13      /* reserved range for processor */
+#define STB_HIPROC      15      /*   specific semantics. */
+
+/* Symbol type - ELFNN_ST_TYPE - st_info */
+#define STT_NOTYPE      0       /* Unspecified type. */
+#define STT_OBJECT      1       /* Data object. */
+#define STT_FUNC        2       /* Function. */
+#define STT_SECTION     3       /* Section. */
+#define STT_FILE        4       /* Source file. */
+#define STT_COMMON      5       /* Uninitialized common block. */
+#define STT_TLS         6       /* TLS object. */
+#define STT_NUM         7
+#define STT_LOOS        10      /* Reserved range for operating system */
+#define STT_HIOS        12      /*   specific semantics. */
+#define STT_LOPROC      13      /* reserved range for processor */
+#define STT_HIPROC      15      /*   specific semantics. */
+
+/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */
+#define STV_DEFAULT     0x0     /* Default visibility (see binding). */
+#define STV_INTERNAL    0x1     /* Special meaning in relocatable objects. */
+#define STV_HIDDEN      0x2     /* Not visible. */
+#define STV_PROTECTED   0x3     /* Visible but not preemptible. */
+
+/* Special symbol table indexes. */
+#define STN_UNDEF       0       /* Undefined symbol index. */
+
+/* Symbol versioning flags. */
+#define VER_DEF_CURRENT 1
+#define VER_DEF_IDX(x)  VER_NDX(x)
+
+#define VER_FLG_BASE    0x01
+#define VER_FLG_WEAK    0x02
+
+#define VER_NEED_CURRENT        1
+#define VER_NEED_WEAK   (1u << 15)
+#define VER_NEED_HIDDEN VER_NDX_HIDDEN
+#define VER_NEED_IDX(x) VER_NDX(x)
+
+#define VER_NDX_LOCAL   0
+#define VER_NDX_GLOBAL  1
+#define VER_NDX_GIVEN   2
+
+#define VER_NDX_HIDDEN  (1u << 15)
+#define VER_NDX(x)      ((x) & ~(1u << 15))
+
+#define CA_SUNW_NULL    0
+#define CA_SUNW_HW_1    1               /* first hardware capabilities entry */
+#define CA_SUNW_SF_1    2               /* first software capabilities entry */
+
+/*
+ * Syminfo flag values
+ */
+#define SYMINFO_FLG_DIRECT      0x0001  /* symbol ref has direct association */
+                                        /*      to object containing defn. */
+#define SYMINFO_FLG_PASSTHRU    0x0002  /* ignored - see SYMINFO_FLG_FILTER */
+#define SYMINFO_FLG_COPY        0x0004  /* symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD    0x0008  /* object containing defn should be */
+                                        /*      lazily-loaded */
+#define SYMINFO_FLG_DIRECTBIND  0x0010  /* ref should be bound directly to */
+                                        /*      object containing defn. */
+#define SYMINFO_FLG_NOEXTDIRECT 0x0020  /* don't let an external reference */
+                                        /*      directly bind to this symbol */
+#define SYMINFO_FLG_FILTER      0x0002  /* symbol ref is associated to a */
+#define SYMINFO_FLG_AUXILIARY   0x0040  /*      standard or auxiliary filter */
+
+/*
+ * Syminfo.si_boundto values.
+ */
+#define SYMINFO_BT_SELF         0xffff  /* symbol bound to self */
+#define SYMINFO_BT_PARENT       0xfffe  /* symbol bound to parent */
+#define SYMINFO_BT_NONE         0xfffd  /* no special symbol binding */
+#define SYMINFO_BT_EXTERN       0xfffc  /* symbol defined as external */
+#define SYMINFO_BT_LOWRESERVE   0xff00  /* beginning of reserved entries */
+
+/*
+ * Syminfo version values.
+ */
+#define SYMINFO_NONE            0       /* Syminfo version */
+#define SYMINFO_CURRENT         1
+#define SYMINFO_NUM             2
+
+/*
+ * Relocation types.
+ *
+ * All machine architectures are defined here to allow tools on one to
+ * handle others.
+ */
+
+#define R_386_NONE              0       /* No relocation. */
+#define R_386_32                1       /* Add symbol value. */
+#define R_386_PC32              2       /* Add PC-relative symbol value. */
+#define R_386_GOT32             3       /* Add PC-relative GOT offset. */
+#define R_386_PLT32             4       /* Add PC-relative PLT offset. */
+#define R_386_COPY              5       /* Copy data from shared object. */
+#define R_386_GLOB_DAT          6       /* Set GOT entry to data address. */
+#define R_386_JMP_SLOT          7       /* Set GOT entry to code address. */
+#define R_386_RELATIVE          8       /* Add load address of shared object. */
+#define R_386_GOTOFF            9       /* Add GOT-relative symbol address. */
+#define R_386_GOTPC             10      /* Add PC-relative GOT table address. */
+#define R_386_TLS_TPOFF         14      /* Negative offset in static TLS block */
+#define R_386_TLS_IE            15      /* Absolute address of GOT for -ve static TLS */
+#define R_386_TLS_GOTIE         16      /* GOT entry for negative static TLS block */
+#define R_386_TLS_LE            17      /* Negative offset relative to static TLS */
+#define R_386_TLS_GD            18      /* 32 bit offset to GOT (index,off) pair */
+#define R_386_TLS_LDM           19      /* 32 bit offset to GOT (index,zero) pair */
+#define R_386_TLS_GD_32         24      /* 32 bit offset to GOT (index,off) pair */
+#define R_386_TLS_GD_PUSH       25      /* pushl instruction for Sun ABI GD sequence */
+#define R_386_TLS_GD_CALL       26      /* call instruction for Sun ABI GD sequence */
+#define R_386_TLS_GD_POP        27      /* popl instruction for Sun ABI GD sequence */
+#define R_386_TLS_LDM_32        28      /* 32 bit offset to GOT (index,zero) pair */
+#define R_386_TLS_LDM_PUSH      29      /* pushl instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDM_CALL      30      /* call instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDM_POP       31      /* popl instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDO_32        32      /* 32 bit offset from start of TLS block */
+#define R_386_TLS_IE_32         33      /* 32 bit offset to GOT static TLS offset entry */
+#define R_386_TLS_LE_32         34      /* 32 bit offset within static TLS block */
+#define R_386_TLS_DTPMOD32      35      /* GOT entry containing TLS index */
+#define R_386_TLS_DTPOFF32      36      /* GOT entry containing TLS offset */
+#define R_386_TLS_TPOFF32       37      /* GOT entry of -ve static TLS offset */
+
+/* Null relocation */
+#define R_AARCH64_NONE                          256     /* No relocation */
+/* Static AArch64 relocations */
+ /* Static data relocations */
+#define R_AARCH64_ABS64                         257     /* S + A */
+#define R_AARCH64_ABS32                         258     /* S + A */
+#define R_AARCH64_ABS16                         259     /* S + A */
+#define R_AARCH64_PREL64                        260     /* S + A - P */
+#define R_AARCH64_PREL32                        261     /* S + A - P */
+#define R_AARCH64_PREL16                        262     /* S + A - P */
+ /* Group relocations to create a 16, 32, 48, or 64 bit unsigned data value or address inline */
+#define R_AARCH64_MOVW_UABS_G0                  263     /* S + A */
+#define R_AARCH64_MOVW_UABS_G0_NC               264     /* S + A */
+#define R_AARCH64_MOVW_UABS_G1                  265     /* S + A */
+#define R_AARCH64_MOVW_UABS_G1_NC               266     /* S + A */
+#define R_AARCH64_MOVW_UABS_G2                  267     /* S + A */
+#define R_AARCH64_MOVW_UABS_G2_NC               268     /* S + A */
+#define R_AARCH64_MOVW_UABS_G3                  269     /* S + A */
+ /* Group relocations to create a 16, 32, 48, or 64 bit signed data or offset value inline */
+#define R_AARCH64_MOVW_SABS_G0                  270     /* S + A */
+#define R_AARCH64_MOVW_SABS_G1                  271     /* S + A */
+#define R_AARCH64_MOVW_SABS_G2                  272     /* S + A */
+ /* Relocations to generate 19, 21 and 33 bit PC-relative addresses */
+#define R_AARCH64_LD_PREL_LO19                  273     /* S + A - P */
+#define R_AARCH64_ADR_PREL_LO21                 274     /* S + A - P */
+#define R_AARCH64_ADR_PREL_PG_HI21              275     /* Page(S+A) - Page(P) */
+#define R_AARCH64_ADR_PREL_PG_HI21_NC           276     /* Page(S+A) - Page(P) */
+#define R_AARCH64_ADD_ABS_LO12_NC               277     /* S + A */
+#define R_AARCH64_LDST8_ABS_LO12_NC             278     /* S + A */
+#define R_AARCH64_LDST16_ABS_LO12_NC            284     /* S + A */
+#define R_AARCH64_LDST32_ABS_LO12_NC            285     /* S + A */
+#define R_AARCH64_LDST64_ABS_LO12_NC            286     /* S + A */
+#define R_AARCH64_LDST128_ABS_LO12_NC           299     /* S + A */
+ /* Relocations for control-flow instructions - all offsets are a multiple of 4 */
+#define R_AARCH64_TSTBR14                       279     /* S+A-P */
+#define R_AARCH64_CONDBR19                      280     /* S+A-P */
+#define R_AARCH64_JUMP26                        282     /* S+A-P */
+#define R_AARCH64_CALL26                        283     /* S+A-P */
+ /* Group relocations to create a 16, 32, 48, or 64 bit PC-relative offset inline */
+#define R_AARCH64_MOVW_PREL_G0                  287     /* S+A-P */
+#define R_AARCH64_MOVW_PREL_G0_NC               288     /* S+A-P */
+#define R_AARCH64_MOVW_PREL_G1                  289     /* S+A-P */
+#define R_AARCH64_MOVW_PREL_G1_NC               290     /* S+A-P */
+#define R_AARCH64_MOVW_PREL_G2                  291     /* S+A-P */
+#define R_AARCH64_MOVW_PREL_G2_NC               292     /* S+A-P */
+#define R_AARCH64_MOVW_PREL_G3                  293     /* S+A-P */
+ /* Group relocations to create a 16, 32, 48, or 64 bit GOT-relative offsets inline */
+#define R_AARCH64_MOVW_GOTOFF_G0                300     /* G(S)-GOT */
+#define R_AARCH64_MOVW_GOTOFF_G0_NC             301     /* G(S)-GOT */
+#define R_AARCH64_MOVW_GOTOFF_G1                302     /* G(S)-GOT */
+#define R_AARCH64_MOVW_GOTOFF_G1_NC             303     /* G(S)-GOT */
+#define R_AARCH64_MOVW_GOTOFF_G2                304     /* G(S)-GOT */
+#define R_AARCH64_MOVW_GOTOFF_G2_NC             305     /* G(S)-GOT */
+#define R_AARCH64_MOVW_GOTOFF_G3                306     /* G(S)-GOT */
+ /*  GOT-relative data relocations */
+#define R_AARCH64_GOTREL64                      307     /* S+A-GOT */
+#define R_AARCH64_GOTREL32                      308     /* S+A-GOT */
+ /* GOT-relative instruction relocations */
+#define R_AARCH64_GOT_LD_PREL19                 309     /* G(S)-P */
+#define R_AARCH64_LD64_GOTOFF_LO15              310     /* G(S)-GOT */
+#define R_AARCH64_ADR_GOT_PAGE                  311     /* Page(G(S))-Page(P) */
+#define R_AARCH64_LD64_GOT_LO12_NC              312     /* G(S) */
+#define R_AARCH64_LD64_GOTPAGE_LO15             313     /* G(S)-Page(GOT) */
+/* Relocations for thread-local storage */
+ /* General Dynamic TLS relocations */
+#define R_AARCH64_TLSGD_ADR_PREL21              512     /* G(TLSIDX(S+A)) - P */
+#define R_AARCH64_TLSGD_ADR_PAGE21              513     /* Page(G(TLSIDX(S+A))) - Page(P) */
+#define R_AARCH64_TLSGD_ADD_LO12_NC             514     /* G(TLSIDX(S+A)) */
+#define R_AARCH64_TLSGD_MOVW_G1                 515     /* G(TLSIDX(S+A)) - GOT */
+#define R_AARCH64_TLSGD_MOVW_G0_NC              516     /* G(TLSIDX(S+A)) - GOT */
+ /* Local Dynamic TLS relocations */
+#define R_AARCH64_TLSLD_ADR_PREL21              517     /* G(LDM(S))) - P */
+#define R_AARCH64_TLSLD_ADR_PAGE21              518     /* Page(G(LDM(S)))-Page(P) */
+#define R_AARCH64_TLSLD_ADD_LO12_NC             519     /* G(LDM(S)) */
+#define R_AARCH64_TLSLD_MOVW_G1                 520     /* G(LDM(S)) - GOT */
+#define R_AARCH64_TLSLD_MOVW_G0_NC              521     /* G(LDM(S)) - GOT */
+#define R_AARCH64_TLSLD_LD_PREL19               522     /* G(LDM(S)) - P */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G2          523     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1          524     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC       525     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0          526     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC       527     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_ADD_DTPREL_HI12         528     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12         529     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC      530     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12       531     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC    532     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12      533     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC   534     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12      535     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC   536     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12      537     /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC   538     /* DTPREL(S+A) */
+ /* Initial Exec TLS relocations */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1        539     /* G(TPREL(S+A)) - GOT */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC     540     /* G(TPREL(S+A)) - GOT */
+#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21     541     /* Page(G(TPREL(S+A))) - Page(P) */
+#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC   542     /* G(TPREL(S+A)) */
+#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19      543     /* G(TPREL(S+A)) - P */
+ /* Local Exec TLS relocations */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G2           544     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1           545     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC        546     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0           547     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC        548     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_ADD_TPREL_HI12          549     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12          550     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC       551     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12        552     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC     553     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12       554     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC    555     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12       556     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC    557     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12       558     /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC    559     /* TPREL(S+A) */
+/* Dynamic relocations */
+ /* Dynamic relocations */
+#define R_AARCH64_COPY                          1024
+#define R_AARCH64_GLOB_DAT                      1025    /* S + A */
+#define R_AARCH64_JUMP_SLOT                     1026    /* S + A */
+#define R_AARCH64_RELATIVE                      1027    /* Delta(S) + A , Delta(P) + A */
+#define R_AARCH64_TLS_DTPREL64                  1028    /* DTPREL(S+A) */
+#define R_AARCH64_TLS_DTPMOD64                  1029    /* LDM(S) */
+#define R_AARCH64_TLS_TPREL64                   1030    /* TPREL(S+A) */
+#define R_AARCH64_TLS_DTPREL32                  1031    /* DTPREL(S+A) */
+#define R_AARCH64_TLS_DTPMOD32                  1032    /* LDM(S) */
+#define R_AARCH64_TLS_TPREL32                   1033    /* DTPREL(S+A) */
+
+#define R_ALPHA_NONE            0       /* No reloc */
+#define R_ALPHA_REFLONG         1       /* Direct 32 bit */
+#define R_ALPHA_REFQUAD         2       /* Direct 64 bit */
+#define R_ALPHA_GPREL32         3       /* GP relative 32 bit */
+#define R_ALPHA_LITERAL         4       /* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE          5       /* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP          6       /* Add displacement to GP */
+#define R_ALPHA_BRADDR          7       /* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT            8       /* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16          9       /* PC relative 16 bit */
+#define R_ALPHA_SREL32          10      /* PC relative 32 bit */
+#define R_ALPHA_SREL64          11      /* PC relative 64 bit */
+#define R_ALPHA_OP_PUSH         12      /* OP stack push */
+#define R_ALPHA_OP_STORE        13      /* OP stack pop and store */
+#define R_ALPHA_OP_PSUB         14      /* OP stack subtract */
+#define R_ALPHA_OP_PRSHIFT      15      /* OP stack right shift */
+#define R_ALPHA_GPVALUE         16
+#define R_ALPHA_GPRELHIGH       17
+#define R_ALPHA_GPRELLOW        18
+#define R_ALPHA_IMMED_GP_16     19
+#define R_ALPHA_IMMED_GP_HI32   20
+#define R_ALPHA_IMMED_SCN_HI32  21
+#define R_ALPHA_IMMED_BR_HI32   22
+#define R_ALPHA_IMMED_LO32      23
+#define R_ALPHA_COPY            24      /* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT        25      /* Create GOT entry */
+#define R_ALPHA_JMP_SLOT        26      /* Create PLT entry */
+#define R_ALPHA_RELATIVE        27      /* Adjust by program base */
+
+#define R_ARM_NONE              0       /* No relocation. */
+#define R_ARM_PC24              1
+#define R_ARM_ABS32             2
+#define R_ARM_REL32             3
+#define R_ARM_PC13              4
+#define R_ARM_ABS16             5
+#define R_ARM_ABS12             6
+#define R_ARM_THM_ABS5          7
+#define R_ARM_ABS8              8
+#define R_ARM_SBREL32           9
+#define R_ARM_THM_PC22          10
+#define R_ARM_THM_PC8           11
+#define R_ARM_AMP_VCALL9        12
+#define R_ARM_SWI24             13
+#define R_ARM_THM_SWI8          14
+#define R_ARM_XPC25             15
+#define R_ARM_THM_XPC22         16
+#define R_ARM_COPY              20      /* Copy data from shared object. */
+#define R_ARM_GLOB_DAT          21      /* Set GOT entry to data address. */
+#define R_ARM_JUMP_SLOT         22      /* Set GOT entry to code address. */
+#define R_ARM_RELATIVE          23      /* Add load address of shared object. */
+#define R_ARM_GOTOFF            24      /* Add GOT-relative symbol address. */
+#define R_ARM_GOTPC             25      /* Add PC-relative GOT table address. */
+#define R_ARM_GOT32             26      /* Add PC-relative GOT offset. */
+#define R_ARM_PLT32             27      /* Add PC-relative PLT offset. */
+#define R_ARM_CALL              28
+#define R_ARM_JMP24             29
+#define R_ARM_MOVW_ABS_NC       43
+#define R_ARM_MOVT_ABS          44
+#define R_ARM_THM_MOVW_ABS_NC   47
+#define R_ARM_THM_MOVT_ABS      48
+
+// Block of PC-relative relocations added to work around gcc putting
+// object relocations in static executables.
+#define R_ARM_THM_JUMP24        30
+#define R_ARM_PREL31            42
+#define R_ARM_MOVW_PREL_NC      45
+#define R_ARM_MOVT_PREL         46
+#define R_ARM_THM_MOVW_PREL_NC  49
+#define R_ARM_THM_MOVT_PREL     50
+#define R_ARM_THM_JMP6          52
+#define R_ARM_THM_ALU_PREL_11_0 53
+#define R_ARM_THM_PC12          54
+#define R_ARM_REL32_NOI         56
+#define R_ARM_ALU_PC_G0_NC      57
+#define R_ARM_ALU_PC_G0         58
+#define R_ARM_ALU_PC_G1_NC      59
+#define R_ARM_ALU_PC_G1         60
+#define R_ARM_ALU_PC_G2         61
+#define R_ARM_LDR_PC_G1         62
+#define R_ARM_LDR_PC_G2         63
+#define R_ARM_LDRS_PC_G0        64
+#define R_ARM_LDRS_PC_G1        65
+#define R_ARM_LDRS_PC_G2        66
+#define R_ARM_LDC_PC_G0         67
+#define R_ARM_LDC_PC_G1         68
+#define R_ARM_LDC_PC_G2         69
+#define R_ARM_GOT_PREL          96
+#define R_ARM_THM_JUMP11        102
+#define R_ARM_THM_JUMP8         103
+#define R_ARM_TLS_GD32          104
+#define R_ARM_TLS_LDM32         105
+#define R_ARM_TLS_IE32          107
+
+#define R_ARM_THM_JUMP19        51
+#define R_ARM_GNU_VTENTRY       100
+#define R_ARM_GNU_VTINHERIT     101
+#define R_ARM_RSBREL32          250
+#define R_ARM_THM_RPC22         251
+#define R_ARM_RREL32            252
+#define R_ARM_RABS32            253
+#define R_ARM_RPC24             254
+#define R_ARM_RBASE             255
+
+
+
+/*      Name                    Value      Field        Calculation */
+#define R_IA_64_NONE            0       /* None */
+#define R_IA_64_IMM14           0x21    /* immediate14  S + A */
+#define R_IA_64_IMM22           0x22    /* immediate22  S + A */
+#define R_IA_64_IMM64           0x23    /* immediate64  S + A */
+#define R_IA_64_DIR32MSB        0x24    /* word32 MSB   S + A */
+#define R_IA_64_DIR32LSB        0x25    /* word32 LSB   S + A */
+#define R_IA_64_DIR64MSB        0x26    /* word64 MSB   S + A */
+#define R_IA_64_DIR64LSB        0x27    /* word64 LSB   S + A */
+#define R_IA_64_GPREL22         0x2a    /* immediate22  @gprel(S + A) */
+#define R_IA_64_GPREL64I        0x2b    /* immediate64  @gprel(S + A) */
+#define R_IA_64_GPREL32MSB      0x2c    /* word32 MSB   @gprel(S + A) */
+#define R_IA_64_GPREL32LSB      0x2d    /* word32 LSB   @gprel(S + A) */
+#define R_IA_64_GPREL64MSB      0x2e    /* word64 MSB   @gprel(S + A) */
+#define R_IA_64_GPREL64LSB      0x2f    /* word64 LSB   @gprel(S + A) */
+#define R_IA_64_LTOFF22         0x32    /* immediate22  @ltoff(S + A) */
+#define R_IA_64_LTOFF64I        0x33    /* immediate64  @ltoff(S + A) */
+#define R_IA_64_PLTOFF22        0x3a    /* immediate22  @pltoff(S + A) */
+#define R_IA_64_PLTOFF64I       0x3b    /* immediate64  @pltoff(S + A) */
+#define R_IA_64_PLTOFF64MSB     0x3e    /* word64 MSB   @pltoff(S + A) */
+#define R_IA_64_PLTOFF64LSB     0x3f    /* word64 LSB   @pltoff(S + A) */
+#define R_IA_64_FPTR64I         0x43    /* immediate64  @fptr(S + A) */
+#define R_IA_64_FPTR32MSB       0x44    /* word32 MSB   @fptr(S + A) */
+#define R_IA_64_FPTR32LSB       0x45    /* word32 LSB   @fptr(S + A) */
+#define R_IA_64_FPTR64MSB       0x46    /* word64 MSB   @fptr(S + A) */
+#define R_IA_64_FPTR64LSB       0x47    /* word64 LSB   @fptr(S + A) */
+#define R_IA_64_PCREL60B        0x48    /* immediate60 form1 S + A - P */
+#define R_IA_64_PCREL21B        0x49    /* immediate21 form1 S + A - P */
+#define R_IA_64_PCREL21M        0x4a    /* immediate21 form2 S + A - P */
+#define R_IA_64_PCREL21F        0x4b    /* immediate21 form3 S + A - P */
+#define R_IA_64_PCREL32MSB      0x4c    /* word32 MSB   S + A - P */
+#define R_IA_64_PCREL32LSB      0x4d    /* word32 LSB   S + A - P */
+#define R_IA_64_PCREL64MSB      0x4e    /* word64 MSB   S + A - P */
+#define R_IA_64_PCREL64LSB      0x4f    /* word64 LSB   S + A - P */
+#define R_IA_64_LTOFF_FPTR22    0x52    /* immediate22  @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64I   0x53    /* immediate64  @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR32MSB 0x54    /* word32 MSB   @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR32LSB 0x55    /* word32 LSB   @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64MSB 0x56    /* word64 MSB   @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64LSB 0x57    /* word64 LSB   @ltoff(@fptr(S + A)) */
+#define R_IA_64_SEGREL32MSB     0x5c    /* word32 MSB   @segrel(S + A) */
+#define R_IA_64_SEGREL32LSB     0x5d    /* word32 LSB   @segrel(S + A) */
+#define R_IA_64_SEGREL64MSB     0x5e    /* word64 MSB   @segrel(S + A) */
+#define R_IA_64_SEGREL64LSB     0x5f    /* word64 LSB   @segrel(S + A) */
+#define R_IA_64_SECREL32MSB     0x64    /* word32 MSB   @secrel(S + A) */
+#define R_IA_64_SECREL32LSB     0x65    /* word32 LSB   @secrel(S + A) */
+#define R_IA_64_SECREL64MSB     0x66    /* word64 MSB   @secrel(S + A) */
+#define R_IA_64_SECREL64LSB     0x67    /* word64 LSB   @secrel(S + A) */
+#define R_IA_64_REL32MSB        0x6c    /* word32 MSB   BD + A */
+#define R_IA_64_REL32LSB        0x6d    /* word32 LSB   BD + A */
+#define R_IA_64_REL64MSB        0x6e    /* word64 MSB   BD + A */
+#define R_IA_64_REL64LSB        0x6f    /* word64 LSB   BD + A */
+#define R_IA_64_LTV32MSB        0x74    /* word32 MSB   S + A */
+#define R_IA_64_LTV32LSB        0x75    /* word32 LSB   S + A */
+#define R_IA_64_LTV64MSB        0x76    /* word64 MSB   S + A */
+#define R_IA_64_LTV64LSB        0x77    /* word64 LSB   S + A */
+#define R_IA_64_PCREL21BI       0x79    /* immediate21 form1 S + A - P */
+#define R_IA_64_PCREL22         0x7a    /* immediate22  S + A - P */
+#define R_IA_64_PCREL64I        0x7b    /* immediate64  S + A - P */
+#define R_IA_64_IPLTMSB         0x80    /* function descriptor MSB special */
+#define R_IA_64_IPLTLSB         0x81    /* function descriptor LSB speciaal */
+#define R_IA_64_SUB             0x85    /* immediate64  A - S */
+#define R_IA_64_LTOFF22X        0x86    /* immediate22  special */
+#define R_IA_64_LDXMOV          0x87    /* immediate22  special */
+#define R_IA_64_TPREL14         0x91    /* imm14        @tprel(S + A) */
+#define R_IA_64_TPREL22         0x92    /* imm22        @tprel(S + A) */
+#define R_IA_64_TPREL64I        0x93    /* imm64        @tprel(S + A) */
+#define R_IA_64_TPREL64MSB      0x96    /* word64 MSB   @tprel(S + A) */
+#define R_IA_64_TPREL64LSB      0x97    /* word64 LSB   @tprel(S + A) */
+#define R_IA_64_LTOFF_TPREL22   0x9a    /* imm22        @ltoff(@tprel(S+A)) */
+#define R_IA_64_DTPMOD64MSB     0xa6    /* word64 MSB   @dtpmod(S + A) */
+#define R_IA_64_DTPMOD64LSB     0xa7    /* word64 LSB   @dtpmod(S + A) */
+#define R_IA_64_LTOFF_DTPMOD22  0xaa    /* imm22        @ltoff(@dtpmod(S+A)) */
+#define R_IA_64_DTPREL14        0xb1    /* imm14        @dtprel(S + A) */
+#define R_IA_64_DTPREL22        0xb2    /* imm22        @dtprel(S + A) */
+#define R_IA_64_DTPREL64I       0xb3    /* imm64        @dtprel(S + A) */
+#define R_IA_64_DTPREL32MSB     0xb4    /* word32 MSB   @dtprel(S + A) */
+#define R_IA_64_DTPREL32LSB     0xb5    /* word32 LSB   @dtprel(S + A) */
+#define R_IA_64_DTPREL64MSB     0xb6    /* word64 MSB   @dtprel(S + A) */
+#define R_IA_64_DTPREL64LSB     0xb7    /* word64 LSB   @dtprel(S + A) */
+#define R_IA_64_LTOFF_DTPREL22  0xba    /* imm22        @ltoff(@dtprel(S+A)) */
+
+#define R_PPC_NONE              0       /* No relocation. */
+#define R_PPC_ADDR32            1
+#define R_PPC_ADDR24            2
+#define R_PPC_ADDR16            3
+#define R_PPC_ADDR16_LO         4
+#define R_PPC_ADDR16_HI         5
+#define R_PPC_ADDR16_HA         6
+#define R_PPC_ADDR14            7
+#define R_PPC_ADDR14_BRTAKEN    8
+#define R_PPC_ADDR14_BRNTAKEN   9
+#define R_PPC_REL24             10
+#define R_PPC_REL14             11
+#define R_PPC_REL14_BRTAKEN     12
+#define R_PPC_REL14_BRNTAKEN    13
+#define R_PPC_GOT16             14
+#define R_PPC_GOT16_LO          15
+#define R_PPC_GOT16_HI          16
+#define R_PPC_GOT16_HA          17
+#define R_PPC_PLTREL24          18
+#define R_PPC_COPY              19
+#define R_PPC_GLOB_DAT          20
+#define R_PPC_JMP_SLOT          21
+#define R_PPC_RELATIVE          22
+#define R_PPC_LOCAL24PC         23
+#define R_PPC_UADDR32           24
+#define R_PPC_UADDR16           25
+#define R_PPC_REL32             26
+#define R_PPC_PLT32             27
+#define R_PPC_PLTREL32          28
+#define R_PPC_PLT16_LO          29
+#define R_PPC_PLT16_HI          30
+#define R_PPC_PLT16_HA          31
+#define R_PPC_SDAREL16          32
+#define R_PPC_SECTOFF           33
+#define R_PPC_SECTOFF_LO        34
+#define R_PPC_SECTOFF_HI        35
+#define R_PPC_SECTOFF_HA        36
+
+/*
+ * TLS relocations
+ */
+#define R_PPC_TLS               67
+#define R_PPC_DTPMOD32          68
+#define R_PPC_TPREL16           69
+#define R_PPC_TPREL16_LO        70
+#define R_PPC_TPREL16_HI        71
+#define R_PPC_TPREL16_HA        72
+#define R_PPC_TPREL32           73
+#define R_PPC_DTPREL16          74
+#define R_PPC_DTPREL16_LO       75
+#define R_PPC_DTPREL16_HI       76
+#define R_PPC_DTPREL16_HA       77
+#define R_PPC_DTPREL32          78
+#define R_PPC_GOT_TLSGD16       79
+#define R_PPC_GOT_TLSGD16_LO    80
+#define R_PPC_GOT_TLSGD16_HI    81
+#define R_PPC_GOT_TLSGD16_HA    82
+#define R_PPC_GOT_TLSLD16       83
+#define R_PPC_GOT_TLSLD16_LO    84
+#define R_PPC_GOT_TLSLD16_HI    85
+#define R_PPC_GOT_TLSLD16_HA    86
+#define R_PPC_GOT_TPREL16       87
+#define R_PPC_GOT_TPREL16_LO    88
+#define R_PPC_GOT_TPREL16_HI    89
+#define R_PPC_GOT_TPREL16_HA    90
+
+/*
+ * The remaining relocs are from the Embedded ELF ABI, and are not in the
+ *  SVR4 ELF ABI.
+ */
+
+#define R_PPC_EMB_NADDR32       101
+#define R_PPC_EMB_NADDR16       102
+#define R_PPC_EMB_NADDR16_LO    103
+#define R_PPC_EMB_NADDR16_HI    104
+#define R_PPC_EMB_NADDR16_HA    105
+#define R_PPC_EMB_SDAI16        106
+#define R_PPC_EMB_SDA2I16       107
+#define R_PPC_EMB_SDA2REL       108
+#define R_PPC_EMB_SDA21         109
+#define R_PPC_EMB_MRKREF        110
+#define R_PPC_EMB_RELSEC16      111
+#define R_PPC_EMB_RELST_LO      112
+#define R_PPC_EMB_RELST_HI      113
+#define R_PPC_EMB_RELST_HA      114
+#define R_PPC_EMB_BIT_FLD       115
+#define R_PPC_EMB_RELSDA        116
+
+#define R_SPARC_NONE            0
+#define R_SPARC_8               1
+#define R_SPARC_16              2
+#define R_SPARC_32              3
+#define R_SPARC_DISP8           4
+#define R_SPARC_DISP16          5
+#define R_SPARC_DISP32          6
+#define R_SPARC_WDISP30         7
+#define R_SPARC_WDISP22         8
+#define R_SPARC_HI22            9
+#define R_SPARC_22              10
+#define R_SPARC_13              11
+#define R_SPARC_LO10            12
+#define R_SPARC_GOT10           13
+#define R_SPARC_GOT13           14
+#define R_SPARC_GOT22           15
+#define R_SPARC_PC10            16
+#define R_SPARC_PC22            17
+#define R_SPARC_WPLT30          18
+#define R_SPARC_COPY            19
+#define R_SPARC_GLOB_DAT        20
+#define R_SPARC_JMP_SLOT        21
+#define R_SPARC_RELATIVE        22
+#define R_SPARC_UA32            23
+#define R_SPARC_PLT32           24
+#define R_SPARC_HIPLT22         25
+#define R_SPARC_LOPLT10         26
+#define R_SPARC_PCPLT32         27
+#define R_SPARC_PCPLT22         28
+#define R_SPARC_PCPLT10         29
+#define R_SPARC_10              30
+#define R_SPARC_11              31
+#define R_SPARC_64              32
+#define R_SPARC_OLO10           33
+#define R_SPARC_HH22            34
+#define R_SPARC_HM10            35
+#define R_SPARC_LM22            36
+#define R_SPARC_PC_HH22         37
+#define R_SPARC_PC_HM10         38
+#define R_SPARC_PC_LM22         39
+#define R_SPARC_WDISP16         40
+#define R_SPARC_WDISP19         41
+#define R_SPARC_GLOB_JMP        42
+#define R_SPARC_7               43
+#define R_SPARC_5               44
+#define R_SPARC_6               45
+#define R_SPARC_DISP64          46
+#define R_SPARC_PLT64           47
+#define R_SPARC_HIX22           48
+#define R_SPARC_LOX10           49
+#define R_SPARC_H44             50
+#define R_SPARC_M44             51
+#define R_SPARC_L44             52
+#define R_SPARC_REGISTER        53
+#define R_SPARC_UA64            54
+#define R_SPARC_UA16            55
+#define R_SPARC_TLS_GD_HI22     56
+#define R_SPARC_TLS_GD_LO10     57
+#define R_SPARC_TLS_GD_ADD      58
+#define R_SPARC_TLS_GD_CALL     59
+#define R_SPARC_TLS_LDM_HI22    60
+#define R_SPARC_TLS_LDM_LO10    61
+#define R_SPARC_TLS_LDM_ADD     62
+#define R_SPARC_TLS_LDM_CALL    63
+#define R_SPARC_TLS_LDO_HIX22   64
+#define R_SPARC_TLS_LDO_LOX10   65
+#define R_SPARC_TLS_LDO_ADD     66
+#define R_SPARC_TLS_IE_HI22     67
+#define R_SPARC_TLS_IE_LO10     68
+#define R_SPARC_TLS_IE_LD       69
+#define R_SPARC_TLS_IE_LDX      70
+#define R_SPARC_TLS_IE_ADD      71
+#define R_SPARC_TLS_LE_HIX22    72
+#define R_SPARC_TLS_LE_LOX10    73
+#define R_SPARC_TLS_DTPMOD32    74
+#define R_SPARC_TLS_DTPMOD64    75
+#define R_SPARC_TLS_DTPOFF32    76
+#define R_SPARC_TLS_DTPOFF64    77
+#define R_SPARC_TLS_TPOFF32     78
+#define R_SPARC_TLS_TPOFF64     79
+
+#define R_X86_64_NONE           0       /* No relocation. */
+#define R_X86_64_64             1       /* Add 64 bit symbol value. */
+#define R_X86_64_PC32           2       /* PC-relative 32 bit signed sym value. */
+#define R_X86_64_GOT32          3       /* PC-relative 32 bit GOT offset. */
+#define R_X86_64_PLT32          4       /* PC-relative 32 bit PLT offset. */
+#define R_X86_64_COPY           5       /* Copy data from shared object. */
+#define R_X86_64_GLOB_DAT       6       /* Set GOT entry to data address. */
+#define R_X86_64_JMP_SLOT       7       /* Set GOT entry to code address. */
+#define R_X86_64_RELATIVE       8       /* Add load address of shared object. */
+#define R_X86_64_GOTPCREL       9       /* Add 32 bit signed pcrel offset to GOT. */
+#define R_X86_64_32             10      /* Add 32 bit zero extended symbol value */
+#define R_X86_64_32S            11      /* Add 32 bit sign extended symbol value */
+#define R_X86_64_16             12      /* Add 16 bit zero extended symbol value */
+#define R_X86_64_PC16           13      /* Add 16 bit signed extended pc relative symbol value */
+#define R_X86_64_8              14      /* Add 8 bit zero extended symbol value */
+#define R_X86_64_PC8            15      /* Add 8 bit signed extended pc relative symbol value */
+#define R_X86_64_DTPMOD64       16      /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64       17      /* Offset in TLS block */
+#define R_X86_64_TPOFF64        18      /* Offset in static TLS block */
+#define R_X86_64_TLSGD          19      /* PC relative offset to GD GOT entry */
+#define R_X86_64_TLSLD          20      /* PC relative offset to LD GOT entry */
+#define R_X86_64_DTPOFF32       21      /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF       22      /* PC relative offset to IE GOT entry */
+#define R_X86_64_TPOFF32        23      /* Offset in static TLS block */
+
+
+#endif /* !_SYS_ELF_COMMON_H_ */
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf
index 5ceba5fa13c3..16131bf7895a 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf
+++ b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf
@@ -128,7 +128,7 @@  [FV.FvMain]
   INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
 
   # Versatile Express FileSystem
-  INF ArmPlatformPkg/FileSystem/BootMonFs/BootMonFs.inf
+  INF Platform/ARM/Drivers/BootMonFs/BootMonFs.inf
 
   #
   # USB support
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
index 5a3b787afb89..c6b88c741627 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
+++ b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
@@ -119,7 +119,7 @@  [LibraryClasses.common]
 
   # RunAxf support via Dynamic Shell Command protocol
   # It uses the Shell libraries.
-  ArmShellCmdRunAxfLib|ArmPlatformPkg/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf
+  ArmShellCmdRunAxfLib|Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf
   ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
   FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
   SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
@@ -370,7 +370,7 @@  [PcdsFixedAtBuild.common]
   #
 
   # List of Device Paths that support BootMonFs
-  gArmPlatformTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59);VenHw(1F15DA3C-37FF-4070-B471-BB4AF12A724A)"
+  gArmBootMonFsTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59);VenHw(1F15DA3C-37FF-4070-B471-BB4AF12A724A)"
 
   #
   # ARM OS Loader
@@ -434,7 +434,7 @@  [Components.common]
   }
 
   # Versatile Express FileSystem
-  ArmPlatformPkg/FileSystem/BootMonFs/BootMonFs.inf
+  Platform/ARM/Drivers/BootMonFs/BootMonFs.inf
 
   #
   # Networking stack
diff --git a/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf
index 1ecdbb0b231e..8bf289f8da83 100644
--- a/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf
+++ b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf
@@ -26,6 +26,7 @@  [Sources.common]
 [Packages]
   ArmPlatformPkg/ArmPlatformPkg.dec
   MdePkg/MdePkg.dec
+  Platform/ARM/ARM.dec
 
 [LibraryClasses]
   ArmShellCmdRunAxfLib