ArmPlatformPkg/ArmJunoPkg : Use FdtPlatformDxe driver to install the FDT

Remove the installation of the FDT for Juno into the UEFI Configuration
Table from the Juno specific DXE driver. Use the FdtPlatformDxe driver to
do it instead.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ronald Cron <Ronald.Cron@arm.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>



git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16938 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Ronald Cron 2015-02-26 10:56:20 +00:00 committed by oliviermartin
parent 04f1a7096a
commit cae7af275e
11 changed files with 31 additions and 503 deletions

View File

@ -77,6 +77,11 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE
#
# FDT installation : enable the development specific features
#
gEmbeddedTokenSpaceGuid.PcdOverridePlatformFdt|TRUE
[PcdsFixedAtBuild.common]
gArmPlatformTokenSpaceGuid.PcdFirmwareVendor|"ARM Juno"
gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"ArmJuno"
@ -127,6 +132,22 @@
# List of Device Paths that support BootMonFs
gArmPlatformTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)"
#
# Define the device path to the FDT for its installation
#
!ifdef $(JUNO_EMULATOR)
# From DRAM
gEmbeddedTokenSpaceGuid.PcdFdtDevicePaths|L"VenHw(30F57E4A-69CE-4FB7-B7A1-4C7CE49D57A6)/MemoryMapped(0x0,0x88000000,0x88200000)"
!else
!ifdef $(JUNO_MODEL)
# From semi-hosting
gEmbeddedTokenSpaceGuid.PcdFdtDevicePaths|L"VenHw(C5B9C74A-6D72-4719-99AB-C59F199091EB)/juno.dtb"
!else
# From NOR flash
gEmbeddedTokenSpaceGuid.PcdFdtDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/juno.dtb"
!endif
!endif
#
# ARM OS Loader
#

View File

@ -108,6 +108,11 @@ READ_LOCK_STATUS = TRUE
INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
INF RuleOverride=ACPITABLE ArmPlatformPkg/ArmJunoPkg/AcpiTables/AcpiTables.inf
#
# FDT installation
#
INF EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf
INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
#

View File

@ -83,9 +83,5 @@ ArmJunoEntryPoint (
return Status;
}
// Try to install the Flat Device Tree (FDT). This function actually installs the
// UEFI Driver Binding Protocol.
Status = JunoFdtInstall (ImageHandle);
return Status;
}

View File

@ -20,7 +20,6 @@
[Sources.common]
ArmJunoDxe.c
InstallFdt.c
PciEmulation.c
PciRootBridgeIo.c
@ -39,7 +38,6 @@
DebugLib
DmaLib
DxeServicesTableLib
FdtLib
IoLib
PcdLib
PrintLib
@ -53,8 +51,6 @@
gArmGlobalVariableGuid
gEfiEndOfDxeEventGroupGuid
gEfiFileInfoGuid
gFdtTableGuid
gArmPlatformUpdateFdtEventGuid
[Protocols]
gEfiBlockIoProtocolGuid

View File

@ -28,9 +28,4 @@ PciEmulationEntryPoint (
VOID
);
EFI_STATUS
JunoFdtInstall (
IN EFI_HANDLE ImageHandle
);
#endif // __ARM_JUNO_DXE_INTERNAL_H__

View File

@ -1,444 +0,0 @@
/** @file
*
* Copyright (c) 2014-2015, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#include "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/ArmPlatformEvents.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 CLOSE_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 CLOSE_PROTOCOL;
}
Size = 0;
File->GetInfo (File, &gEfiFileInfoGuid, &Size, NULL);
FileInfo = AllocatePool (Size);
Status = File->GetInfo (File, &gEfiFileInfoGuid, &Size, FileInfo);
if (EFI_ERROR (Status)) {
goto CLOSE_FILE;
}
// 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;
}
}
}
CLOSE_FILE:
File->Close (File);
CLOSE_PROTOCOL:
// We do not need the FileSystem protocol
gBS->CloseProtocol (
ControllerHandle,
&gEfiSimpleFileSystemProtocolGuid,
gImageHandle,
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
LoadFdtOnEvent (
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;
EFI_EVENT ArmPlatformUpdateFdtEvent;
//
// 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;
}
}
// Context is not NULL when this function is called for a gEfiEndOfDxeEventGroupGuid event
if (Context) {
// 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;
}
// Register the event triggered when the 'Fdt' variable is updated.
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
LoadFdtOnEvent,
NULL,
&gArmPlatformUpdateFdtEventGuid,
&ArmPlatformUpdateFdtEvent
);
ASSERT_EFI_ERROR (Status);
}
//
// Force to connect the FileSystem that contains the FDT
//
BdsConnectDevicePath (mFdtFileSystemDevicePath, &Handle, NULL);
}
STATIC CONST BOOLEAN mIsEndOfDxeEvent = TRUE;
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,
LoadFdtOnEvent,
&mIsEndOfDxeEvent,
&gEfiEndOfDxeEventGroupGuid,
&EndOfDxeEvent
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -42,9 +42,6 @@
gArmBootMonFsFileInfoGuid = { 0x41e26b9c, 0xada6, 0x45b3, { 0x80, 0x8e, 0x23, 0x57, 0xa3, 0x5b, 0x60, 0xd6 } }
## Include/Guid/ArmPlatformEvents.h
gArmPlatformUpdateFdtEventGuid = { 0xaffe115b, 0x8589, 0x456d, { 0xba, 0xb5, 0x8f, 0x2e, 0xda, 0x53, 0xae, 0xb7 } }
[Ppis]
## Include/Ppi/ArmGlobalVariable.h
gArmGlobalVariablePpiGuid = { 0xab1c1816, 0xd542, 0x4e6f, {0x9b, 0x1e, 0x8e, 0xcd, 0x92, 0x53, 0xe2, 0xe7} }

View File

@ -411,3 +411,8 @@
# FV Filesystem
MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf
#
# FDT installation
#
EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf

View File

@ -53,7 +53,6 @@
gEfiEndOfDxeEventGroupGuid
gEfiFileSystemInfoGuid
gArmGlobalVariableGuid
gArmPlatformUpdateFdtEventGuid
[Protocols]
gEfiBdsArchProtocolGuid

View File

@ -15,7 +15,6 @@
#include "BdsInternal.h"
#include <Guid/ArmGlobalVariableHob.h>
#include <Guid/ArmPlatformEvents.h>
extern BDS_LOAD_OPTION_SUPPORT *BdsLoadOptionSupportList;
@ -835,7 +834,6 @@ UpdateFdtPath (
BDS_SUPPORTED_DEVICE *SupportedBootDevice;
EFI_DEVICE_PATH_PROTOCOL *FdtDevicePathNodes;
EFI_DEVICE_PATH_PROTOCOL *FdtDevicePath;
EFI_EVENT UpdateFdtEvent;
Status = SelectBootDevice (&SupportedBootDevice);
if (EFI_ERROR(Status)) {
@ -875,23 +873,6 @@ UpdateFdtPath (
ASSERT_EFI_ERROR(Status);
}
if (!EFI_ERROR (Status)) {
//
// Signal FDT has been updated
//
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
EmptyCallbackFunction,
NULL,
&gArmPlatformUpdateFdtEventGuid,
&UpdateFdtEvent
);
if (!EFI_ERROR (Status)) {
gBS->SignalEvent (UpdateFdtEvent);
}
}
EXIT:
if (Status == EFI_ABORTED) {
Print(L"\n");

View File

@ -1,23 +0,0 @@
/** @file
*
* Copyright (c) 2015, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#ifndef __ARM_PLATFORM_EVENTS_H__
#define __ARM_PLATFORM_EVENTS_H__
#define ARM_PLATFORM_UPDATE_FDT_EVENT_GUID \
{ 0xaffe115b, 0x8589, 0x456d, { 0xba, 0xb5, 0x8f, 0x2e, 0xda, 0x53, 0xae, 0xb7 } }
extern EFI_GUID gArmPlatformUpdateFdtEventGuid;
#endif