summaryrefslogtreecommitdiff
path: root/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe
diff options
context:
space:
mode:
Diffstat (limited to 'ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe')
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c81
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf76
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h36
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/InstallFdt.c423
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.c486
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.h284
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciRootBridgeIo.c299
7 files changed, 1685 insertions, 0 deletions
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
new file mode 100644
index 0000000000..70d632927a
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
@@ -0,0 +1,81 @@
+/** @file
+*
+* Copyright (c) 2013-2014, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "ArmJunoDxeInternal.h"
+#include <Library/ArmShellCmdLib.h>
+
+EFI_STATUS
+EFIAPI
+ArmJunoEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS HypBase;
+
+ Status = PciEmulationEntryPoint ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // If a hypervisor has been declared then we need to make sure its region is protected at runtime
+ //
+ // Note: This code is only a workaround for our dummy hypervisor (ArmPkg/Extra/AArch64ToAArch32Shim/)
+ // that does not set up (yet) the stage 2 translation table to hide its own memory to EL1.
+ //
+ if (FixedPcdGet32 (PcdHypFvSize) != 0) {
+ // Ensure the hypervisor region is strictly contained into a EFI_PAGE_SIZE-aligned region.
+ // The memory must be a multiple of EFI_PAGE_SIZE to ensure we do not reserve more memory than the hypervisor itself.
+ // A UEFI Runtime region size granularity cannot be smaller than EFI_PAGE_SIZE. If the hypervisor size is not rounded
+ // to this size then there is a risk some non-runtime memory could be visible to the OS view.
+ if (((FixedPcdGet32 (PcdHypFvSize) & EFI_PAGE_MASK) == 0) && ((FixedPcdGet32 (PcdHypFvBaseAddress) & EFI_PAGE_MASK) == 0)) {
+ // The memory needs to be declared because the DXE core marked it as reserved and removed it from the memory space
+ // as it contains the Firmware.
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeSystemMemory,
+ FixedPcdGet32 (PcdHypFvBaseAddress), FixedPcdGet32 (PcdHypFvSize),
+ EFI_MEMORY_WB | EFI_MEMORY_RUNTIME
+ );
+ if (!EFI_ERROR (Status)) {
+ // We allocate the memory to ensure it is marked as runtime memory
+ HypBase = FixedPcdGet32 (PcdHypFvBaseAddress);
+ Status = gBS->AllocatePages (AllocateAddress, EfiRuntimeServicesCode,
+ EFI_SIZE_TO_PAGES (FixedPcdGet32 (PcdHypFvSize)), &HypBase);
+ }
+ } else {
+ // The hypervisor must be contained into a EFI_PAGE_SIZE-aligned region and its size must also be aligned
+ // on a EFI_PAGE_SIZE boundary (ie: 4KB).
+ Status = EFI_UNSUPPORTED;
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ // Install dynamic Shell command to run baremetal binaries.
+ Status = ShellDynCmdRunAxfInstall (ImageHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ArmJunoDxe: Failed to install ShellDynCmdRunAxf\n"));
+ }
+
+ // Try to install the Flat Device Tree (FDT). This function actually installs the
+ // UEFI Driver Binding Protocol.
+ Status = JunoFdtInstall (ImageHandle);
+
+ return Status;
+}
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
new file mode 100644
index 0000000000..bf930d23d9
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
@@ -0,0 +1,76 @@
+#
+# Copyright (c) 2013-2014, ARM Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmJunoDxe
+ FILE_GUID = 1484ebe8-2681-45f1-a2e5-12ecad893b62
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = ArmJunoEntryPoint
+
+[Sources.common]
+ ArmJunoDxe.c
+ InstallFdt.c
+ PciEmulation.c
+ PciRootBridgeIo.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ ArmShellCmdRunAxfLib
+ BaseMemoryLib
+ BdsLib
+ DebugLib
+ DmaLib
+ DxeServicesTableLib
+ FdtLib
+ IoLib
+ PcdLib
+ PrintLib
+ SerialPortLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiLib
+ UefiDriverEntryPoint
+
+[Guids]
+ gArmGlobalVariableGuid
+ gEfiEndOfDxeEventGroupGuid
+ gEfiFileInfoGuid
+ gFdtTableGuid
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathFromTextProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+
+ gArmTokenSpaceGuid.PcdHypFvBaseAddress
+ gArmTokenSpaceGuid.PcdHypFvSize
+
+ gArmJunoTokenSpaceGuid.PcdSynopsysUsbEhciBaseAddress
+ gArmJunoTokenSpaceGuid.PcdSynopsysUsbOhciBaseAddress
+
+ gArmPlatformTokenSpaceGuid.PcdFdtDevicePath
+
+[Depex]
+ TRUE
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h
new file mode 100644
index 0000000000..5ebb5161f8
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h
@@ -0,0 +1,36 @@
+/** @file
+*
+* Copyright (c) 2013-2014, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __ARM_JUNO_DXE_INTERNAL_H__
+#define __ARM_JUNO_DXE_INTERNAL_H__
+
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <IndustryStandard/Acpi.h>
+
+EFI_STATUS
+PciEmulationEntryPoint (
+ VOID
+ );
+
+EFI_STATUS
+JunoFdtInstall (
+ IN EFI_HANDLE ImageHandle
+ );
+
+#endif // __ARM_JUNO_DXE_INTERNAL_H__
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/InstallFdt.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/InstallFdt.c
new file mode 100644
index 0000000000..a4220a1895
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/InstallFdt.c
@@ -0,0 +1,423 @@
+/** @file
+*
+* Copyright (c) 2014, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "ArmJunoDxeInternal.h"
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePathFromText.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/BdsLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include <Guid/ArmGlobalVariableHob.h>
+#include <Guid/EventGroup.h>
+#include <Guid/Fdt.h>
+#include <Guid/FileInfo.h>
+
+#include <libfdt.h>
+
+#define FDT_DEFAULT_FILENAME L"juno"
+
+#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))
+
+// Hardware Vendor Device Path node for the Juno NOR Flash. We use the Juno NOR Flash if the user
+// has not specified another filesystem location into the UEFI Variable 'Fdt'.
+// The Juno NOR Flash has its own filesystem format (supported by ArmPlatformPkg/FileSystem/BootMonFs).
+STATIC CONST struct {
+ VENDOR_DEVICE_PATH NorGuid;
+ EFI_DEVICE_PATH End;
+} mJunoNorFlashDevicePath = {
+ {
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0 } },
+ {0xE7223039, 0x5836, 0x41E1, { 0xB5, 0x42, 0xD7, 0xEC, 0x73, 0x6C, 0x5E, 0x59} }
+ },
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } }
+};
+
+STATIC EFI_DEVICE_PATH* mFdtFileSystemDevicePath = NULL;
+STATIC CHAR16* mFdtFileName = NULL;
+
+STATIC BOOLEAN mFdtTableInstalled = FALSE;
+
+/**
+ See definition EFI_DRIVER_BINDING_PROTOCOL.Supported()
+**/
+EFI_STATUS
+EFIAPI
+JunoFdtSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ //
+ // Check if the Handle support the Simple File System Protocol
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ gImageHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Check if a DevicePath is attached to the handle
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **)&DevicePath,
+ gImageHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Check if the Device Path is the one from the NOR Flash
+ if (CompareMem (mFdtFileSystemDevicePath, DevicePath, GetDevicePathSize (mFdtFileSystemDevicePath)) != 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, gImageHandle, ControllerHandle);
+ return Status;
+}
+
+/**
+ This function is used to print messages back to the user.
+
+ We use the Serial terminal for these messages as the gST->ConOut might not be initialized at this stage.
+
+ @param Message Message to display to the user
+**/
+STATIC
+VOID
+PrintMessage (
+ IN CHAR8* Message,
+ ...
+ )
+{
+ UINTN CharCount;
+ CHAR8 Buffer[100];
+ VA_LIST Marker;
+
+ VA_START (Marker, Message);
+ CharCount = AsciiVSPrint (Buffer, sizeof (Buffer), Message, Marker);
+ VA_END (Marker);
+
+ SerialPortWrite ((UINT8*)Buffer, CharCount);
+}
+
+/**
+ See definition EFI_DRIVER_BINDING_PROTOCOL.Start ()
+**/
+EFI_STATUS
+EFIAPI
+JunoFdtStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *BootMonFs;
+ EFI_FILE_PROTOCOL *Fs;
+ EFI_FILE_PROTOCOL *File;
+ UINTN Size;
+ EFI_PHYSICAL_ADDRESS FdtBlob;
+ EFI_FILE_INFO *FileInfo;
+
+ if (mFdtTableInstalled) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID**)&BootMonFs,
+ gImageHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Try to Open the volume and get root directory
+ Status = BootMonFs->OpenVolume (BootMonFs, &Fs);
+ if (EFI_ERROR (Status)) {
+ PrintMessage ("Warning: Fail to open file system that should contain FDT file.\n");
+ goto UNLOAD_PROTOCOL;
+ }
+
+ File = NULL;
+ Status = Fs->Open (Fs, &File, mFdtFileName, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR (Status)) {
+ PrintMessage ("Warning: Fail to load FDT file '%s'.\n", mFdtFileName);
+ goto UNLOAD_PROTOCOL;
+ }
+
+ Size = 0;
+ File->GetInfo (File, &gEfiFileInfoGuid, &Size, NULL);
+ FileInfo = AllocatePool (Size);
+ Status = File->GetInfo (File, &gEfiFileInfoGuid, &Size, FileInfo);
+ if (EFI_ERROR (Status)) {
+ goto UNLOAD_PROTOCOL;
+ }
+
+ // Get the file size
+ Size = FileInfo->FileSize;
+ FreePool (FileInfo);
+
+ // The FDT blob is attached to the Configuration Table. It is better to load it as Runtime Service Data
+ // to prevent the kernel to overwrite its data
+ Status = gBS->AllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (Size), &FdtBlob);
+ if (!EFI_ERROR (Status)) {
+ Status = File->Read (File, &Size, (VOID*)(UINTN)(FdtBlob));
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (FdtBlob, EFI_SIZE_TO_PAGES (Size));
+ } else {
+ // Check the FDT header is valid. We only make this check in DEBUG mode in case the FDT header change on
+ // production device and this ASSERT() becomes not valid.
+ ASSERT (fdt_check_header ((VOID*)(UINTN)(FdtBlob)) == 0);
+
+ // Ensure the Size of the Device Tree is smaller than the size of the read file
+ ASSERT ((UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlob) <= Size);
+
+ // Install the FDT into the Configuration Table
+ Status = gBS->InstallConfigurationTable (&gFdtTableGuid, (VOID*)(UINTN)(FdtBlob));
+ if (!EFI_ERROR (Status)) {
+ mFdtTableInstalled = TRUE;
+ }
+ }
+ }
+
+UNLOAD_PROTOCOL:
+ // We do not need the FileSystem protocol
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ DriverBinding->ImageHandle,
+ ControllerHandle);
+
+ return Status;
+}
+
+/**
+ See definition EFI_DRIVER_BINDING_PROTOCOL.Stop()
+**/
+EFI_STATUS
+EFIAPI
+JunoFdtStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ UINTN Index;
+ VOID* FdtBlob;
+ UINTN FdtSize;
+
+ // Look for FDT Table
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+ // Check for correct GUID type
+ if (CompareGuid (&gFdtTableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
+ FdtBlob = gST->ConfigurationTable[Index].VendorTable;
+ FdtSize = (UINTN)fdt_totalsize (FdtBlob);
+
+ // Uninstall the FDT Configuration Table
+ gBS->InstallConfigurationTable (&gFdtTableGuid, NULL);
+
+ // Free the memory
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)FdtBlob, EFI_SIZE_TO_PAGES (FdtSize));
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+//
+// Driver Binding Protocol for Juno FDT support
+//
+EFI_DRIVER_BINDING_PROTOCOL mJunoFdtBinding = {
+ JunoFdtSupported,
+ JunoFdtStart,
+ JunoFdtStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+/**
+ Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+ This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context Pointer to the notification function's context.
+
+**/
+STATIC
+VOID
+EFIAPI
+OnEndOfDxe (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ EFI_DEVICE_PATH *DevicePathNode;
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN VariableSize;
+ CHAR16* FdtDevicePathStr;
+ EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
+
+ //
+ // Read the 'FDT' UEFI Variable to know where we should we read the blob from.
+ // The 'Fdt' variable contains either the full device path or only the filename of the FDT.
+ // If 'Fdt' only contains the filename then we assume its location is on the NOR Flash.
+ //
+ VariableSize = 0;
+ Status = gRT->GetVariable (L"Fdt", &gArmGlobalVariableGuid, NULL, &VariableSize, mFdtFileSystemDevicePath);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ // Get the environment variable value
+ mFdtFileSystemDevicePath = AllocatePool (VariableSize);
+ if (mFdtFileSystemDevicePath != NULL) {
+ Status = gRT->GetVariable (L"Fdt", &gArmGlobalVariableGuid, NULL, &VariableSize, mFdtFileSystemDevicePath);
+ if (EFI_ERROR (Status)) {
+ FreePool (mFdtFileSystemDevicePath);
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+ } else {
+ ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);
+ return;
+ }
+ } else if (Status == EFI_NOT_FOUND) {
+ // If the 'Fdt' variable does not exist then we get the FDT location from the PCD
+ FdtDevicePathStr = (CHAR16*)PcdGetPtr (PcdFdtDevicePath);
+
+ Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ // Conversion of the Device Path string into EFI Device Path
+ mFdtFileSystemDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (FdtDevicePathStr);
+ }
+
+ if (mFdtFileSystemDevicePath != NULL) {
+ // Look for the FDT filename that should be contained into the FilePath device path node
+ DevicePathNode = mFdtFileSystemDevicePath;
+ while (!IsDevicePathEnd (DevicePathNode)) {
+ if (IS_DEVICE_PATH_NODE (DevicePathNode, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP)) {
+ // Extract the name from the File Path Node. The name of the Filename is the size of the
+ // device path node minus the size of the device path node header.
+ mFdtFileName = AllocateCopyPool (
+ DevicePathNodeLength (DevicePathNode) - sizeof(EFI_DEVICE_PATH_PROTOCOL),
+ ((FILEPATH_DEVICE_PATH*)DevicePathNode)->PathName);
+ if (mFdtFileName == NULL) {
+ ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);
+ return;
+ }
+
+ // We remove the FilePath device path node from the FileSystem Device Path
+ // because it will never match a device path installed by the FileSystem driver
+ SetDevicePathEndNode (DevicePathNode);
+ break;
+ }
+ DevicePathNode = NextDevicePathNode (DevicePathNode);
+ }
+
+ // The UEFI Variable might just contain the FDT filename. In this case we assume the FileSystem is
+ // the NOR Flash based one (ie: BootMonFs).
+ // If it was only containing the FilePath device node then the previous condition should have
+ // replaced it by the End Device Path Node.
+ if (IsDevicePathEndType (mFdtFileSystemDevicePath)) {
+ mFdtFileSystemDevicePath = (EFI_DEVICE_PATH*)&mJunoNorFlashDevicePath;
+ }
+ } else {
+ // Fallback on the NOR Flash filesystem
+ mFdtFileSystemDevicePath = (EFI_DEVICE_PATH*)&mJunoNorFlashDevicePath;
+ }
+
+ // If the FDT FileName has been provided during the FileSystem identification
+ if (mFdtFileName == NULL) {
+ mFdtFileName = AllocateCopyPool (StrSize (FDT_DEFAULT_FILENAME), FDT_DEFAULT_FILENAME);
+ if (mFdtFileName == NULL) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+ }
+
+ // Install the Binding protocol to verify when the FileSystem that contains the FDT has been installed
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gImageHandle,
+ &gEfiDriverBindingProtocolGuid, &mJunoFdtBinding,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ //
+ // Force to connect the FileSystem that contains the FDT
+ //
+ BdsConnectDevicePath (mFdtFileSystemDevicePath, &Handle, NULL);
+}
+
+EFI_STATUS
+JunoFdtInstall (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT EndOfDxeEvent;
+
+ // Register the event handling function to set the End Of DXE flag.
+ // We wait until the end of the DXE phase to load the FDT to make sure
+ // all the required drivers (NOR Flash, UEFI Variable, BootMonFs) are dispatched
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ OnEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.c
new file mode 100644
index 0000000000..7c2d756fe1
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.c
@@ -0,0 +1,486 @@
+/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2013 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PciEmulation.h"
+
+#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ PCI_DEVICE_PATH PciDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_IO_DEVICE_PATH;
+
+typedef struct {
+ UINT32 Signature;
+ EFI_PCI_IO_DEVICE_PATH DevicePath;
+ EFI_PCI_IO_PROTOCOL PciIoProtocol;
+ PCI_TYPE00 *ConfigSpace;
+ PCI_ROOT_BRIDGE RootBridge;
+ UINTN Segment;
+} EFI_PCI_IO_PRIVATE_DATA;
+
+#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o')
+#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
+
+EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate =
+{
+ {
+ { ACPI_DEVICE_PATH, ACPI_DP, { sizeof (ACPI_HID_DEVICE_PATH), 0 } },
+ EISA_PNP_ID(0x0A03), // HID
+ 0 // UID
+ },
+ {
+ { HARDWARE_DEVICE_PATH, HW_PCI_DP, { sizeof (PCI_DEVICE_PATH), 0 } },
+ 0,
+ 0
+ },
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} }
+};
+
+STATIC
+VOID
+ConfigureUSBHost (
+ VOID
+ )
+{
+}
+
+
+EFI_STATUS
+PciIoPollMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoPollIo (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoMemRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ return PciRootBridgeIoMemRead (&Private->RootBridge.Io,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Private->ConfigSpace->Device.Bar[BarIndex] + Offset, //Fix me ConfigSpace
+ Count,
+ Buffer
+ );
+}
+
+EFI_STATUS
+PciIoMemWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ return PciRootBridgeIoMemWrite (&Private->RootBridge.Io,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Private->ConfigSpace->Device.Bar[BarIndex] + Offset, //Fix me ConfigSpace
+ Count,
+ Buffer
+ );
+}
+
+EFI_STATUS
+PciIoIoRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoIoWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoPciRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
+ EFI_STATUS Status;
+
+ Status = PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
+ Count,
+ TRUE,
+ (PTR)(UINTN)Buffer,
+ TRUE,
+ (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset) //Fix me ConfigSpace
+ );
+ return Status;
+}
+
+EFI_STATUS
+PciIoPciWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Count,
+ TRUE,
+ (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset), //Fix me ConfigSpace
+ TRUE,
+ (PTR)(UINTN)Buffer
+ );
+}
+
+EFI_STATUS
+PciIoCopyMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 DestBarIndex,
+ IN UINT64 DestOffset,
+ IN UINT8 SrcBarIndex,
+ IN UINT64 SrcOffset,
+ IN UINTN Count
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoMap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ DMA_MAP_OPERATION DmaOperation;
+
+ if (Operation == EfiPciIoOperationBusMasterRead) {
+ DmaOperation = MapOperationBusMasterRead;
+ } else if (Operation == EfiPciIoOperationBusMasterWrite) {
+ DmaOperation = MapOperationBusMasterWrite;
+ } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
+ DmaOperation = MapOperationBusMasterCommonBuffer;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
+}
+
+EFI_STATUS
+PciIoUnmap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ return DmaUnmap (Mapping);
+}
+
+EFI_STATUS
+PciIoAllocateBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
+ // Check this
+ return EFI_UNSUPPORTED;
+ }
+
+ return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
+}
+
+
+EFI_STATUS
+PciIoFreeBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+{
+ return DmaFreeBuffer (Pages, HostAddress);
+}
+
+
+EFI_STATUS
+PciIoFlush (
+ IN EFI_PCI_IO_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoGetLocation (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ OUT UINTN *SegmentNumber,
+ OUT UINTN *BusNumber,
+ OUT UINTN *DeviceNumber,
+ OUT UINTN *FunctionNumber
+ )
+{
+ EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (SegmentNumber != NULL) {
+ *SegmentNumber = Private->Segment;
+ }
+
+ if (BusNumber != NULL) {
+ *BusNumber = 0xff;
+ }
+
+ if (DeviceNumber != NULL) {
+ *DeviceNumber = 0;
+ }
+
+ if (FunctionNumber != NULL) {
+ *FunctionNumber = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes,
+ OUT UINT64 *Result OPTIONAL
+ )
+{
+ switch (Operation) {
+ case EfiPciIoAttributeOperationGet:
+ case EfiPciIoAttributeOperationSupported:
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ // We are not a real PCI device so just say things we kind of do
+ *Result = EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_DEVICE_ENABLE;
+ break;
+
+ case EfiPciIoAttributeOperationSet:
+ case EfiPciIoAttributeOperationEnable:
+ case EfiPciIoAttributeOperationDisable:
+ // Since we are not a real PCI device no enable/set or disable operations exist.
+ return EFI_SUCCESS;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ };
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoGetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT8 BarIndex,
+ OUT UINT64 *Supports, OPTIONAL
+ OUT VOID **Resources OPTIONAL
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoSetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN UINT8 BarIndex,
+ IN OUT UINT64 *Offset,
+ IN OUT UINT64 *Length
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_PCI_IO_PROTOCOL PciIoTemplate =
+{
+ PciIoPollMem,
+ PciIoPollIo,
+ { PciIoMemRead, PciIoMemWrite },
+ { PciIoIoRead, PciIoIoWrite },
+ { PciIoPciRead, PciIoPciWrite },
+ PciIoCopyMem,
+ PciIoMap,
+ PciIoUnmap,
+ PciIoAllocateBuffer,
+ PciIoFreeBuffer,
+ PciIoFlush,
+ PciIoGetLocation,
+ PciIoAttributes,
+ PciIoGetBarAttributes,
+ PciIoSetBarAttributes,
+ 0,
+ 0
+};
+
+EFI_STATUS
+PciInstallDevice (
+ IN UINTN DeviceId,
+ IN PHYSICAL_ADDRESS MemoryStart,
+ IN UINT64 MemorySize,
+ IN UINTN ClassCode1,
+ IN UINTN ClassCode2,
+ IN UINTN ClassCode3
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_PCI_IO_PRIVATE_DATA *Private;
+
+ // Configure USB host
+ ConfigureUSBHost ();
+
+ // Create a private structure
+ Private = AllocatePool (sizeof (EFI_PCI_IO_PRIVATE_DATA));
+ if (Private == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+
+ Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature
+ Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too
+ Private->RootBridge.MemoryStart = MemoryStart; // Get the USB capability register base
+ Private->Segment = 0; // Default to segment zero
+
+ // Calculate the total size of the USB controller (OHCI + EHCI).
+ Private->RootBridge.MemorySize = MemorySize; //CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));
+
+ // Create fake PCI config space: OHCI + EHCI
+ Private->ConfigSpace = AllocateZeroPool (sizeof (PCI_TYPE00));
+ if (Private->ConfigSpace == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ FreePool (Private);
+ return Status;
+ }
+
+ //
+ // Configure PCI config space: OHCI + EHCI
+ //
+ Private->ConfigSpace->Hdr.VendorId = 0x3530; //TODO: Define one
+ Private->ConfigSpace->Hdr.DeviceId = 0x3530; //TODO: Define one
+ Private->ConfigSpace->Hdr.ClassCode[0] = ClassCode1;
+ Private->ConfigSpace->Hdr.ClassCode[1] = ClassCode2;
+ Private->ConfigSpace->Hdr.ClassCode[2] = ClassCode3;
+ Private->ConfigSpace->Device.Bar[0] = MemoryStart;
+
+ Handle = NULL;
+
+ // Unique device path.
+ CopyMem (&Private->DevicePath, &PciIoDevicePathTemplate, sizeof (PciIoDevicePathTemplate));
+ Private->DevicePath.AcpiDevicePath.UID = 0;
+ Private->DevicePath.PciDevicePath.Device = DeviceId;
+
+ // Copy protocol structure
+ CopyMem (&Private->PciIoProtocol, &PciIoTemplate, sizeof (PciIoTemplate));
+
+ Status = gBS->InstallMultipleProtocolInterfaces (&Handle,
+ &gEfiPciIoProtocolGuid, &Private->PciIoProtocol,
+ &gEfiDevicePathProtocolGuid, &Private->DevicePath,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces () failed.\n"));
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+PciEmulationEntryPoint (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PciInstallDevice (0, FixedPcdGet32 (PcdSynopsysUsbOhciBaseAddress), SIZE_64KB, PCI_IF_OHCI, PCI_CLASS_SERIAL_USB, PCI_CLASS_SERIAL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PciEmulation: failed to install OHCI device.\n"));
+ }
+
+ Status = PciInstallDevice (1, FixedPcdGet32 (PcdSynopsysUsbEhciBaseAddress), SIZE_64KB, PCI_IF_EHCI, PCI_CLASS_SERIAL_USB, PCI_CLASS_SERIAL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PciEmulation: failed to install EHCI device.\n"));
+ }
+
+ return Status;
+}
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.h b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.h
new file mode 100644
index 0000000000..de2855d01d
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.h
@@ -0,0 +1,284 @@
+/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2013 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCI_ROOT_BRIDGE_H_
+#define _PCI_ROOT_BRIDGE_H_
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DmaLib.h>
+
+#include <Protocol/EmbeddedExternalDevice.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+
+#include <IndustryStandard/Pci23.h>
+
+#include "ArmJunoDxeInternal.h"
+
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL
+
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+
+#define ACPI_CONFIG_IO 0
+#define ACPI_CONFIG_MMIO 1
+#define ACPI_CONFIG_BUS 2
+
+typedef struct {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Desc[3];
+ EFI_ACPI_END_TAG_DESCRIPTOR EndDesc;
+} ACPI_CONFIG_INFO;
+
+
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'F')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
+
+ UINT8 StartBus;
+ UINT8 EndBus;
+ UINT16 Type;
+ UINT32 MemoryStart;
+ UINT32 MemorySize;
+ UINTN IoOffset;
+ UINT32 IoStart;
+ UINT32 IoSize;
+ UINT64 PciAttributes;
+
+ ACPI_CONFIG_INFO *Config;
+
+} PCI_ROOT_BRIDGE;
+
+
+#define INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+
+typedef union {
+ UINT8 volatile *Buffer;
+ UINT8 volatile *Ui8;
+ UINT16 volatile *Ui16;
+ UINT32 volatile *Ui32;
+ UINT64 volatile *Ui64;
+ UINTN volatile Ui;
+} PTR;
+
+
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+//
+// Private Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ );
+
+BOOLEAN
+PciIoMemAddressValid (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Address
+ );
+
+EFI_STATUS
+EmulatePciIoForEhci (
+ INTN MvPciIfMaxIf
+ );
+
+#endif
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciRootBridgeIo.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciRootBridgeIo.c
new file mode 100644
index 0000000000..f1eaceff28
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciRootBridgeIo.c
@@ -0,0 +1,299 @@
+/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PciEmulation.h"
+
+BOOLEAN
+PciRootBridgeMemAddressValid (
+ IN PCI_ROOT_BRIDGE *Private,
+ IN UINT64 Address
+ )
+{
+ if ((Address >= Private->MemoryStart) && (Address < (Private->MemoryStart + Private->MemorySize))) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+EFI_STATUS
+PciRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ )
+{
+ UINTN Stride;
+ UINTN InStride;
+ UINTN OutStride;
+
+ Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ Stride = (UINTN)1 << Width;
+ InStride = InStrideFlag ? Stride : 0;
+ OutStride = OutStrideFlag ? Stride : 0;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (;Count > 0; Count--, In.Buffer += InStride, Out.Buffer += OutStride) {
+ *In.Ui8 = *Out.Ui8;
+ }
+ break;
+ case EfiPciWidthUint16:
+ for (;Count > 0; Count--, In.Buffer += InStride, Out.Buffer += OutStride) {
+ *In.Ui16 = *Out.Ui16;
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (;Count > 0; Count--, In.Buffer += InStride, Out.Buffer += OutStride) {
+ *In.Ui32 = *Out.Ui32;
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE *Private;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (!PciRootBridgeMemAddressValid (Private, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ In.Buffer = Buffer;
+ Out.Buffer = (VOID *)(UINTN) Address;
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ case EfiPciWidthUint16:
+ case EfiPciWidthUint32:
+ case EfiPciWidthUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+
+ case EfiPciWidthFifoUint8:
+ case EfiPciWidthFifoUint16:
+ case EfiPciWidthFifoUint32:
+ case EfiPciWidthFifoUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+
+ case EfiPciWidthFillUint8:
+ case EfiPciWidthFillUint16:
+ case EfiPciWidthFillUint32:
+ case EfiPciWidthFillUint64:
+ return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+
+ default:
+ break;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE *Private;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (!PciRootBridgeMemAddressValid (Private, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ In.Buffer = (VOID *)(UINTN) Address;
+ Out.Buffer = Buffer;
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ case EfiPciWidthUint16:
+ case EfiPciWidthUint32:
+ case EfiPciWidthUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+
+ case EfiPciWidthFifoUint8:
+ case EfiPciWidthFifoUint16:
+ case EfiPciWidthFifoUint32:
+ case EfiPciWidthFifoUint64:
+ return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+
+ case EfiPciWidthFillUint8:
+ case EfiPciWidthFillUint16:
+ case EfiPciWidthFillUint32:
+ case EfiPciWidthFillUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+
+ default:
+ break;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}