Skip to content

Commit 2452539

Browse files
committed
Update KEP Library
1 parent f32e266 commit 2452539

8 files changed

Lines changed: 155 additions & 158 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
Copyright (c) 2021 Samuel Tulach
3+
Copyright (c) 2022-2023 DuoWoA authors
4+
5+
SPDX-License-Identifier: MIT
6+
**/
7+
8+
#ifndef _ASSEMBLY_UTILS_H_
9+
#define _ASSEMBLY_UTILS_H_
10+
11+
//
12+
// ARM64 Instruction Details
13+
//
14+
#define ARM64_INSTRUCTION_LENGTH 4
15+
#define ARM64_TOTAL_INSTRUCTION_LENGTH(x) (ARM64_INSTRUCTION_LENGTH * (x))
16+
#define ARM64_INSTRUCTION(x) (*(UINT32 *)(x))
17+
18+
//
19+
// ARM64 Instruction Helpers
20+
//
21+
#define ARM64_BRANCH_LOCATION_INSTRUCTION(CurrentOffset, TargetOffset) (0x94000000U | ((UINT32)(((TargetOffset) - (CurrentOffset)) / ARM64_INSTRUCTION_LENGTH) & 0x7FFFFFFU))
22+
23+
#endif /* _ASSEMBLY_UTILS_H_ */

Silicon/Silicium/SiliciumPkg/Library/KernelErrataPatcherLib/AArch64/OsLoaderHelper.S

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@
88
GCC_ASM_IMPORT (KernelErrataPatcherExitBootServices)
99
GCC_ASM_EXPORT (ExitBootServicesWrapper)
1010

11-
//EFI_STATUS
12-
//EFIAPI
13-
//ExitBootServicesWrapper (
14-
// IN EFI_HANDLE ImageHandle,
15-
// IN UINTN MapKey
16-
// );
1711
ExitBootServicesWrapper:
1812
// Save Return Address
1913
mov x2, x30

Silicon/Silicium/SiliciumPkg/Library/KernelErrataPatcherLib/KernelErrataPatcherLib.c

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,36 +39,46 @@ KernelErrataPatcherExitBootServices (
3939
// Calculate new CRC32
4040
gBS->CalculateCrc32 (gBS, sizeof (EFI_BOOT_SERVICES), &gBS->Hdr.CRC32);
4141

42-
// Get winload.efi Base Address
43-
WinloadBase = LocateWinloadBase (fwpKernelSetupPhase1, &WinloadLength);
44-
if (!WinloadBase) {
42+
// Locate Winload Memory Range
43+
Status = LocateWinloadMemoryRange (fwpKernelSetupPhase1, &WinloadBase, &WinloadLength);
44+
if (EFI_ERROR (Status)) {
45+
DEBUG ((EFI_D_ERROR, "%a: Failed to Locate Winload Memory Range! Status = %r\n", __FUNCTION__, Status));
4546
goto exit;
4647
}
4748

4849
// Unprotect winload.efi
49-
Status = UnprotectWinload (WinloadBase + EFI_PAGE_SIZE, WinloadLength);
50+
Status = SetWinloadProtection (WinloadBase, WinloadLength, FALSE);
5051
if (EFI_ERROR (Status)) {
51-
goto exit;
52+
DEBUG ((EFI_D_ERROR, "%a: Failed to Unprotect Winload! Status = %r\n", __FUNCTION__, Status));
53+
goto reprotect;
5254
}
5355

5456
// Apply Platform Errata Patches
55-
Status = ApplyPlatformErrataPatches (WinloadBase, SCAN_MAX);
57+
Status = ApplyPlatformErrataPatches (WinloadBase, WinloadLength);
5658
if (EFI_ERROR (Status)) {
57-
goto exit;
59+
goto reprotect;
5860
}
5961

6062
// Get Platform Shell Code
6163
GetPlatformTransferToKernelShellCode (&TransferToKernelShellCode, &TransferToKernelShellCodeSize);
64+
if (TransferToKernelShellCode == NULL || TransferToKernelShellCodeSize == 0) {
65+
goto reprotect;
66+
}
6267

63-
// Apply Platform Shell Code
64-
if (TransferToKernelShellCode != NULL && TransferToKernelShellCodeSize) {
65-
PatchOsLoaderArm64TransferToKernel (WinloadBase + 0xC00, TransferToKernelShellCode, TransferToKernelShellCodeSize);
68+
// Inject Shell Code
69+
Status = PatchOsLoaderArm64TransferToKernel (WinloadBase, WinloadLength, TransferToKernelShellCode, TransferToKernelShellCodeSize);
70+
if (EFI_ERROR (Status)) {
71+
DEBUG ((EFI_D_ERROR, "%a: Failed to Inject Shell Code! Status = %r\n", __FUNCTION__, Status));
6672
}
6773

68-
exit:
69-
// Re-Protect winload.efi
70-
ReProtectWinload (WinloadBase + EFI_PAGE_SIZE, WinloadLength);
74+
reprotect:
75+
// Protect winload.efi
76+
Status = SetWinloadProtection (WinloadBase, WinloadLength, TRUE);
77+
if (EFI_ERROR (Status)) {
78+
DEBUG ((EFI_D_ERROR, "%a: Failed to Protect Winload! Status = %r\n", __FUNCTION__, Status));
79+
}
7180

81+
exit:
7282
// Call Original EBS
7383
return gBS->ExitBootServices (ImageHandle, MapKey);
7484
}
@@ -106,7 +116,7 @@ KernelErrataPatcherLibConstructor (
106116
Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, ReadyToBootHandler, NULL, &gEfiEventReadyToBootGuid, &ReadyToBootEvent);
107117
if (EFI_ERROR (Status)) {
108118
DEBUG ((EFI_D_ERROR, "%a: Failed to Create Ready To Boot Event! Status = %r\n", __FUNCTION__, Status));
109-
return Status;
119+
return EFI_SUCCESS;
110120
}
111121

112122
// Locate Memory Attribute Protocol

Silicon/Silicium/SiliciumPkg/Library/KernelErrataPatcherLib/KernelErrataPatcherLib.h

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,6 @@
1010
#ifndef _KERNEL_ERRATA_PATCHER_LIB_H_
1111
#define _KERNEL_ERRATA_PATCHER_LIB_H_
1212

13-
//
14-
// ARM64 Instruction Infos
15-
//
16-
#define ARM64_INSTRUCTION_LENGTH 4
17-
#define ARM64_TOTAL_INSTRUCTION_LENGTH(x) (ARM64_INSTRUCTION_LENGTH * x)
18-
#define ARM64_BRANCH_LOCATION_INSTRUCTION(CurrentOffset, TargetOffset) (0x94000000U | ((UINT32)((TargetOffset - CurrentOffset) / ARM64_INSTRUCTION_LENGTH) & 0x7FFFFFFU))
19-
20-
//
21-
// Max Scan Size
22-
//
23-
#define SCAN_MAX 0x300000
24-
2513
//
2614
// Functions
2715
//
@@ -40,32 +28,29 @@ ExitBootServicesWrapper (
4028
IN UINTN MapKey
4129
);
4230

43-
EFI_PHYSICAL_ADDRESS
44-
LocateWinloadBase (
45-
IN EFI_PHYSICAL_ADDRESS Base,
46-
OUT UINTN *Length
47-
);
31+
EFI_STATUS
32+
LocateMemoryAttributeProtocol ();
4833

4934
EFI_STATUS
50-
UnprotectWinload (
35+
SetWinloadProtection (
5136
IN EFI_PHYSICAL_ADDRESS Base,
52-
IN UINTN Length
37+
IN UINTN Length,
38+
IN BOOLEAN Enable
39+
);
40+
41+
EFI_STATUS
42+
LocateWinloadMemoryRange (
43+
IN EFI_PHYSICAL_ADDRESS fwpKernelSetupPhase1,
44+
OUT EFI_PHYSICAL_ADDRESS *Base,
45+
OUT UINTN *Length
5346
);
5447

55-
VOID
48+
EFI_STATUS
5649
PatchOsLoaderArm64TransferToKernel (
5750
IN EFI_PHYSICAL_ADDRESS Base,
51+
IN UINT64 Length,
5852
IN UINT8 *ShellCode,
5953
IN UINTN ShellCodeSize
6054
);
6155

62-
EFI_STATUS
63-
ReProtectWinload (
64-
IN EFI_PHYSICAL_ADDRESS Base,
65-
IN UINTN Length
66-
);
67-
68-
EFI_STATUS
69-
LocateMemoryAttributeProtocol ();
70-
7156
#endif /* _KERNEL_ERRATA_PATCHER_LIB_H_ */

Silicon/Silicium/SiliciumPkg/Library/KernelErrataPatcherLib/KernelErrataPatcherLib.inf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
[LibraryClasses]
2828
DebugLib
2929
UefiBootServicesTableLib
30+
CacheMaintenanceLib
3031
ErrataPatchesLib
3132
PerformanceLib
3233
BaseMemoryLib

Silicon/Silicium/SiliciumPkg/Library/KernelErrataPatcherLib/MemoryAttribute.c

Lines changed: 9 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,67 +18,26 @@
1818
// Global Variables
1919
//
2020
STATIC EFI_MEMORY_ATTRIBUTE_PROTOCOL *mMemoryAttributeProtocol;
21-
STATIC UINT64 MemoryAttributes;
2221

2322
EFI_STATUS
24-
UnprotectWinload (
23+
SetWinloadProtection (
2524
IN EFI_PHYSICAL_ADDRESS Base,
26-
IN UINTN Length)
25+
IN UINTN Length,
26+
IN BOOLEAN Enable)
2727
{
28-
EFI_STATUS Status;
29-
30-
// Verify Memory Attribute Protocol
31-
if (mMemoryAttributeProtocol == NULL) {
32-
return EFI_SUCCESS;
33-
}
34-
35-
// Get winload.efi Memory Attributes
36-
Status = mMemoryAttributeProtocol->GetMemoryAttributes (mMemoryAttributeProtocol, Base, Length, &MemoryAttributes);
37-
if (EFI_ERROR (Status)) {
38-
DEBUG ((EFI_D_ERROR, "%a: Failed to get winload.efi Memory Attributes! Status = %r\n", __FUNCTION__, Status));
39-
return Status;
40-
}
41-
42-
// Verify Read-Only Memory Attribute
43-
if (!(MemoryAttributes & EFI_MEMORY_RO)) {
44-
return EFI_SUCCESS;
45-
}
46-
47-
// Clear Ready-Only Memory Attribute
48-
Status = mMemoryAttributeProtocol->ClearMemoryAttributes (mMemoryAttributeProtocol, Base, Length, EFI_MEMORY_RO);
49-
if (EFI_ERROR (Status)) {
50-
DEBUG ((EFI_D_ERROR, "%a: Failed to Clear winload.efi Ready-Only Memory Attribute! Status = %r\n", __FUNCTION__, Status));
51-
return Status;
52-
}
53-
54-
return EFI_SUCCESS;
55-
}
56-
57-
EFI_STATUS
58-
ReProtectWinload (
59-
IN EFI_PHYSICAL_ADDRESS Base,
60-
IN UINTN Length)
61-
{
62-
EFI_STATUS Status;
63-
6428
// Verify Memory Attribute Protocol
6529
if (mMemoryAttributeProtocol == NULL) {
6630
return EFI_SUCCESS;
6731
}
6832

69-
// Verify Read-Only Memory Attribute
70-
if (MemoryAttributes & EFI_MEMORY_RO) {
71-
return EFI_SUCCESS;
72-
}
73-
74-
// Set Ready-Only Memory Attribute
75-
Status = mMemoryAttributeProtocol->SetMemoryAttributes (mMemoryAttributeProtocol, Base, Length, EFI_MEMORY_RO);
76-
if (EFI_ERROR (Status)) {
77-
DEBUG ((EFI_D_ERROR, "%a: Failed to Set winload.efi Ready-Only Memory Attribute! Status = %r\n", __FUNCTION__, Status));
78-
return Status;
33+
// Verify Parameters
34+
if (Base == 0 || Length == 0) {
35+
return EFI_INVALID_PARAMETER;
7936
}
8037

81-
return EFI_SUCCESS;
38+
// Set / Clear Read-Only Memory Attribute
39+
return Enable ? mMemoryAttributeProtocol->SetMemoryAttributes (mMemoryAttributeProtocol, Base, Length, EFI_MEMORY_RO)
40+
: mMemoryAttributeProtocol->ClearMemoryAttributes (mMemoryAttributeProtocol, Base, Length, EFI_MEMORY_RO);
8241
}
8342

8443
EFI_STATUS

Silicon/Silicium/SiliciumPkg/Library/KernelErrataPatcherLib/Winload.c

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,86 +9,105 @@
99

1010
#include <Library/DebugLib.h>
1111
#include <Library/BaseMemoryLib.h>
12+
#include <Library/CacheMaintenanceLib.h>
13+
#include <Library/AssemblyUtilsLib.h>
1214

1315
#include "KernelErrataPatcherLib.h"
1416
#include "Winload.h"
1517

16-
EFI_PHYSICAL_ADDRESS
17-
LocateWinloadBase (
18-
IN EFI_PHYSICAL_ADDRESS Base,
18+
EFI_STATUS
19+
LocateWinloadMemoryRange (
20+
IN EFI_PHYSICAL_ADDRESS fwpKernelSetupPhase1,
21+
OUT EFI_PHYSICAL_ADDRESS *Base,
1922
OUT UINTN *Length)
2023
{
21-
// Align Base Address
22-
Base = ALIGN_VALUE (Base, EFI_PAGE_SIZE);
24+
// Verify Parameters
25+
if (Base == NULL || Length == NULL) {
26+
return EFI_INVALID_PARAMETER;
27+
}
28+
29+
// Align FWP Address
30+
fwpKernelSetupPhase1 = ALIGN_VALUE (fwpKernelSetupPhase1, EFI_PAGE_SIZE);
31+
32+
// Set FWP End Address
33+
EFI_PHYSICAL_ADDRESS fwpKernelSetupPhase1End = fwpKernelSetupPhase1 - MAX_FWP_SCAN_LENGTH;
2334

24-
// Set Scan Length
25-
EFI_PHYSICAL_ADDRESS BaseEnd = Base - SCAN_MAX;
35+
// Go thru FWP Scan Area
36+
for (EFI_PHYSICAL_ADDRESS Current = fwpKernelSetupPhase1; Current > fwpKernelSetupPhase1End; Current -= EFI_PAGE_SIZE) {
37+
// Get DOS Header
38+
EFI_IMAGE_DOS_HEADER *DosHeader = (EFI_IMAGE_DOS_HEADER *)Current;
2639

27-
for (; Base > BaseEnd; Base -= EFI_PAGE_SIZE) {
28-
// Verify DOS Signature
29-
if (*(UINT16 *)Base != EFI_IMAGE_DOS_SIGNATURE) {
40+
// Verify DOS Data
41+
if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE || DosHeader->e_lfanew > MAX_FWP_SCAN_LENGTH) {
3042
continue;
3143
}
3244

33-
// Set Base Offset
34-
UINT32 BaseOffset = *(UINT32 *)(Base + 0x3C);
35-
36-
// Set new winload.efi Base Address
37-
EFI_PHYSICAL_ADDRESS NewBase = Base + BaseOffset;
45+
// Get NT Header
46+
EFI_IMAGE_NT_HEADERS64 *NtHeader = (EFI_IMAGE_NT_HEADERS64 *)(Current + DosHeader->e_lfanew);
3847

3948
// Verify NT Signature
40-
if (*(UINT16 *)NewBase != EFI_IMAGE_NT_SIGNATURE) {
49+
if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
4150
continue;
4251
}
4352

44-
// Set winload.efi Length
45-
*Length = *(UINT32 *)(NewBase + 0x110);
46-
47-
// Align Length
48-
*Length = ALIGN_VALUE (*Length, EFI_PAGE_SIZE);
53+
// Pass Data
54+
*Base = Current;
55+
*Length = ALIGN_VALUE (NtHeader->OptionalHeader.SizeOfImage, EFI_PAGE_SIZE);
4956

50-
return Base;
57+
return EFI_SUCCESS;
5158
}
5259

53-
return 0;
60+
return EFI_NOT_FOUND;
5461
}
5562

56-
VOID
63+
EFI_STATUS
5764
PatchOsLoaderArm64TransferToKernel (
5865
IN EFI_PHYSICAL_ADDRESS Base,
66+
IN UINT64 Length,
5967
IN UINT8 *ShellCode,
6068
IN UINTN ShellCodeSize)
6169
{
70+
// Verify Parameters
71+
if (Base == 0 || ShellCode == NULL || ShellCodeSize == 0) {
72+
return EFI_INVALID_PARAMETER;
73+
}
74+
75+
// Go thru each Windows Semester
6276
for (UINT8 i = 0; i < ARRAY_SIZE (WinSemesterData); i++) {
63-
// Set Transfer To Kernel Address
64-
EFI_PHYSICAL_ADDRESS TransferToKernelAddr = Base + WinSemesterData[i].TransferToKernelOffset;
77+
// Set Transfer To Kernel Details
78+
EFI_PHYSICAL_ADDRESS TransferToKernelAddr = Base + 0xC00 + WinSemesterData[i].TransferToKernelOffset;
79+
EFI_PHYSICAL_ADDRESS TransferToKernelAddrEnd = TransferToKernelAddr + Length;
6580

6681
// Set new Transfer To Kernel Address
6782
EFI_PHYSICAL_ADDRESS NewTransferToKernelAddr = TransferToKernelAddr - ShellCodeSize;
6883

69-
for (EFI_PHYSICAL_ADDRESS Current = TransferToKernelAddr; Current < TransferToKernelAddr + SCAN_MAX; Current += sizeof (UINT32)) {
84+
// Go thru Transfer To Kernel Memory Area
85+
for (EFI_PHYSICAL_ADDRESS Current = TransferToKernelAddr; Current < TransferToKernelAddrEnd; Current += ARM64_INSTRUCTION_LENGTH) {
7086
// Verify Branch Instruction
71-
if (ARM64_BRANCH_LOCATION_INSTRUCTION (Current, TransferToKernelAddr) != *(UINT32 *)Current) {
87+
if (ARM64_INSTRUCTION (Current) != ARM64_BRANCH_LOCATION_INSTRUCTION (Current, TransferToKernelAddr)) {
7288
continue;
7389
}
7490

7591
// Verify Next Instruction
76-
if (*(UINT32*)(Current + sizeof (UINT32)) != WinSemesterData[i].Instruction) {
92+
if (ARM64_INSTRUCTION (Current + ARM64_TOTAL_INSTRUCTION_LENGTH (1)) != WinSemesterData[i].TargetInstruction) {
7793
continue;
7894
}
7995

80-
// Print Windows Semester
81-
DEBUG ((EFI_D_WARN, "%a: Detected Windows Semester = %a\n", __FUNCTION__, WinSemesterData[i].Name));
96+
// Copy Shell Code
97+
CopyMem ((VOID *)NewTransferToKernelAddr, (CONST VOID *)ShellCode, ShellCodeSize);
8298

8399
// Inject Jump Instruction
84-
*(UINT32 *)Current = ARM64_BRANCH_LOCATION_INSTRUCTION (Current, NewTransferToKernelAddr);
100+
ARM64_INSTRUCTION (Current) = ARM64_BRANCH_LOCATION_INSTRUCTION (Current, NewTransferToKernelAddr);
85101

86-
// Copy Shell Code
87-
CopyMem ((VOID *)NewTransferToKernelAddr, (CONST VOID *)ShellCode, ShellCodeSize);
102+
// Flush Cache
103+
WriteBackInvalidateDataCacheRange ((VOID *)NewTransferToKernelAddr, ShellCodeSize);
104+
InvalidateInstructionCacheRange ((VOID *)NewTransferToKernelAddr, ShellCodeSize);
105+
WriteBackInvalidateDataCacheRange ((VOID *)Current, ARM64_INSTRUCTION_LENGTH);
106+
InvalidateInstructionCacheRange ((VOID *)Current, ARM64_INSTRUCTION_LENGTH);
88107

89-
return;
108+
return EFI_SUCCESS;
90109
}
91110
}
92111

93-
DEBUG ((EFI_D_ERROR, "%a: Failed to Auto-Detect Windows Semester!\n", __FUNCTION__));
112+
return EFI_NOT_FOUND;
94113
}

0 commit comments

Comments
 (0)