--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ RuntimeLib.c\r
+\r
+Abstract:\r
+\r
+ Light weight lib to support Tiano drivers.\r
+\r
+--*/\r
+\r
+#include <SalApi.h>\r
+#include <RuntimeLibInternal.h>\r
+\r
+//\r
+// Driver Lib Module Globals\r
+//\r
+\r
+STATIC EFI_EVENT mRuntimeNotifyEvent;\r
+STATIC EFI_EVENT mEfiVirtualNotifyEvent;\r
+\r
+STATIC EFI_PLABEL mPlabel;\r
+STATIC EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *mEsalBootService;\r
+\r
+EFI_RUNTIME_SERVICES *mRT = NULL;\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+RuntimeDriverExitBootServices (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Set AtRuntime flag as TRUE after ExitBootServices\r
+\r
+Arguments:\r
+\r
+ Event - The Event that is being processed\r
+ \r
+ Context - Event Context\r
+\r
+Returns: \r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_EVENT_NOTIFY ChildNotifyEventHandler;\r
+ UINTN Index;\r
+\r
+ for (Index = 0; _gDriverExitBootServicesEvent[Index] != NULL; Index++) {\r
+ ChildNotifyEventHandler = _gDriverExitBootServicesEvent[Index];\r
+ ChildNotifyEventHandler (Event, NULL);\r
+ }\r
+}\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+RuntimeLibVirtualNotifyEvent (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Fixup internal data so that EFI can be call in virtual mode.\r
+ Call the passed in Child Notify event and convert any pointers in \r
+ lib to virtual mode.\r
+\r
+Arguments:\r
+\r
+ Event - The Event that is being processed\r
+ \r
+ Context - Event Context\r
+\r
+Returns: \r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+ EFI_EVENT_NOTIFY ChildNotifyEventHandler;\r
+\r
+ for (Index = 0; _gDriverSetVirtualAddressMapEvent[Index] != NULL; Index++) {\r
+ ChildNotifyEventHandler = _gDriverSetVirtualAddressMapEvent[Index];\r
+ ChildNotifyEventHandler (Event, NULL);\r
+ }\r
+\r
+ mRT->ConvertPointer (0x0, (VOID **) &mPlabel.EntryPoint);\r
+ mRT->ConvertPointer (EFI_IPF_GP_POINTER, (VOID **) &mPlabel.GP);\r
+\r
+ SetEsalVirtualEntryPoint (mPlabel.EntryPoint, mPlabel.GP);\r
+\r
+ //\r
+ // Clear out BootService globals\r
+ //\r
+ gBS = NULL;\r
+ gST = NULL;\r
+ mRT = NULL;\r
+}\r
+\r
+EFI_STATUS\r
+RuntimeDriverLibConstruct (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Intialize runtime Driver Lib if it has not yet been initialized. \r
+\r
+Arguments:\r
+\r
+ ImageHandle - The firmware allocated handle for the EFI image.\r
+ \r
+ SystemTable - A pointer to the EFI System Table.\r
+\r
+ GoVirtualChildEvent - Caller can register a virtual notification event.\r
+\r
+Returns: \r
+\r
+ EFI_STATUS always returns EFI_SUCCESS except EFI_ALREADY_STARTED if already started.\r
+\r
+--*/\r
+{\r
+ EFI_PLABEL *Plabel;\r
+ EFI_STATUS Status;\r
+\r
+ mRT = SystemTable->RuntimeServices;\r
+\r
+ //\r
+ // The protocol contains a function pointer, which is an indirect procedure call.\r
+ // An indirect procedure call goes through a plabel, and pointer to a function is\r
+ // a pointer to a plabel. To implement indirect procedure calls that can work in\r
+ // both physical and virtual mode, two plabels are required (one physical and one\r
+ // virtual). So lets grap the physical PLABEL for the EsalEntryPoint and store it\r
+ // away. We cache it in a module global, so we can register the vitrual version.\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiExtendedSalBootServiceProtocolGuid, NULL, &mEsalBootService);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Plabel = (EFI_PLABEL *) (UINTN) mEsalBootService->ExtendedSalProc;\r
+\r
+ mPlabel.EntryPoint = Plabel->EntryPoint;\r
+ mPlabel.GP = Plabel->GP;\r
+\r
+ SetEsalPhysicalEntryPoint (mPlabel.EntryPoint, mPlabel.GP);\r
+\r
+ //\r
+ // Register our ExitBootServices () notify function\r
+ //\r
+\r
+ Status = gBS->CreateEvent (\r
+ EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,\r
+ EFI_TPL_NOTIFY,\r
+ RuntimeDriverExitBootServices,\r
+ NULL,\r
+ &mRuntimeNotifyEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Register SetVirtualAddressMap () notify function\r
+ //\r
+ \r
+ Status = gBS->CreateEvent (\r
+ EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\r
+ EFI_TPL_NOTIFY,\r
+ RuntimeLibVirtualNotifyEvent,\r
+ NULL,\r
+ mEfiVirtualNotifyEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+RuntimeDriverLibDeconstruct (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This routine will free some resources which have been allocated in\r
+ EfiInitializeRuntimeDriverLib(). If a runtime driver exits with an error, \r
+ it must call this routine to free the allocated resource before the exiting.\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS - Shotdown the Runtime Driver Lib successfully\r
+ EFI_UNSUPPORTED - Runtime Driver lib was not initialized at all\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Close our ExitBootServices () notify function\r
+ //\r
+ Status = gBS->CloseEvent (mRuntimeNotifyEvent);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Close SetVirtualAddressMap () notify function\r
+ //\r
+ Status = gBS->CloseEvent (mEfiVirtualNotifyEvent);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+EfiAtRuntime (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Return TRUE if ExitBootService () has been called\r
+\r
+Arguments:\r
+ NONE\r
+\r
+Returns: \r
+ TRUE - If ExitBootService () has been called\r
+\r
+--*/\r
+{\r
+ EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID;\r
+ SAL_RETURN_REGS ReturnReg;\r
+\r
+ ReturnReg = EfiCallEsalService (&Guid, IsEfiRuntime, 0, 0, 0, 0, 0, 0, 0);\r
+\r
+ return (BOOLEAN) (ReturnReg.r9 == 1);\r
+}\r
+\r
+BOOLEAN\r
+EfiGoneVirtual (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Return TRUE if SetVirtualAddressMap () has been called\r
+\r
+Arguments:\r
+ NONE\r
+\r
+Returns: \r
+ TRUE - If SetVirtualAddressMap () has been called\r
+\r
+--*/\r
+{\r
+ EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID;\r
+ SAL_RETURN_REGS ReturnReg;\r
+\r
+ ReturnReg = EfiCallEsalService (&Guid, IsVirtual, 0, 0, 0, 0, 0, 0, 0);\r
+\r
+ return (BOOLEAN) (ReturnReg.r9 == 1);\r
+}\r