summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c
new file mode 100644
index 00000000..9fb01731
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c
@@ -0,0 +1,279 @@
+/** @file
+ This file deals with Architecture Protocol (AP) registration in
+ the Dxe Core. The mArchProtocols[] array represents a list of
+ events that represent the Architectural Protocols.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "DxeMain.h"
+
+//
+// DXE Core Global Variables for all of the Architectural Protocols.
+// If a protocol is installed mArchProtocols[].Present will be TRUE.
+//
+// CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event
+// and mArchProtocols[].Registration as it creates events for every array
+// entry.
+//
+EFI_CORE_PROTOCOL_NOTIFY_ENTRY mArchProtocols[] = {
+ { &gEfiSecurityArchProtocolGuid, (VOID **)&gSecurity, NULL, NULL, FALSE },
+ { &gEfiCpuArchProtocolGuid, (VOID **)&gCpu, NULL, NULL, FALSE },
+ { &gEfiMetronomeArchProtocolGuid, (VOID **)&gMetronome, NULL, NULL, FALSE },
+ { &gEfiTimerArchProtocolGuid, (VOID **)&gTimer, NULL, NULL, FALSE },
+ { &gEfiBdsArchProtocolGuid, (VOID **)&gBds, NULL, NULL, FALSE },
+ { &gEfiWatchdogTimerArchProtocolGuid, (VOID **)&gWatchdogTimer, NULL, NULL, FALSE },
+ { &gEfiRuntimeArchProtocolGuid, (VOID **)&gRuntime, NULL, NULL, FALSE },
+ { &gEfiVariableArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+ { &gEfiVariableWriteArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+ { &gEfiCapsuleArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+ { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+ { &gEfiResetArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+ { &gEfiRealTimeClockArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE },
+ { NULL, (VOID **)NULL, NULL, NULL, FALSE }
+};
+
+//
+// Optional protocols that the DXE Core will use if they are present
+//
+EFI_CORE_PROTOCOL_NOTIFY_ENTRY mOptionalProtocols[] = {
+ { &gEfiSecurity2ArchProtocolGuid, (VOID **)&gSecurity2, NULL, NULL, FALSE },
+ { &gEfiSmmBase2ProtocolGuid, (VOID **)&gSmmBase2, NULL, NULL, FALSE },
+ { NULL, (VOID **)NULL, NULL, NULL, FALSE }
+};
+
+//
+// Following is needed to display missing architectural protocols in debug builds
+//
+typedef struct {
+ EFI_GUID *ProtocolGuid;
+ CHAR8 *GuidString;
+} GUID_TO_STRING_PROTOCOL_ENTRY;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST GUID_TO_STRING_PROTOCOL_ENTRY mMissingProtocols[] = {
+ { &gEfiSecurityArchProtocolGuid, "Security" },
+ { &gEfiCpuArchProtocolGuid, "CPU" },
+ { &gEfiMetronomeArchProtocolGuid, "Metronome" },
+ { &gEfiTimerArchProtocolGuid, "Timer" },
+ { &gEfiBdsArchProtocolGuid, "Bds" },
+ { &gEfiWatchdogTimerArchProtocolGuid, "Watchdog Timer" },
+ { &gEfiRuntimeArchProtocolGuid, "Runtime" },
+ { &gEfiVariableArchProtocolGuid, "Variable" },
+ { &gEfiVariableWriteArchProtocolGuid, "Variable Write" },
+ { &gEfiCapsuleArchProtocolGuid, "Capsule" },
+ { &gEfiMonotonicCounterArchProtocolGuid, "Monotonic Counter" },
+ { &gEfiResetArchProtocolGuid, "Reset" },
+ { &gEfiRealTimeClockArchProtocolGuid, "Real Time Clock" },
+ { NULL, "" }
+};
+
+/**
+ Return TRUE if all AP services are available.
+
+ @retval EFI_SUCCESS All AP services are available
+ @retval EFI_NOT_FOUND At least one AP service is not available
+
+**/
+EFI_STATUS
+CoreAllEfiServicesAvailable (
+ VOID
+ )
+{
+ EFI_CORE_PROTOCOL_NOTIFY_ENTRY *Entry;
+
+ for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
+ if (!Entry->Present) {
+ return EFI_NOT_FOUND;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Notification event handler registered by CoreNotifyOnArchProtocolInstallation ().
+ This notify function is registered for every architectural protocol. This handler
+ updates mArchProtocol[] array entry with protocol instance data and sets it's
+ present flag to TRUE. If any constructor is required it is executed. The EFI
+ System Table headers are updated.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+GenericProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_CORE_PROTOCOL_NOTIFY_ENTRY *Entry;
+ VOID *Protocol;
+ LIST_ENTRY *Link;
+ LIST_ENTRY TempLinkNode;
+
+ Protocol = NULL;
+
+ //
+ // Get Entry from Context
+ //
+ Entry = (EFI_CORE_PROTOCOL_NOTIFY_ENTRY *)Context;
+
+ //
+ // See if the expected protocol is present in the handle database
+ //
+ Status = CoreLocateProtocol (Entry->ProtocolGuid, Entry->Registration, &Protocol);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Mark the protocol as present
+ //
+ Entry->Present = TRUE;
+
+ //
+ // Update protocol global variable if one exists. Entry->Protocol points to a global variable
+ // if one exists in the DXE core for this Architectural Protocol
+ //
+ if (Entry->Protocol != NULL) {
+ *(Entry->Protocol) = Protocol;
+ }
+
+ //
+ // Do special operations for Architectural Protocols
+ //
+
+ if (CompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid)) {
+ //
+ // Register the Core timer tick handler with the Timer AP
+ //
+ gTimer->RegisterHandler (gTimer, CoreTimerTick);
+ }
+
+ if (CompareGuid (Entry->ProtocolGuid, &gEfiRuntimeArchProtocolGuid)) {
+ //
+ // When runtime architectural protocol is available, updates CRC32 in the Debug Table
+ //
+ CoreUpdateDebugTableCrc32 ();
+
+ //
+ // Update the Runtime Architectural protocol with the template that the core was
+ // using so there would not need to be a dependency on the Runtime AP
+ //
+
+ //
+ // Copy all the registered Image to new gRuntime protocol
+ //
+ for (Link = gRuntimeTemplate.ImageHead.ForwardLink; Link != &gRuntimeTemplate.ImageHead; Link = TempLinkNode.ForwardLink) {
+ CopyMem (&TempLinkNode, Link, sizeof(LIST_ENTRY));
+ InsertTailList (&gRuntime->ImageHead, Link);
+ }
+ //
+ // Copy all the registered Event to new gRuntime protocol
+ //
+ for (Link = gRuntimeTemplate.EventHead.ForwardLink; Link != &gRuntimeTemplate.EventHead; Link = TempLinkNode.ForwardLink) {
+ CopyMem (&TempLinkNode, Link, sizeof(LIST_ENTRY));
+ InsertTailList (&gRuntime->EventHead, Link);
+ }
+
+ //
+ // Clean up gRuntimeTemplate
+ //
+ gRuntimeTemplate.ImageHead.ForwardLink = &gRuntimeTemplate.ImageHead;
+ gRuntimeTemplate.ImageHead.BackLink = &gRuntimeTemplate.ImageHead;
+ gRuntimeTemplate.EventHead.ForwardLink = &gRuntimeTemplate.EventHead;
+ gRuntimeTemplate.EventHead.BackLink = &gRuntimeTemplate.EventHead;
+ }
+
+ //
+ // It's over kill to do them all every time, but it saves a lot of code.
+ //
+ CalculateEfiHdrCrc (&gDxeCoreRT->Hdr);
+ CalculateEfiHdrCrc (&gBS->Hdr);
+ CalculateEfiHdrCrc (&gDxeCoreST->Hdr);
+ CalculateEfiHdrCrc (&gDxeCoreDS->Hdr);
+}
+
+/**
+ Creates an event for each entry in a table that is fired everytime a Protocol
+ of a specific type is installed.
+
+ @param Entry Pointer to EFI_CORE_PROTOCOL_NOTIFY_ENTRY.
+
+**/
+VOID
+CoreNotifyOnProtocolEntryTable (
+ EFI_CORE_PROTOCOL_NOTIFY_ENTRY *Entry
+ )
+{
+ EFI_STATUS Status;
+
+ for (; Entry->ProtocolGuid != NULL; Entry++) {
+ //
+ // Create the event
+ //
+ Status = CoreCreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ GenericProtocolNotify,
+ Entry,
+ &Entry->Event
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Register for protocol notifactions on this event
+ //
+ Status = CoreRegisterProtocolNotify (
+ Entry->ProtocolGuid,
+ Entry->Event,
+ &Entry->Registration
+ );
+ ASSERT_EFI_ERROR(Status);
+ }
+}
+
+/**
+ Creates an events for the Architectural Protocols and the optional protocols
+ that are fired everytime a Protocol of a specific type is installed.
+
+**/
+VOID
+CoreNotifyOnProtocolInstallation (
+ VOID
+ )
+{
+ CoreNotifyOnProtocolEntryTable (mArchProtocols);
+ CoreNotifyOnProtocolEntryTable (mOptionalProtocols);
+}
+
+
+/**
+ Displays Architectural protocols that were not loaded and are required for DXE
+ core to function. Only used in Debug Builds.
+
+**/
+VOID
+CoreDisplayMissingArchProtocols (
+ VOID
+ )
+{
+ EFI_CORE_PROTOCOL_NOTIFY_ENTRY *Entry;
+ CONST GUID_TO_STRING_PROTOCOL_ENTRY *MissingEntry;
+
+ for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
+ if (!Entry->Present) {
+ for (MissingEntry = mMissingProtocols; MissingEntry->ProtocolGuid != NULL; MissingEntry++) {
+ if (CompareGuid (Entry->ProtocolGuid, MissingEntry->ProtocolGuid)) {
+ DEBUG ((DEBUG_ERROR, "\n%a Arch Protocol not present!!\n", MissingEntry->GuidString));
+ break;
+ }
+ }
+ }
+ }
+}