]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPkg/BdsLib: Upgrade the library to use natively the Device Path
authoroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 11 Jun 2011 11:56:30 +0000 (11:56 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 11 Jun 2011 11:56:30 +0000 (11:56 +0000)
The previous version was using the string representation of the Device Path.
This new version takes as paramater the binary representation of the Device Path

It also tries to detect which kind of device support it refers by using the remaining
part of the Device Path after it has been loaded by gBS->ConnectController()

Lots of bug have been fixed as well in this new version.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11799 6f19259b-4bc3-4df7-8a09-765794883524

13 files changed:
ArmPkg/ArmPkg.dec
ArmPkg/Include/Library/BdsLib.h [new file with mode: 0644]
ArmPkg/Include/Library/BdsUnixLib.h
ArmPkg/Library/BdsLib/BdsAppLoader.c
ArmPkg/Library/BdsLib/BdsFilePath.c
ArmPkg/Library/BdsLib/BdsFilePathFs.c [deleted file]
ArmPkg/Library/BdsLib/BdsFilePathFv.c [deleted file]
ArmPkg/Library/BdsLib/BdsFilePathMem.c [deleted file]
ArmPkg/Library/BdsLib/BdsHelper.c
ArmPkg/Library/BdsLib/BdsInternal.h
ArmPkg/Library/BdsLib/BdsLib.inf
ArmPkg/Library/BdsLib/BdsLinuxLoader.c
ArmPkg/Library/BdsLib/BdsLinuxLoader.h

index 37fc7f2931880a899b7da07455d015e843fd631a..0357810c56ad26ed0d8b71340298ea766e340256 100644 (file)
   # BdsLib\r
   #\r
   gArmTokenSpaceGuid.PcdArmMachineType|0|UINT32|0x0000001E\r
-  gArmTokenSpaceGuid.PcdLinuxKernelDP|L""|VOID*|0x0000001F\r
-  gArmTokenSpaceGuid.PcdLinuxAtag|""|VOID*|0x00000020\r
-  gArmTokenSpaceGuid.PcdFdtDP|L""|VOID*|0x00000021\r
+  # The compressed Linux kernel is expected to be under 128MB from the beginning of the System Memory\r
+  gArmTokenSpaceGuid.PcdArmLinuxKernelMaxOffset|0x08000000|UINT32|0x0000001F\r
+  # The Linux ATAGs are expected to be under 0x4000 (16KB) from the beginning of the System Memory\r
+  gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset|0x4000|UINT32|0x00000020\r
 \r
diff --git a/ArmPkg/Include/Library/BdsLib.h b/ArmPkg/Include/Library/BdsLib.h
new file mode 100644 (file)
index 0000000..a6ae2f1
--- /dev/null
@@ -0,0 +1,66 @@
+/** @file\r
+*\r
+*  Copyright (c) 2011, ARM Limited. All rights reserved.\r
+*  \r
+*  This program and the accompanying materials                          \r
+*  are licensed and made available under the terms and conditions of the BSD License         \r
+*  which accompanies this distribution.  The full text of the license may be found at        \r
+*  http://opensource.org/licenses/bsd-license.php                                            \r
+*\r
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+*\r
+**/\r
+\r
+#ifndef __BDS_ENTRY_H__\r
+#define __BDS_ENTRY_H__\r
+\r
+/**\r
+  Connect all DXE drivers\r
+\r
+  @retval EFI_SUCCESS           All drivers have been connected\r
+  @retval EFI_NOT_FOUND         No handles match the search.\r
+  @retval EFI_OUT_OF_RESOURCES  There is not resource pool memory to store the matching results.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsConnectAllDrivers (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Start a Linux kernel from a Device Path\r
+\r
+  @param  LinuxKernel           Device Path to the Linux Kernel\r
+  @param  Parameters            Linux kernel agruments\r
+  @param  Fdt                   Device Path to the Flat Device Tree\r
+\r
+  @retval EFI_SUCCESS           All drivers have been connected\r
+  @retval EFI_NOT_FOUND         The Linux kernel Device Path has not been found\r
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource memory to store the matching results.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsBootLinux (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
+  IN  CONST CHAR8*  Arguments,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath\r
+  );\r
+\r
+/**\r
+  Start an EFI Application from any Firmware Volume\r
+\r
+  @param  EfiApp                EFI Application Name\r
+\r
+  @retval EFI_SUCCESS           All drivers have been connected\r
+  @retval EFI_NOT_FOUND         The Linux kernel Device Path has not been found\r
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource memory to store the matching results.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsLoadApplication (\r
+  IN EFI_HANDLE                  ParentImageHandle,\r
+  IN CHAR16*                     EfiApp\r
+  );\r
+\r
+#endif\r
index 969f95112445a028b77d46308b9c38b544c80693..d5f5ffa202bff23139f68cc2c52a1c2532cd79e3 100644 (file)
 *\r
 **/\r
 \r
-#ifndef __BDS_ENTRY_H__\r
-#define __BDS_ENTRY_H__\r
+#ifndef _BDS_UNIX_LIB_H_\r
+#define _BDS_UNIX_LIB_H_\r
 \r
-EFI_STATUS\r
-BdsConnectAllDrivers ( VOID );\r
+/**\r
+  Start a Linux kernel from a Device Path\r
 \r
-EFI_STATUS\r
-BdsBootLinux (\r
-    IN  CONST CHAR16* LinuxKernel,\r
-    IN  CONST CHAR8*  ATag,\r
-    IN  CONST CHAR16* Fdt\r
-);\r
+  @param  LinuxKernel           Device Path to the Linux Kernel\r
+  @param  Parameters            Linux kernel agruments\r
+  @param  Fdt                   Device Path to the Flat Device Tree\r
 \r
-EFI_STATUS\r
-BdsLoadApplication (\r
-    IN  CHAR16* EfiApp\r
-);\r
+  @retval EFI_SUCCESS           All drivers have been connected\r
+  @retval EFI_NOT_FOUND         The Linux kernel Device Path has not been found\r
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource memory to store the matching results.\r
 \r
+**/\r
 EFI_STATUS\r
-BdsLoadApplicationFromPath (\r
-    IN  CHAR16* EfiAppPath\r
-);\r
+BdsBootLinux (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
+  IN  CONST CHAR8*              Arguments,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath\r
+  );\r
 \r
 #endif\r
index 16b45ceb4cb2bcfd4f0f8fd7858d3152f12a37e3..d14e3c5dcc0fd26f2341e9d6834eda88faf670c4 100644 (file)
-/** @file\r
-*\r
-*  Copyright (c) 2011, ARM Limited. All rights reserved.\r
-*  \r
-*  This program and the accompanying materials                          \r
-*  are licensed and made available under the terms and conditions of the BSD License         \r
-*  which accompanies this distribution.  The full text of the license may be found at        \r
-*  http://opensource.org/licenses/bsd-license.php                                            \r
-*\r
-*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
-*\r
-**/\r
-\r
-#include "BdsInternal.h"\r
-\r
-EFI_STATUS\r
-BdsLoadPeCoff (\r
- IN  BDS_FILE     *EfiAppFile\r
- )\r
-{\r
-    EFI_STATUS                          Status;\r
-    EFI_HANDLE                          ImageHandle;\r
-    MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   NewNode;\r
-    EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
-\r
-    // Only support loading from FV right now\r
-    ASSERT(EfiAppFile->Type == BDS_FILETYPE_FV);\r
-\r
-    // Generate the Device Path for the file\r
-    DevicePath = DuplicateDevicePath(EfiAppFile->DevicePath);\r
-    EfiInitializeFwVolDevicepathNode (&NewNode, &(EfiAppFile->File.Fv.Guid));\r
-    DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&NewNode);\r
-\r
-    Status = gBS->LoadImage (TRUE, gImageHandle, DevicePath, NULL, 0, &ImageHandle);\r
-    if (!EFI_ERROR (Status)) {\r
-        //\r
-        // Before calling the image, enable the Watchdog Timer for\r
-        // the 5 Minute period\r
-        //\r
-        gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
-        Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
-        //\r
-        // Clear the Watchdog Timer after the image returns\r
-        //\r
-        gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
-    }\r
-  \r
-    return Status;\r
-}\r
-\r
-EFI_STATUS BdsLoadApplicationFromPath(\r
-    IN  CHAR16* EfiAppPath\r
-) {\r
-    EFI_STATUS Status;\r
-    BDS_FILE   EfiAppFile;\r
-\r
-    // Need to connect every drivers to ensure no dependencies are missing for the application\r
-    Status = BdsConnectAllDrivers();\r
-    if (EFI_ERROR(Status)) {\r
-        DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));\r
-        return Status;\r
-    }\r
-\r
-    // Locate the application from a device path\r
-    Status = BdsLoadFilePath(EfiAppPath, &EfiAppFile);\r
-    if (EFI_ERROR(Status)) {\r
-        DEBUG ((EFI_D_ERROR, "ERROR: Do not find EFI application %s\n",EfiAppPath));\r
-        return Status;\r
-    }\r
-\r
-    // Start the application\r
-    Status = BdsLoadPeCoff(&EfiAppFile);\r
-\r
-    return Status;\r
-}\r
-\r
-EFI_STATUS BdsLoadApplication(\r
-    IN  CHAR16* EfiApp\r
-) {\r
-    EFI_STATUS                      Status;\r
-    UINTN                           NoHandles, HandleIndex;\r
-    EFI_HANDLE                      *Handles;\r
-    BDS_FILE                        EfiAppFile;\r
-\r
-    // Need to connect every drivers to ensure no dependencies are missing for the application\r
-    Status = BdsConnectAllDrivers();\r
-    if (EFI_ERROR(Status)) {\r
-        DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));\r
-        return Status;\r
-    }\r
-\r
-    // Search the application in any Firmware Volume\r
-    Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Handles);\r
-    if (EFI_ERROR (Status) || (NoHandles == 0)) {\r
-        DEBUG ((EFI_D_ERROR, "FAIL to find Firmware Volume\n"));\r
-        return Status;\r
-    }\r
-\r
-    // Search in all Firmware Volume for the EFI Application\r
-    for (HandleIndex = 0; HandleIndex < NoHandles; HandleIndex++) {\r
-        Status = BdsLoadFileFromFirmwareVolume(Handles[HandleIndex],EfiApp,EFI_FV_FILETYPE_APPLICATION,&EfiAppFile);\r
-        if (!EFI_ERROR (Status)) {\r
-            // Start the application\r
-            Status = BdsLoadPeCoff(&EfiAppFile);\r
-            return Status;\r
-        }\r
-    }\r
-\r
-    return Status;\r
-}\r
+/** @file
+*
+*  Copyright (c) 2011, 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 "BdsInternal.h"
+
+//#include <Library/PeCoffLib.h>
+#include <Library/DxeServicesLib.h>
+
+//TODO: RemoveMe
+#include <Protocol/DevicePathToText.h>
+
+/**
+  Retrieves the magic value from the PE/COFF header.
+
+  @param  Hdr             The buffer in which to return the PE32, PE32+, or TE header.
+
+  @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
+  @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
+
+**/
+UINT16
+PeCoffLoaderGetPeHeaderMagicValue (
+  IN  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr
+  )
+{
+  //
+  // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
+  //       in the PE/COFF Header.  If the MachineType is Itanium(IA64) and the
+  //       Magic value in the OptionalHeader is  EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+  //       then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+  //
+  if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+    return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+  }
+  //
+  // Return the magic value from the PC/COFF Optional Header
+  //
+  return Hdr.Pe32->OptionalHeader.Magic;
+}
+
+STATIC
+BOOLEAN
+IsLoadableImage (
+  VOID*   Image
+  )
+{
+  UINT16                       Magic;
+  EFI_IMAGE_DOS_HEADER        *DosHeader;
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Header;
+
+  if (Image == NULL) {
+    return FALSE;
+  }
+
+  DosHeader = (EFI_IMAGE_DOS_HEADER*)Image;
+  if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+    Header.Pe32 = (EFI_IMAGE_NT_HEADERS32*)((UINT8*)Image + DosHeader->e_lfanew);
+  } else {
+    Header.Pe32 = (EFI_IMAGE_NT_HEADERS32*)(Image);
+  }
+
+  if (Header.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+    // It is a TE Image
+    return TRUE;
+  } else if (Header.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {
+    Magic = PeCoffLoaderGetPeHeaderMagicValue (Header);
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+      // It is a PE32 Image
+      return TRUE;
+    } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+      // It is a PE32+ Image
+      return TRUE;
+    } else {
+      DEBUG ((EFI_D_ERROR,"BdsLoadBinaryFromPath(): Fail unrecognized PE Image\n"));
+    }
+  } else {
+    DEBUG ((EFI_D_ERROR,"BdsLoadBinaryFromPath(): Fail unrecognize image\n"));
+  }
+
+  return FALSE;
+}
+
+STATIC
+EFI_STATUS
+BdsLoadFileFromFirmwareVolume (
+  IN  EFI_HANDLE      FvHandle,
+  IN  CHAR16    *FilePath,
+  IN  EFI_FV_FILETYPE FileTypeFilter,
+  OUT EFI_DEVICE_PATH     **EfiAppDevicePath
+  )
+{
+  EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+  VOID                          *Key;
+  EFI_STATUS                    Status, FileStatus;
+  EFI_GUID                      NameGuid;
+  EFI_FV_FILETYPE               FileType;
+  EFI_FV_FILE_ATTRIBUTES        Attributes;
+  UINTN                         Size;
+  UINTN                         UiStringLen;
+  CHAR16                        *UiSection;
+  UINT32                        Authentication;
+  EFI_DEVICE_PATH               *FvDevicePath;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH    FileDevicePath;
+
+  Status = gBS->HandleProtocol (FvHandle,&gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FvProtocol);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  // Length of FilePath
+  UiStringLen = StrLen (FilePath);
+
+  // Allocate Key
+  Key = AllocatePool (FvProtocol->KeySize);
+  ASSERT (Key != NULL);
+  ZeroMem (Key, FvProtocol->KeySize);
+
+  do {
+    // Search in all files
+    FileType = FileTypeFilter;
+
+    Status = FvProtocol->GetNextFile (FvProtocol, Key, &FileType, &NameGuid, &Attributes, &Size);
+    if (!EFI_ERROR (Status)) {
+      UiSection = NULL;
+      FileStatus = FvProtocol->ReadSection (
+                    FvProtocol,
+                    &NameGuid,
+                    EFI_SECTION_USER_INTERFACE,
+                    0,
+                    (VOID **)&UiSection,
+                    &Size,
+                    &Authentication
+                    );
+      if (!EFI_ERROR (FileStatus)) {
+        if (StrnCmp (FilePath, UiSection, UiStringLen) == 0) {
+          //
+          // We found a UiString match.
+          //
+          Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
+
+          // Generate the Device Path for the file
+          //DevicePath = DuplicateDevicePath(FvDevicePath);
+          EfiInitializeFwVolDevicepathNode (&FileDevicePath, &NameGuid);
+          *EfiAppDevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath);
+
+          FreePool (Key);
+          FreePool (UiSection);
+          return FileStatus;
+        }
+        FreePool (UiSection);
+      }
+    }
+  } while (!EFI_ERROR (Status));
+
+  FreePool(Key);
+  return Status;
+}
+
+/**
+  Start an EFI Application from any Firmware Volume
+
+  @param  EfiApp                EFI Application Name
+
+  @retval EFI_SUCCESS           All drivers have been connected
+  @retval EFI_NOT_FOUND         The Linux kernel Device Path has not been found
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource memory to store the matching results.
+
+**/
+EFI_STATUS
+BdsLoadApplication (
+  IN EFI_HANDLE                  ParentImageHandle,
+  IN CHAR16*                     EfiApp
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           NoHandles, HandleIndex;
+  EFI_HANDLE                      *Handles;
+  EFI_DEVICE_PATH                 *FvDevicePath;
+  EFI_DEVICE_PATH                 *EfiAppDevicePath;
+
+  // Need to connect every drivers to ensure no dependencies are missing for the application
+  Status = BdsConnectAllDrivers();
+  if (EFI_ERROR(Status)) {
+    DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));
+    return Status;
+  }
+
+  // Search the application in any Firmware Volume
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Handles);
+  if (EFI_ERROR (Status) || (NoHandles == 0)) {
+    DEBUG ((EFI_D_ERROR, "FAIL to find Firmware Volume\n"));
+    return Status;
+  }
+
+  // Search in all Firmware Volume for the EFI Application
+  for (HandleIndex = 0; HandleIndex < NoHandles; HandleIndex++) {
+    Status = BdsLoadFileFromFirmwareVolume (Handles[HandleIndex], EfiApp, EFI_FV_FILETYPE_APPLICATION, &EfiAppDevicePath);
+    if (!EFI_ERROR (Status)) {
+      // Start the application
+      Status = BdsStartEfiApplication (ParentImageHandle, EfiAppDevicePath);
+      return Status;
+    }
+  }
+
+  return Status;
+}
index b1460b9c9db1d44e85afd6d378043e19c9d0b49a..f7a06e5a89f241195e8e305ea0817b8feb5db431 100644 (file)
 
 #include "BdsInternal.h"
 
-// Count the number of DevicePath Node
-static UINTN NumberNodeFromDevicePath(
-    IN  EFI_DEVICE_PATH_PROTOCOL* DevicePath
-) {
-    UINTN NumberDevicePathNode = 0;
-
-    while (!IsDevicePathEnd (DevicePath)) {
-        NumberDevicePathNode++;
-        DevicePath = NextDevicePathNode(DevicePath);
+#include <Protocol/UsbIo.h>
+#include <Protocol/DiskIo.h>
+
+#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))
+
+// Extract the FilePath from the Device Path
+CHAR16*
+BdsExtractFilePathFromDevicePath (
+  IN  CONST CHAR16    *StrDevicePath,
+  IN  UINTN           NumberDevicePathNode
+  )
+{
+  UINTN       Node;
+  CHAR16      *Str;
+
+  Str = (CHAR16*)StrDevicePath;
+  Node = 0;
+  while ((Str != NULL) && (*Str != L'\0') && (Node < NumberDevicePathNode)) {
+    if ((*Str == L'/') || (*Str == L'\\')) {
+        Node++;
     }
-    return NumberDevicePathNode;
+    Str++;
+  }
+
+  if (*Str == L'\0') {
+    return NULL;
+  } else {
+    return Str;
+  }
 }
 
-// Extract the FilePath from the Device Path
-CHAR16* BdsExtractFilePathFromDevicePath(
-    IN  CONST CHAR16    *StrDevicePath,
-    IN  UINTN           NumberDevicePathNode
-) {
-    UINTN       Node;
-    CHAR16      *Str;
-
-    Str = (CHAR16*)StrDevicePath;
-    Node = 0;
-    while ((Str != NULL) && (*Str != L'\0') && (Node < NumberDevicePathNode)) {
-        if ((*Str == L'/') || (*Str == L'\\')) {
-            Node++;
+BOOLEAN
+BdsIsRemovableUsb (
+  IN  EFI_DEVICE_PATH*  DevicePath
+  )
+{
+  return ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
+          ((DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP) ||
+           (DevicePathSubType (DevicePath) == MSG_USB_WWID_DP)));
+}
+
+EFI_STATUS
+BdsGetDeviceUsb (
+  IN  EFI_DEVICE_PATH*  RemovableDevicePath,
+  OUT EFI_HANDLE*       DeviceHandle,
+  OUT EFI_DEVICE_PATH** NewDevicePath
+  )
+{
+  EFI_STATUS                    Status;
+  UINTN                         Index;
+  UINTN                         UsbIoHandleCount;
+  EFI_HANDLE                    *UsbIoBuffer;
+  EFI_DEVICE_PATH*              UsbIoDevicePath;
+  EFI_DEVICE_PATH*              TmpDevicePath;
+  USB_WWID_DEVICE_PATH*         WwidDevicePath1;
+  USB_WWID_DEVICE_PATH*         WwidDevicePath2;
+  USB_CLASS_DEVICE_PATH*        UsbClassDevicePath1;
+  USB_CLASS_DEVICE_PATH*        UsbClassDevicePath2;
+
+  // Get all the UsbIo handles
+  UsbIoHandleCount = 0;
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiUsbIoProtocolGuid, NULL, &UsbIoHandleCount, &UsbIoBuffer);
+  if (EFI_ERROR(Status) || (UsbIoHandleCount == 0)) {
+    return Status;
+  }
+
+  // Check if one of the handles matches the USB description
+  for (Index = 0; Index < UsbIoHandleCount; Index++) {
+    Status = gBS->HandleProtocol (UsbIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &UsbIoDevicePath);
+    if (!EFI_ERROR(Status)) {
+      TmpDevicePath = UsbIoDevicePath;
+      while (!IsDevicePathEnd (TmpDevicePath)) {
+        // Check if the Device Path node is a USB Removable device Path node
+        if (BdsIsRemovableUsb (TmpDevicePath)) {
+          if (TmpDevicePath->SubType == MSG_USB_WWID_DP) {
+            WwidDevicePath1 = (USB_WWID_DEVICE_PATH*)RemovableDevicePath;
+            WwidDevicePath2 = (USB_WWID_DEVICE_PATH*)TmpDevicePath;
+            if ((WwidDevicePath1->VendorId == WwidDevicePath2->VendorId) &&
+                (WwidDevicePath1->ProductId == WwidDevicePath2->ProductId) &&
+                (CompareMem (WwidDevicePath1+1, WwidDevicePath2+1, DevicePathNodeLength(WwidDevicePath1)-sizeof(USB_WWID_DEVICE_PATH)) == 0))
+            {
+              *DeviceHandle = UsbIoBuffer[Index];
+              // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path
+              *NewDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePathNode(RemovableDevicePath));
+              return EFI_SUCCESS;
+            }
+          } else {
+            UsbClassDevicePath1 = (USB_CLASS_DEVICE_PATH*)RemovableDevicePath;
+            UsbClassDevicePath2 = (USB_CLASS_DEVICE_PATH*)TmpDevicePath;
+            if ((UsbClassDevicePath1->VendorId != 0xFFFF) && (UsbClassDevicePath1->VendorId == UsbClassDevicePath2->VendorId) &&
+                (UsbClassDevicePath1->ProductId != 0xFFFF) && (UsbClassDevicePath1->ProductId == UsbClassDevicePath2->ProductId) &&
+                (UsbClassDevicePath1->DeviceClass != 0xFF) && (UsbClassDevicePath1->DeviceClass == UsbClassDevicePath2->DeviceClass) &&
+                (UsbClassDevicePath1->DeviceSubClass != 0xFF) && (UsbClassDevicePath1->DeviceSubClass == UsbClassDevicePath2->DeviceSubClass) &&
+                (UsbClassDevicePath1->DeviceProtocol != 0xFF) && (UsbClassDevicePath1->DeviceProtocol == UsbClassDevicePath2->DeviceProtocol))
+            {
+              *DeviceHandle = UsbIoBuffer[Index];
+              // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path
+              *NewDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePathNode(RemovableDevicePath));
+              return EFI_SUCCESS;
+            }
+          }
         }
-        Str++;
-    }
+        TmpDevicePath = NextDevicePathNode (TmpDevicePath);
+      }
 
-    if (*Str == L'\0') {
-        return NULL;
-    } else {
-        return Str;
     }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+BOOLEAN
+BdsIsRemovableHd (
+  IN  EFI_DEVICE_PATH*  DevicePath
+  )
+{
+  return IS_DEVICE_PATH_NODE(DevicePath, MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP);
 }
 
 EFI_STATUS
-BdsLoadDevicePath(
-    IN  EFI_DEVICE_PATH_PROTOCOL* DevicePath,
-    OUT EFI_HANDLE                *Handle
-) {
-    EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath;
-    EFI_STATUS                  Status;
-
-    if ((DevicePath == NULL) || (Handle == NULL)) {
-        return EFI_INVALID_PARAMETER;
-    }
+BdsGetDeviceHd (
+  IN  EFI_DEVICE_PATH*  RemovableDevicePath,
+  OUT EFI_HANDLE*       DeviceHandle,
+  OUT EFI_DEVICE_PATH** NewDevicePath
+  )
+{
+  EFI_STATUS                    Status;
+  UINTN                         Index;
+  UINTN                         PartitionHandleCount;
+  EFI_HANDLE                    *PartitionBuffer;
+  EFI_DEVICE_PATH*              PartitionDevicePath;
+  EFI_DEVICE_PATH*              TmpDevicePath;
+  HARDDRIVE_DEVICE_PATH*        HardDriveDevicePath1;
+  HARDDRIVE_DEVICE_PATH*        HardDriveDevicePath2;
 
-    do {
-        RemainingDevicePath = DevicePath;
-        // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns
-        // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified
-        // to point to the remaining part of the device path
-        Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle);
-        if (!EFI_ERROR (Status)) {
-            // Recursive = FALSE: We do not want to start all the device tree
-            Status = gBS->ConnectController (*Handle, NULL, RemainingDevicePath, FALSE);
-        }
+  // Get all the DiskIo handles
+  PartitionHandleCount = 0;
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDiskIoProtocolGuid, NULL, &PartitionHandleCount, &PartitionBuffer);
+  if (EFI_ERROR(Status) || (PartitionHandleCount == 0)) {
+    return Status;
+  }
 
-        // We need to check if RemainingDevicePath does not point on the last node. Otherwise, calling
-        // NextDevicePathNode() will return an undetermined Device Path Node
-        if (!IsDevicePathEnd (RemainingDevicePath)) {
-            RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);
+  // Check if one of the handles matches the Hard Disk Description
+  for (Index = 0; Index < PartitionHandleCount; Index++) {
+    Status = gBS->HandleProtocol (PartitionBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &PartitionDevicePath);
+    if (!EFI_ERROR(Status)) {
+      TmpDevicePath = PartitionDevicePath;
+      while (!IsDevicePathEnd (TmpDevicePath)) {
+        // Check if the Device Path node is a HD Removable device Path node
+        if (BdsIsRemovableHd (TmpDevicePath)) {
+          HardDriveDevicePath1 = (HARDDRIVE_DEVICE_PATH*)RemovableDevicePath;
+          HardDriveDevicePath2 = (HARDDRIVE_DEVICE_PATH*)TmpDevicePath;
+          if ((HardDriveDevicePath1->SignatureType == HardDriveDevicePath2->SignatureType) &&
+              (CompareGuid ((EFI_GUID *)HardDriveDevicePath1->Signature,(EFI_GUID *)HardDriveDevicePath2->Signature) == TRUE) &&
+              (HardDriveDevicePath1->PartitionNumber == HardDriveDevicePath2->PartitionNumber))
+          {
+            *DeviceHandle = PartitionBuffer[Index];
+            // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path
+            *NewDevicePath = AppendDevicePath (PartitionDevicePath, NextDevicePathNode(RemovableDevicePath));
+            return EFI_SUCCESS;
+          }
         }
-    } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
+        TmpDevicePath = NextDevicePathNode (TmpDevicePath);
+      }
 
-    if (!EFI_ERROR (Status)) {
-        // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver
-        // Binding Protocol are connected (such as DiskIo and SimpleFileSystem)
-        RemainingDevicePath = DevicePath;
-        Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle);
-        if (!EFI_ERROR (Status)) {
-            Status = gBS->ConnectController (*Handle, NULL, RemainingDevicePath, FALSE);
-            if (EFI_ERROR (Status)) {
-                // If the last node is a Memory Map Device Path just return EFI_SUCCESS.
-                if ((RemainingDevicePath->Type == HARDWARE_DEVICE_PATH) && (RemainingDevicePath->SubType == HW_MEMMAP_DP)) {
-                    Status = EFI_SUCCESS;
-                }
-            }
-        }
-    } else if (IsDevicePathEnd (RemainingDevicePath)) {
-        // Case when the DevicePath contains a MemoryMap Device Path Node and all drivers are connected.
-        // Ensure the Device Path exists
-        RemainingDevicePath = DevicePath;
-        Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle);
     }
+  }
 
-    return Status;
+  return EFI_NOT_FOUND;
 }
 
+/*BOOLEAN
+BdsIsRemovableCdrom (
+  IN  EFI_DEVICE_PATH*  DevicePath
+  )
+{
+  return IS_DEVICE_PATH_NODE(DevicePath, MEDIA_DEVICE_PATH, MEDIA_CDROM_DP);
+}
 
 EFI_STATUS
-BdsLoadFilePath (
-    IN  CONST CHAR16        *DeviceFilePath,
-    OUT BDS_FILE            *File
-) {
-    EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
-    EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL  *EfiDevicePathFromTextProtocol;
-    EFI_STATUS Status;
-    EFI_HANDLE Handle;
-    UINTN                               NumberDevicePathNode;
-    CHAR16                              *FilePath;
-
-    //Do a sanity check on the Device file path
-    if (DeviceFilePath == NULL) {
-        return EFI_INVALID_PARAMETER;
+BdsGetDeviceCdrom (
+  IN  EFI_DEVICE_PATH*  RemovableDevicePath,
+  OUT EFI_HANDLE*       DeviceHandle,
+  OUT EFI_DEVICE_PATH** DevicePath
+  )
+{
+  ASSERT(0);
+  return EFI_UNSUPPORTED;
+}*/
+
+typedef BOOLEAN
+(*BDS_IS_REMOVABLE) (
+  IN  EFI_DEVICE_PATH*  DevicePath
+  );
+
+typedef EFI_STATUS
+(*BDS_GET_DEVICE) (
+  IN  EFI_DEVICE_PATH*  RemovableDevicePath,
+  OUT EFI_HANDLE*       DeviceHandle,
+  OUT EFI_DEVICE_PATH** DevicePath
+  );
+
+typedef struct {
+  BDS_IS_REMOVABLE    IsRemovable;
+  BDS_GET_DEVICE      GetDevice;
+} BDS_REMOVABLE_DEVICE_SUPPORT;
+
+BDS_REMOVABLE_DEVICE_SUPPORT  RemovableDeviceSupport[] = {
+  { BdsIsRemovableUsb, BdsGetDeviceUsb },
+  { BdsIsRemovableHd, BdsGetDeviceHd },
+  //{ BdsIsRemovableCdrom, BdsGetDeviceCdrom }
+};
+
+STATIC
+BOOLEAN
+IsRemovableDevice (
+  IN  EFI_DEVICE_PATH*  DevicePath
+  )
+{
+  UINTN             Index;
+  EFI_DEVICE_PATH*  TmpDevicePath;
+
+  TmpDevicePath = DevicePath;
+  while (!IsDevicePathEnd (TmpDevicePath)) {
+    for (Index = 0; Index < sizeof(RemovableDeviceSupport) / sizeof(BDS_REMOVABLE_DEVICE_SUPPORT); Index++) {
+      if (RemovableDeviceSupport[Index].IsRemovable(TmpDevicePath)) {
+        return TRUE;
+      }
     }
+    TmpDevicePath = NextDevicePathNode (TmpDevicePath);
+  }
+
+  return FALSE;
+}
 
-    //  Convert the Device Path String into Device Path Protocol
-    Status = gBS->LocateProtocol(&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
-    ASSERT_EFI_ERROR(Status);
-    DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath(DeviceFilePath);
+STATIC
+EFI_STATUS
+TryRemovableDevice (
+  IN  EFI_DEVICE_PATH*  DevicePath,
+  OUT EFI_HANDLE*       DeviceHandle,
+  OUT EFI_DEVICE_PATH** NewDevicePath
+  )
+{
+  EFI_STATUS        Status;
+  UINTN             Index;
+  EFI_DEVICE_PATH*  TmpDevicePath;
+  BDS_REMOVABLE_DEVICE_SUPPORT* RemovableDevice;
+  EFI_DEVICE_PATH* RemovableDevicePath;
+  BOOLEAN         RemovableFound;
 
-    //Do a sanity check on the Device Path
-    if (DevicePath == NULL) {
-        return EFI_INVALID_PARAMETER;
+  RemovableFound = FALSE;
+  TmpDevicePath = DevicePath;
+  while (!IsDevicePathEnd (TmpDevicePath) && !RemovableFound) {
+    for (Index = 0; Index < sizeof(RemovableDeviceSupport) / sizeof(BDS_REMOVABLE_DEVICE_SUPPORT); Index++) {
+      RemovableDevice = &RemovableDeviceSupport[Index];
+      if (RemovableDevice->IsRemovable(TmpDevicePath)) {
+        RemovableDevicePath = TmpDevicePath;
+        RemovableFound = TRUE;
+        break;
+      }
     }
+    TmpDevicePath = NextDevicePathNode (TmpDevicePath);
+  }
 
-    // Count the number of DevicePath Node
-    NumberDevicePathNode = NumberNodeFromDevicePath(DevicePath);
-    // Extract the FilePath from the Device Path
-    FilePath = BdsExtractFilePathFromDevicePath(DeviceFilePath,NumberDevicePathNode);
+  if (!RemovableFound) {
+    return EFI_NOT_FOUND;
+  }
 
-    Status = BdsLoadDevicePath(DevicePath,&Handle);
-    if (EFI_ERROR (Status)) {
-        return Status;
+  // Search into the current started drivers
+  Status = RemovableDevice->GetDevice (RemovableDevicePath, DeviceHandle, NewDevicePath);
+  if (Status == EFI_NOT_FOUND) {
+    // Connect all the drivers
+    BdsConnectAllDrivers ();
+
+    // Search again into all the drivers
+    Status = RemovableDevice->GetDevice (RemovableDevicePath, DeviceHandle, NewDevicePath);
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+BdsConnectDevicePath (
+  IN  EFI_DEVICE_PATH_PROTOCOL* DevicePath,
+  OUT EFI_HANDLE                *Handle,
+  OUT EFI_DEVICE_PATH_PROTOCOL  **RemainingDevicePath
+  )
+{
+  EFI_DEVICE_PATH*            Remaining;
+  EFI_DEVICE_PATH*            NewDevicePath;
+  EFI_STATUS                  Status;
+
+  if ((DevicePath == NULL) || (Handle == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  do {
+    Remaining = DevicePath;
+    // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns
+    // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified
+    // to point to the remaining part of the device path
+    Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, Handle);
+    if (!EFI_ERROR (Status)) {
+      // Recursive = FALSE: We do not want to start all the device tree
+      Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE);
     }
 
-    //If FilePath == NULL then let consider if a MemoryMap Device Path
-    if (FilePath == NULL) {
-        // Check if the Node is a MemoryMap Device Path
-        Status = BdsLoadFileFromMemMap(Handle,DevicePath,File);
-    } else {
-        Status = BdsLoadFileFromSimpleFileSystem(Handle,FilePath,File);
-        if (EFI_ERROR (Status)) {
-            Status = BdsLoadFileFromFirmwareVolume(Handle,FilePath,EFI_FV_FILETYPE_ALL,File);
+    /*// We need to check if RemainingDevicePath does not point on the last node. Otherwise, calling
+    // NextDevicePathNode() will return an undetermined Device Path Node
+    if (!IsDevicePathEnd (RemainingDevicePath)) {
+      RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);
+    }*/
+  } while (!EFI_ERROR (Status) && !IsDevicePathEnd (Remaining));
+
+  if (!EFI_ERROR (Status)) {
+    // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver
+    // Binding Protocol are connected (such as DiskIo and SimpleFileSystem)
+    Remaining = DevicePath;
+    Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&Remaining,Handle);
+    if (!EFI_ERROR (Status)) {
+      Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE);
+      if (EFI_ERROR (Status)) {
+        // If the last node is a Memory Map Device Path just return EFI_SUCCESS.
+        if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {
+            Status = EFI_SUCCESS;
         }
+      }
     }
+  } else if (!IsDevicePathEnd (Remaining) && !IsRemovableDevice (Remaining)) {
+
+    /*// If the remaining Device Path is a FilePath or MemoryMap then we consider the Device Path has been loaded correctly
+    if ((Remaining->Type == MEDIA_DEVICE_PATH) && (Remaining->SubType == MEDIA_FILEPATH_DP)) {
+      Status = EFI_SUCCESS;
+    } else if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {
+      Status = EFI_SUCCESS;
+    }*/
 
+    //TODO: Should we just return success and leave the caller decide if it is the expected RemainingPath
+    Status = EFI_SUCCESS;
+  } else {
+    Status = TryRemovableDevice (DevicePath, Handle, &NewDevicePath);
     if (!EFI_ERROR (Status)) {
-        File->DevicePath = DevicePath;
+      return BdsConnectDevicePath (NewDevicePath, Handle, RemainingDevicePath);
+    }
+  }
+
+  if (RemainingDevicePath) {
+    *RemainingDevicePath = Remaining;
+  }
+
+  return Status;
+}
+
+BOOLEAN
+BdsFileSystemSupport (
+  IN EFI_DEVICE_PATH *DevicePath,
+  IN EFI_HANDLE Handle,
+  IN EFI_DEVICE_PATH *RemainingDevicePath
+  )
+{
+  EFI_STATUS  Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL     *FsProtocol;
+
+  Status = gBS->HandleProtocol (Handle,&gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);
+
+  return (!EFI_ERROR(Status) && IS_DEVICE_PATH_NODE(RemainingDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP));
+}
+
+EFI_STATUS
+BdsFileSystemLoadImage (
+  IN     EFI_DEVICE_PATH *DevicePath,
+  IN     EFI_HANDLE Handle,
+  IN     EFI_DEVICE_PATH *RemainingDevicePath,
+  IN     EFI_ALLOCATE_TYPE     Type,
+  IN OUT EFI_PHYSICAL_ADDRESS* Image,
+  OUT    UINTN                 *ImageSize
+  )
+{
+  FILEPATH_DEVICE_PATH*             FilePathDevicePath;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL     *FsProtocol;
+  EFI_FILE_PROTOCOL                   *Fs;
+  EFI_STATUS Status;
+  EFI_FILE_INFO       *FileInfo;
+  EFI_FILE_PROTOCOL   *File;
+  UINTN               Size;
+
+  ASSERT (IS_DEVICE_PATH_NODE(RemainingDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP));
+
+  FilePathDevicePath = (FILEPATH_DEVICE_PATH*)RemainingDevicePath;
+
+  Status = gBS->HandleProtocol(Handle,&gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //Try to Open the volume and get root directory
+  Status = FsProtocol->OpenVolume (FsProtocol, &Fs);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  File = NULL;
+  Status = Fs->Open(Fs, &File, FilePathDevicePath->PathName, EFI_FILE_MODE_READ, 0);
+
+  Size = 0;
+  File->GetInfo(File, &gEfiFileInfoGuid, &Size, NULL);
+  FileInfo = AllocatePool (Size);
+  Status = File->GetInfo(File, &gEfiFileInfoGuid, &Size, FileInfo);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  // Get the file size
+  Size = FileInfo->FileSize;
+  if (ImageSize) {
+    *ImageSize = Size;
+  }
+  FreePool(FileInfo);
+
+  Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size),Image);
+  if (!EFI_ERROR(Status)) {
+    Status = File->Read (File, &Size, (VOID*)(UINTN)(*Image));
+  }
+
+  return Status;
+}
+
+BOOLEAN
+BdsMemoryMapSupport (
+  IN EFI_DEVICE_PATH *DevicePath,
+  IN EFI_HANDLE Handle,
+  IN EFI_DEVICE_PATH *RemainingDevicePath
+  )
+{
+  return IS_DEVICE_PATH_NODE(RemainingDevicePath,HARDWARE_DEVICE_PATH,HW_MEMMAP_DP);
+}
+
+EFI_STATUS
+BdsMemoryMapLoadImage (
+  IN     EFI_DEVICE_PATH *DevicePath,
+  IN     EFI_HANDLE Handle,
+  IN     EFI_DEVICE_PATH *RemainingDevicePath,
+  IN     EFI_ALLOCATE_TYPE     Type,
+  IN OUT EFI_PHYSICAL_ADDRESS* Image,
+  OUT    UINTN                 *ImageSize
+  )
+{
+  EFI_STATUS            Status;
+  MEMMAP_DEVICE_PATH*   MemMapPathDevicePath;
+  UINTN                 Size;
+
+  ASSERT (IS_DEVICE_PATH_NODE(RemainingDevicePath,HARDWARE_DEVICE_PATH,HW_MEMMAP_DP));
+
+  MemMapPathDevicePath = (MEMMAP_DEVICE_PATH*)RemainingDevicePath;
+
+  Size = MemMapPathDevicePath->EndingAddress - MemMapPathDevicePath->StartingAddress;
+  if (Size == 0) {
+      return EFI_INVALID_PARAMETER;
+  }
+
+  Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size),Image);
+  if (!EFI_ERROR(Status)) {
+    CopyMem ((VOID*)(UINTN)(*Image), (CONST VOID*)(UINTN)MemMapPathDevicePath->StartingAddress, Size);
+
+    if (ImageSize != NULL) {
+        *ImageSize = Size;
     }
+  }
 
+  return Status;
+}
+
+BOOLEAN
+BdsFirmwareVolumeSupport (
+  IN EFI_DEVICE_PATH *DevicePath,
+  IN EFI_HANDLE Handle,
+  IN EFI_DEVICE_PATH *RemainingDevicePath
+  )
+{
+  return IS_DEVICE_PATH_NODE(RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP);
+}
+
+EFI_STATUS
+BdsFirmwareVolumeLoadImage (
+  IN     EFI_DEVICE_PATH *DevicePath,
+  IN     EFI_HANDLE Handle,
+  IN     EFI_DEVICE_PATH *RemainingDevicePath,
+  IN     EFI_ALLOCATE_TYPE     Type,
+  IN OUT EFI_PHYSICAL_ADDRESS* Image,
+  OUT    UINTN                 *ImageSize
+  )
+{
+  EFI_STATUS            Status;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL     *FwVol;
+  EFI_GUID                          *FvNameGuid;
+  EFI_SECTION_TYPE                  SectionType;
+  EFI_FV_FILETYPE                   FvType;
+  EFI_FV_FILE_ATTRIBUTES            Attrib;
+  UINT32                            AuthenticationStatus;
+  VOID* ImageBuffer;
+
+  ASSERT (IS_DEVICE_PATH_NODE(RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP));
+
+  Status = gBS->HandleProtocol(Handle,&gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FwVol);
+  if (EFI_ERROR(Status)) {
     return Status;
+  }
+
+  FvNameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)RemainingDevicePath);
+  if (FvNameGuid == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+  }
+
+  SectionType = EFI_SECTION_PE32;
+  AuthenticationStatus = 0;
+  //Note: ReadSection at the opposite of ReadFile does not allow to pass ImageBuffer == NULL to get the size of the file.
+  ImageBuffer = NULL;
+  Status = FwVol->ReadSection (
+                    FwVol,
+                    FvNameGuid,
+                    SectionType,
+                    0,
+                    &ImageBuffer,
+                    ImageSize,
+                    &AuthenticationStatus
+                    );
+  if (!EFI_ERROR (Status)) {
+#if 0
+    // In case the buffer has some address requirements, we must copy the buffer to a buffer following the requirements
+    if (Type != AllocateAnyPages) {
+      Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize),Image);
+      if (!EFI_ERROR(Status)) {
+        CopyMem ((VOID*)(UINTN)(*Image), ImageBuffer, *ImageSize);
+        FreePool (ImageBuffer);
+      }
+    }
+#else
+    // We must copy the buffer into a page allocations. Otherwise, the caller could call gBS->FreePages() on the pool allocation
+    Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image);
+    if (!EFI_ERROR(Status)) {
+      CopyMem ((VOID*)(UINTN)(*Image), ImageBuffer, *ImageSize);
+      FreePool (ImageBuffer);
+    }
+#endif
+  } else {
+    // Try a raw file, since a PE32 SECTION does not exist
+    Status = FwVol->ReadFile (
+                        FwVol,
+                        FvNameGuid,
+                        NULL,
+                        ImageSize,
+                        &FvType,
+                        &Attrib,
+                        &AuthenticationStatus
+                        );
+    if (!EFI_ERROR(Status)) {
+      Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize),Image);
+      if (!EFI_ERROR(Status)) {
+        Status = FwVol->ReadFile (
+                                FwVol,
+                                FvNameGuid,
+                                (VOID*)(UINTN)(*Image),
+                                ImageSize,
+                                &FvType,
+                                &Attrib,
+                                &AuthenticationStatus
+                                );
+      }
+    }
+  }
+  return Status;
 }
 
-EFI_STATUS BdsCopyRawFileToRuntimeMemory(
-    IN  BDS_FILE            *File,
-    OUT VOID                **FileImage,
-    OUT UINTN               *FileSize
-) {
-    if (File == NULL) {
-        return EFI_INVALID_PARAMETER;
+BOOLEAN
+BdsPxeSupport (
+  IN EFI_DEVICE_PATH*           DevicePath,
+  IN EFI_HANDLE                 Handle,
+  IN EFI_DEVICE_PATH*           RemainingDevicePath
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_PXE_BASE_CODE_PROTOCOL* PxeBcProtocol;
+
+  if (!IsDevicePathEnd(RemainingDevicePath)) {
+    return FALSE;
+  }
+
+  Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+EFI_STATUS
+BdsPxeLoadImage (
+  IN     EFI_DEVICE_PATH*       DevicePath,
+  IN     EFI_HANDLE             Handle,
+  IN     EFI_DEVICE_PATH*       RemainingDevicePath,
+  IN     EFI_ALLOCATE_TYPE      Type,
+  IN OUT EFI_PHYSICAL_ADDRESS   *Image,
+  OUT    UINTN                  *ImageSize
+  )
+{
+  EFI_STATUS              Status;
+  EFI_LOAD_FILE_PROTOCOL  *LoadFileProtocol;
+  UINTN                   BufferSize;
+
+  // Get Load File Protocol attached to the PXE protocol
+  Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFileProtocol);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = LoadFileProtocol->LoadFile (LoadFileProtocol, DevicePath, TRUE, &BufferSize, NULL);
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(BufferSize), Image);
+    if (EFI_ERROR(Status)) {
+      return Status;
     }
 
-    if (File->Type == BDS_FILETYPE_FS) {
-        return BdsCopyRawFileToRuntimeMemoryFS(File->File.Fs.Handle,FileImage,FileSize);
-    } else if (File->Type == BDS_FILETYPE_FV) {
-        return BdsCopyRawFileToRuntimeMemoryFV(&(File->File.Fv),FileImage,FileSize);
-    } else if (File->Type == BDS_FILETYPE_MEM) {
-        return BdsCopyRawFileToRuntimeMemoryMemMap(&(File->File.Mem),FileImage,FileSize);
-    } else {
-        return EFI_INVALID_PARAMETER;
+    Status = LoadFileProtocol->LoadFile (LoadFileProtocol, DevicePath, TRUE, &BufferSize, (VOID*)(UINTN)(*Image));
+    if (!EFI_ERROR(Status) && (ImageSize != NULL)) {
+      *ImageSize = BufferSize;
     }
+  }
+
+  return Status;
+}
+
+BOOLEAN
+BdsTftpSupport (
+  IN EFI_DEVICE_PATH*           DevicePath,
+  IN EFI_HANDLE                 Handle,
+  IN EFI_DEVICE_PATH*           RemainingDevicePath
+  )
+{
+  EFI_STATUS  Status;
+  EFI_DEVICE_PATH  *NextDevicePath;
+  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBcProtocol;
+
+  // Validate the Remaining Device Path
+  if (IsDevicePathEnd(RemainingDevicePath)) {
+    return FALSE;
+  }
+  if (!IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP) &&
+      !IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv6_DP)) {
+    return FALSE;
+  }
+  NextDevicePath = NextDevicePathNode (RemainingDevicePath);
+  if (IsDevicePathEnd(NextDevicePath)) {
+    return FALSE;
+  }
+  if (!IS_DEVICE_PATH_NODE(NextDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP)) {
+    return FALSE;
+  }
+
+  Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+EFI_STATUS
+BdsTftpLoadImage (
+  IN     EFI_DEVICE_PATH*       DevicePath,
+  IN     EFI_HANDLE             Handle,
+  IN     EFI_DEVICE_PATH*       RemainingDevicePath,
+  IN     EFI_ALLOCATE_TYPE      Type,
+  IN OUT EFI_PHYSICAL_ADDRESS   *Image,
+  OUT    UINTN                  *ImageSize
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_PXE_BASE_CODE_PROTOCOL  *Pxe;
+  UINT64                      TftpBufferSize;
+  VOID*                       TftpBuffer;
+  EFI_IP_ADDRESS              ServerIp;
+  IPv4_DEVICE_PATH*           IPv4DevicePathNode;
+  FILEPATH_DEVICE_PATH*       FilePathDevicePath;
+  EFI_IP_ADDRESS              LocalIp;
+
+  ASSERT(IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP));
+
+  IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath;
+  FilePathDevicePath = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);
+
+  Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Status = Pxe->Start (Pxe, FALSE);
+  if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
+    return Status;
+  }
+
+  if (!IPv4DevicePathNode->StaticIpAddress) {
+    Status = Pxe->Dhcp(Pxe, TRUE);
+  } else {
+    CopyMem (&LocalIp.v4, &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
+    Status = Pxe->SetStationIp (Pxe, &LocalIp, NULL);
+  }
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  CopyMem (&ServerIp.v4, &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));
+
+  Status = Pxe->Mtftp (
+                  Pxe,
+                  EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
+                  NULL,
+                  FALSE,
+                  &TftpBufferSize,
+                  NULL,
+                  &ServerIp,
+                  (UINT8 *)FilePathDevicePath->PathName,
+                  NULL,
+                  TRUE
+                  );
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  // Allocate a buffer to hold the whole file.
+  TftpBuffer = AllocatePool(TftpBufferSize);
+  if (TftpBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = Pxe->Mtftp (
+                  Pxe,
+                  EFI_PXE_BASE_CODE_TFTP_READ_FILE,
+                  TftpBuffer,
+                  FALSE,
+                  &TftpBufferSize,
+                  NULL,
+                  &ServerIp,
+                  (UINT8 *)FilePathDevicePath->PathName,
+                  NULL,
+                  FALSE
+                  );
+  if (EFI_ERROR(Status)) {
+    FreePool(TftpBuffer);
+  } else if (ImageSize != NULL) {
+    *ImageSize = (UINTN)TftpBufferSize;
+  }
+
+  return Status;
+}
+
+BDS_FILE_LOADER FileLoaders[] = {
+    { BdsFileSystemSupport, BdsFileSystemLoadImage },
+    { BdsFirmwareVolumeSupport, BdsFirmwareVolumeLoadImage },
+    //{ BdsLoadFileSupport, BdsLoadFileLoadImage },
+    { BdsMemoryMapSupport, BdsMemoryMapLoadImage },
+    { BdsPxeSupport, BdsPxeLoadImage },
+    { BdsTftpSupport, BdsTftpLoadImage },
+    { NULL, NULL }
+};
+
+EFI_STATUS
+BdsLoadImage (
+  IN     EFI_DEVICE_PATH       *DevicePath,
+  IN     EFI_ALLOCATE_TYPE     Type,
+  IN OUT EFI_PHYSICAL_ADDRESS* Image,
+  OUT    UINTN                 *FileSize
+  )
+{
+  EFI_STATUS      Status;
+  EFI_HANDLE      Handle;
+  EFI_DEVICE_PATH *RemainingDevicePath;
+  BDS_FILE_LOADER*  FileLoader;
+
+  Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  FileLoader = FileLoaders;
+  while (FileLoader->Support != NULL) {
+    if (FileLoader->Support (DevicePath, Handle, RemainingDevicePath)) {
+      return FileLoader->LoadImage (DevicePath, Handle, RemainingDevicePath, Type, Image, FileSize);
+    }
+    FileLoader++;
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+BdsStartEfiApplication (
+  IN EFI_HANDLE                  ParentImageHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_HANDLE                   ImageHandle;
+  EFI_PHYSICAL_ADDRESS         BinaryBuffer;
+  UINTN                        BinarySize;
+
+  // Find the nearest supported file loader
+  Status = BdsLoadImage (DevicePath, AllocateAnyPages,&BinaryBuffer,&BinarySize);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  // Load the image from the Buffer with Boot Services function
+  Status = gBS->LoadImage (TRUE, ParentImageHandle, DevicePath, (VOID*)(UINTN)BinaryBuffer, BinarySize, &ImageHandle);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  // Before calling the image, enable the Watchdog Timer for  the 5 Minute period
+  gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
+  // Start the image
+  Status = gBS->StartImage (ImageHandle, NULL, NULL);
+  // Clear the Watchdog Timer after the image returns
+  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
+
+  return Status;
 }
diff --git a/ArmPkg/Library/BdsLib/BdsFilePathFs.c b/ArmPkg/Library/BdsLib/BdsFilePathFs.c
deleted file mode 100644 (file)
index 0b7f9d3..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/** @file
-*
-*  Copyright (c) 2011, 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 "BdsInternal.h"
-
-EFI_STATUS BdsLoadFileFromSimpleFileSystem(
-    IN  EFI_HANDLE Handle,
-    IN  CHAR16                              *FilePath,
-    OUT BDS_FILE            *File
-) {
-    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL     *FsProtocol;
-    EFI_FILE_PROTOCOL                   *Fs;
-    EFI_STATUS Status;
-    EFI_FILE_PROTOCOL   *FileHandle = NULL;
-
-    if (File == NULL) {
-        return EFI_INVALID_PARAMETER;
-    }
-
-    Status = gBS->HandleProtocol(Handle,&gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol);
-    if (EFI_ERROR(Status)) {
-        return Status;
-    }
-
-    //Try to Open the volume and get root directory
-  Status = FsProtocol->OpenVolume(FsProtocol, &Fs);
-  if (EFI_ERROR(Status)) {
-        return Status;
-    }
-
-    Status = Fs->Open(Fs, &FileHandle, FilePath, EFI_FILE_MODE_READ, 0);
-
-    File->Type = BDS_FILETYPE_FS;
-    File->FilePath = FilePath;
-    File->File.Fs.Handle = FileHandle;
-
-    return Status;
-}
-
-EFI_STATUS BdsCopyRawFileToRuntimeMemoryFS(
-    IN  EFI_FILE_PROTOCOL   *File,
-    OUT VOID                **FileImage,
-    OUT UINTN               *FileSize
-) {
-    EFI_FILE_INFO   *FileInfo;
-    UINTN           Size;
-    VOID*           Image;
-    EFI_STATUS      Status;
-
-    Size = 0;
-    File->GetInfo(File, &gEfiFileInfoGuid, &Size, NULL);
-    FileInfo = AllocatePool (Size);
-    Status = File->GetInfo(File, &gEfiFileInfoGuid, &Size, FileInfo);
-    if (EFI_ERROR(Status)) {
-        return Status;
-    }
-
-    // Get the file size
-    Size = FileInfo->FileSize;
-    if (FileSize) {
-        *FileSize = Size;
-    }
-    FreePool(FileInfo);
-
-    Image = AllocateRuntimePool(Size);
-    if (Image == NULL) {
-        return EFI_OUT_OF_RESOURCES;
-    }
-
-    Status = File->Read(File, &Size, Image);
-    if (!EFI_ERROR(Status)) {
-        *FileImage = Image;
-    }
-    return Status;
-}
diff --git a/ArmPkg/Library/BdsLib/BdsFilePathFv.c b/ArmPkg/Library/BdsLib/BdsFilePathFv.c
deleted file mode 100644 (file)
index f5b4e57..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/** @file
-*
-*  Copyright (c) 2011, 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 "BdsInternal.h"
-
-EFI_STATUS BdsLoadFileFromFirmwareVolume(
-    IN  EFI_HANDLE      FvHandle,
-    IN  CHAR16    *FilePath,
-    IN  EFI_FV_FILETYPE FileTypeFilter,
-    OUT BDS_FILE        *File
-) {
-    EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
-    VOID                          *Key;    
-    EFI_STATUS                    Status, FileStatus;
-    EFI_GUID                      NameGuid;
-    EFI_FV_FILETYPE               FileType;
-    EFI_FV_FILE_ATTRIBUTES        Attributes;
-    UINTN                         Size;
-    UINTN                         UiStringLen;
-    CHAR16                        *UiSection;
-    UINT32                        Authentication;
-
-    if (File == NULL) {
-        return EFI_INVALID_PARAMETER;
-    }
-
-    Status = gBS->HandleProtocol(FvHandle,&gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FvProtocol);
-    if (EFI_ERROR(Status)) {
-        return Status;
-    }
-
-    // Length of FilePath
-    UiStringLen = StrLen (FilePath);
-
-    // Allocate Key
-    Key = AllocatePool (FvProtocol->KeySize);
-    ASSERT (Key != NULL);
-    ZeroMem (Key, FvProtocol->KeySize);
-
-    do {
-        // Search in all files
-        FileType = FileTypeFilter;
-
-        Status = FvProtocol->GetNextFile (FvProtocol, Key, &FileType, &NameGuid, &Attributes, &Size);
-        if (!EFI_ERROR (Status)) {
-            UiSection = NULL;
-            FileStatus = FvProtocol->ReadSection (
-                          FvProtocol, 
-                          &NameGuid, 
-                          EFI_SECTION_USER_INTERFACE, 
-                          0,
-                          (VOID **)&UiSection,
-                          &Size,
-                          &Authentication
-                          );
-            if (!EFI_ERROR (FileStatus)) {
-              if (StrnCmp (FilePath, UiSection, UiStringLen) == 0) {
-                  
-                //
-                // We found a UiString match. 
-                //
-                //*FileGuid = NameGuid;
-                File->Type = BDS_FILETYPE_FV;
-                File->FilePath = FilePath;
-                CopyGuid (&(File->File.Fv.Guid),&NameGuid);
-                File->File.Fv.FvProtocol = FvProtocol;
-                File->File.Fv.FileType = FileType;
-
-                Status = gBS->HandleProtocol(FvHandle,&gEfiDevicePathProtocolGuid, (VOID **)&(File->DevicePath));
-
-                FreePool (Key);
-                FreePool (UiSection);
-                return FileStatus;
-              }
-              FreePool (UiSection);
-            }
-        }
-    } while (!EFI_ERROR (Status));
-
-    FreePool(Key);
-    return Status;
-}
-
-EFI_STATUS BdsCopyRawFileToRuntimeMemoryFV(
-    IN  BDS_FV_FILE         *FvFile,
-    OUT VOID                **FileImage,
-    OUT UINTN               *FileSize
-) {
-    EFI_STATUS Status = EFI_INVALID_PARAMETER;
-    EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
-    EFI_FV_FILETYPE               FileType;
-    EFI_GUID*    NameGuid;
-    EFI_FV_FILE_ATTRIBUTES        Attributes;
-    UINT32                        Authentication;
-
-    FvProtocol = FvFile->FvProtocol;
-    FileType = FvFile->FileType;
-    NameGuid = &(FvFile->Guid);
-
-    if (FileType == EFI_FV_FILETYPE_RAW) {
-        *FileImage = NULL;
-        *FileSize = 0;
-        Status = FvProtocol->ReadFile(
-            FvProtocol,NameGuid,                            // IN
-            FileImage,FileSize,                             // IN OUT
-            &FileType,&Attributes,&Authentication           // OUT
-        );
-        ASSERT_EFI_ERROR(Status);
-
-        // This raw file also contains a header
-        *FileSize = *FileSize - 4;
-        *FileImage = (UINT8*)FileImage + 4;
-    } else if (FileType == EFI_FV_FILETYPE_FREEFORM) {
-        Status = FvProtocol->ReadSection (
-            FvProtocol,NameGuid,EFI_SECTION_RAW,0,          // IN
-            FileImage,FileSize,                             // IN OUT
-            &Authentication                                 // OUT
-        );
-        ASSERT_EFI_ERROR(Status);
-    } else {
-        ASSERT(0); //Maybe support application as well ???
-    }
-
-    return Status;
-}
diff --git a/ArmPkg/Library/BdsLib/BdsFilePathMem.c b/ArmPkg/Library/BdsLib/BdsFilePathMem.c
deleted file mode 100644 (file)
index dddaa3d..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/** @file
-*
-*  Copyright (c) 2011, 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 "BdsInternal.h"
-
-
-EFI_STATUS BdsLoadFileFromMemMap (
-    IN  EFI_HANDLE                  Handle,
-    IN  EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
-    OUT BDS_FILE                    *File
-) {
-    EFI_DEVICE_PATH_PROTOCOL            *LastDevicePath;
-
-    if ((File == NULL) || (DevicePath == NULL) || (IsDevicePathEnd (DevicePath))) {
-        return EFI_INVALID_PARAMETER;
-    }
-
-    // Check if the last node of the device Path is a Memory Map Device Node
-    LastDevicePath = DevicePath;
-    DevicePath = NextDevicePathNode(DevicePath);
-    while (!IsDevicePathEnd (DevicePath)) {
-        LastDevicePath = DevicePath;
-        DevicePath = NextDevicePathNode(DevicePath);
-    }
-    if ((LastDevicePath->Type != HARDWARE_DEVICE_PATH) || (LastDevicePath->SubType != HW_MEMMAP_DP)) {
-        return EFI_UNSUPPORTED;
-    }
-
-    File->Type = BDS_FILETYPE_MEM;
-    File->File.Mem.MemoryType = ((MEMMAP_DEVICE_PATH*)LastDevicePath)->MemoryType;
-    File->File.Mem.StartingAddress = ((MEMMAP_DEVICE_PATH*)LastDevicePath)->StartingAddress;
-    File->File.Mem.EndingAddress = ((MEMMAP_DEVICE_PATH*)LastDevicePath)->EndingAddress;
-
-    return EFI_SUCCESS;
-}
-
-EFI_STATUS BdsCopyRawFileToRuntimeMemoryMemMap(
-    IN  BDS_MEM_FILE        *MemFile,
-    OUT VOID                **FileImage,
-    OUT UINTN               *FileSize
-) {
-    UINTN           Size;
-    VOID*           Image;
-
-    Size = MemFile->EndingAddress - MemFile->StartingAddress;
-
-    if ((Size == 0) || (FileImage == NULL)) {
-        return EFI_INVALID_PARAMETER;
-    }
-    if (FileSize != NULL) {
-        *FileSize = Size;
-    }
-
-    Image = AllocateRuntimePool(Size);
-    if (Image == NULL) {
-        return EFI_OUT_OF_RESOURCES;
-    }
-
-    *FileImage = CopyMem(Image,(CONST VOID*)(UINTN)MemFile->StartingAddress,Size);
-
-    return EFI_SUCCESS;
-}
index 88e8fa34533c18069e0be2281463e9b91a51e600..fa9483ea816d0ad66fb99c85036a1f69230a3d16 100644 (file)
-/** @file\r
-*\r
-*  Copyright (c) 2011, ARM Limited. All rights reserved.\r
-*  \r
-*  This program and the accompanying materials                          \r
-*  are licensed and made available under the terms and conditions of the BSD License         \r
-*  which accompanies this distribution.  The full text of the license may be found at        \r
-*  http://opensource.org/licenses/bsd-license.php                                            \r
-*\r
-*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
-*\r
-**/\r
-\r
-#include "BdsInternal.h"\r
-\r
-#include <Library/DxeServicesTableLib.h>\r
-#include <Library/HobLib.h>\r
-\r
-EFI_STATUS\r
-ShutdownUefiBootServices( VOID )\r
-{\r
-  EFI_STATUS              Status;\r
-  UINTN                   MemoryMapSize;\r
-  EFI_MEMORY_DESCRIPTOR   *MemoryMap;\r
-  UINTN                   MapKey;\r
-  UINTN                   DescriptorSize;\r
-  UINT32                  DescriptorVersion;\r
-  UINTN                   Pages;\r
-\r
-  MemoryMap = NULL;\r
-  MemoryMapSize = 0;\r
-  do {\r
-    Status = gBS->GetMemoryMap (\r
-                    &MemoryMapSize,\r
-                    MemoryMap,\r
-                    &MapKey,\r
-                    &DescriptorSize,\r
-                    &DescriptorVersion\r
-                    );\r
-    if (Status == EFI_BUFFER_TOO_SMALL) {\r
-\r
-      Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;\r
-      MemoryMap = AllocatePages (Pages);\r
-\r
-      //\r
-      // Get System MemoryMap\r
-      //\r
-      Status = gBS->GetMemoryMap (\r
-                      &MemoryMapSize,\r
-                      MemoryMap,\r
-                      &MapKey,\r
-                      &DescriptorSize,\r
-                      &DescriptorVersion\r
-                      );\r
-      // Don't do anything between the GetMemoryMap() and ExitBootServices()\r
-      if (!EFI_ERROR (Status)) {\r
-        Status = gBS->ExitBootServices (gImageHandle, MapKey);\r
-        if (EFI_ERROR (Status)) {\r
-          FreePages (MemoryMap, Pages);\r
-          MemoryMap = NULL;\r
-          MemoryMapSize = 0;\r
-        }\r
-      }\r
-    }\r
-  } while (EFI_ERROR (Status));\r
-\r
-  return Status;\r
-}\r
-\r
-EFI_STATUS\r
-BdsConnectAllDrivers( VOID ) {\r
-    UINTN                     HandleCount, Index;\r
-    EFI_HANDLE                *HandleBuffer;\r
-    EFI_STATUS                Status;\r
-\r
-    do {\r
-        // Locate all the driver handles\r
-        Status = gBS->LocateHandleBuffer (\r
-                    AllHandles,\r
-                    NULL,\r
-                    NULL,\r
-                    &HandleCount,\r
-                    &HandleBuffer\r
-                    );\r
-        if (EFI_ERROR (Status)) {\r
-            break;\r
-        }\r
-\r
-        // Connect every handles\r
-        for (Index = 0; Index < HandleCount; Index++) {\r
-            gBS->ConnectController(HandleBuffer[Index], NULL, NULL, TRUE);\r
-        }\r
-\r
-        if (HandleBuffer != NULL) {\r
-            FreePool (HandleBuffer);\r
-        }\r
-        \r
-        // Check if new handles have been created after the start of the previous handles\r
-        Status = gDS->Dispatch ();\r
-    } while (!EFI_ERROR(Status));\r
-\r
-    return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-InsertSystemMemoryResources (\r
-  LIST_ENTRY *ResourceList,\r
-  EFI_HOB_RESOURCE_DESCRIPTOR *ResHob\r
-  )\r
-{\r
-  BDS_SYSTEM_MEMORY_RESOURCE  *NewResource;\r
-  LIST_ENTRY                  *Link;\r
-  LIST_ENTRY                  *NextLink;\r
-  LIST_ENTRY                  AttachedResources;\r
-  BDS_SYSTEM_MEMORY_RESOURCE  *Resource;\r
-  EFI_PHYSICAL_ADDRESS        NewResourceEnd;\r
-\r
-  if (IsListEmpty (ResourceList)) {\r
-    NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));\r
-    NewResource->PhysicalStart = ResHob->PhysicalStart;\r
-    NewResource->ResourceLength = ResHob->ResourceLength;\r
-    InsertTailList (ResourceList, &NewResource->Link);\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  InitializeListHead (&AttachedResources);\r
-\r
-  Link = ResourceList->ForwardLink;\r
-  ASSERT (Link != NULL);\r
-  while (Link != ResourceList) {\r
-    Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;\r
-\r
-    // Sanity Check. The resources should not overlapped.\r
-    ASSERT(!((ResHob->PhysicalStart >= Resource->PhysicalStart) && (ResHob->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))));\r
-    ASSERT(!((ResHob->PhysicalStart + ResHob->ResourceLength - 1 >= Resource->PhysicalStart) &&\r
-        ((ResHob->PhysicalStart + ResHob->ResourceLength - 1) < (Resource->PhysicalStart + Resource->ResourceLength))));\r
-\r
-    // The new resource is attached after this resource descriptor\r
-    if (ResHob->PhysicalStart == Resource->PhysicalStart + Resource->ResourceLength) {\r
-      Resource->ResourceLength =  Resource->ResourceLength + ResHob->ResourceLength;\r
-\r
-      NextLink = RemoveEntryList (&Resource->Link);\r
-      InsertTailList (&AttachedResources, &Resource->Link);\r
-      Link = NextLink;\r
-    }\r
-    // The new resource is attached before this resource descriptor\r
-    else if (ResHob->PhysicalStart + ResHob->ResourceLength == Resource->PhysicalStart) {\r
-      Resource->PhysicalStart = ResHob->PhysicalStart;\r
-      Resource->ResourceLength =  Resource->ResourceLength + ResHob->ResourceLength;\r
-\r
-      NextLink = RemoveEntryList (&Resource->Link);\r
-      InsertTailList (&AttachedResources, &Resource->Link);\r
-      Link = NextLink;\r
-    } else {\r
-      Link = Link->ForwardLink;\r
-    }\r
-  }\r
-\r
-  if (!IsListEmpty (&AttachedResources)) {\r
-    // See if we can merge the attached resource with other resources\r
-\r
-    NewResource = (BDS_SYSTEM_MEMORY_RESOURCE*)GetFirstNode (&AttachedResources);\r
-    Link = RemoveEntryList (&NewResource->Link);\r
-    while (!IsListEmpty (&AttachedResources)) {\r
-      // Merge resources\r
-      Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;\r
-\r
-      // Ensure they overlap each other\r
-      ASSERT(\r
-          ((NewResource->PhysicalStart >= Resource->PhysicalStart) && (NewResource->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))) ||\r
-          (((NewResource->PhysicalStart + NewResource->ResourceLength) >= Resource->PhysicalStart) && ((NewResource->PhysicalStart + NewResource->ResourceLength) < (Resource->PhysicalStart + Resource->ResourceLength)))\r
-      );\r
-\r
-      NewResourceEnd = MAX (NewResource->PhysicalStart + NewResource->ResourceLength, Resource->PhysicalStart + Resource->ResourceLength);\r
-      NewResource->PhysicalStart = MIN (NewResource->PhysicalStart, Resource->PhysicalStart);\r
-      NewResource->ResourceLength = NewResourceEnd - NewResource->PhysicalStart;\r
-\r
-      Link = RemoveEntryList (Link);\r
-    }\r
-  } else {\r
-    // None of the Resource of the list is attached to this ResHob. Create a new entry for it\r
-    NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));\r
-    NewResource->PhysicalStart = ResHob->PhysicalStart;\r
-    NewResource->ResourceLength = ResHob->ResourceLength;\r
-  }\r
-  InsertTailList (ResourceList, &NewResource->Link);\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-GetSystemMemoryResources (\r
-  IN  LIST_ENTRY *ResourceList\r
-  )\r
-{\r
-  EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;\r
-\r
-  InitializeListHead (ResourceList);\r
-\r
-  // Find the first System Memory Resource Descriptor\r
-  ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
-  while ((ResHob != NULL) && (ResHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)) {\r
-    ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));\r
-  }\r
-\r
-  // Did not find any\r
-  if (ResHob == NULL) {\r
-    return EFI_NOT_FOUND;\r
-  } else {\r
-    InsertSystemMemoryResources (ResourceList, ResHob);\r
-  }\r
-\r
-  ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));\r
-  while (ResHob != NULL) {\r
-    if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
-      InsertSystemMemoryResources (ResourceList, ResHob);\r
-    }\r
-    ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
+/** @file
+*
+*  Copyright (c) 2011, 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 "BdsInternal.h"
+
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PrintLib.h>
+#include <Library/SerialPortLib.h>
+
+STATIC CHAR8 *mTokenList[] = {
+  /*"SEC",*/
+  "PEI",
+  "DXE",
+  "BDS",
+  NULL
+};
+
+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;
+  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;
+}
+
+/**
+  Connect all DXE drivers
+
+  @retval EFI_SUCCESS           All drivers have been connected
+  @retval EFI_NOT_FOUND         No handles match the search.
+  @retval EFI_OUT_OF_RESOURCES  There is not resource pool memory to store the matching results.
+
+**/
+EFI_STATUS
+BdsConnectAllDrivers (
+  VOID
+  )
+{
+  UINTN                     HandleCount, Index;
+  EFI_HANDLE                *HandleBuffer;
+  EFI_STATUS                Status;
+
+  do {
+    // Locate all the driver handles
+    Status = gBS->LocateHandleBuffer (
+                AllHandles,
+                NULL,
+                NULL,
+                &HandleCount,
+                &HandleBuffer
+                );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    // Connect every handles
+    for (Index = 0; Index < HandleCount; Index++) {
+      gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+    }
+
+    if (HandleBuffer != NULL) {
+      FreePool (HandleBuffer);
+    }
+
+    // Check if new handles have been created after the start of the previous handles
+    Status = gDS->Dispatch ();
+  } while (!EFI_ERROR(Status));
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+InsertSystemMemoryResources (
+  LIST_ENTRY *ResourceList,
+  EFI_HOB_RESOURCE_DESCRIPTOR *ResHob
+  )
+{
+  BDS_SYSTEM_MEMORY_RESOURCE  *NewResource;
+  LIST_ENTRY                  *Link;
+  LIST_ENTRY                  *NextLink;
+  LIST_ENTRY                  AttachedResources;
+  BDS_SYSTEM_MEMORY_RESOURCE  *Resource;
+  EFI_PHYSICAL_ADDRESS        NewResourceEnd;
+
+  if (IsListEmpty (ResourceList)) {
+    NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));
+    NewResource->PhysicalStart = ResHob->PhysicalStart;
+    NewResource->ResourceLength = ResHob->ResourceLength;
+    InsertTailList (ResourceList, &NewResource->Link);
+    return EFI_SUCCESS;
+  }
+
+  InitializeListHead (&AttachedResources);
+
+  Link = ResourceList->ForwardLink;
+  ASSERT (Link != NULL);
+  while (Link != ResourceList) {
+    Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;
+
+    // Sanity Check. The resources should not overlapped.
+    ASSERT(!((ResHob->PhysicalStart >= Resource->PhysicalStart) && (ResHob->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))));
+    ASSERT(!((ResHob->PhysicalStart + ResHob->ResourceLength - 1 >= Resource->PhysicalStart) &&
+        ((ResHob->PhysicalStart + ResHob->ResourceLength - 1) < (Resource->PhysicalStart + Resource->ResourceLength))));
+
+    // The new resource is attached after this resource descriptor
+    if (ResHob->PhysicalStart == Resource->PhysicalStart + Resource->ResourceLength) {
+      Resource->ResourceLength =  Resource->ResourceLength + ResHob->ResourceLength;
+
+      NextLink = RemoveEntryList (&Resource->Link);
+      InsertTailList (&AttachedResources, &Resource->Link);
+      Link = NextLink;
+    }
+    // The new resource is attached before this resource descriptor
+    else if (ResHob->PhysicalStart + ResHob->ResourceLength == Resource->PhysicalStart) {
+      Resource->PhysicalStart = ResHob->PhysicalStart;
+      Resource->ResourceLength =  Resource->ResourceLength + ResHob->ResourceLength;
+
+      NextLink = RemoveEntryList (&Resource->Link);
+      InsertTailList (&AttachedResources, &Resource->Link);
+      Link = NextLink;
+    } else {
+      Link = Link->ForwardLink;
+    }
+  }
+
+  if (!IsListEmpty (&AttachedResources)) {
+    // See if we can merge the attached resource with other resources
+
+    NewResource = (BDS_SYSTEM_MEMORY_RESOURCE*)GetFirstNode (&AttachedResources);
+    Link = RemoveEntryList (&NewResource->Link);
+    while (!IsListEmpty (&AttachedResources)) {
+      // Merge resources
+      Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;
+
+      // Ensure they overlap each other
+      ASSERT(
+          ((NewResource->PhysicalStart >= Resource->PhysicalStart) && (NewResource->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))) ||
+          (((NewResource->PhysicalStart + NewResource->ResourceLength) >= Resource->PhysicalStart) && ((NewResource->PhysicalStart + NewResource->ResourceLength) < (Resource->PhysicalStart + Resource->ResourceLength)))
+      );
+
+      NewResourceEnd = MAX (NewResource->PhysicalStart + NewResource->ResourceLength, Resource->PhysicalStart + Resource->ResourceLength);
+      NewResource->PhysicalStart = MIN (NewResource->PhysicalStart, Resource->PhysicalStart);
+      NewResource->ResourceLength = NewResourceEnd - NewResource->PhysicalStart;
+
+      Link = RemoveEntryList (Link);
+    }
+  } else {
+    // None of the Resource of the list is attached to this ResHob. Create a new entry for it
+    NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));
+    NewResource->PhysicalStart = ResHob->PhysicalStart;
+    NewResource->ResourceLength = ResHob->ResourceLength;
+  }
+  InsertTailList (ResourceList, &NewResource->Link);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetSystemMemoryResources (
+  IN  LIST_ENTRY *ResourceList
+  )
+{
+  EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;
+
+  InitializeListHead (ResourceList);
+
+  // Find the first System Memory Resource Descriptor
+  ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+  while ((ResHob != NULL) && (ResHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)) {
+    ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
+  }
+
+  // Did not find any
+  if (ResHob == NULL) {
+    return EFI_NOT_FOUND;
+  } else {
+    InsertSystemMemoryResources (ResourceList, ResHob);
+  }
+
+  ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
+  while (ResHob != NULL) {
+    if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+      InsertSystemMemoryResources (ResourceList, ResHob);
+    }
+    ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
+  }
+
+  return EFI_SUCCESS;
+}
+
+VOID
+PrintPerformance (
+  VOID
+  )
+{
+  UINTN       Key;
+  CONST VOID  *Handle;
+  CONST CHAR8 *Token, *Module;
+  UINT64      Start, Stop, TimeStamp;
+  UINT64      Delta, TicksPerSecond, Milliseconds;
+  UINTN       Index;
+  CHAR8       Buffer[100];
+  UINTN       CharCount;
+
+  TicksPerSecond = GetPerformanceCounterProperties (NULL, NULL);
+
+  TimeStamp = 0;
+  Key       = 0;
+  do {
+    Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
+    if (Key != 0) {
+      for (Index = 0; mTokenList[Index] != NULL; Index++) {
+        if (AsciiStriCmp (mTokenList[Index], Token) == 0) {
+          Delta = Start - Stop;
+          TimeStamp += Delta;
+          Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);
+          CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"%6a %6ld ms\n", Token, Milliseconds);
+          SerialPortWrite ((UINT8 *) Buffer, CharCount);
+          break;
+        }
+      }
+    }
+  } while (Key != 0);
+
+  CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));
+  SerialPortWrite ((UINT8 *) Buffer, CharCount);
+}
index 07f722e03fdd65a515a12ad94dd6f853fcf924b1..a497df03ea97abbce779dc2ebb242333a58b18a1 100644 (file)
@@ -24,6 +24,7 @@
 #include <Library/MemoryAllocationLib.h>
 #include <Library/DebugLib.h>
 #include <Library/BdsUnixLib.h>
+#include <Library/PerformanceLib.h>
 
 #include <Guid/FileInfo.h>
 
 #include <Protocol/DevicePathFromText.h>
 #include <Protocol/SimpleFileSystem.h>
 #include <Protocol/FirmwareVolume2.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/PxeBaseCode.h>
 
 
-typedef enum { BDS_FILETYPE_MEM, BDS_FILETYPE_FS, BDS_FILETYPE_FV } BDS_FILE_TYPE;
+typedef BOOLEAN (*BDS_FILE_LOADER_SUPPORT) (
+    IN EFI_DEVICE_PATH            *DevicePath,
+    IN EFI_HANDLE                 Handle,
+    IN EFI_DEVICE_PATH            *RemainingDevicePath
+    );
 
-typedef struct {
-    UINT32                  MemoryType;
-    EFI_PHYSICAL_ADDRESS    StartingAddress;
-    EFI_PHYSICAL_ADDRESS    EndingAddress;
-} BDS_MEM_FILE;
-
-typedef struct {
-    EFI_FILE_PROTOCOL   *Handle;
-} BDS_FS_FILE;
+typedef EFI_STATUS (*BDS_FILE_LOADER_LOAD_IMAGE) (
+    IN     EFI_DEVICE_PATH        *DevicePath,
+    IN     EFI_HANDLE             Handle,
+    IN     EFI_DEVICE_PATH        *RemainingDevicePath,
+    IN     EFI_ALLOCATE_TYPE      Type,
+    IN OUT EFI_PHYSICAL_ADDRESS*  Image,
+    OUT    UINTN                  *ImageSize
+    );
 
 typedef struct {
-    EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
-    EFI_FV_FILETYPE               FileType;
-    EFI_GUID            Guid;
-} BDS_FV_FILE;
-
-typedef struct _BDS_FILE {
-    CHAR16* FilePath;
-    EFI_DEVICE_PATH_PROTOCOL    *DevicePath;
-    BDS_FILE_TYPE Type;
-    union {
-        BDS_MEM_FILE    Mem;
-        BDS_FS_FILE Fs;
-        BDS_FV_FILE Fv;
-    } File;
-} BDS_FILE;
+  BDS_FILE_LOADER_SUPPORT     Support;
+  BDS_FILE_LOADER_LOAD_IMAGE  LoadImage;
+} BDS_FILE_LOADER;
 
 typedef struct _BDS_SYSTEM_MEMORY_RESOURCE {
-    LIST_ENTRY                  Link; // This attribute must be the first entry of this structure (to avoid pointer computation)
-    EFI_PHYSICAL_ADDRESS        PhysicalStart;
-    UINT64                      ResourceLength;
+  LIST_ENTRY                  Link; // This attribute must be the first entry of this structure (to avoid pointer computation)
+  EFI_PHYSICAL_ADDRESS        PhysicalStart;
+  UINT64                      ResourceLength;
 } BDS_SYSTEM_MEMORY_RESOURCE;
 
 
 // BdsHelper.c
 EFI_STATUS
-ShutdownUefiBootServices( VOID );
+ShutdownUefiBootServices (
+  VOID
+  );
 
 EFI_STATUS
-GetSystemMemoryResources (LIST_ENTRY *ResourceList);
-
-// BdsFilePath.c
-EFI_STATUS BdsLoadDevicePath(
-    IN  EFI_DEVICE_PATH_PROTOCOL* DevicePath,
-    OUT EFI_HANDLE                *Handle
-);
-
-EFI_STATUS BdsLoadFilePath(
-    IN  CONST CHAR16        *DeviceFilePath,
-    OUT BDS_FILE            *File
-);
-
-EFI_STATUS BdsCopyRawFileToRuntimeMemory(
-    IN  BDS_FILE            *File,
-    OUT VOID                **FileImage,
-    OUT UINTN               *FileSize
-);
-
-// BdsFilePathFs.c
-EFI_STATUS BdsLoadFileFromSimpleFileSystem(
-    IN  EFI_HANDLE Handle,
-    IN  CHAR16                              *FilePath,
-    OUT BDS_FILE            *File
-);
-
-EFI_STATUS BdsCopyRawFileToRuntimeMemoryFS(
-    IN  EFI_FILE_PROTOCOL   *File,
-    OUT VOID                **FileImage,
-    OUT UINTN               *FileSize
-);
-
-// BdsFilePathFv.c
-EFI_STATUS BdsLoadFileFromFirmwareVolume(
-    IN  EFI_HANDLE          FvHandle,
-    IN  CHAR16                              *FilePath,
-    IN  EFI_FV_FILETYPE     FileTypeFilter,
-    OUT BDS_FILE            *File
-);
-
-EFI_STATUS BdsCopyRawFileToRuntimeMemoryFV(
-    IN  BDS_FV_FILE         *FvFile,
-    OUT VOID                **FileImage,
-    OUT UINTN               *FileSize
-);
-
-// BdsFilePathMem.c
-EFI_STATUS BdsLoadFileFromMemMap (
-    IN  EFI_HANDLE                  Handle,
-    IN  EFI_DEVICE_PATH_PROTOCOL    *DevicePath,
-    OUT BDS_FILE                    *File
-);
-
-EFI_STATUS BdsCopyRawFileToRuntimeMemoryMemMap(
-    IN  BDS_MEM_FILE        *MemFile,
-    OUT VOID                **FileImage,
-    OUT UINTN               *FileSize
-);
+GetSystemMemoryResources (
+  LIST_ENTRY *ResourceList
+  );
+
+VOID
+PrintPerformance (
+  VOID
+  );
+EFI_STATUS
+BdsLoadImage (
+  IN     EFI_DEVICE_PATH       *DevicePath,
+  IN     EFI_ALLOCATE_TYPE     Type,
+  IN OUT EFI_PHYSICAL_ADDRESS* Image,
+  OUT    UINTN                 *FileSize
+  );
 
 #endif
index 223f47b3dbb80897ab1251f526ebc9ce85da379a..d74eeda3a16ca371e913f03c77b88c5253c8032c 100644 (file)
   INF_VERSION                    = 0x00010005
   BASE_NAME                      = BdsLib
   FILE_GUID                      = ddbf73a0-bb25-11df-8e4e-0002a5d5c51b
-  MODULE_TYPE                    = UEFI_DRIVER
+  MODULE_TYPE                    = DXE_DRIVER
   VERSION_STRING                 = 1.0
   LIBRARY_CLASS                  = BdsLib
 
 [Sources.common]
   BdsFilePath.c
-  BdsFilePathFs.c
-  BdsFilePathFv.c
-  BdsFilePathMem.c
   BdsLinuxLoader.c
   BdsAppLoader.c
   BdsHelper.c
   ArmPkg/ArmPkg.dec
 
 [LibraryClasses]
-  DevicePathLib
+  ArmLib
   BaseLib
-  HobLib
   DebugLib
-  UefiDriverEntryPoint
-  DxeServicesTableLib
-  ArmLib
+  DevicePathLib
+  HobLib
+  PerformanceLib
 
 [Guids]
   gEfiFileInfoGuid
   gEfiDevicePathFromTextProtocolGuid
   gEfiSimpleFileSystemProtocolGuid
   gEfiFirmwareVolume2ProtocolGuid
+  gEfiLoadFileProtocolGuid
+  gEfiPxeBaseCodeProtocolGuid
+  gEfiDiskIoProtocolGuid
+  gEfiUsbIoProtocolGuid
     
 [FeaturePcd]  
 
 [FixedPcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+
   gArmTokenSpaceGuid.PcdArmMachineType
+  gArmTokenSpaceGuid.PcdArmLinuxKernelMaxOffset
+  gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset
   
 [Pcd]
   
index 69435936b7446429a859a37c1aed85d2d8a915aa..ca5e5470432489b71465d483ec6154e9210246cf 100644 (file)
 #include <Library/ArmLib.h>
 #include <Library/HobLib.h>
 
-STATIC
-EFI_STATUS
-GetARMLinuxMachineType (
-    IN  BOOLEAN FdtSupported,
-    OUT UINT32  *MachineType
-) {
-  if (FdtSupported)
-  {
-    // FDT requires that the machine type is set to the maximum 32-bit number.
-    *MachineType = 0xFFFFFFFF;
-  }
-  else
-  {
-    // Non-FDT requires a specific machine type.
-    // This OS Boot loader supports just one machine type,
-    // but that could change in the future.
-    *MachineType = PcdGet32(PcdArmMachineType);
-  }
+#define ALIGN32_BELOW(addr)   ALIGN_POINTER(addr - 32,32)
 
-  return EFI_SUCCESS;
-}
+#define LINUX_ATAG_MAX_OFFSET     (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxAtagMaxOffset))
+#define LINUX_KERNEL_MAX_OFFSET   (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxKernelMaxOffset))
+
+// Point to the current ATAG
+STATIC LINUX_ATAG *mLinuxKernelCurrentAtag;
 
 STATIC
 VOID
-SetupCoreTag( IN UINT32 PageSize )
+SetupCoreTag (
+  IN UINT32 PageSize
+  )
 {
-  Params->header.size = tag_size(atag_core);
-  Params->header.type = ATAG_CORE;
+  mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_CORE);
+  mLinuxKernelCurrentAtag->header.type = ATAG_CORE;
 
-  Params->body.core_tag.flags    = 1;            /* ensure read-only */
-  Params->body.core_tag.pagesize = PageSize;     /* systems PageSize (4k) */
-  Params->body.core_tag.rootdev  = 0;            /* zero root device (typically overridden from kernel command line )*/
+  mLinuxKernelCurrentAtag->body.core_tag.flags    = 1;            /* ensure read-only */
+  mLinuxKernelCurrentAtag->body.core_tag.pagesize = PageSize;     /* systems PageSize (4k) */
+  mLinuxKernelCurrentAtag->body.core_tag.rootdev  = 0;            /* zero root device (typically overridden from kernel command line )*/
 
-  Params = next_tag_address(Params);             /* move pointer to next tag */
+  // move pointer to next tag
+  mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
 }
 
 STATIC
 VOID
-SetupMemTag( IN UINTN StartAddress, IN UINT32 Size )
+SetupMemTag (
+  IN UINTN StartAddress,
+  IN UINT32 Size
+  )
 {
-  Params->header.size = tag_size(atag_mem);
-  Params->header.type = ATAG_MEM;
+  mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_MEM);
+  mLinuxKernelCurrentAtag->header.type = ATAG_MEM;
 
-  Params->body.mem_tag.start = StartAddress;    /* Start of memory chunk for AtagMem */
-  Params->body.mem_tag.size  = Size;             /* Size of memory chunk for AtagMem */
+  mLinuxKernelCurrentAtag->body.mem_tag.start = StartAddress;    /* Start of memory chunk for AtagMem */
+  mLinuxKernelCurrentAtag->body.mem_tag.size  = Size;             /* Size of memory chunk for AtagMem */
 
-  Params = next_tag_address(Params);             /* move pointer to next tag */
+  // move pointer to next tag
+  mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
 }
 
 STATIC
 VOID
-SetupCmdlineTag( IN CONST CHAR8 *CmdLine )
+SetupCmdlineTag (
+  IN CONST CHAR8 *CmdLine
+  )
 {
   UINT32 LineLength;
 
@@ -81,98 +76,92 @@ SetupCmdlineTag( IN CONST CHAR8 *CmdLine )
    * Do not insert a tag for an empty CommandLine, don't even modify the tag address pointer.
    * Remember, you have at least one null string terminator character.
    */
-  if( LineLength > 1 )
-  {
-    Params->header.size = ((UINT32)sizeof(struct atag_header) + LineLength + (UINT32)3) >> 2;
-    Params->header.type = ATAG_CMDLINE;
+  if(LineLength > 1) {
+    mLinuxKernelCurrentAtag->header.size = ((UINT32)sizeof(LINUX_ATAG_HEADER) + LineLength + (UINT32)3) >> 2;
+    mLinuxKernelCurrentAtag->header.type = ATAG_CMDLINE;
 
     /* place CommandLine into tag */
-    AsciiStrCpy(Params->body.cmdline_tag.cmdline, CmdLine);
+    AsciiStrCpy(mLinuxKernelCurrentAtag->body.cmdline_tag.cmdline, CmdLine);
 
-    Params = next_tag_address(Params);             /* move pointer to next tag */
+    // move pointer to next tag
+    mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
   }
 }
 
 STATIC
 VOID
-SetupEndTag( VOID )
+SetupEndTag (
+  VOID
+  )
 {
   // Empty tag ends list; this has zero length and no body
-  Params->header.type = ATAG_NONE;
-  Params->header.size = 0;
+  mLinuxKernelCurrentAtag->header.type = ATAG_NONE;
+  mLinuxKernelCurrentAtag->header.size = 0;
 
   /* We can not calculate the next address by using the standard macro:
    * Params = next_tag_address(Params);
    * because it relies on the header.size, which here it is 0 (zero).
-   * The easiest way is to add the sizeof(Params->header).
+   * The easiest way is to add the sizeof(mLinuxKernelCurrentAtag->header).
    */
-  Params = (struct atag *)((UINT32)Params + sizeof(Params->header));
+  mLinuxKernelCurrentAtag = (LINUX_ATAG*)((UINT32)mLinuxKernelCurrentAtag + sizeof(mLinuxKernelCurrentAtag->header));
 }
 
 STATIC
 EFI_STATUS
-PrepareAtagList(
-    IN OUT struct atag      **AtagStartAddress,
-    IN     CONST CHAR8*     CommandLineString,
-    OUT    UINT32           *AtagSize
-) {
-  LIST_ENTRY    *ResourceLink;
-  LIST_ENTRY ResourceList;
+PrepareAtagList (
+  IN  CONST CHAR8*     CommandLineString,
+  OUT LINUX_ATAG       **AtagBase,
+  OUT UINT32           *AtagSize
+  )
+{
+  EFI_STATUS                  Status;
+  LIST_ENTRY                  *ResourceLink;
+  LIST_ENTRY                  ResourceList;
+  EFI_PHYSICAL_ADDRESS        AtagStartAddress;
   BDS_SYSTEM_MEMORY_RESOURCE  *Resource;
 
-  // If no address supplied then this function will decide where to put it
-  if( *AtagStartAddress == 0 )
-  {
-    /* WARNING: At the time of writing (2010-July-30) the linux kernel expects
-     * the atag list it in the first 1MB of memory and preferably at address 0x100.
-     * This has a very high risk of overwriting UEFI code, but as
-     * the linux kernel does not expect any runtime services from uefi
-     * and there is no afterlife section following the linux kernel termination,
-     * it does not matter if we stamp over that memory area.
-     *
-     * The proposed workaround is to create the atag list somewhere in boot services memory
-     * and then transfer it to address 0x100 (or to runtime services memory) immediately
-     * before starting the kernel.
-     * An additional benefit of this is that when we copy the ATAG list to it's final place,
-     * we can trim down the memory allocation size. Before we create the list we don't know
-     * how much space it is going to take, so we are over-allocating space.
-     */
-    *AtagStartAddress = (struct atag *) AllocatePool(ATAG_MAX_SIZE);
+  AtagStartAddress = LINUX_ATAG_MAX_OFFSET;
+  Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((EFI_D_ERROR,"Failed to allocate Atag at 0x%lX (%r)\n",AtagStartAddress,Status));
+    Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);
+    ASSERT_EFI_ERROR(Status);
   }
 
-  // Ensure the pointer is not NULL.
-  ASSERT( *AtagStartAddress != (struct atag *)NULL );
-
   // Ready to setup the atag list
-  Params = *AtagStartAddress;
+  mLinuxKernelCurrentAtag = (LINUX_ATAG*)(UINTN)AtagStartAddress;
 
   // Standard core tag 4k PageSize
   SetupCoreTag( (UINT32)SIZE_4KB );
 
   // Physical memory setup
-  GetSystemMemoryResources(&ResourceList);
+  GetSystemMemoryResources (&ResourceList);
   ResourceLink = ResourceList.ForwardLink;
   while (ResourceLink != NULL && ResourceLink != &ResourceList) {
-    Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceList.ForwardLink;
+    Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceLink;
+    DEBUG((EFI_D_INFO,"- [0x%08X,0x%08X]\n",(UINT32)Resource->PhysicalStart,(UINT32)Resource->PhysicalStart+(UINT32)Resource->ResourceLength));
     SetupMemTag( (UINT32)Resource->PhysicalStart, (UINT32)Resource->ResourceLength );
     ResourceLink = ResourceLink->ForwardLink;
   }
 
   // CommandLine setting root device
-  SetupCmdlineTag( CommandLineString );
+  SetupCmdlineTag (CommandLineString);
 
   // end of tags
   SetupEndTag();
 
   // Calculate atag list size
-  *AtagSize = (UINT32)Params - (UINT32)*AtagStartAddress + 1;
+  *AtagBase = (LINUX_ATAG*)(UINTN)AtagStartAddress;
+  *AtagSize = (UINT32)mLinuxKernelCurrentAtag - (UINT32)AtagStartAddress + 1;
 
   return EFI_SUCCESS;
 }
 
 STATIC
 EFI_STATUS
-PreparePlatformHardware( VOID )
+PreparePlatformHardware (
+  VOID
+  )
 {
   //Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called.
 
@@ -185,153 +174,131 @@ PreparePlatformHardware( VOID )
   ArmDisableInstructionCache ();
 
   // turn off MMU
-  ArmInvalidateTlb();
   ArmDisableMmu();
 
   return EFI_SUCCESS;
 }
 
-/*************************************************
- * R0, R1, R2 correspond to registers R0, R1, R2
- *************************************************/
-//STATIC
-EFI_STATUS
-StartLinuxKernel( IN VOID* KernelAddress, IN UINTN R0, IN UINTN R1, IN UINTN R2 )
-{
-  VOID     (*Kernel)(UINT32 Zero, UINT32 Arch, UINTN AtagListParams);
+/**
+  Start a Linux kernel from a Device Path
 
-  // set the kernel address
-  Kernel = (VOID (*)(UINT32, UINT32, UINTN)) KernelAddress;
+  @param  LinuxKernel           Device Path to the Linux Kernel
+  @param  Parameters            Linux kernel agruments
+  @param  Fdt                   Device Path to the Flat Device Tree
 
-  // Outside BootServices, so can't use Print();
-  DEBUG((EFI_D_ERROR, "\nStarting the kernel:\n\n"));
+  @retval EFI_SUCCESS           All drivers have been connected
+  @retval EFI_NOT_FOUND         The Linux kernel Device Path has not been found
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource memory to store the matching results.
 
-  // jump to kernel with register set
-  Kernel( R0, R1, R2 );
+**/
+EFI_STATUS
+BdsBootLinux (
+  IN  EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,
+  IN  CONST CHAR8*  Arguments,
+  IN  EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath
+  )
+{
+  EFI_STATUS            Status;
+  UINT32                LinuxImageSize;
+  UINT32                KernelParamsSize;
+  VOID*                 KernelParamsAddress = NULL;
+  UINT32                MachineType;
+  BOOLEAN               FdtSupported = FALSE;
+  LINUX_KERNEL          LinuxKernel;
+  EFI_PHYSICAL_ADDRESS  LinuxImage;;
+
+
+  PERF_START (NULL, "BDS", NULL, 0);
+
+  // Load the Linux kernel from a device path
+  LinuxImage = LINUX_KERNEL_MAX_OFFSET;
+  Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((EFI_D_ERROR, "ERROR: Do not find Linux kernel.\n"));
+    return Status;
+  }
+  LinuxKernel = (LINUX_KERNEL)(UINTN)LinuxImage;
 
-  // Kernel should never exit
-  // After Life services are not provided
-  ASSERT( FALSE );
+  // Load the FDT binary from a device path
+  KernelParamsAddress = (VOID*)LINUX_ATAG_MAX_OFFSET;
+  Status = BdsLoadImage (FdtDevicePath, AllocateMaxAddress, (EFI_PHYSICAL_ADDRESS*)&KernelParamsAddress, &KernelParamsSize);
+  if (!EFI_ERROR(Status)) {
+    FdtSupported = TRUE;
+  }
 
-  return EFI_SUCCESS;
-}
+  //
+  // Setup the Linux Kernel Parameters
+  //
+  if (!FdtSupported) {
+    // Non-FDT requires a specific machine type.
+    // This OS Boot loader supports just one machine type,
+    // but that could change in the future.
+    MachineType = PcdGet32(PcdArmMachineType);
 
-EFI_STATUS BdsBootLinux(
-    IN  CONST CHAR16* LinuxKernel,
-    IN  CONST CHAR8*  ATag,
-    IN  CONST CHAR16* Fdt
-) {
-    BDS_FILE   LinuxKernelFile;
-    BDS_FILE   FdtFile;
-    EFI_STATUS          Status;
-    VOID*               LinuxImage;
-
-    UINT32              KernelParamsSize;
-    VOID*               KernelParamsAddress = NULL;
-    UINTN               KernelParamsNewAddress;
-    UINTN               *AtagAddress;
-    UINT32              MachineType;
-    BOOLEAN             FdtSupported = FALSE;
-    EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;
-
-    // Load the Linux kernel from a device path
-    Status = BdsLoadFilePath(LinuxKernel, &LinuxKernelFile);
-    if (EFI_ERROR(Status)) {
-        DEBUG ((EFI_D_ERROR, "ERROR: Do not find Linux kernel %s\n",LinuxKernel));
-        return Status;
+    // By setting address=0 we leave the memory allocation to the function
+    Status = PrepareAtagList (Arguments, (LINUX_ATAG**)&KernelParamsAddress, &KernelParamsSize);
+    if(EFI_ERROR(Status)) {
+      Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status);
+      goto Exit;
     }
+  } else {
+    MachineType = 0xFFFFFFFF;
+  }
 
-    // Copy the Linux Kernel from the raw file to Runtime memory
-    Status = BdsCopyRawFileToRuntimeMemory(&LinuxKernelFile,&LinuxImage,NULL);
-    if (EFI_ERROR(Status)) {
-        goto Exit;
-    }
+  // Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on
+  // ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event.
+  Status = ShutdownUefiBootServices ();
+  if(EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%X\n", Status));
+    goto Exit;
+  }
 
-    // Load the FDT binary from a device path
-    Status = BdsLoadFilePath(Fdt, &FdtFile);
-    if (!EFI_ERROR(Status)) {
-        // Copy the FDT binary from the raw file to Runtime memory
-        Status = BdsCopyRawFileToRuntimeMemory(&FdtFile,&KernelParamsAddress,&KernelParamsSize);
-        if (EFI_ERROR(Status)) {
-            goto Exit;
-        } else {
-            FdtSupported = TRUE;
-        }
-    }
+  // Move the kernel parameters to any address inside the first 1MB.
+  // This is necessary because the ARM Linux kernel requires
+  // the FTD / ATAG List to reside entirely inside the first 1MB of
+  // physical memory.
+  if ((UINTN)KernelParamsAddress > LINUX_ATAG_MAX_OFFSET) {
+    //Note: There is no requirement on the alignment
+    KernelParamsAddress = CopyMem (ALIGN32_BELOW(LINUX_ATAG_MAX_OFFSET - KernelParamsSize), KernelParamsAddress, KernelParamsSize);
+  }
 
-    /**********************************************************
-    * Setup the platform type
-    **********************************************************/
-    Status = GetARMLinuxMachineType(FdtSupported, &MachineType);
-    if(EFI_ERROR(Status))
-    {
-        Print(L"ERROR  : Can not prepare ARM Linux machine type. Status=0x%X\n", Status);
-        goto Exit;
-    }
+  if ((UINTN)LinuxImage > LINUX_KERNEL_MAX_OFFSET) {
+    //Note: There is no requirement on the alignment
+    LinuxKernel = (LINUX_KERNEL)CopyMem (ALIGN32_BELOW(LINUX_KERNEL_MAX_OFFSET - LinuxImageSize), (VOID*)(UINTN)LinuxImage, LinuxImageSize);
+  }
 
-    if (!FdtSupported) {
-        /**********************************************************
-         * Setup the ATAG list
-         **********************************************************/
-        // By setting address=0 we leave the memory allocation to the function
-        AtagAddress = 0;
-        Status = PrepareAtagList( (struct atag **)&AtagAddress, ATag, &KernelParamsSize );
-        KernelParamsAddress = (VOID*)AtagAddress;
-        if(EFI_ERROR(Status))
-        {
-            Print(L"ERROR  : Can not prepare ATAG list. Status=0x%X\n", Status);
-            goto Exit;
-        }
-    }
+  //TODO: Check there is no overlapping between kernel and Atag
 
-    /**********************************************************
-    * Switch off interrupts, caches, mmu, etc
-    **********************************************************/
-    Status = PreparePlatformHardware();
-    if(EFI_ERROR(Status))
-    {
-        Print(L"ERROR  : Can not prepare platform hardware. Status=0x%X\n", Status);
-        goto Exit;
-    }
+  //
+  // Switch off interrupts, caches, mmu, etc
+  //
+  Status = PreparePlatformHardware ();
+  ASSERT_EFI_ERROR(Status);
 
-    // Initialize the ATag destination
-    KernelParamsNewAddress = 0x100;
-
-    // Update the ATag destination by finding the start address of the first System Memory Resource Descriptor Hob
-    ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
-    while (ResHob != NULL) {
-        if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
-            KernelParamsNewAddress = (UINTN)ResHob->PhysicalStart + 0x100;
-            break;
-        }
-        ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength)); 
-    }
+  // Register and print out performance information
+  PERF_END (NULL, "BDS", NULL, 0);
+  if (PerformanceMeasurementEnabled ()) {
+    PrintPerformance ();
+  }
 
-    // Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on
-    // ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event.
-    Status = ShutdownUefiBootServices();
-    if(EFI_ERROR(Status))
-    {
-        Print(L"ERROR  : Can not shutdown UEFI boot services. Status=0x%X\n", Status);
-        goto Exit;
-    }
+  //
+  // Start the Linux Kernel
+  //
 
-    // Move the kernel parameters to any address inside the first 1MB.
-    // This is necessary because the ARM Linux kernel requires
-    // the FTD / ATAG List to reside entirely inside the first 1MB of
-    // physical memory.
-    CopyMem((VOID*)KernelParamsNewAddress, KernelParamsAddress, KernelParamsSize);
+  // Outside BootServices, so can't use Print();
+  DEBUG((EFI_D_ERROR, "\nStarting the kernel:\n\n"));
 
-    //**********************************************************
-    // * Start the Linux Kernel
-    // **********************************************************
-    // Lift off ...
-    Status = StartLinuxKernel(LinuxImage, (UINTN)0, (UINTN)MachineType, KernelParamsNewAddress );
+  // jump to kernel with register set
+  LinuxKernel ((UINTN)0, (UINTN)MachineType, (UINTN)KernelParamsAddress);
 
-    // Only be here if we fail to start Linux
-    DEBUG((EFI_D_ERROR, "ERROR  : Can not start the kernel. Status=0x%X\n", Status));
+  // Kernel should never exit
+  // After Life services are not provided
+  ASSERT(FALSE);
 
 Exit:
-    // Free Runtimee Memory (kernel and FDT)
-    return Status;
+  // Only be here if we fail to start Linux
+  Print (L"ERROR  : Can not start the kernel. Status=0x%X\n", Status);
+
+  // Free Runtimee Memory (kernel and FDT)
+  return Status;
 }
index 2869f652f867ea60658092cba960afe4772bf3fa..82b7a4f081263fe51e31f1c2256b2a5bc4700748 100644 (file)
@@ -15,8 +15,7 @@
 #ifndef __BDSLINUXLOADER_H
 #define __BDSLINUXLOADER_H
 
-#define ATAG_MAX_SIZE       0x4000
-//PcdKernelParamsMaxMemorySize
+#define ATAG_MAX_SIZE       0x3000
 
 /* ATAG : list of possible tags */
 #define ATAG_NONE            0x00000000
 #define ATAG_CMDLINE         0x54410009
 #define ATAG_ARM_MP_CORE     0x5441000A
 
-// Some system addresses
-// These should probably come from the platform header file or from pcd values
-#define DRAM_BASE            0x10000000
-#define ZIMAGE_LOAD_ADDRESS  (DRAM_BASE + 0x8000)
-#define INITRD_LOAD_ADDRESS  (DRAM_BASE + 0x800000)
-
-#define SIZE_1B              0x00000001
-#define SIZE_2B              0x00000002
-#define SIZE_4B              0x00000004
-#define SIZE_8B              0x00000008
-#define SIZE_16B             0x00000010
-#define SIZE_32B             0x00000020
-#define SIZE_64B             0x00000040
-#define SIZE_128B            0x00000080
-#define SIZE_256B            0x00000100
-#define SIZE_512B            0x00000200
-#define SIZE_1KB             0x00000400
-#define SIZE_2KB             0x00000800
-#define SIZE_4KB             0x00001000
-#define SIZE_8KB             0x00002000
-#define SIZE_16KB            0x00004000
-#define SIZE_32KB            0x00008000
-#define SIZE_64KB            0x00010000
-#define SIZE_128KB           0x00020000
-#define SIZE_256KB           0x00040000
-#define SIZE_512KB           0x00080000
-#define SIZE_1MB             0x00100000
-#define SIZE_2MB             0x00200000
-#define SIZE_4MB             0x00400000
-#define SIZE_8MB             0x00800000
-#define SIZE_16MB            0x01000000
-#define SIZE_32MB            0x02000000
-#define SIZE_64MB            0x04000000
-#define SIZE_100MB           0x06400000
-#define SIZE_128MB           0x08000000
-#define SIZE_256MB           0x10000000
-#define SIZE_512MB           0x20000000
-#define SIZE_1GB             0x40000000
-#define SIZE_2GB             0x80000000
-
 /* structures for each atag */
-struct atag_header {
+typedef struct {
   UINT32  size; /* length of tag in words including this header */
   UINT32  type;  /* tag type */
-};
+} LINUX_ATAG_HEADER;
 
-struct atag_core {
+typedef struct {
   UINT32  flags;
   UINT32  pagesize;
   UINT32  rootdev;
-};
+} LINUX_ATAG_CORE;
 
-struct atag_mem {
+typedef struct {
   UINT32  size;
   UINTN  start;
-};
+} LINUX_ATAG_MEM;
 
-struct atag_videotext {
+typedef struct {
   UINT8   x;
   UINT8   y;
   UINT16  video_page;
@@ -98,29 +57,29 @@ struct atag_videotext {
   UINT8   video_lines;
   UINT8   video_isvga;
   UINT16  video_points;
-};
+} LINUX_ATAG_VIDEOTEXT;
 
-struct atag_ramdisk {
+typedef struct {
   UINT32  flags;
   UINT32  size;
   UINTN  start;
-};
+} LINUX_ATAG_RAMDISK;
 
-struct atag_initrd2 {
+typedef struct {
   UINT32  start;
   UINT32  size;
-};
+} LINUX_ATAG_INITRD2;
 
-struct atag_serialnr {
+typedef struct {
   UINT32  low;
   UINT32  high;
-};
+} LINUX_ATAG_SERIALNR;
 
-struct atag_revision {
+typedef struct {
   UINT32  rev;
-};
+} LINUX_ATAG_REVISION;
 
-struct atag_videolfb {
+typedef struct {
   UINT16  lfb_width;
   UINT16  lfb_height;
   UINT16  lfb_depth;
@@ -135,31 +94,30 @@ struct atag_videolfb {
   UINT8   blue_pos;
   UINT8   rsvd_size;
   UINT8   rsvd_pos;
-};
+} LINUX_ATAG_VIDEOLFB;
 
-struct atag_cmdline {
+typedef struct {
   CHAR8   cmdline[1];
-};
+} LINUX_ATAG_CMDLINE;
 
-struct atag {
-  struct atag_header header;
+typedef struct {
+  LINUX_ATAG_HEADER header;
   union {
-    struct atag_core         core_tag;
-    struct atag_mem          mem_tag;
-    struct atag_videotext    videotext_tag;
-    struct atag_ramdisk      ramdisk_tag;
-    struct atag_initrd2      initrd2_tag;
-    struct atag_serialnr     serialnr_tag;
-    struct atag_revision     revision_tag;
-    struct atag_videolfb     videolfb_tag;
-    struct atag_cmdline      cmdline_tag;
+    LINUX_ATAG_CORE         core_tag;
+    LINUX_ATAG_MEM          mem_tag;
+    LINUX_ATAG_VIDEOTEXT    videotext_tag;
+    LINUX_ATAG_RAMDISK      ramdisk_tag;
+    LINUX_ATAG_INITRD2      initrd2_tag;
+    LINUX_ATAG_SERIALNR     serialnr_tag;
+    LINUX_ATAG_REVISION     revision_tag;
+    LINUX_ATAG_VIDEOLFB     videolfb_tag;
+    LINUX_ATAG_CMDLINE      cmdline_tag;
   } body;
-};
+} LINUX_ATAG;
 
-#define next_tag_address(t)     ((struct atag *)((UINT32)(t) + (((t)->header.size) << 2) ))
-#define tag_size(type)  ((UINT32)((sizeof(struct atag_header) + sizeof(struct type)) >> 2))
+typedef VOID (*LINUX_KERNEL)(UINT32 Zero, UINT32 Arch, UINTN ParametersBase);
 
-STATIC struct atag *Params; /* used to point at the current tag */
+#define next_tag_address(t)     ((LINUX_ATAG*)((UINT32)(t) + (((t)->header.size) << 2) ))
+#define tag_size(type)          ((UINT32)((sizeof(LINUX_ATAG_HEADER) + sizeof(type)) >> 2))
 
 #endif
-