summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ArmPkg/ArmPkg.dec7
-rw-r--r--ArmPkg/Include/Library/BdsLib.h66
-rw-r--r--ArmPkg/Include/Library/BdsUnixLib.h33
-rw-r--r--ArmPkg/Library/BdsLib/BdsAppLoader.c328
-rw-r--r--ArmPkg/Library/BdsLib/BdsFilePath.c912
-rw-r--r--ArmPkg/Library/BdsLib/BdsFilePathFs.c86
-rw-r--r--ArmPkg/Library/BdsLib/BdsFilePathFv.c136
-rw-r--r--ArmPkg/Library/BdsLib/BdsFilePathMem.c73
-rw-r--r--ArmPkg/Library/BdsLib/BdsHelper.c508
-rw-r--r--ArmPkg/Library/BdsLib/BdsInternal.h127
-rw-r--r--ArmPkg/Library/BdsLib/BdsLib.inf23
-rw-r--r--ArmPkg/Library/BdsLib/BdsLinuxLoader.c375
-rw-r--r--ArmPkg/Library/BdsLib/BdsLinuxLoader.h114
13 files changed, 1635 insertions, 1153 deletions
diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
index 37fc7f2931..0357810c56 100644
--- a/ArmPkg/ArmPkg.dec
+++ b/ArmPkg/ArmPkg.dec
@@ -125,7 +125,8 @@
# BdsLib
#
gArmTokenSpaceGuid.PcdArmMachineType|0|UINT32|0x0000001E
- gArmTokenSpaceGuid.PcdLinuxKernelDP|L""|VOID*|0x0000001F
- gArmTokenSpaceGuid.PcdLinuxAtag|""|VOID*|0x00000020
- gArmTokenSpaceGuid.PcdFdtDP|L""|VOID*|0x00000021
+ # The compressed Linux kernel is expected to be under 128MB from the beginning of the System Memory
+ gArmTokenSpaceGuid.PcdArmLinuxKernelMaxOffset|0x08000000|UINT32|0x0000001F
+ # The Linux ATAGs are expected to be under 0x4000 (16KB) from the beginning of the System Memory
+ gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset|0x4000|UINT32|0x00000020
diff --git a/ArmPkg/Include/Library/BdsLib.h b/ArmPkg/Include/Library/BdsLib.h
new file mode 100644
index 0000000000..a6ae2f108b
--- /dev/null
+++ b/ArmPkg/Include/Library/BdsLib.h
@@ -0,0 +1,66 @@
+/** @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.
+*
+**/
+
+#ifndef __BDS_ENTRY_H__
+#define __BDS_ENTRY_H__
+
+/**
+ 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
+ );
+
+/**
+ Start a Linux kernel from a Device Path
+
+ @param LinuxKernel Device Path to the Linux Kernel
+ @param Parameters Linux kernel agruments
+ @param Fdt Device Path to the Flat Device Tree
+
+ @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
+BdsBootLinux (
+ IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,
+ IN CONST CHAR8* Arguments,
+ IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath
+ );
+
+/**
+ 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
+ );
+
+#endif
diff --git a/ArmPkg/Include/Library/BdsUnixLib.h b/ArmPkg/Include/Library/BdsUnixLib.h
index 969f951124..d5f5ffa202 100644
--- a/ArmPkg/Include/Library/BdsUnixLib.h
+++ b/ArmPkg/Include/Library/BdsUnixLib.h
@@ -12,27 +12,26 @@
*
**/
-#ifndef __BDS_ENTRY_H__
-#define __BDS_ENTRY_H__
+#ifndef _BDS_UNIX_LIB_H_
+#define _BDS_UNIX_LIB_H_
-EFI_STATUS
-BdsConnectAllDrivers ( VOID );
+/**
+ Start a Linux kernel from a Device Path
-EFI_STATUS
-BdsBootLinux (
- IN CONST CHAR16* LinuxKernel,
- IN CONST CHAR8* ATag,
- IN CONST CHAR16* Fdt
-);
+ @param LinuxKernel Device Path to the Linux Kernel
+ @param Parameters Linux kernel agruments
+ @param Fdt Device Path to the Flat Device Tree
-EFI_STATUS
-BdsLoadApplication (
- IN CHAR16* EfiApp
-);
+ @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
-BdsLoadApplicationFromPath (
- IN CHAR16* EfiAppPath
-);
+BdsBootLinux (
+ IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,
+ IN CONST CHAR8* Arguments,
+ IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath
+ );
#endif
diff --git a/ArmPkg/Library/BdsLib/BdsAppLoader.c b/ArmPkg/Library/BdsLib/BdsAppLoader.c
index 16b45ceb4c..d14e3c5dcc 100644
--- a/ArmPkg/Library/BdsLib/BdsAppLoader.c
+++ b/ArmPkg/Library/BdsLib/BdsAppLoader.c
@@ -1,111 +1,217 @@
-/** @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
-BdsLoadPeCoff (
- IN BDS_FILE *EfiAppFile
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE ImageHandle;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH NewNode;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
-
- // Only support loading from FV right now
- ASSERT(EfiAppFile->Type == BDS_FILETYPE_FV);
-
- // Generate the Device Path for the file
- DevicePath = DuplicateDevicePath(EfiAppFile->DevicePath);
- EfiInitializeFwVolDevicepathNode (&NewNode, &(EfiAppFile->File.Fv.Guid));
- DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&NewNode);
-
- Status = gBS->LoadImage (TRUE, gImageHandle, DevicePath, NULL, 0, &ImageHandle);
- if (!EFI_ERROR (Status)) {
- //
- // Before calling the image, enable the Watchdog Timer for
- // the 5 Minute period
- //
- gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
- Status = gBS->StartImage (ImageHandle, NULL, NULL);
- //
- // Clear the Watchdog Timer after the image returns
- //
- gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
- }
-
- return Status;
-}
-
-EFI_STATUS BdsLoadApplicationFromPath(
- IN CHAR16* EfiAppPath
-) {
- EFI_STATUS Status;
- BDS_FILE EfiAppFile;
-
- // 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;
- }
-
- // Locate the application from a device path
- Status = BdsLoadFilePath(EfiAppPath, &EfiAppFile);
- if (EFI_ERROR(Status)) {
- DEBUG ((EFI_D_ERROR, "ERROR: Do not find EFI application %s\n",EfiAppPath));
- return Status;
- }
-
- // Start the application
- Status = BdsLoadPeCoff(&EfiAppFile);
-
- return Status;
-}
-
-EFI_STATUS BdsLoadApplication(
- IN CHAR16* EfiApp
-) {
- EFI_STATUS Status;
- UINTN NoHandles, HandleIndex;
- EFI_HANDLE *Handles;
- BDS_FILE EfiAppFile;
-
- // 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,&EfiAppFile);
- if (!EFI_ERROR (Status)) {
- // Start the application
- Status = BdsLoadPeCoff(&EfiAppFile);
- return Status;
- }
- }
-
- return Status;
-}
+/** @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;
+}
diff --git a/ArmPkg/Library/BdsLib/BdsFilePath.c b/ArmPkg/Library/BdsLib/BdsFilePath.c
index b1460b9c9d..f7a06e5a89 100644
--- a/ArmPkg/Library/BdsLib/BdsFilePath.c
+++ b/ArmPkg/Library/BdsLib/BdsFilePath.c
@@ -14,169 +14,829 @@
#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
index 0b7f9d39a5..0000000000
--- a/ArmPkg/Library/BdsLib/BdsFilePathFs.c
+++ /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
index f5b4e57cbf..0000000000
--- a/ArmPkg/Library/BdsLib/BdsFilePathFv.c
+++ /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
index dddaa3d670..0000000000
--- a/ArmPkg/Library/BdsLib/BdsFilePathMem.c
+++ /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;
-}
diff --git a/ArmPkg/Library/BdsLib/BdsHelper.c b/ArmPkg/Library/BdsLib/BdsHelper.c
index 88e8fa3453..fa9483ea81 100644
--- a/ArmPkg/Library/BdsLib/BdsHelper.c
+++ b/ArmPkg/Library/BdsLib/BdsHelper.c
@@ -1,223 +1,285 @@
-/** @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>
-
-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;
-}
-
-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;
-}
+/** @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);
+}
diff --git a/ArmPkg/Library/BdsLib/BdsInternal.h b/ArmPkg/Library/BdsLib/BdsInternal.h
index 07f722e03f..a497df03ea 100644
--- a/ArmPkg/Library/BdsLib/BdsInternal.h
+++ b/ArmPkg/Library/BdsLib/BdsInternal.h
@@ -24,6 +24,7 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/BdsUnixLib.h>
+#include <Library/PerformanceLib.h>
#include <Guid/FileInfo.h>
@@ -31,106 +32,58 @@
#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
diff --git a/ArmPkg/Library/BdsLib/BdsLib.inf b/ArmPkg/Library/BdsLib/BdsLib.inf
index 223f47b3db..d74eeda3a1 100644
--- a/ArmPkg/Library/BdsLib/BdsLib.inf
+++ b/ArmPkg/Library/BdsLib/BdsLib.inf
@@ -15,15 +15,12 @@
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
@@ -34,13 +31,12 @@
ArmPkg/ArmPkg.dec
[LibraryClasses]
- DevicePathLib
+ ArmLib
BaseLib
- HobLib
DebugLib
- UefiDriverEntryPoint
- DxeServicesTableLib
- ArmLib
+ DevicePathLib
+ HobLib
+ PerformanceLib
[Guids]
gEfiFileInfoGuid
@@ -51,11 +47,20 @@
gEfiDevicePathFromTextProtocolGuid
gEfiSimpleFileSystemProtocolGuid
gEfiFirmwareVolume2ProtocolGuid
+ gEfiLoadFileProtocolGuid
+ gEfiPxeBaseCodeProtocolGuid
+ gEfiDiskIoProtocolGuid
+ gEfiUsbIoProtocolGuid
[FeaturePcd]
[FixedPcd]
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+
gArmTokenSpaceGuid.PcdArmMachineType
+ gArmTokenSpaceGuid.PcdArmLinuxKernelMaxOffset
+ gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset
[Pcd]
diff --git a/ArmPkg/Library/BdsLib/BdsLinuxLoader.c b/ArmPkg/Library/BdsLib/BdsLinuxLoader.c
index 69435936b7..ca5e547043 100644
--- a/ArmPkg/Library/BdsLib/BdsLinuxLoader.c
+++ b/ArmPkg/Library/BdsLib/BdsLinuxLoader.c
@@ -19,58 +19,53 @@
#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;
}
diff --git a/ArmPkg/Library/BdsLib/BdsLinuxLoader.h b/ArmPkg/Library/BdsLib/BdsLinuxLoader.h
index 2869f652f8..82b7a4f081 100644
--- a/ArmPkg/Library/BdsLib/BdsLinuxLoader.h
+++ b/ArmPkg/Library/BdsLib/BdsLinuxLoader.h
@@ -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
@@ -31,64 +30,24 @@
#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
-