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/EfiShell.h>
#include <Protocol/EfiShellDynamicCommand.h> #include <Protocol/EfiShellDynamicCommand.h>
#include <Guid/EventGroup.h>
#include <Guid/Fdt.h> #include <Guid/Fdt.h>
#include <libfdt.h> #include <libfdt.h>
@ -39,17 +38,6 @@
// Internal types // 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 ( STATIC SHELL_STATUS EFIAPI ShellDynCmdSetFdtHandler (
IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
IN EFI_SYSTEM_TABLE *SystemTable, IN EFI_SYSTEM_TABLE *SystemTable,
@ -92,6 +80,105 @@ STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
STATIC EFI_HANDLE mFdtPlatformDxeHiiHandle; 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. Main entry point of the FDT platform driver.
@ -113,23 +200,11 @@ FdtPlatformEntryPoint (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
EFI_EVENT EndOfDxeEvent;
// //
// Create an event belonging to the "gEfiEndOfDxeEventGroupGuid" group. // Install the Device Tree from its expected location
// 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.
// //
Status = gBS->CreateEventEx ( Status = RunFdtInstallation (NULL);
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
OnEndOfDxe,
NULL,
&gEfiEndOfDxeEventGroupGuid,
&EndOfDxeEvent
);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
@ -184,32 +259,6 @@ FdtPlatformEntryPoint (
return Status; 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. Run the FDT installation process.
@ -353,106 +402,6 @@ RunFdtInstallation (
return Status; 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 This is the shell command "setfdt" handler function. This function handles
the command when it is invoked in the shell. the command when it is invoked in the shell.
@ -612,7 +561,6 @@ ShellDynCmdSetFdtHandler (
} }
Error: Error:
gBS->UninstallMultipleProtocolInterfaces ( gBS->UninstallMultipleProtocolInterfaces (
gImageHandle, gImageHandle,
&gEfiShellProtocolGuid, Shell, &gEfiShellProtocolGuid, Shell,