EmbeddedPkg/FdtPlatformDxe: Run FDT installation process at TPL_APPLICATION level

The current mechanism relies on EndOfDxe event that runs at TPL_CALLBACK level.
It prevents some protocols to run as excepted because they require TPL_CALLBACK
(eg: TFTP transfer).

This change moves FDT installation in the driver entrypoint (that is called at
TPL_APPLICATION level).

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



git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17298 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Olivier Martin 2015-05-05 15:12:58 +00:00 committed by oliviermartin
parent cc053ee6da
commit cd66c5a2f1
1 changed files with 101 additions and 153 deletions

View File

@ -30,7 +30,6 @@
#include <Protocol/EfiShell.h>
#include <Protocol/EfiShellDynamicCommand.h>
#include <Guid/EventGroup.h>
#include <Guid/Fdt.h>
#include <libfdt.h>
@ -39,17 +38,6 @@
// Internal types
//
STATIC VOID OnEndOfDxe (
IN EFI_EVENT Event,
IN VOID *Context
);
STATIC EFI_STATUS RunFdtInstallation (
VOID
);
STATIC EFI_STATUS InstallFdt (
IN CONST CHAR16* TextDevicePath
);
STATIC SHELL_STATUS EFIAPI ShellDynCmdSetFdtHandler (
IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
IN EFI_SYSTEM_TABLE *SystemTable,
@ -92,6 +80,105 @@ STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
STATIC EFI_HANDLE mFdtPlatformDxeHiiHandle;
/**
Install the FDT specified by its device path in text form.
@param[in] TextDevicePath Device path of the FDT to install in text form
@retval EFI_SUCCESS The FDT was installed.
@retval EFI_NOT_FOUND Failed to locate a protocol or a file.
@retval EFI_INVALID_PARAMETER Invalid device path.
@retval EFI_UNSUPPORTED Device path not supported.
@retval EFI_OUT_OF_RESOURCES An allocation failed.
**/
STATIC
EFI_STATUS
InstallFdt (
IN CONST CHAR16* TextDevicePath
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
EFI_DEVICE_PATH *DevicePath;
EFI_PHYSICAL_ADDRESS FdtBlobBase;
UINTN FdtBlobSize;
UINTN NumPages;
EFI_PHYSICAL_ADDRESS FdtConfigurationTableBase;
Status = gBS->LocateProtocol (
&gEfiDevicePathFromTextProtocolGuid,
NULL,
(VOID **)&EfiDevicePathFromTextProtocol
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "InstallFdt() - Failed to locate EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol\n"));
return Status;
}
DevicePath = (EFI_DEVICE_PATH*)EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (TextDevicePath);
if (DevicePath == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Load the FDT given its device path.
// This operation may fail if the device path is not supported.
//
FdtBlobBase = 0;
NumPages = 0;
Status = BdsLoadImage (DevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);
if (EFI_ERROR (Status)) {
goto Error;
}
// 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)FdtBlobBase) == 0);
//
// Ensure the Size of the Device Tree is smaller than the size of the read file
//
ASSERT ((UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) <= FdtBlobSize);
//
// Store the FDT as Runtime Service Data to prevent the Kernel from
// overwritting its data.
//
NumPages = EFI_SIZE_TO_PAGES (FdtBlobSize);
Status = gBS->AllocatePages (
AllocateAnyPages, EfiRuntimeServicesData,
NumPages, &FdtConfigurationTableBase
);
if (EFI_ERROR (Status)) {
goto Error;
}
CopyMem (
(VOID*)(UINTN)FdtConfigurationTableBase,
(VOID*)(UINTN)FdtBlobBase,
FdtBlobSize
);
//
// Install the FDT into the Configuration Table
//
Status = gBS->InstallConfigurationTable (
&gFdtTableGuid,
(VOID*)(UINTN)FdtConfigurationTableBase
);
if (EFI_ERROR (Status)) {
gBS->FreePages (FdtConfigurationTableBase, NumPages);
}
Error:
if (FdtBlobBase != 0) {
gBS->FreePages (FdtBlobBase, NumPages);
}
FreePool (DevicePath);
return Status;
}
/**
Main entry point of the FDT platform driver.
@ -113,23 +200,11 @@ FdtPlatformEntryPoint (
)
{
EFI_STATUS Status;
EFI_EVENT EndOfDxeEvent;
//
// Create an event belonging to the "gEfiEndOfDxeEventGroupGuid" group.
// The "OnEndOfDxe()" function is declared as the call back function.
// It will be called at the end of the DXE phase when an event of the
// same group is signalled to inform about the end of the DXE phase.
// Install the Device Tree from its expected location
//
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
OnEndOfDxe,
NULL,
&gEfiEndOfDxeEventGroupGuid,
&EndOfDxeEvent
);
Status = RunFdtInstallation (NULL);
if (EFI_ERROR (Status)) {
return Status;
}
@ -184,32 +259,6 @@ FdtPlatformEntryPoint (
return Status;
}
/**
Notification function of the event defined as belonging to the
EFI_END_OF_DXE_EVENT_GROUP_GUID event group that was created in
the entry point of the driver.
This function is called when an event belonging to the
EFI_END_OF_DXE_EVENT_GROUP_GUID event group is signalled. Such an
event is signalled once at the end of the dispatching of all
drivers (end of the so called DXE phase).
@param[in] Event Event declared in the entry point of the driver whose
notification function is being invoked.
@param[in] Context NULL
**/
STATIC
VOID
OnEndOfDxe (
IN EFI_EVENT Event,
IN VOID *Context
)
{
RunFdtInstallation ();
gBS->CloseEvent (Event);
}
/**
Run the FDT installation process.
@ -353,106 +402,6 @@ RunFdtInstallation (
return Status;
}
/**
Install the FDT specified by its device path in text form.
@param[in] TextDevicePath Device path of the FDT to install in text form
@retval EFI_SUCCESS The FDT was installed.
@retval EFI_NOT_FOUND Failed to locate a protocol or a file.
@retval EFI_INVALID_PARAMETER Invalid device path.
@retval EFI_UNSUPPORTED Device path not supported.
@retval EFI_OUT_OF_RESOURCES An allocation failed.
**/
STATIC
EFI_STATUS
InstallFdt (
IN CONST CHAR16* TextDevicePath
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
EFI_DEVICE_PATH *DevicePath;
EFI_PHYSICAL_ADDRESS FdtBlobBase;
UINTN FdtBlobSize;
UINTN NbPages;
EFI_PHYSICAL_ADDRESS RsFdtBlobBase;
Status = gBS->LocateProtocol (
&gEfiDevicePathFromTextProtocolGuid,
NULL,
(VOID **)&EfiDevicePathFromTextProtocol
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "InstallFdt() - Failed to locate EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol\n"));
return Status;
}
DevicePath = (EFI_DEVICE_PATH*)EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (TextDevicePath);
if (DevicePath == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Load the FDT given its device path.
// This operation may fail if the device path is not supported.
//
FdtBlobBase = 0;
NbPages = 0;
Status = BdsLoadImage (DevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);
if (EFI_ERROR (Status)) {
goto Error;
}
// 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)FdtBlobBase) == 0);
//
// Ensure the Size of the Device Tree is smaller than the size of the read file
//
ASSERT ((UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) <= FdtBlobSize);
//
// Store the FDT as Runtime Service Data to prevent the Kernel from
// overwritting its data.
//
NbPages = EFI_SIZE_TO_PAGES (FdtBlobSize);
Status = gBS->AllocatePages (
AllocateAnyPages, EfiRuntimeServicesData,
NbPages, &RsFdtBlobBase
);
if (EFI_ERROR (Status)) {
goto Error;
}
CopyMem (
(VOID*)((UINTN)RsFdtBlobBase),
(VOID*)((UINTN)FdtBlobBase),
FdtBlobSize
);
//
// Install the FDT into the Configuration Table
//
Status = gBS->InstallConfigurationTable (
&gFdtTableGuid,
(VOID*)((UINTN)RsFdtBlobBase)
);
if (EFI_ERROR (Status)) {
gBS->FreePages (RsFdtBlobBase, NbPages);
}
Error :
if (FdtBlobBase != 0) {
gBS->FreePages (FdtBlobBase, NbPages);
}
FreePool (DevicePath);
return Status;
}
/**
This is the shell command "setfdt" handler function. This function handles
the command when it is invoked in the shell.
@ -612,7 +561,6 @@ ShellDynCmdSetFdtHandler (
}
Error:
gBS->UninstallMultipleProtocolInterfaces (
gImageHandle,
&gEfiShellProtocolGuid, Shell,