Skip to content

Commit

Permalink
RtlSleep: wait for a timer event instead of stalling
Browse files Browse the repository at this point in the history
  • Loading branch information
Mattiwatti committed Mar 26, 2023
1 parent e588a7d commit 8b673b9
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 12 deletions.
2 changes: 1 addition & 1 deletion EfiGuardDxe/EfiGuardDxe.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ ExitBootServicesEvent(
PrintKernelPatchInfo();

// Give time for user to register their loss and allow for the grieving process to set in
RtlSleep(2000);
RtlStall(2000);

// Prompt user to ask what they want to do
Print(L"\r\nPress any key to continue anyway, or press ESC to reboot.\r\n");
Expand Down
38 changes: 28 additions & 10 deletions EfiGuardDxe/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,46 @@
#include <Library/UefiBootServicesTableLib.h>

#ifndef ZYDIS_DISABLE_FORMATTER

#include <Library/PrintLib.h>
#include <Zycore/Format.h>

STATIC ZydisFormatterFunc DefaultInstructionFormatter;

#endif

//
// When debugging, we can choose between poor debugging facilities (VirtualBox) or poor performance and Windows compatibility (QEMU).
// (I guess there is also the closed source thing with the horrible user interface that installs 50 drivers on the host (VMware))
// This is a bandaid to make Print() calls readable ...for a while... when using VirtualBox or a live machine with no debugger
//

EFI_STATUS
EFIAPI
RtlSleep(
IN UINTN Milliseconds
)
{
ASSERT(gBS != NULL);
ASSERT(gBS->Stall != NULL);

// Create a timer event, set its timeout, and wait for it
EFI_EVENT TimerEvent;
EFI_STATUS Status = gBS->CreateEvent(EVT_TIMER, 0, NULL, NULL, &TimerEvent);
if (EFI_ERROR(Status))
return RtlStall(Milliseconds); // Fall back to stalling CPU

gBS->SetTimer(TimerEvent,
TimerRelative,
EFI_TIMER_PERIOD_MILLISECONDS(Milliseconds));

UINTN Index;
Status = gBS->WaitForEvent(1, &TimerEvent, &Index);
if (EFI_ERROR(Status))
Status = RtlStall(Milliseconds);

gBS->CloseEvent(TimerEvent);
return Status;
}

EFI_STATUS
EFIAPI
RtlStall(
IN UINTN Milliseconds
)
{
ASSERT(gBS != NULL);
return gBS->Stall(Milliseconds * 1000);
}

Expand Down Expand Up @@ -189,7 +207,7 @@ WaitForKey(
if (Tpl == TPL_APPLICATION)
gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &Index); // Yep
else
RtlSleep(1); // Nope; burn CPU. // TODO: find a way to parallelize this to achieve GeForce FX 5800 temperatures
RtlStall(1); // Nope; burn CPU. // TODO: find a way to parallelize this to achieve GeForce FX 5800 temperatures

// At TPL_APPLICATION, we will always get EFI_SUCCESS (barring hardware failures). At higher TPLs we may also get EFI_NOT_READY
Status = gST->ConIn->ReadKeyStroke(gST->ConIn, &Key);
Expand Down
11 changes: 10 additions & 1 deletion EfiGuardDxe/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,23 @@


//
// Stalls CPU for N milliseconds
// Waits for a timer event for N milliseconds.
// Requires current TPL to be TPL_APPLICATION.
//
EFI_STATUS
EFIAPI
RtlSleep(
IN UINTN Milliseconds
);

//
// Stalls CPU for N milliseconds.
//
EFI_STATUS
RtlStall(
IN UINTN Milliseconds
);

//
// Prints info about a loaded image
//
Expand Down

0 comments on commit 8b673b9

Please sign in to comment.