mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-27 16:58:09 +01:00
7c0aa811ec
Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
443 lines
12 KiB
C
443 lines
12 KiB
C
/** @file
|
|
|
|
RuntimeServices overrides module.
|
|
|
|
By dmazar, 26/09/2012
|
|
|
|
**/
|
|
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
|
|
#include <Guid/EventGroup.h>
|
|
#include <Protocol/DataHub.h>
|
|
|
|
#include "Common.h"
|
|
|
|
|
|
/** Original runtime services. */
|
|
EFI_RUNTIME_SERVICES gOrgRS;
|
|
|
|
|
|
/** Virtual address change event. */
|
|
EFI_EVENT gVirtualAddressChangeEvent = NULL;
|
|
|
|
|
|
////////////////////////////////////////////
|
|
//
|
|
// Runtime services overrides
|
|
//
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrGetTime(
|
|
OUT EFI_TIME *Time,
|
|
OUT EFI_TIME_CAPABILITIES *Capabilities
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gOrgRS.GetTime(Time, Capabilities);
|
|
if (Capabilities != NULL) {
|
|
PRINT("->GetTime(%t, {Res = %x, Acc = %x, To0: %c}) = %r\n",
|
|
Time,
|
|
Capabilities->Resolution, Capabilities->Accuracy, Capabilities->SetsToZero ? L'T' : 'F',
|
|
Status);
|
|
} else {
|
|
PRINT("->GetTime(%t, NULL) = %r\n", Time, Status);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrSetTime(
|
|
IN EFI_TIME *Time
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gOrgRS.SetTime(Time);
|
|
PRINT("->SetTime(%t) = %r\n", Time, Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrGetWakeupTime(
|
|
OUT BOOLEAN *Enabled,
|
|
OUT BOOLEAN *Pending,
|
|
OUT EFI_TIME *Time
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gOrgRS.GetWakeupTime(Enabled, Pending, Time);
|
|
PRINT("->GetWakeupTime(%c, %c, %t) = %r\n", *Enabled ? L'T' : 'F', *Pending ? L'T' : 'F', Time, Status);
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrSetWakeupTime(
|
|
IN BOOLEAN Enabled,
|
|
IN EFI_TIME *Time
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gOrgRS.SetWakeupTime(Enabled, Time);
|
|
PRINT("->SetWakeupTime(%c, %t) = %r\n", Enabled ? L'T' : 'F', Time, Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrSetVirtualAddressMap(
|
|
IN UINTN MemoryMapSize,
|
|
IN UINTN DescriptorSize,
|
|
IN UINT32 DescriptorVersion,
|
|
IN EFI_MEMORY_DESCRIPTOR *VirtualMap
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
PRINT("->SetVirtualAddressMap(%d, %d, 0x%x, %p) START ...\n", MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap);
|
|
//PrintSystemTable(gST);
|
|
//PrintMemMap(MemoryMapSize, VirtualMap, DescriptorSize, DescriptorVersion);
|
|
Status = gOrgRS.SetVirtualAddressMap(MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap);
|
|
|
|
// Prints beyond this point may cause hangs, so don't print anything
|
|
//PRINT("->SetVirtualAddressMap(%d, %d, 0x%x, %p) END = %r\n", MemoryMapSize, DescriptorSize, DescriptorVersion, VirtualMap, Status);
|
|
//PrintSystemTable(gST);
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrConvertPointer(
|
|
IN UINTN DebugDisposition,
|
|
IN OUT VOID **Address
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
// We should call PRINT before actual convertion takes place, as otherwise we may call it with converted buffer
|
|
VOID *AddressOut = *Address;
|
|
|
|
Status = gOrgRS.ConvertPointer(DebugDisposition, &AddressOut);
|
|
PRINT("->ConvertPointer(%d, %p/%p) = %r\n", DebugDisposition, *Address, AddressOut, Status);
|
|
*Address = AddressOut;
|
|
|
|
/*
|
|
VOID *AddressIn = *Address;
|
|
|
|
Status = gOrgRS.ConvertPointer(DebugDisposition, Address);
|
|
PRINT("->ConvertPointer(%d, %p/%p) = %r\n", DebugDisposition, AddressIn, *Address, Status);
|
|
*/
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrGetVariable(
|
|
IN CHAR16 *VariableName,
|
|
IN EFI_GUID *VendorGuid,
|
|
OUT UINT32 *Attributes,
|
|
IN OUT UINTN *DataSize,
|
|
OUT VOID *Data
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 OurAttributes;
|
|
|
|
|
|
//
|
|
// Attributes could be NULL, but it's still good
|
|
// to get and see them.
|
|
//
|
|
if (Attributes != NULL) {
|
|
OurAttributes = *Attributes;
|
|
}
|
|
Status = gOrgRS.GetVariable(VariableName, VendorGuid, &OurAttributes, DataSize, Data);
|
|
if (Attributes != NULL) {
|
|
*Attributes = OurAttributes;
|
|
}
|
|
|
|
#if CLEANER_LOG == 1
|
|
// Better not print this to avoid EfiTime "SPAM" on some AMI firmware - reported by XyZ
|
|
if (StrStr(VariableName, L"EfiTime") == 0) {
|
|
PRINT("->GetVariable(%s, %s, %x/%x, %x, %p) = %r\n",
|
|
VariableName, GuidStr(VendorGuid), Attributes != NULL ? *Attributes : 0, OurAttributes, *DataSize, Data, Status);
|
|
}
|
|
#else
|
|
PRINT("->GetVariable(%s, %s, %x/%x, %x, %p) = %r\n",
|
|
VariableName, GuidStr(VendorGuid), Attributes != NULL ? *Attributes : 0, OurAttributes, *DataSize, Data, Status);
|
|
//PRINT("->GetVariable(%s)\n", VariableName);
|
|
#endif
|
|
|
|
if (!EFI_ERROR(Status)) {
|
|
PrintBytes((CHAR8 *)Data, *DataSize);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrGetNextVariableName(
|
|
IN OUT UINTN *VariableNameSize,
|
|
IN OUT CHAR16 *VariableName,
|
|
IN OUT EFI_GUID *VendorGuid
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
PRINT("->GetNextVariableName(%x, %s, %s)", *VariableNameSize, VariableName, GuidStr(VendorGuid));
|
|
Status = gOrgRS.GetNextVariableName(VariableNameSize, VariableName, VendorGuid);
|
|
PRINT(" -> (%x, %s, %s) = %r\n", *VariableNameSize, VariableName, GuidStr(VendorGuid), Status);
|
|
//PRINT("->GetNextVariableName()\n");
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrSetVariable(
|
|
IN CHAR16 *VariableName,
|
|
IN EFI_GUID *VendorGuid,
|
|
IN UINT32 Attributes,
|
|
IN UINTN DataSize,
|
|
IN VOID *Data
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gOrgRS.SetVariable(VariableName, VendorGuid, Attributes, DataSize, Data);
|
|
//PRINT("->SetVariable(%s)\n", VariableName);
|
|
PRINT("->SetVariable(%s, %s, %x, %x, %p) = %r\n", VariableName, GuidStr(VendorGuid), Attributes, DataSize, Data, Status);
|
|
PrintBytes((CHAR8 *)Data, DataSize);
|
|
//PRINT("->SetVariable(%s)\n", VariableName);
|
|
return Status;
|
|
}
|
|
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrGetNextHighMonotonicCount(
|
|
OUT UINT32 *HighCount
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gOrgRS.GetNextHighMonotonicCount(HighCount);
|
|
PRINT("->GetNextHighMonotonicCount(%x) = %r\n", *HighCount, Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID EFIAPI
|
|
OvrResetSystem(
|
|
IN EFI_RESET_TYPE ResetType,
|
|
IN EFI_STATUS ResetStatus,
|
|
IN UINTN DataSize,
|
|
IN VOID *ResetData
|
|
)
|
|
{
|
|
|
|
PRINT("->ResetSystem(%s, %r, %x, %p)\n", EfiResetType[ResetType], ResetStatus, DataSize, ResetData);
|
|
PrintBytes((CHAR8 *)ResetData, DataSize);
|
|
// gOrgRS.ResetSystem(ResetType, ResetStatus, DataSize, ResetData);
|
|
}
|
|
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrUpdateCapsule(
|
|
IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
|
|
IN UINTN CapsuleCount,
|
|
IN EFI_PHYSICAL_ADDRESS ScatterGatherList
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gOrgRS.UpdateCapsule(CapsuleHeaderArray, CapsuleCount, ScatterGatherList);
|
|
PRINT("->UpdateCapsule(%p, %x, %lx) = %r\n", CapsuleHeaderArray, CapsuleCount, ScatterGatherList, Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrQueryCapsuleCapabilities(
|
|
IN EFI_CAPSULE_HEADER **CapsuleHeaderArray,
|
|
IN UINTN CapsuleCount,
|
|
OUT UINT64 *MaximumCapsuleSize,
|
|
OUT EFI_RESET_TYPE *ResetType
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gOrgRS.QueryCapsuleCapabilities(CapsuleHeaderArray, CapsuleCount, MaximumCapsuleSize, ResetType);
|
|
PRINT("->QueryCapsuleCapabilities(%p, %x, %lx, %s) = %r\n",
|
|
CapsuleHeaderArray, CapsuleCount, *MaximumCapsuleSize, EfiResetType[*ResetType], Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
EFI_STATUS EFIAPI
|
|
OvrQueryVariableInfo(
|
|
IN UINT32 Attributes,
|
|
OUT UINT64 *MaximumVariableStorageSize,
|
|
OUT UINT64 *RemainingVariableStorageSize,
|
|
OUT UINT64 *MaximumVariableSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gOrgRS.QueryVariableInfo(Attributes, MaximumVariableStorageSize, RemainingVariableStorageSize, MaximumVariableSize);
|
|
PRINT("->QueryVariableInfo(%x, %lx, %lx, %lx) = %r\n",
|
|
Attributes, *MaximumVariableStorageSize, *RemainingVariableStorageSize, *MaximumVariableSize, Status);
|
|
return Status;
|
|
}
|
|
|
|
|
|
/** Virtual address change event. Converts our pointers
|
|
* to be valid in runtime with new virtual addresses.
|
|
*/
|
|
VOID
|
|
EFIAPI
|
|
VirtualAddressChangeEvent(
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
PRINT("VirtualAddressChangeEvent\n");
|
|
|
|
//
|
|
// Convert original RT services so we cam continue use them.
|
|
//
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.GetTime);
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.SetTime);
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.GetWakeupTime);
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.SetWakeupTime);
|
|
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.GetVariable);
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.GetNextVariableName);
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.SetVariable);
|
|
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.GetNextHighMonotonicCount);
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.ResetSystem);
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.UpdateCapsule);
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.QueryCapsuleCapabilities);
|
|
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gOrgRS.QueryVariableInfo);
|
|
|
|
//
|
|
// Convert our pointers to allocated buffers.
|
|
//
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &GuidPrintBuffer);
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gVariableNameBuffer);
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gVariableDataBuffer);
|
|
// LogPrint's buffer should be converted last, as otherwise LogPrint may be called with incorrect pointer
|
|
OvrConvertPointer(EFI_OPTIONAL_PTR, (VOID **) &gLogLineBuffer);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////
|
|
//
|
|
// Other functions
|
|
//
|
|
|
|
/** Installs our runtime services overrides. */
|
|
EFI_STATUS EFIAPI
|
|
OvrRuntimeServices(EFI_RUNTIME_SERVICES *RS)
|
|
{
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
|
|
PRINT("Overriding runtime services ...\n");
|
|
|
|
// store orig BS
|
|
CopyMem(&gOrgRS, RS, sizeof(EFI_RUNTIME_SERVICES));
|
|
|
|
RS->GetTime = OvrGetTime;
|
|
RS->SetTime = OvrSetTime;
|
|
RS->GetWakeupTime = OvrGetWakeupTime;
|
|
RS->SetWakeupTime = OvrSetWakeupTime;
|
|
|
|
RS->SetVirtualAddressMap = OvrSetVirtualAddressMap;
|
|
RS->ConvertPointer = OvrConvertPointer;
|
|
|
|
RS->GetVariable = OvrGetVariable;
|
|
RS->GetNextVariableName = OvrGetNextVariableName;
|
|
RS->SetVariable = OvrSetVariable;
|
|
|
|
RS->GetNextHighMonotonicCount = OvrGetNextHighMonotonicCount;
|
|
RS->ResetSystem = OvrResetSystem;
|
|
RS->UpdateCapsule = OvrUpdateCapsule;
|
|
RS->QueryCapsuleCapabilities = OvrQueryCapsuleCapabilities;
|
|
|
|
RS->QueryVariableInfo = OvrQueryVariableInfo;
|
|
|
|
RS->Hdr.CRC32 = 0;
|
|
gBS->CalculateCrc32(RS, RS->Hdr.HeaderSize, &RS->Hdr.CRC32);
|
|
|
|
#if WORK_DURING_RUNTIME >= 1
|
|
//
|
|
// Register callback for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
|
|
//
|
|
#if WORK_DURING_RUNTIME == 2
|
|
// new style - does not work on Phoenix UEFI
|
|
Status = gBS->CreateEventEx (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_NOTIFY,
|
|
VirtualAddressChangeEvent,
|
|
NULL,
|
|
&gEfiEventVirtualAddressChangeGuid,
|
|
&gVirtualAddressChangeEvent
|
|
);
|
|
#elif WORK_DURING_RUNTIME == 1
|
|
// old style
|
|
Status = gBS->CreateEvent (
|
|
EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
|
|
TPL_NOTIFY,
|
|
VirtualAddressChangeEvent,
|
|
NULL,
|
|
&gVirtualAddressChangeEvent
|
|
);
|
|
#endif
|
|
PRINT("Runtime services: setting VirtualAddressChangeEvent = %r\n", Status);
|
|
#endif
|
|
|
|
PRINT("Runtime services overriden!\n");
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** Restores original runtime services. */
|
|
EFI_STATUS EFIAPI
|
|
RestoreRuntimeServices(EFI_RUNTIME_SERVICES *RS)
|
|
{
|
|
|
|
PRINT("Restoring original runtime services ...\n");
|
|
|
|
RS->GetTime = gOrgRS.GetTime;
|
|
RS->SetTime = gOrgRS.SetTime;
|
|
RS->GetWakeupTime = gOrgRS.GetWakeupTime;
|
|
RS->SetWakeupTime = gOrgRS.SetWakeupTime;
|
|
|
|
RS->SetVirtualAddressMap = gOrgRS.SetVirtualAddressMap;
|
|
RS->ConvertPointer = gOrgRS.ConvertPointer;
|
|
|
|
RS->GetVariable = gOrgRS.GetVariable;
|
|
RS->GetNextVariableName = gOrgRS.GetNextVariableName;
|
|
RS->SetVariable = gOrgRS.SetVariable;
|
|
|
|
RS->GetNextHighMonotonicCount = gOrgRS.GetNextHighMonotonicCount;
|
|
RS->ResetSystem = gOrgRS.ResetSystem;
|
|
RS->UpdateCapsule = gOrgRS.UpdateCapsule;
|
|
RS->QueryCapsuleCapabilities = gOrgRS.QueryCapsuleCapabilities;
|
|
|
|
RS->QueryVariableInfo = gOrgRS.QueryVariableInfo;
|
|
|
|
RS->Hdr.CRC32 = 0;
|
|
gBS->CalculateCrc32(RS, RS->Hdr.HeaderSize, &RS->Hdr.CRC32);
|
|
|
|
PRINT("Runtime services restored!\n");
|
|
|
|
return EFI_SUCCESS;
|
|
}
|