X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=ArmVirtPkg%2FFdtClientDxe%2FFdtClientDxe.c;h=5bfde381ecd0d53996272771bdee6ebe5d5ada96;hp=547a29fce62c9fc06cc525776daf5ba983af708f;hb=32f5975770c309723ebb17642f89bbf9670955fd;hpb=a00601c6de65d0d1b43bd91ba6c43238d9db2ed4 diff --git a/ArmVirtPkg/FdtClientDxe/FdtClientDxe.c b/ArmVirtPkg/FdtClientDxe/FdtClientDxe.c index 547a29fce6..5bfde381ec 100644 --- a/ArmVirtPkg/FdtClientDxe/FdtClientDxe.c +++ b/ArmVirtPkg/FdtClientDxe/FdtClientDxe.c @@ -22,6 +22,7 @@ #include #include +#include #include @@ -77,6 +78,33 @@ SetNodeProperty ( return EFI_SUCCESS; } +STATIC +BOOLEAN +IsNodeEnabled ( + INT32 Node + ) +{ + CONST CHAR8 *NodeStatus; + INT32 Len; + + // + // A missing status property implies 'ok' so ignore any errors that + // may occur here. If the status property is present, check whether + // it is set to 'ok' or 'okay', anything else is treated as 'disabled'. + // + NodeStatus = fdt_getprop (mDeviceTreeBase, Node, "status", &Len); + if (NodeStatus == NULL) { + return TRUE; + } + if (Len >= 5 && AsciiStrCmp (NodeStatus, "okay") == 0) { + return TRUE; + } + if (Len >= 3 && AsciiStrCmp (NodeStatus, "ok") == 0) { + return TRUE; + } + return FALSE; +} + STATIC EFI_STATUS EFIAPI @@ -100,6 +128,10 @@ FindNextCompatibleNode ( break; } + if (!IsNodeEnabled (Next)) { + continue; + } + Type = fdt_getprop (mDeviceTreeBase, Next, "compatible", &Len); if (Type == NULL) { continue; @@ -221,6 +253,11 @@ FindNextMemoryNodeReg ( break; } + if (!IsNodeEnabled (Next)) { + DEBUG ((DEBUG_WARN, "%a: ignoring disabled memory node\n", __FUNCTION__)); + continue; + } + DeviceType = fdt_getprop (mDeviceTreeBase, Next, "device_type", &Len); if (DeviceType != NULL && AsciiStrCmp (DeviceType, "memory") == 0) { // @@ -306,6 +343,40 @@ STATIC FDT_CLIENT_PROTOCOL mFdtClientProtocol = { GetOrInsertChosenNode, }; +STATIC +VOID +EFIAPI +OnPlatformHasDeviceTree ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + VOID *Interface; + VOID *DeviceTreeBase; + + Status = gBS->LocateProtocol ( + &gEdkiiPlatformHasDeviceTreeGuid, + NULL, // Registration + &Interface + ); + if (EFI_ERROR (Status)) { + return; + } + + DeviceTreeBase = Context; + DEBUG (( + DEBUG_INFO, + "%a: exposing DTB @ 0x%p to OS\n", + __FUNCTION__, + DeviceTreeBase + )); + Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DeviceTreeBase); + ASSERT_EFI_ERROR (Status); + + gBS->CloseEvent (Event); +} + EFI_STATUS EFIAPI InitializeFdtClientDxe ( @@ -316,6 +387,8 @@ InitializeFdtClientDxe ( VOID *Hob; VOID *DeviceTreeBase; EFI_STATUS Status; + EFI_EVENT PlatformHasDeviceTreeEvent; + VOID *Registration; Hob = GetFirstGuidHob (&gFdtHobGuid); if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) { @@ -333,15 +406,65 @@ InitializeFdtClientDxe ( DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, mDeviceTreeBase)); - if (!FeaturePcdGet (PcdPureAcpiBoot)) { - // - // Only install the FDT as a configuration table if we want to leave it up - // to the OS to decide whether it prefers ACPI over DT. - // - Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DeviceTreeBase); - ASSERT_EFI_ERROR (Status); + // + // Register a protocol notify for the EDKII Platform Has Device Tree + // Protocol. + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + OnPlatformHasDeviceTree, + DeviceTreeBase, // Context + &PlatformHasDeviceTreeEvent + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: CreateEvent(): %r\n", __FUNCTION__, Status)); + return Status; + } + + Status = gBS->RegisterProtocolNotify ( + &gEdkiiPlatformHasDeviceTreeGuid, + PlatformHasDeviceTreeEvent, + &Registration + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: RegisterProtocolNotify(): %r\n", + __FUNCTION__, + Status + )); + goto CloseEvent; } - return gBS->InstallProtocolInterface (&ImageHandle, &gFdtClientProtocolGuid, - EFI_NATIVE_INTERFACE, &mFdtClientProtocol); + // + // Kick the event; the protocol could be available already. + // + Status = gBS->SignalEvent (PlatformHasDeviceTreeEvent); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: SignalEvent(): %r\n", __FUNCTION__, Status)); + goto CloseEvent; + } + + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gFdtClientProtocolGuid, + EFI_NATIVE_INTERFACE, + &mFdtClientProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: InstallProtocolInterface(): %r\n", + __FUNCTION__, + Status + )); + goto CloseEvent; + } + + return Status; + +CloseEvent: + gBS->CloseEvent (PlatformHasDeviceTreeEvent); + return Status; }