CloverBootloader/Protocols/DumpUefiCalls/BootServices.c

957 lines
26 KiB
C
Raw Normal View History

/** @file
BootServices 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 "Common.h"
/** Flag is TRUE before ExitBootServices() is called. FALSE in runtime. */
BOOLEAN InBootServices = TRUE;
/** Original boot services. */
EFI_BOOT_SERVICES gOrgBS;
#if CAPTURE_CONSOLE_OUTPUT >= 1
EFI_TEXT_STRING gOrgConOutOutputString = 0;
BOOLEAN InConsolePrint = FALSE;
#endif
/** Helper function that calls GetMemoryMap() and returns new MapKey.
* Uses gOrgBS.GetMemoryMap to avoid our log PRINT.
*/
EFI_STATUS
GetMemoryMapKey(OUT UINTN *MapKey)
{
EFI_STATUS Status;
UINTN MemoryMapSize;
EFI_MEMORY_DESCRIPTOR *MemoryMap;
UINTN DescriptorSize;
UINT32 DescriptorVersion;
Status = GetMemoryMapAlloc(gOrgBS.GetMemoryMap, &MemoryMapSize, &MemoryMap, MapKey, &DescriptorSize, &DescriptorVersion);
return Status;
}
////////////////////////////////////////////
//
// Boot services overrides
//
EFI_TPL EFIAPI
OvrRaiseTPL(IN EFI_TPL NewTpl)
{
EFI_TPL Status;
Status = gOrgBS.RaiseTPL(NewTpl);
// do not print - it's called by UEFI events and timers (from timer interrupts) many times
//PRINT("->RaiseTPL(NewTpl=%d) = %d\n", NewTpl, Status);
return Status;
}
VOID EFIAPI
OvrRestoreTPL(IN EFI_TPL OldTpl)
{
gOrgBS.RestoreTPL(OldTpl);
// do not print - it's called by UEFI events and timers (from timer interrupts) many times
//PRINT("->RestoreTPL(OldTpl=%d)\n", OldTpl);
return;
}
EFI_STATUS EFIAPI
OvrAllocatePages(
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN NumberOfPages,
IN OUT EFI_PHYSICAL_ADDRESS *Memory
)
{
EFI_STATUS Status;
// EFI_PHYSICAL_ADDRESS inMemory = *Memory;
Status = gOrgBS.AllocatePages(Type, MemoryType, NumberOfPages, Memory);
// PRINT("-> AllocatePages(%s, %s, 0x%x, 0x%lx/0x%lx) = %r\n", EfiAllocateTypeDesc[Type], EfiMemoryTypeDesc[MemoryType], NumberOfPages, inMemory, *Memory, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrFreePages(
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN Pages
)
{
EFI_STATUS Status;
Status = gOrgBS.FreePages(Memory, Pages);
// PRINT("->FreePages(0x%lx, 0x%x) = %r\n", Memory, Pages, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrGetMemoryMap(
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
OUT UINTN *MapKey,
OUT UINTN *DescriptorSize,
OUT UINT32 *DescriptorVersion
)
{
EFI_STATUS Status;
// UINTN inMemoryMapSize = *MemoryMapSize;
Status = gOrgBS.GetMemoryMap(MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
// if print to console, then ExitBootServices will not work
// PRINT("->GetMemoryMap(0x%x/0x%x, %p, 0x%x, 0x%x, 0x%x) = %r\n", inMemoryMapSize, *MemoryMapSize, MemoryMap, *MapKey, *DescriptorSize, *DescriptorVersion, Status);
if (Status == EFI_SUCCESS) {
#if PRINT_MEMORY_MAP == 1
PrintMemMap(*MemoryMapSize, MemoryMap, *DescriptorSize, *DescriptorVersion);
#endif
}
//Print(L"OvrGetMemoryMap\n");
return Status;
}
EFI_STATUS EFIAPI
OvrAllocatePool(
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
)
{
EFI_STATUS Status;
Status = gOrgBS.AllocatePool(PoolType, Size, Buffer);
// printing to console requires AllocatePool - recursion, but this is solved by safety check in LogPrint
// do not print to serial - too many calls from UEFI
//DebugPrint(1, "->AllocatePool(%s, 0x%x, %p) = %r\n", EfiMemoryTypeDesc[PoolType], Size, *Buffer, Status);
#if PRINT_ALLOCATE_POOL == 1
PRINT("->AllocatePool(%s, 0x%x, %p) = %r\n", EfiMemoryTypeDesc[PoolType], Size, *Buffer, Status);
#endif
return Status;
}
EFI_STATUS EFIAPI
OvrFreePool(
IN VOID *Buffer
)
{
EFI_STATUS Status;
Status = gOrgBS.FreePool(Buffer);
// do not print to console - requires FreePool - recursion
// do not print to serial - too many calls from UEFI
//DebugPrint(1, "->FreePool(%p) = %r\n", Buffer, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrCreateEvent(
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN VOID *NotifyContext,
OUT EFI_EVENT *Event
)
{
EFI_STATUS Status;
Status = gOrgBS.CreateEvent(Type, NotifyTpl, NotifyFunction, NotifyContext, Event);
//PRINT("->CreateEvent(0x%x, 0x%x, %p, %p, %p) = %r\n", Type, NotifyTpl, NotifyFunction, NotifyContext, *Event, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrSetTimer(
IN EFI_EVENT Event,
IN EFI_TIMER_DELAY Type,
IN UINT64 TriggerTime
)
{
EFI_STATUS Status;
Status = gOrgBS.SetTimer(Event, Type, TriggerTime);
PRINT("->SetTimer(%p, %d, 0x%x) = %r\n", Event, Type, TriggerTime, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrWaitForEvent(
IN UINTN NumberOfEvents,
IN EFI_EVENT *Event,
OUT UINTN *Index
)
{
EFI_STATUS Status;
Status = gOrgBS.WaitForEvent(NumberOfEvents, Event, Index);
// PRINT("->WaitForEvent(%d, %p, %d) = %r\n", NumberOfEvents, *Event, *Index, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrSignalEvent(
IN EFI_EVENT Event
)
{
EFI_STATUS Status;
Status = gOrgBS.SignalEvent(Event);
//PRINT("->SignalEvent(%p) = %r\n", Event, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrCloseEvent(
IN EFI_EVENT Event
)
{
EFI_STATUS Status;
Status = gOrgBS.CloseEvent(Event);
//PRINT("->CloseEvent(%p) = %r\n", Event, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrCheckEvent(
IN EFI_EVENT Event
)
{
EFI_STATUS Status;
Status = gOrgBS.CheckEvent(Event);
//PRINT("->CheckEvent(%p) = %r\n", Event, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrInstallProtocolInterface(
IN OUT EFI_HANDLE *Handle,
IN EFI_GUID *Protocol,
IN EFI_INTERFACE_TYPE InterfaceType,
IN VOID *Interface
)
{
EFI_STATUS Status;
Status = gOrgBS.InstallProtocolInterface(Handle, Protocol, InterfaceType, Interface);
PRINT("->InstallProtocolInterface(%p, %s, %d, %p) = %r\n", Handle, GuidStr(Protocol), InterfaceType, Interface, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrReinstallProtocolInterface(
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN VOID *OldInterface,
IN VOID *NewInterface
)
{
EFI_STATUS Status;
Status = gOrgBS.ReinstallProtocolInterface(Handle, Protocol, OldInterface, NewInterface);
PRINT("->ReinstallProtocolInterface(%p, %s, %p, %p) = %r\n", Handle, GuidStr(Protocol), OldInterface, NewInterface, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrUninstallProtocolInterface(
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN VOID *Interface
)
{
EFI_STATUS Status;
Status = gOrgBS.UninstallProtocolInterface(Handle, Protocol, Interface);
PRINT("->UninstallProtocolInterface(%p, %s, %p) = %r\n", Handle, GuidStr(Protocol), Interface, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrHandleProtocol(
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT VOID **Interface
)
{
EFI_STATUS Status;
Status = gOrgBS.HandleProtocol(Handle, Protocol, Interface);
PRINT("->HandleProtocol(%p, %s, %p) = %r\n", Handle, GuidStr(Protocol), *Interface, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrRegisterProtocolNotify(
IN EFI_GUID *Protocol,
IN EFI_EVENT Event,
OUT VOID **Registration
)
{
EFI_STATUS Status;
Status = gOrgBS.RegisterProtocolNotify(Protocol, Event, Registration);
PRINT("->RegisterProtocolNotify(%s, %p, %p) = %r\n", GuidStr(Protocol), Event, *Registration, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrLocateHandle(
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol,
IN VOID *SearchKey,
IN OUT UINTN *BufferSize,
OUT EFI_HANDLE *Buffer
)
{
EFI_STATUS Status;
UINTN BufferSizeIn = *BufferSize;
Status = gOrgBS.LocateHandle(SearchType, Protocol, SearchKey, BufferSize, Buffer);
PRINT("->LocateHandle(%d, %s, %p, 0x%x/0x%x, %p) = %r\n", SearchType, GuidStr(Protocol), SearchKey, BufferSizeIn, *BufferSize, Buffer, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrLocateDevicePath(
IN EFI_GUID *Protocol,
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
OUT EFI_HANDLE *Device
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePathIn = *DevicePath;
// PRINT("... try to do LocateDevicePath\n");
Status = gOrgBS.LocateDevicePath(Protocol, DevicePath, Device);
// TODO: device path to str
PRINT("->LocateDevicePath(%s, %p/%p, %p) = %r\n", GuidStr(Protocol), DevicePathIn, DevicePath, Device, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrInstallConfigurationTable(
IN EFI_GUID *Guid,
IN VOID *Table
)
{
EFI_STATUS Status;
Status = gOrgBS.InstallConfigurationTable(Guid, Table);
// TODO: table guids to Lib.c
PRINT("->InstallConfigurationTable(%s, %p) = %r\n", GuidStr(Guid), Table, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrLoadImage(
IN BOOLEAN BootPolicy,
IN EFI_HANDLE ParentImageHandle,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN VOID *SourceBuffer,
IN UINTN SourceSize,
OUT EFI_HANDLE *ImageHandle
)
{
EFI_STATUS Status;
Status = gOrgBS.LoadImage(BootPolicy, ParentImageHandle, DevicePath, SourceBuffer, SourceSize, ImageHandle);
// TODO: dev path to str
PRINT("->LoadImage(%c, %p, %p, %p, 0x%x, %p) = %r\n", BootPolicy ? L'T' : L'F', ParentImageHandle, DevicePath, SourceBuffer, SourceSize, ImageHandle, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrStartImage(
IN EFI_HANDLE ImageHandle,
OUT UINTN *ExitDataSize,
OUT CHAR16 **ExitData
)
{
EFI_STATUS Status;
Status = gOrgBS.StartImage(ImageHandle, ExitDataSize, ExitData);
PRINT("->StartImage(%p, 0x%x, %p) = %r\n", ImageHandle, *ExitDataSize, *ExitData, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrExit(
IN EFI_HANDLE ImageHandle,
IN EFI_STATUS ExitStatus,
IN UINTN ExitDataSize,
IN CHAR16 *ExitData
)
{
EFI_STATUS Status;
Status = gOrgBS.Exit(ImageHandle, ExitStatus, ExitDataSize, ExitData);
PRINT("->Exit(%p, %r, 0x%x, %s) = %r\n", ImageHandle, ExitStatus, ExitDataSize, ExitData, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrUnloadImage(
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
Status = gOrgBS.UnloadImage(ImageHandle);
PRINT("->UnloadImage(%p) = %r\n", ImageHandle, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrExitBootServices(
IN EFI_HANDLE ImageHandle,
IN UINTN MapKey
)
{
EFI_STATUS Status;
UINTN NewMapKey;
PRINT("ExitBootServices called. Doing some more dumps ...\n");
#if PRINT_DUMPS >= 1
// Print ST
PrintSystemTable(gST);
// Print RT vars
PrintRTVariables(&gOrgRS);
#endif
// Restore RT services if we should not log calls during runtime
#if WORK_DURING_RUNTIME == 0
RestoreRuntimeServices(gRT);
#endif
PRINT("->ExitBootServices(%p, 0x%x) ...\n", ImageHandle, MapKey);
// Set flag to FALSE to stop some loggers from messing with memory
InBootServices = FALSE;
// Restore original OutputString
#if CAPTURE_CONSOLE_OUTPUT >= 1
gST->ConOut->OutputString = gOrgConOutOutputString;
#endif
// Notify loggers that boot services are over
// Saving our log file can cause a vast amount of logging output on some firmwares, so do this after stopping loggers.
LogOnExitBootServices();
// Call original
Status = gOrgBS.ExitBootServices(ImageHandle, MapKey);
if (Status == EFI_SUCCESS) {
PRINT("... ExitBootServices = %r\n", Status);
} else {
//
// Error exiting boot services. Probably because
// some of our loggers changed memory map state.
// We'll just force exiting by obtaining new
// MapKey and calling ExitBootServices again.
//
PRINT("... ExitBootServices = %r\n", Status);
PRINT("Forcing ExitBootServices ...\n");
Status = GetMemoryMapKey(&NewMapKey);
if (Status == EFI_SUCCESS) {
// we have latest mem map and NewMapKey
// we'll try again ExitBootServices with NewMapKey
Status = gOrgBS.ExitBootServices(ImageHandle, NewMapKey);
PRINT("ExitBootServices: 2nd try = %r\n", Status);
} else {
PRINT("ERROR obtaining new map key: %r\n", Status);
Status = EFI_INVALID_PARAMETER;
}
}
return Status;
}
EFI_STATUS EFIAPI
OvrGetNextMonotonicCount(
OUT UINT64 *Count
)
{
EFI_STATUS Status;
Status = gOrgBS.GetNextMonotonicCount(Count);
PRINT("->GetNextMonotonicCount(0x%x) = %r\n", *Count, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrStall(
IN UINTN Microseconds
)
{
EFI_STATUS Status;
Status = gOrgBS.Stall(Microseconds);
// do not print - too many calls
//PRINT("->Stall(%d) = %r\n", Microseconds, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrSetWatchdogTimer(
IN UINTN Timeout,
IN UINT64 WatchdogCode,
IN UINTN DataSize,
IN CHAR16 *WatchdogData
)
{
EFI_STATUS Status;
Status = gOrgBS.SetWatchdogTimer(Timeout, WatchdogCode, DataSize, WatchdogData);
PRINT("->SetWatchdogTimer(%d, 0x%x, %d, %s) = %r\n", Timeout, WatchdogCode, DataSize, WatchdogData, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrConnectController(
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE *DriverImageHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
IN BOOLEAN Recursive
)
{
EFI_STATUS Status;
Status = gOrgBS.ConnectController(ControllerHandle, DriverImageHandle, RemainingDevicePath, Recursive);
// TODO: dev path to str
PRINT("->ConnectController(%p, %p, %p, %c) = %r\n", ControllerHandle, DriverImageHandle, RemainingDevicePath, Recursive ? L'T' : L'F', Status);
return Status;
}
EFI_STATUS EFIAPI
OvrDisconnectController(
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE DriverImageHandle,
IN EFI_HANDLE ChildHandle
)
{
EFI_STATUS Status;
Status = gOrgBS.DisconnectController(ControllerHandle, DriverImageHandle, ChildHandle);
PRINT("->DisconnectController(%p, %p, %p) = %r\n", ControllerHandle, DriverImageHandle, ChildHandle, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrOpenProtocol(
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT VOID **Interface,
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle,
IN UINT32 Attributes
)
{
EFI_STATUS Status;
VOID *InterfaceIn = *Interface;
Status = gOrgBS.OpenProtocol(Handle, Protocol, Interface, AgentHandle, ControllerHandle, Attributes);
PRINT("->OpenProtocol(%p, %s, %p/%p, %p, %p, %x) = %r\n", Handle, GuidStr(Protocol), InterfaceIn, *Interface, AgentHandle, ControllerHandle, Attributes, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrCloseProtocol(
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle
)
{
EFI_STATUS Status;
Status = gOrgBS.CloseProtocol(Handle, Protocol, AgentHandle, ControllerHandle);
PRINT("->CloseProtocol(%p, %s, %p, %p) = %r\n", Handle, GuidStr(Protocol), AgentHandle, ControllerHandle, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrOpenProtocolInformation(
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
OUT UINTN *EntryCount
)
{
EFI_STATUS Status;
Status = gOrgBS.OpenProtocolInformation(Handle, Protocol, EntryBuffer, EntryCount);
PRINT("->OpenProtocolInformation(%p, %s, %p, %d) = %r\n", Handle, GuidStr(Protocol), *EntryBuffer, *EntryCount, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrProtocolsPerHandle(
IN EFI_HANDLE Handle,
OUT EFI_GUID ***ProtocolBuffer,
OUT UINTN *ProtocolBufferCount
)
{
EFI_STATUS Status;
Status = gOrgBS.ProtocolsPerHandle(Handle, ProtocolBuffer, ProtocolBufferCount);
// TODO: print list of protocols returned
PRINT("->ProtocolsPerHandle(%p, %p, %d) = %r\n", Handle, *ProtocolBuffer, *ProtocolBufferCount, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrLocateHandleBuffer(
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol,
IN VOID *SearchKey,
IN OUT UINTN *NoHandles,
OUT EFI_HANDLE **Buffer
)
{
EFI_STATUS Status;
STATIC UINTN OldBuffer = 0;
Status = gOrgBS.LocateHandleBuffer(SearchType, Protocol, SearchKey, NoHandles, Buffer);
if (!CompareGuid(Protocol, &mEfiSimplePointerProtocolGuid) || (UINTN)Buffer != OldBuffer) {
OldBuffer = (UINTN)Buffer;
PRINT("->LocateHandleBuffer(%s, %s, %p, %d, %p) = %r\n", EfiLocateSearchType[SearchType], GuidStr(Protocol), SearchKey, *NoHandles, *Buffer, Status);
}
return Status;
}
EFI_STATUS EFIAPI
OvrLocateProtocol(
IN EFI_GUID *Protocol,
IN VOID *Registration,
OUT VOID **Interface
)
{
EFI_STATUS Status;
VOID *InterfaceIn = *Interface;
Status = gOrgBS.LocateProtocol(Protocol, Registration, Interface);
PRINT("->LocateProtocol(%s, %p, %p/%p) = %r\n", GuidStr(Protocol), Registration, InterfaceIn, *Interface, Status);
return Status;
}
EFI_STATUS EFIAPI
OvrInstallMultipleProtocolInterfaces(
IN OUT EFI_HANDLE *Handle,
...
)
{
EFI_STATUS Status;
EFI_HANDLE HandleIn = *Handle;
VA_LIST Args;
EFI_GUID *Protocol[4];
VOID *Interface[4];
UINTN Index;
// oh my, va args ... well, we'll just have to support constant number
VA_START(Args, Handle);
// will start with Index=1 to cover the case when no Protocol/Interface is specified at all
for (Index = 1; Index < 4; Index++) {
Protocol[Index] = VA_ARG(Args, EFI_GUID *);
if (Protocol[Index] == NULL) {
Index--;
break;
}
Interface[Index] = VA_ARG(Args, VOID *);
}
VA_END(Args);
switch (Index) {
case 0:
Status = gOrgBS.InstallMultipleProtocolInterfaces(Handle, NULL);
PRINT("->InstallMultipleProtocolInterfaces(%p/%p) = %r\n", HandleIn, *Handle, Status);
break;
case 1:
Status = gOrgBS.InstallMultipleProtocolInterfaces(Handle, Protocol[1], Interface[1], NULL);
PRINT("->InstallMultipleProtocolInterfaces(%p/%p, %s, %p) = %r\n",
HandleIn, *Handle,
GuidStr(Protocol[1]), Interface[1],
Status);
break;
case 2:
Status = gOrgBS.InstallMultipleProtocolInterfaces(Handle, Protocol[1], Interface[1], Protocol[2], Interface[2], NULL);
PRINT("->InstallMultipleProtocolInterfaces(%p/%p, %s, %p, %s, %p) = %r\n",
HandleIn, *Handle,
GuidStr(Protocol[1]), Interface[1],
GuidStr(Protocol[2]), Interface[2],
Status);
break;
case 3:
Status = gOrgBS.InstallMultipleProtocolInterfaces(Handle, Protocol[1], Interface[1], Protocol[2], Interface[2], Protocol[3], Interface[3], NULL);
PRINT("->InstallMultipleProtocolInterfaces(%p/%p, %s, %p, %s, %p, %s, %p) = %r\n",
HandleIn, *Handle,
GuidStr(Protocol[1]), Interface[1],
GuidStr(Protocol[2]), Interface[2],
GuidStr(Protocol[3]), Interface[3],
Status);
break;
default:
Status = EFI_UNSUPPORTED;
PRINT("->InstallMultipleProtocolInterfaces(%p, ...) = %r, too many Protocol/Interface pairs\n", *Handle, Status);
break;
}
return Status;
}
EFI_STATUS EFIAPI
OvrUninstallMultipleProtocolInterfaces(
IN EFI_HANDLE Handle,
...
)
{
EFI_STATUS Status;
EFI_HANDLE HandleIn = Handle;
VA_LIST Args;
EFI_GUID *Protocol[4];
VOID *Interface[4];
UINTN Index;
// again, va args ... we'll just have to support constant number
VA_START(Args, Handle);
// will start with Index=1 to cover the case when no Protocol/Interface is specified at all
for (Index = 1; Index < 4; Index++) {
Protocol[Index] = VA_ARG(Args, EFI_GUID *);
if (Protocol[Index] == NULL) {
Index--;
break;
}
Interface[Index] = VA_ARG(Args, VOID *);
}
VA_END(Args);
switch (Index) {
case 0:
Status = gOrgBS.UninstallMultipleProtocolInterfaces(Handle);
PRINT("->UninstallMultipleProtocolInterfaces(%p/%p) = %r\n", HandleIn, Handle, Status);
break;
case 1:
Status = gOrgBS.UninstallMultipleProtocolInterfaces(Handle, Protocol[1], Interface[1]);
PRINT("->UninstallMultipleProtocolInterfaces(%p/%p, %s, %p) = %r\n",
HandleIn, Handle,
GuidStr(Protocol[1]), Interface[1],
Status);
break;
case 2:
Status = gOrgBS.UninstallMultipleProtocolInterfaces(Handle, Protocol[1], Interface[1], Protocol[2], Interface[2]);
PRINT("->UninstallMultipleProtocolInterfaces(%p/%p, %s, %p, %s, %p) = %r\n",
HandleIn, Handle,
GuidStr(Protocol[1]), Interface[1],
GuidStr(Protocol[2]), Interface[2],
Status);
break;
case 3:
Status = gOrgBS.UninstallMultipleProtocolInterfaces(Handle, Protocol[1], Interface[1], Protocol[2], Interface[2], Protocol[3], Interface[3]);
PRINT("->UninstallMultipleProtocolInterfaces(%p/%p, %s, %p, %s, %p, %s, %p) = %r\n",
HandleIn, Handle,
GuidStr(Protocol[1]), Interface[1],
GuidStr(Protocol[2]), Interface[2],
GuidStr(Protocol[3]), Interface[3],
Status);
break;
default:
Status = EFI_UNSUPPORTED;
PRINT("->UninstallMultipleProtocolInterfaces(%p, ...) = %r, too many Protocol/Interface pairs\n", Handle, Status);
break;
}
return Status;
}
EFI_STATUS EFIAPI
OvrCalculateCrc32(
IN VOID *Data,
IN UINTN DataSize,
OUT UINT32 *Crc32
)
{
EFI_STATUS Status;
Status = gOrgBS.CalculateCrc32(Data, DataSize, Crc32);
// Omit printing this when using append while logging, as it can end up in calling a file operating inside another file operation
// (some implementations of File functions use CalculateCrc32)
#if (LOG_TO_FILE <= 2) && (CLEANER_LOG != 1)
// Better not print this for cleaner logs - reported by XyZ
PRINT("->CalculateCrc32(%p, %d, 0x%x) = %r\n", Data, DataSize, Crc32, Status);
#endif
return Status;
}
VOID EFIAPI
OvrCopyMem(
IN VOID *Destination,
IN VOID *Source,
IN UINTN Length
)
{
gOrgBS.CopyMem(Destination, Source, Length);
//PRINT("->CopyMem(%p, %p, 0x%x)\n", Destination, Source, Length);
return;
}
VOID EFIAPI
OvrSetMem(
IN VOID *Buffer,
IN UINTN Size,
IN UINT8 Value
)
{
gOrgBS.SetMem(Buffer, Size, Value);
//PRINT("->SetMem(%p, 0x%x, 0x%x)\n", Buffer, Size, Value);
return;
}
EFI_STATUS EFIAPI
OvrCreateEventEx(
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN CONST VOID *NotifyContext,
IN CONST EFI_GUID *EventGroup,
OUT EFI_EVENT *Event
)
{
EFI_STATUS Status;
Status = gOrgBS.CreateEventEx(Type, NotifyTpl, NotifyFunction, NotifyContext, EventGroup, Event);
// PRINT("->CreateEventEx(0x%x, 0x%x, %p, %p, %g, %p) = %r\n", Type, NotifyTpl, NotifyFunction, NotifyContext, EventGroup, *Event, Status);
return Status;
}
////////////////////////////////////////////
//
// Other functions
//
#if CAPTURE_CONSOLE_OUTPUT >= 1
EFI_STATUS EFIAPI
OvrConOutOutputString(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, IN CHAR16 *String) {
EFI_STATUS Status;
#if CAPTURE_CONSOLE_OUTPUT <= 1
Status = gOrgConOutOutputString(This,String);
#else
Status = EFI_SUCCESS;
#endif
// Print to file only if not invoked from our PRINT()
if (!InConsolePrint) {
// Set var to avoid printing to screen again when overriding OutputString
InConsolePrint = TRUE;
PRINT("%s",String);
InConsolePrint = FALSE;
}
return Status;
}
#endif
/** Installs our boot services overrides. */
EFI_STATUS EFIAPI
OvrBootServices(EFI_BOOT_SERVICES *BS)
{
PRINT("Overriding boot services ...\n");
// store orig BS
CopyMem(&gOrgBS, BS, sizeof(EFI_BOOT_SERVICES));
BS->RaiseTPL = OvrRaiseTPL;
BS->RestoreTPL = OvrRestoreTPL;
BS->AllocatePages = OvrAllocatePages;
BS->FreePages = OvrFreePages;
BS->GetMemoryMap = OvrGetMemoryMap;
BS->AllocatePool = OvrAllocatePool;
BS->FreePool = OvrFreePool;
BS->CreateEvent = OvrCreateEvent;
BS->SetTimer = OvrSetTimer;
BS->WaitForEvent = OvrWaitForEvent;
BS->SignalEvent = OvrSignalEvent;
BS->CloseEvent = OvrCloseEvent;
BS->CheckEvent = OvrCheckEvent;
BS->InstallProtocolInterface = OvrInstallProtocolInterface;
BS->ReinstallProtocolInterface = OvrReinstallProtocolInterface;
BS->UninstallProtocolInterface = OvrUninstallProtocolInterface;
BS->HandleProtocol = OvrHandleProtocol;
BS->RegisterProtocolNotify = OvrRegisterProtocolNotify;
BS->LocateHandle = OvrLocateHandle;
BS->LocateDevicePath = OvrLocateDevicePath;
BS->InstallConfigurationTable = OvrInstallConfigurationTable;
BS->LoadImage = OvrLoadImage;
BS->StartImage = OvrStartImage;
BS->Exit = OvrExit;
BS->UnloadImage = OvrUnloadImage;
BS->ExitBootServices = OvrExitBootServices;
BS->GetNextMonotonicCount = OvrGetNextMonotonicCount;
BS->Stall = OvrStall;
BS->SetWatchdogTimer = OvrSetWatchdogTimer;
BS->ConnectController = OvrConnectController;
BS->DisconnectController = OvrDisconnectController;
BS->OpenProtocol = OvrOpenProtocol;
BS->CloseProtocol = OvrCloseProtocol;
BS->OpenProtocolInformation = OvrOpenProtocolInformation;
BS->ProtocolsPerHandle = OvrProtocolsPerHandle;
BS->LocateHandleBuffer = OvrLocateHandleBuffer;
BS->LocateProtocol = OvrLocateProtocol;
BS->InstallMultipleProtocolInterfaces = OvrInstallMultipleProtocolInterfaces;
BS->UninstallMultipleProtocolInterfaces = OvrUninstallMultipleProtocolInterfaces;
BS->CalculateCrc32 = OvrCalculateCrc32;
BS->CopyMem = OvrCopyMem;
BS->SetMem = OvrSetMem;
BS->CreateEventEx = OvrCreateEventEx;
BS->Hdr.CRC32 = 0;
// use orig function to avoid our PRINT
gOrgBS.CalculateCrc32(BS, BS->Hdr.HeaderSize, &BS->Hdr.CRC32);
PRINT("Boot services overriden!\n");
#if CAPTURE_CONSOLE_OUTPUT >= 1
PRINT("Overriding console output ...\n");
#if CAPTURE_CONSOLE_OUTPUT == 2
PRINT("Preventing any further console output, please wait until booting starts ...\n");
#endif
gOrgConOutOutputString = gST->ConOut->OutputString;
gST->ConOut->OutputString = OvrConOutOutputString;
PRINT("Console output overriden!\n");
#endif
return EFI_SUCCESS;
}