Compare commits

..

21 Commits

Author SHA1 Message Date
58ba3f5db0 Nuke Old Mutex Implementation
To many changes to make , so i just updated with my recent iteration.

Signed-off-by: CodingWorkshop Signing Team <signing@codingworkshop.eu.org>
2025-09-25 14:57:10 +02:00
cb3a90c637 Introduce Alcyone Specific Mutex Algorithms.
Added Following New Api:
KeInitializeRecursiveFastMutex
KeAcquireFastMutexTimeout
KeIsMutexOwned
KeAcquireGuardedMutexTimeout

Signed-off-by: CodingWorkshop Signing Team <signing@codingworkshop.eu.org>
2025-09-25 14:50:50 +02:00
Quinn Stephens
5f0a5d0588 [SDK] Fix preprocessor usage
Signed-off-by: Quinn Stephens <quinn@osmora.org>
2025-06-12 14:03:21 -04:00
Quinn Stephens
5c52adf492 [SDK] Big update
Signed-off-by: Quinn Stephens <quinn@osmora.org>
2025-06-11 20:00:34 -04:00
Quinn Stephens
e3f81a4c08 [SDK] Minor improvements to CRT, RTL, and headers
Signed-off-by: Quinn Stephens <quinn@osmora.org>
2024-11-16 07:10:11 -05:00
e81100b2e5 [NTOSKRNL:CC] Better Annotation for Initialization 2024-11-09 15:45:49 +01:00
f6620f9372 [NTOSKRNL:CC] Implemented CcSetDirtyInMask 2024-11-08 08:58:18 +01:00
d81565e7ec [NTOSKRNL:CC] Implemented CcCanIWrite and CcDeferWrite 2024-11-03 18:56:31 +01:00
377ff4fb9b [NTOSKRNL:CC] Add Lock Guard for DPC Level SPinlock 2024-11-01 14:44:28 +01:00
2472e39635 [BOOT:LIB] More initialization and cleanup
Started BlpMmDestroy(), MmMdDestroy(), MmPaDestroy(),
EfiSetWatchdogTimer(), EfiOpenProtocol(), EfiConInExSetState(), and
BlDestroyLibrary().
Completed BlpFwInitialize().
Improved InitializeLibrary().
2024-10-06 13:50:21 -04:00
620ede5862 [BOOT:LIB] Declare global variables in bootlib.h 2024-10-06 08:04:40 -04:00
67ab5dc5d4 [SDK:CRT] Implement wcscpy_s() and wcscat_s() 2024-10-06 08:02:08 -04:00
b0b7be0837 [BOOT] Make assembly files compile 2024-10-05 15:45:55 -04:00
24a31cab26 [BOOT] Execution contexts and more refactoring 2024-10-05 15:44:25 -04:00
7c3dafc051 [BOOT] Huge refactor 2024-10-05 15:39:04 -04:00
6a678794d3 [NTOSKRNL:CC] Implemented CcFindBitmapRangeToDirty 2024-09-28 14:17:38 +02:00
955c88d858 [NTOSKRNL:CC] Cache Utility Handler : Initial Commit
Initial Commit with Function parameter blocks
2024-09-17 12:46:27 +02:00
2a19fd42de [BOOT] Improve debug logging 2024-09-01 17:54:40 -04:00
43c6c75710 [BOOT:MM] Fix descriptor memory leaks
Sometimes when handling MmMdAddDescriptorToList() errors, descriptors
were not freed with MmMdFreeDescriptor().
2024-09-01 16:56:18 -04:00
65e33fdad5 [BOOT:MM] Finish MmMdRemoveRegionFromMdlEx() 2024-09-01 16:49:19 -04:00
3aae765c9c [BOOT:MM] Implement MmMdFindDescriptorFromMdl() 2024-09-01 12:41:08 -04:00
52 changed files with 6706 additions and 1206 deletions

View File

@@ -37,13 +37,14 @@ Arguments:
Return Value: Return Value:
EFI_SUCCESS if successful.
EFI_INVALID_PARAMETER if EfiInitCreateInputParameters() fails. EFI_INVALID_PARAMETER if EfiInitCreateInputParameters() fails.
Any status code returned by EfiGetEfiStatusCode(BmMain()). Any other error code if BmMain() fails.
--*/ --*/
{ {
PBOOT_INPUT_PARAMETERS InputParameters; PBOOT_APPLICATION_PARAMETERS InputParameters;
// //
// Create firmware-independent input structure from EFI parameters. // Create firmware-independent input structure from EFI parameters.
@@ -54,7 +55,7 @@ Return Value:
} }
// //
// Transfer control to the firmware-independent boot manager. // Transfer control to the firmware-independent boot manager code.
// //
return EfiGetEfiStatusCode(BmMain(InputParameters)); return EfiGetEfiStatusCode(BmMain(InputParameters));
} }

View File

@@ -13,11 +13,11 @@ Abstract:
--*/ --*/
#include "bootlib.h" #include "bootmgr.h"
NTSTATUS NTSTATUS
BmOpenDataStore ( BmOpenDataStore (
IN OUT PHANDLE DataStore IN OUT PHANDLE Handle
) )
/*++ /*++
@@ -28,7 +28,7 @@ Routine Description:
Arguments: Arguments:
DataStore - Pointer to a HANDLE that recieves the data store handle. Handle - Pointer to a HANDLE that recieves the data store handle.
Return Value: Return Value:
@@ -37,7 +37,7 @@ Return Value:
--*/ --*/
{ {
*DataStore = INVALID_HANDLE_VALUE; *Handle = INVALID_HANDLE_VALUE;
/* /*
NTSTATUS Status; NTSTATUS Status;
@@ -51,5 +51,6 @@ Return Value:
return BmGetDataStorePath(&Device, &FilePath, &FilePathSet); return BmGetDataStorePath(&Device, &FilePath, &FilePathSet);
*/ */
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View File

@@ -9,16 +9,15 @@ Module Name:
Abstract: Abstract:
Main functions of the boot manager. Boot manager main routine.
--*/ --*/
#include "bootmgr.h" #include "bootmgr.h"
#include "bootlib.h"
NTSTATUS NTSTATUS
BmMain ( BmMain (
IN PBOOT_INPUT_PARAMETERS InputParameters IN PBOOT_APPLICATION_PARAMETERS ApplicationParameters
) )
/*++ /*++
@@ -29,7 +28,7 @@ Routine Description:
Arguments: Arguments:
InputParameters - Input parameters for the boot manager. ApplicationParameters - Input parameters for the boot manager.
Return Value: Return Value:
@@ -41,15 +40,16 @@ Return Value:
{ {
NTSTATUS Status; NTSTATUS Status;
BOOT_LIBRARY_PARAMETERS LibraryParameters; BOOT_LIBRARY_PARAMETERS LibraryParameters;
HANDLE DataStore; HANDLE DataStoreHandle;
LibraryParameters.Flags = 0; LibraryParameters.Flags = 0;
LibraryParameters.TranslationType = TRANSLATION_TYPE_NONE;
LibraryParameters.MinimumPageAllocation = 16; LibraryParameters.MinimumPageAllocation = 16;
// //
// Initialize the boot library. // Initialize the boot library.
// //
Status = BlInitializeLibrary(InputParameters, &LibraryParameters); Status = BlInitializeLibrary(ApplicationParameters, &LibraryParameters);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
ConsolePrintf(L"BlInitializeLibrary() failed: 0x%x\r\n", Status); ConsolePrintf(L"BlInitializeLibrary() failed: 0x%x\r\n", Status);
goto Exit; goto Exit;
@@ -58,9 +58,17 @@ Return Value:
// //
// Open the boot data store. // Open the boot data store.
// //
(VOID)BmOpenDataStore(&DataStore); (VOID)BmOpenDataStore(&DataStoreHandle);
while (TRUE); //
// Stop here for now.
// Later this will be used to wait for input.
//
while (TRUE) {
#if defined(__x86_64__) || defined(__i386__)
asm volatile("hlt");
#endif
}
Exit: Exit:
BlDestroyLibrary(); BlDestroyLibrary();

View File

@@ -17,7 +17,269 @@ Abstract:
#define _BOOTLIB_H #define _BOOTLIB_H
#include <nt.h> #include <nt.h>
#include "bootmgr.h"
#if defined(_EFI)
#include "efi.h"
#define PAGE_SIZE EFI_PAGE_SIZE
#define PAGE_SHIFT EFI_PAGE_SHIFT
#endif /* _EFI */
//
// Address translation types.
//
#define TRANSLATION_TYPE_NONE 0
#define TRANSLATION_TYPE_MAX 1
//
// Set machine type.
//
#if defined(__x86_64__)
#define BOOT_MACHINE_TYPE IMAGE_FILE_MACHINE_AMD64
#elif defined(__i386__)
#define BOOT_MACHINE_TYPE IMAGE_FILE_MACHINE_I386
#endif
#if defined(__i386__) || defined(__x86_64__)
typedef struct __attribute__((packed)) {
USHORT Limit;
ULONG_PTR Base;
} DESCRIPTOR_TABLE_REGISTER, *PDESCRIPTOR_TABLE_REGISTER;
typedef struct __attribute__((packed)) {
DESCRIPTOR_TABLE_REGISTER Gdt;
DESCRIPTOR_TABLE_REGISTER Idt;
USHORT LdtSelector;
USHORT CS, DS, ES, FS, GS, SS;
} DESCRIPTOR_TABLE_CONTEXT, *PDESCRIPTOR_TABLE_CONTEXT;
#endif
//
// Firmware platform flags.
//
#define FIRMWARE_FLAG_EXECUTION_CONTEXT_SUPPORTED 0x00100000
//
// Execution contexts represent the current state
// of the processor/system.
//
typedef enum {
ExecutionContextApplication,
ExecutionContextFirmware,
ExecutionContextMax
} EXECUTION_CONTEXT_TYPE;
#define EXECUTION_CONTEXT_INTERRUPTS_ENABLED 0x02
#define EXECUTION_CONTEXT_PAGING_ENABLED 0x04
typedef struct {
EXECUTION_CONTEXT_TYPE Type;
#if defined(__i386__) || defined(__x86_64__)
ULONG_PTR Cr3;
#endif
ULONG Flags;
DESCRIPTOR_TABLE_CONTEXT DescriptorTableContext;
} EXECUTION_CONTEXT, *PEXECUTION_CONTEXT;
//
// Application entry option.
// Used to represent options passed to a boot
// application by whatever started it.
//
typedef struct {
ULONG Type;
ULONG DataOffset;
ULONG DataSize;
ULONG OtherOptionsOffset;
ULONG NextOptionOffset;
BOOLEAN IsInvalid;
UCHAR Reserved[3];
} BOOT_ENTRY_OPTION, *PBOOT_ENTRY_OPTION;
//
// Application entry.
// Used for any boot environment application,
// including the boot manager itself.
//
#define BOOT_APPLICATION_ENTRY_NO_BCD_IDENTIFIER 0x01
typedef struct {
ULONG Attributes;
GUID BcdIdentifier;
PBOOT_ENTRY_OPTION Options;
} BOOT_APPLICATION_ENTRY, *PBOOT_APPLICATION_ENTRY;
//
// Initial application entry.
// Special form of BOOT_APPLICATION_ENTRY used
// when firmware first loads the boot manager.
//
#define BOOT_INIT_APPLICATION_ENTRY_SIGNATURE 0x544e4550415442 /* "BTAPENT" */
typedef struct {
ULONGLONG Signature;
ULONG Attributes;
GUID BcdIdentifier;
UCHAR Reserved[16];
BOOT_ENTRY_OPTION Options;
} BOOT_INIT_APPLICATION_ENTRY, *PBOOT_INIT_APPLICATION_ENTRY;
typedef ULONG MEMORY_TYPE;
//
// Memory type classes.
//
#define MEMORY_CLASS_APPLICATION 0xD
#define MEMORY_CLASS_LIBRARY 0xE
#define MEMORY_CLASS_SYSTEM 0xF
//
// Memory types.
//
#define MEMORY_TYPE_BOOT_APPLICATION 0xD0000002
#define MEMORY_TYPE_BOOT_APPLICATION_2 0xD0000013
#define MEMORY_TYPE_FREE 0xF0000001
#define MEMORY_TYPE_UNUSABLE 0xF0000002
#define MEMORY_TYPE_RESERVED 0xF0000003
#define MEMORY_TYPE_BOOT_SERVICES 0xF0000004
#define MEMORY_TYPE_FREE_ZEROED 0xF0000005
#define MEMORY_TYPE_RUNTIME_SERVICES_CODE 0xF0000006
#define MEMORY_TYPE_PERSISTENT 0xF0000007
#define MEMORY_TYPE_ACPI_RECLAIM 0xF0000008
#define MEMORY_TYPE_ACPI_NVS 0xF0000009
#define MEMORY_TYPE_MMIO 0xF000000A
#define MEMORY_TYPE_MMIO_PORT_SPACE 0xF000000B
#define MEMORY_TYPE_PAL_CODE 0xF000000C
#define MEMORY_TYPE_RUNTIME_SERVICES_DATA 0xF000000E
//
// Memory caching attributes.
//
#define MEMORY_ATTRIBUTE_UC 0x00000001
#define MEMORY_ATTRIBUTE_WC 0x00000002
#define MEMORY_ATTRIBUTE_WT 0x00000004
#define MEMORY_ATTRIBUTE_WB 0x00000008
#define MEMORY_ATTRIBUTE_UCE 0x00000010
//
// Memory protection attributes.
//
#define MEMORY_ATTRIBUTE_WP 0x00000100
#define MEMORY_ATTRIBUTE_RP 0x00000200
#define MEMORY_ATTRIBUTE_XP 0x00000400
//
// Memory location attributes.
//
#define MEMORY_ATTRIBUTE_BELOW_1MIB 0x00080000
//
// Memory runtime mapping attributes.
//
#define MEMORY_ATTRIBUTE_RUNTIME 0x01000000
typedef struct {
LIST_ENTRY ListEntry;
ULONGLONG FirstPage;
ULONGLONG MappedFirstPage;
ULONG PageCount;
ULONG Attributes;
MEMORY_TYPE Type;
} MEMORY_DESCRIPTOR, *PMEMORY_DESCRIPTOR;
typedef enum {
MDL_TYPE_PHYSICAL,
MDL_TYPE_VIRTUAL
} MEMORY_DESCRIPTOR_LIST_TYPE;
typedef struct {
LIST_ENTRY ListEntry;
PLIST_ENTRY Head;
PLIST_ENTRY Current;
MEMORY_DESCRIPTOR_LIST_TYPE Type;
} MEMORY_DESCRIPTOR_LIST, *PMEMORY_DESCRIPTOR_LIST;
#define BOOT_MEMORY_INFO_VERSION 1
typedef struct {
ULONG Version;
ULONG MdlOffset;
ULONG DescriptorCount;
ULONG DescriptorSize;
ULONG FirstPageOffset;
} BOOT_MEMORY_INFO, *PBOOT_MEMORY_INFO;
#define BOOT_FIRMWARE_DATA_VERSION 2
typedef struct {
ULONG Version;
ULONG Reserved;
EFI_HANDLE ImageHandle;
EFI_SYSTEM_TABLE *SystemTable;
ULONG Reserved2;
#if defined(__i386__) || defined(__x86_64__)
ULONG_PTR Cr3;
#endif
DESCRIPTOR_TABLE_CONTEXT DescriptorTableContext;
} BOOT_FIRMWARE_DATA, *PBOOT_FIRMWARE_DATA;
#define BOOT_RETURN_DATA_VERSION 1
typedef struct {
ULONG Version;
NTSTATUS Status;
ULONG Flags;
} BOOT_RETURN_DATA, *PBOOT_RETURN_DATA;
//
// Firmware-independent application parameters.
// Passed to any boot application's entry point.
//
#define BOOT_APPLICATION_PARAMETERS_SIGNATURE 0x50504120544f4f42 /* "BOOT APP" */
#define BOOT_APPLICATION_PARAMETERS_VERSION 2
typedef struct {
ULONGLONG Signature;
ULONG Version;
ULONG Size;
//
// Machine information.
//
ULONG MachineType;
ULONG TranslationType;
//
// Image information.
//
PVOID ImageBase;
ULONG ImageSize;
//
// Offsets to ancillary structures.
//
ULONG MemoryInfoOffset;
ULONG ApplicationEntryOffset;
ULONG BootDeviceOffset;
ULONG FirmwareDataOffset;
ULONG ReturnDataOffset;
ULONG PlatformDataOffset;
} BOOT_APPLICATION_PARAMETERS, *PBOOT_APPLICATION_PARAMETERS;
//
// Library parameters.
// Specifies how the boot library should be
// set up.
//
typedef struct { typedef struct {
ULONG Flags; ULONG Flags;
@@ -25,6 +287,154 @@ typedef struct {
ULONG MinimumPageAllocation; ULONG MinimumPageAllocation;
} BOOT_LIBRARY_PARAMETERS, *PBOOT_LIBRARY_PARAMETERS; } BOOT_LIBRARY_PARAMETERS, *PBOOT_LIBRARY_PARAMETERS;
typedef struct {
LARGE_INTEGER ImageBase;
ULONG ImageSize;
ULONG ImageOffset;
} BOOT_RAMDISK_IDENTIFIER, *PBOOT_RAMDISK_IDENTIFIER;
#define BOOT_HARDDRIVE_PARTITION_TYPE_GPT 0x00
#define BOOT_HARDDRIVE_PARTITION_TYPE_MBR 0x01
#define BOOT_HARDDRIVE_PARTITION_TYPE_RAW 0x02
typedef struct {
ULONG PartitionType;
union {
struct {
ULONG Signature;
} Mbr;
struct {
GUID Signature;
} Gpt;
struct {
ULONG DriveNumber;
} Raw;
};
} BOOT_HARDDRIVE_IDENTIFIER, *PBOOT_HARDDRIVE_IDENTIFIER;
typedef struct {
ULONG DriveNumber;
} BOOT_CDROM_IDENTIFIER, *PBOOT_CDROM_IDENTIFIER;
#define BOOT_BLOCK_DEVICE_TYPE_HARDDRIVE 0x00
#define BOOT_BLOCK_DEVICE_TYPE_CDROM 0x02
#define BOOT_BLOCK_DEVICE_TYPE_RAMDISK 0x03
typedef struct {
ULONG Type;
union {
BOOT_RAMDISK_IDENTIFIER Ramdisk;
BOOT_HARDDRIVE_IDENTIFIER Harddrive;
BOOT_CDROM_IDENTIFIER Cdrom;
};
} BOOT_BLOCK_IDENTIFIER, *PBOOT_BLOCK_IDENTIFIER;
typedef struct {
union {
struct {
ULONG PartitionNumber;
} Mbr;
struct {
GUID PartitionIdentifier;
} Gpt;
struct {
ULONG BootEntry;
} ElTorito;
};
BOOT_BLOCK_IDENTIFIER Parent;
} BOOT_PARTITION_IDENTIFIER, *PBOOT_PARTITION_IDENTIFIER;
typedef struct {
union {
struct {
PVOID PartitionOffset;
} Mbr;
struct {
GUID PartitionIdentifier;
} Gpt;
struct {
ULONG BootEntry;
} ElTorito;
};
BOOT_BLOCK_IDENTIFIER Parent;
} BOOT_PARTITION_IDENTIFIER_EX, *PBOOT_PARTITION_IDENTIFIER_EX;
#define BOOT_DEVICE_TYPE_BLOCK 0x00
#define BOOT_DEVICE_TYPE_PARTITION 0x02
#define BOOT_DEVICE_TYPE_PARTITION_EX 0x06
#define BOOT_DEVICE_ATTRIBUTE_NO_PARENT_SIGNATURE 0x04
typedef struct {
ULONG Type;
ULONG Attributes;
ULONG Size;
ULONG Pad;
union {
BOOT_BLOCK_IDENTIFIER Block;
BOOT_PARTITION_IDENTIFIER Partition;
BOOT_PARTITION_IDENTIFIER_EX PartitionEx;
};
} BOOT_DEVICE, *PBOOT_DEVICE;
typedef ULONG BCDE_DATA_TYPE;
#define BCDE_DATA_FORMAT_MASK 0x0F000000
#define BCDE_DATA_FORMAT_DEVICE 0x01000000
#define BCDE_DATA_FORMAT_STRING 0x02000000
#define BCDE_DATA_TYPE_APPLICATION_DEVICE 0x11000001
#define BCDE_DATA_TYPE_APPLICATION_PATH 0x22000002
#define BCDE_DATA_TYPE_BCD_DEVICE 0x21000022
#define BCDE_DATA_TYPE_BCD_PATH 0x22000023
typedef struct {
GUID Options;
BOOT_DEVICE Device;
} BCDE_DEVICE, *PBCDE_DEVICE;
//
// Enable/disable debug printing.
//
#if defined(_DEBUG)
#define DebugPrint(String) ConsolePrint(String)
#define DebugPrintf(Format, ...) ConsolePrintf(Format, __VA_ARGS__)
#else
#define DebugPrint(String)
#define DebugPrintf(Format, ...)
#endif
extern PEXECUTION_CONTEXT CurrentExecutionContext;
extern ULONG BlPlatformFlags;
extern PBOOT_DEVICE BlpBootDevice;
extern PBOOT_APPLICATION_PARAMETERS BlpApplicationParameters;
extern BOOT_LIBRARY_PARAMETERS BlpLibraryParameters;
extern BOOT_APPLICATION_ENTRY BlpApplicationEntry;
#if defined(_EFI)
extern PBOOT_FIRMWARE_DATA EfiFirmwareParameters;
extern EFI_HANDLE EfiImageHandle;
extern EFI_SYSTEM_TABLE *EfiST;
extern EFI_BOOT_SERVICES *EfiBS;
extern EFI_RUNTIME_SERVICES *EfiRT;
extern SIMPLE_TEXT_OUTPUT_INTERFACE *EfiConOut;
extern SIMPLE_INPUT_INTERFACE *EfiConIn;
extern EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *EfiConInEx;
#endif
VOID VOID
ConsolePrint ( ConsolePrint (
IN PWSTR String IN PWSTR String
@@ -36,25 +446,23 @@ ConsolePrintf (
... ...
); );
// VOID
// Enable/disable debug printing. BlpArchGetDescriptorTableContext (
// PDESCRIPTOR_TABLE_CONTEXT Context
#ifdef _DEBUG
#define DebugPrint(String) ConsolePrint(String)
#define DebugPrintf(Format, ...) ConsolePrintf(Format, __VA_ARGS__)
#else
#define DebugPrint(String)
#define DebugPrintf(Format, ...)
#endif
ULONG
BlGetBootOptionSize (
IN PBOOT_APPLICATION_OPTION Option
); );
ULONG BOOLEAN
BlGetBootOptionListSize ( BlArchIsFiveLevelPagingActive (
IN PBOOT_APPLICATION_OPTION Options );
VOID
BlpArchSwitchContext (
IN EXECUTION_CONTEXT_TYPE Type
);
NTSTATUS
BlpArchInitialize (
IN ULONG Stage
); );
NTSTATUS NTSTATUS
@@ -63,6 +471,11 @@ BlpFwInitialize (
IN PBOOT_FIRMWARE_DATA FirmwareData IN PBOOT_FIRMWARE_DATA FirmwareData
); );
NTSTATUS
BlpMmDestroy (
IN ULONG Stage
);
NTSTATUS NTSTATUS
BlpMmInitializeConstraints ( BlpMmInitializeConstraints (
VOID VOID
@@ -75,9 +488,34 @@ BlpMmInitialize (
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
); );
ULONG
BlGetBootOptionSize (
IN PBOOT_ENTRY_OPTION Option
);
ULONG
BlGetBootOptionListSize (
IN PBOOT_ENTRY_OPTION Options
);
NTSTATUS
BlGetBootOptionDevice (
IN PBOOT_ENTRY_OPTION Options,
IN BCDE_DATA_TYPE Type,
IN OUT PBOOT_DEVICE *Device,
IN OUT PBOOT_ENTRY_OPTION *OtherOptions
);
NTSTATUS
BlGetBootOptionString (
IN PBOOT_ENTRY_OPTION Options,
IN BCDE_DATA_TYPE Type,
IN OUT PWSTR *String
);
NTSTATUS NTSTATUS
BlInitializeLibrary ( BlInitializeLibrary (
IN PBOOT_INPUT_PARAMETERS InputParameters, IN PBOOT_APPLICATION_PARAMETERS ApplicationParameters,
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
); );

View File

@@ -16,311 +16,16 @@ Abstract:
#ifndef _BOOTMGR_H #ifndef _BOOTMGR_H
#define _BOOTMGR_H #define _BOOTMGR_H
#include <nt.h> #include "bootlib.h"
#include "efi.h"
//
// Set machine type.
//
#if defined(__x86_64__)
#define BOOT_MACHINE_TYPE IMAGE_FILE_MACHINE_AMD64
#elif defined(__i386__)
#define BOOT_MACHINE_TYPE IMAGE_FILE_MACHINE_I386
#endif
//
// Use EFI page size.
//
#define PAGE_SIZE EFI_PAGE_SIZE
#define PAGE_SHIFT EFI_PAGE_SHIFT
//
// Address translation types.
//
#define BOOT_TRANSLATION_TYPE_NONE 0
#define BOOT_TRANSLATION_TYPE_MAX 1
#define BOOT_INPUT_PARAMETERS_SIGNATURE 0x50504120544f4f42 /* "BOOT APP" */
#define BOOT_INPUT_PARAMETERS_VERSION 2
typedef struct {
ULONGLONG Signature;
ULONG Version;
ULONG Size;
//
// Machine information.
//
ULONG MachineType;
ULONG TranslationType;
//
// Image information.
//
PVOID ImageBase;
ULONG ImageSize;
//
// Offsets to ancillary structures.
//
ULONG MemoryInfoOffset;
ULONG ApplicationEntryOffset;
ULONG BootDeviceOffset;
ULONG FirmwareDataOffset;
ULONG ReturnDataOffset;
ULONG PlatformDataOffset;
} BOOT_INPUT_PARAMETERS, *PBOOT_INPUT_PARAMETERS;
typedef struct {
ULONG Type;
ULONG DataOffset;
ULONG DataSize;
ULONG OtherOptionsOffset;
ULONG NextOptionOffset;
BOOLEAN IsInvalid;
UCHAR Unknown[3];
} BOOT_APPLICATION_OPTION, *PBOOT_APPLICATION_OPTION;
#define BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE 0x544e4550415442 /* "BTAPENT" */
#define BOOT_INPUT_APPLICATION_ENTRY_NO_BCD_IDENTIFIER 0x01
typedef struct {
ULONGLONG Signature;
ULONG Attributes;
GUID BcdIdentifier;
UCHAR Unknown[16];
BOOT_APPLICATION_OPTION Options;
} BOOT_INPUT_APPLICATION_ENTRY, *PBOOT_INPUT_APPLICATION_ENTRY;
typedef struct {
ULONG Attributes;
GUID BcdIdentifier;
PBOOT_APPLICATION_OPTION Options;
} BOOT_APPLICATION_ENTRY, *PBOOT_APPLICATION_ENTRY;
#define BOOT_MEMORY_INFO_VERSION 1
typedef struct {
ULONG Version;
ULONG MdlOffset;
ULONG DescriptorCount;
ULONG DescriptorSize;
ULONG FirstPageOffset;
} BOOT_MEMORY_INFO, *PBOOT_MEMORY_INFO;
//
// Memory descriptor caching attributes.
//
#define MEMORY_ATTRIBUTE_UC 0x0000000000000001
#define MEMORY_ATTRIBUTE_WC 0x0000000000000002
#define MEMORY_ATTRIBUTE_WT 0x0000000000000004
#define MEMORY_ATTRIBUTE_WB 0x0000000000000008
#define MEMORY_ATTRIBUTE_UCE 0x0000000000000010
//
// Memory descriptor protection attributes.
//
#define MEMORY_ATTRIBUTE_WP 0x000000000000100
#define MEMORY_ATTRIBUTE_RP 0x000000000000200
#define MEMORY_ATTRIBUTE_XP 0x000000000000400
//
// Memory descriptor location attributes.
//
#define MEMORY_ATTRIBUTE_BELOW_1MIB 0x80000
//
// Memory descriptor runtime mapping attributes.
//
#define MEMORY_ATTRIBUTE_RUNTIME 0x1000000
#define MEMORY_CLASS_APPLICATION 0xD
#define MEMORY_CLASS_LIBRARY 0xE
#define MEMORY_CLASS_SYSTEM 0xF
#define MEMORY_TYPE_BOOT_APPLICATION 0xD0000002
#define MEMORY_TYPE_BOOT_APPLICATION_2 0xD0000013
#define MEMORY_TYPE_FREE 0xF0000001
#define MEMORY_TYPE_UNUSABLE 0xF0000002
#define MEMORY_TYPE_RESERVED 0xF0000003
#define MEMORY_TYPE_BOOT_SERVICES 0xF0000004
#define MEMORY_TYPE_FREE_ZEROED 0xF0000005
#define MEMORY_TYPE_RUNTIME_SERVICES_CODE 0xF0000006
#define MEMORY_TYPE_PERSISTENT 0xF0000007
#define MEMORY_TYPE_ACPI_RECLAIM 0xF0000008
#define MEMORY_TYPE_ACPI_NVS 0xF0000009
#define MEMORY_TYPE_MMIO 0xF000000A
#define MEMORY_TYPE_MMIO_PORT_SPACE 0xF000000B
#define MEMORY_TYPE_PAL_CODE 0xF000000C
#define MEMORY_TYPE_RUNTIME_SERVICES_DATA 0xF000000E
typedef ULONG MEMORY_TYPE;
typedef struct {
LIST_ENTRY ListEntry;
ULONGLONG FirstPage;
ULONGLONG MappedFirstPage;
ULONG PageCount;
ULONG Attributes;
MEMORY_TYPE Type;
} MEMORY_DESCRIPTOR, *PMEMORY_DESCRIPTOR;
typedef enum {
MDL_TYPE_PHYSICAL,
MDL_TYPE_VIRTUAL
} MEMORY_DESCRIPTOR_LIST_TYPE;
typedef struct {
LIST_ENTRY ListEntry;
PLIST_ENTRY Head;
PLIST_ENTRY Current;
MEMORY_DESCRIPTOR_LIST_TYPE Type;
} MEMORY_DESCRIPTOR_LIST, *PMEMORY_DESCRIPTOR_LIST;
#define BOOT_FIRMWARE_DATA_VERSION 2
typedef struct {
ULONG Version;
ULONG Reserved;
EFI_HANDLE ImageHandle;
EFI_SYSTEM_TABLE *SystemTable;
} BOOT_FIRMWARE_DATA, *PBOOT_FIRMWARE_DATA;
#define BOOT_RETURN_DATA_VERSION 1
typedef struct {
ULONG Version;
NTSTATUS Status;
ULONG Flags;
} BOOT_RETURN_DATA, *PBOOT_RETURN_DATA;
typedef struct {
LARGE_INTEGER ImageBase;
ULONG ImageSize;
ULONG ImageOffset;
} BOOT_RAMDISK_IDENTIFIER, *PBOOT_RAMDISK_IDENTIFIER;
#define BOOT_HARDDRIVE_PARTITION_TYPE_GPT 0x00
#define BOOT_HARDDRIVE_PARTITION_TYPE_MBR 0x01
#define BOOT_HARDDRIVE_PARTITION_TYPE_RAW 0x02
typedef struct {
ULONG PartitionType;
union {
struct {
ULONG Signature;
} Mbr;
struct {
GUID Signature;
} Gpt;
struct {
ULONG DriveNumber;
} Raw;
};
} BOOT_HARDDRIVE_IDENTIFIER, *PBOOT_HARDDRIVE_IDENTIFIER;
typedef struct {
ULONG DriveNumber;
} BOOT_CDROM_IDENTIFIER, *PBOOT_CDROM_IDENTIFIER;
#define BOOT_BLOCK_DEVICE_TYPE_HARDDRIVE 0x00
#define BOOT_BLOCK_DEVICE_TYPE_CDROM 0x02
#define BOOT_BLOCK_DEVICE_TYPE_RAMDISK 0x03
typedef struct {
ULONG Type;
union {
BOOT_RAMDISK_IDENTIFIER Ramdisk;
BOOT_HARDDRIVE_IDENTIFIER Harddrive;
BOOT_CDROM_IDENTIFIER Cdrom;
};
} BOOT_BLOCK_IDENTIFIER, *PBOOT_BLOCK_IDENTIFIER;
typedef struct {
union {
struct {
ULONG PartitionNumber;
} Mbr;
struct {
GUID PartitionIdentifier;
} Gpt;
struct {
ULONG BootEntry;
} ElTorito;
};
BOOT_BLOCK_IDENTIFIER Parent;
} BOOT_PARTITION_IDENTIFIER, *PBOOT_PARTITION_IDENTIFIER;
typedef struct {
union {
struct {
PVOID PartitionOffset;
} Mbr;
struct {
GUID PartitionIdentifier;
} Gpt;
struct {
ULONG BootEntry;
} ElTorito;
};
BOOT_BLOCK_IDENTIFIER Parent;
} BOOT_PARTITION_IDENTIFIER_EX, *PBOOT_PARTITION_IDENTIFIER_EX;
#define BOOT_DEVICE_TYPE_BLOCK 0x00
#define BOOT_DEVICE_TYPE_PARTITION 0x02
#define BOOT_DEVICE_TYPE_PARTITION_EX 0x06
#define BOOT_DEVICE_ATTRIBUTE_NO_PARENT_SIGNATURE 0x04
typedef struct {
ULONG Type;
ULONG Attributes;
ULONG Size;
ULONG Pad;
union {
BOOT_BLOCK_IDENTIFIER Block;
BOOT_PARTITION_IDENTIFIER Partition;
BOOT_PARTITION_IDENTIFIER_EX PartitionEx;
};
} BOOT_DEVICE, *PBOOT_DEVICE;
#define BCDE_DATA_FORMAT_MASK 0x0F000000
#define BCDE_DATA_FORMAT_DEVICE 1
typedef enum {
BCDE_DATA_TYPE_APPLICATION_DEVICE = 0x11000001,
BCDE_DATA_TYPE_APPLICATION_PATH = 0x22000002
} BCDE_DATA_TYPE;
typedef struct {
GUID OtherOptions;
BOOT_DEVICE Device;
} BCDE_DEVICE, *PBCDE_DEVICE;
NTSTATUS NTSTATUS
BmOpenDataStore ( BmOpenDataStore (
IN OUT PHANDLE DataStore IN OUT PHANDLE Handle
); );
NTSTATUS NTSTATUS
BmMain ( BmMain (
IN PBOOT_INPUT_PARAMETERS InputParameters IN PBOOT_APPLICATION_PARAMETERS ApplicationParameters
); );
#endif #endif

View File

@@ -16,48 +16,13 @@ Abstract:
#ifndef _EFIAPI_H #ifndef _EFIAPI_H
#define _EFIAPI_H #define _EFIAPI_H
#define EFI_MAKE_REVISION(Major, Minor) (((Major) << 16) | (Minor))
#define EFI_SPECIFICATION_MAJOR_REVISION 1 #define EFI_SPECIFICATION_MAJOR_REVISION 1
#define EFI_SPECIFICATION_MINOR_REVISION 02 #define EFI_SPECIFICATION_MINOR_REVISION 02
#define EFI_SPECIFICATION_VERSION ((EFI_SPECIFICATION_MAJOR_REVISION << 16) || EFI_SPECIFICATION_MINOR_REVISION) #define EFI_SPECIFICATION_VERSION EFI_MAKE_REVISION(EFI_SPECIFICATION_MAJOR_REVISION, EFI_SPECIFICATION_MINOR_REVISION)
INTERFACE_DECL(_EFI_SYSTEM_TABLE); INTERFACE_DECL(_EFI_SYSTEM_TABLE);
/*
* Loaded image protocol definitions.
*/
typedef
EFI_STATUS
(EFIAPI *EFI_IMAGE_UNLOAD) (
IN EFI_HANDLE ImageHandle
);
#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
{ 0x5b1b31a1, 0x9562, 0x11d2, { 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } }
#define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID
#define EFI_IMAGE_INFORMATION_REVISION 0x1000
typedef struct {
UINT32 Revision;
EFI_HANDLE ParentHandle;
struct _EFI_SYSTEM_TABLE *SystemTable;
EFI_HANDLE DeviceHandle;
EFI_DEVICE_PATH *FilePath;
VOID *Reserved;
UINT32 LoadOptionsSize;
VOID *LoadOptions;
VOID *ImageBase;
UINT64 ImageSize;
EFI_MEMORY_TYPE ImageCodeType;
EFI_MEMORY_TYPE ImageDataType;
EFI_IMAGE_UNLOAD Unload;
} EFI_LOADED_IMAGE;
/* /*
* EFI table header. * EFI table header.
*/ */
@@ -141,6 +106,42 @@ EFI_STATUS
OUT VOID **Interface OUT VOID **Interface
); );
typedef
EFI_STATUS
(EFIAPI *EFI_OPEN_PROTOCOL) (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT VOID **Interface,
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle,
IN UINT32 Attributes
);
#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002
#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004
#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008
#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010
#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020
typedef
EFI_STATUS
(EFIAPI *EFI_CLOSE_PROTOCOL) (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle
);
typedef
EFI_STATUS
(EFIAPI *EFI_SET_WATCHDOG_TIMER) (
IN UINTN Timeout,
IN UINT64 WatchdogCode,
IN UINTN DataSize,
IN CHAR16 *WatchdogData OPTIONAL
);
typedef struct _EFI_BOOT_SERVICES { typedef struct _EFI_BOOT_SERVICES {
EFI_TABLE_HEADER Hdr; EFI_TABLE_HEADER Hdr;
@@ -178,13 +179,13 @@ typedef struct _EFI_BOOT_SERVICES {
EFI_HANDLE GetNextHighMonotonicCount; EFI_HANDLE GetNextHighMonotonicCount;
EFI_HANDLE Stall; EFI_HANDLE Stall;
EFI_HANDLE SetWatchdogTimer; EFI_SET_WATCHDOG_TIMER SetWatchdogTimer;
EFI_HANDLE ConnectController; EFI_HANDLE ConnectController;
EFI_HANDLE DisconnectController; EFI_HANDLE DisconnectController;
EFI_HANDLE OpenProtocol; EFI_OPEN_PROTOCOL OpenProtocol;
EFI_HANDLE CloseProtocol; EFI_CLOSE_PROTOCOL CloseProtocol;
EFI_HANDLE OpenProtocolInformation; EFI_HANDLE OpenProtocolInformation;
EFI_HANDLE ProtocolsPerHandle; EFI_HANDLE ProtocolsPerHandle;

View File

@@ -305,4 +305,80 @@ typedef struct _SIMPLE_INPUT_INTERFACE {
EFI_EVENT WaitForKey; EFI_EVENT WaitForKey;
} SIMPLE_INPUT_INTERFACE, EFI_SIMPLE_TEXT_IN_PROTOCOL; } SIMPLE_INPUT_INTERFACE, EFI_SIMPLE_TEXT_IN_PROTOCOL;
INTERFACE_DECL(_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL);
#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
{ 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
#define SIMPLE_TEXT_INPUT_EX_PROTOCOL EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID
typedef UINT8 EFI_KEY_TOGGLE_STATE;
#define EFI_SCROLL_LOCK_ACTIVE 0x01
#define EFI_NUM_LOCK_ACTIVE 0x02
#define EFI_CAPS_LOCK_ACTIVE 0x04
#define EFI_KEY_STATE_EXPOSED 0x40
#define EFI_TOGGLE_STATE_VALID 0x80
typedef struct {
UINT32 KeyShiftState;
EFI_KEY_TOGGLE_STATE KeyToggleState;
} EFI_KEY_STATE;
typedef struct {
EFI_INPUT_KEY Key;
EFI_KEY_STATE KeyState;
} EFI_KEY_DATA;
typedef
EFI_STATUS
(EFIAPI *EFI_KEY_NOTIFY_FUNCTION) (
IN EFI_KEY_DATA *KeyData
);
typedef
EFI_STATUS
(EFIAPI *EFI_INPUT_RESET_EX) (
IN struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
typedef
EFI_STATUS
(EFIAPI *EFI_INPUT_READ_KEY_EX) (
IN struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
OUT EFI_KEY_DATA *KeyData
);
typedef
EFI_STATUS
(EFIAPI *EFI_SET_STATE) (
IN struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN EFI_KEY_TOGGLE_STATE *KeyToggleState
);
typedef
EFI_STATUS
(EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY) (
IN struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN EFI_KEY_DATA *KeyData,
IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
OUT VOID **NotifyHandle
);
typedef
EFI_STATUS
(EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY) (
IN struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN VOID *NotificationHandle
);
typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL {
EFI_INPUT_RESET_EX Reset;
EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx;
EFI_EVENT WaitForKeyEx;
EFI_SET_STATE SetState;
EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify;
EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify;
} EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
#endif #endif

View File

@@ -16,10 +16,19 @@ Abstract:
#ifndef _EFILIB_H #ifndef _EFILIB_H
#define _EFILIB_H #define _EFILIB_H
#include "bootmgr.h" #include "bootlib.h"
#include "efi.h" #include "efi.h"
PBOOT_INPUT_PARAMETERS extern EFI_GUID EfiSimpleTextInputExProtocol;
PBOOT_APPLICATION_PARAMETERS
EfiInitCreateInputParametersEx (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable,
IN ULONG Flags
);
PBOOT_APPLICATION_PARAMETERS
EfiInitCreateInputParameters ( EfiInitCreateInputParameters (
IN EFI_HANDLE ImageHandle, IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable IN EFI_SYSTEM_TABLE *SystemTable
@@ -35,4 +44,48 @@ EfiGetNtStatusCode (
IN EFI_STATUS Status IN EFI_STATUS Status
); );
NTSTATUS
EfiGetMemoryMap (
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
IN OUT UINTN *MapKey,
IN OUT UINTN *DescriptorSize,
IN OUT UINT32 *DescriptorVersion
);
NTSTATUS
EfiAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT EFI_PHYSICAL_ADDRESS *Memory
);
NTSTATUS
EfiFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN Pages
);
NTSTATUS
EfiSetWatchdogTimer (
IN UINTN Timeout,
IN UINT64 WatchdogCode,
IN UINTN DataSize,
IN CHAR16 *WatchdogData
);
NTSTATUS
EfiOpenProtocol (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN OUT VOID **Interface
);
NTSTATUS
EfiConInExSetState (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *Protocol,
IN EFI_KEY_TOGGLE_STATE *KeyToggleState
);
#endif #endif

View File

@@ -17,9 +17,41 @@ Abstract:
#define _EFIPROT_H #define _EFIPROT_H
/* /*
* Device path protocol definitions. * Loaded image protocol definitions.
*/ */
typedef
EFI_STATUS
(EFIAPI *EFI_IMAGE_UNLOAD) (
IN EFI_HANDLE ImageHandle
);
#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
{ 0x5b1b31a1, 0x9562, 0x11d2, { 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } }
#define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID
#define EFI_IMAGE_INFORMATION_REVISION 0x1000
typedef struct {
UINT32 Revision;
EFI_HANDLE ParentHandle;
struct _EFI_SYSTEM_TABLE *SystemTable;
EFI_HANDLE DeviceHandle;
EFI_DEVICE_PATH *FilePath;
VOID *Reserved;
UINT32 LoadOptionsSize;
VOID *LoadOptions;
VOID *ImageBase;
UINT64 ImageSize;
EFI_MEMORY_TYPE ImageCodeType;
EFI_MEMORY_TYPE ImageDataType;
EFI_IMAGE_UNLOAD Unload;
} EFI_LOADED_IMAGE;
#define EFI_DEVICE_PATH_PROTOCOL_GUID \ #define EFI_DEVICE_PATH_PROTOCOL_GUID \
{ 0x9576e91, 0x6d3f, 0x11d2, { 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } } { 0x9576e91, 0x6d3f, 0x11d2, { 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } }
#define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID #define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID

View File

@@ -20,6 +20,9 @@ Abstract:
#define MDL_OPERATION_FLAGS_TRUNCATE 0x00000002 #define MDL_OPERATION_FLAGS_TRUNCATE 0x00000002
#define MDL_OPERATION_FLAGS_PHYSICAL 0x40000000 #define MDL_OPERATION_FLAGS_PHYSICAL 0x40000000
#define MDL_OPERATION_FLAGS_VIRTUAL 0x80000000
extern ULONG MmTranslationType;
NTSTATUS NTSTATUS
MmFwGetMemoryMap ( MmFwGetMemoryMap (
@@ -69,6 +72,14 @@ MmMdRemoveRegionFromMdlEx (
OUT PMEMORY_DESCRIPTOR_LIST Unused OUT PMEMORY_DESCRIPTOR_LIST Unused
); );
NTSTATUS
MmMdRemoveRegionFromMdl (
IN PMEMORY_DESCRIPTOR_LIST Mdl,
IN ULONGLONG RemoveStart,
IN ULONGLONG PageCount,
IN ULONG Flags
);
NTSTATUS NTSTATUS
MmMdFreeDescriptor ( MmMdFreeDescriptor (
IN PMEMORY_DESCRIPTOR Descriptor IN PMEMORY_DESCRIPTOR Descriptor
@@ -88,12 +99,21 @@ MmMdInitDescriptor (
IN MEMORY_TYPE Type IN MEMORY_TYPE Type
); );
NTSTATUS
MmMdDestroy (
);
VOID VOID
MmMdInitialize ( MmMdInitialize (
IN ULONG Unused, IN ULONG Unused,
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
); );
NTSTATUS
MmPaDestroy (
IN ULONG Stage
);
NTSTATUS NTSTATUS
MmPaInitialize ( MmPaInitialize (
IN PBOOT_MEMORY_INFO MemoryInfo, IN PBOOT_MEMORY_INFO MemoryInfo,

View File

@@ -15,9 +15,7 @@ Abstract:
#include <stdarg.h> #include <stdarg.h>
#include <wchar.h> #include <wchar.h>
#include "bootmgr.h" #include "bootlib.h"
extern SIMPLE_TEXT_OUTPUT_INTERFACE *EfiConOut;
VOID VOID
ConsolePrint ( ConsolePrint (
@@ -41,7 +39,18 @@ Return Value:
--*/ --*/
{ {
EXECUTION_CONTEXT_TYPE ContextType;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiConOut->OutputString(EfiConOut, String); EfiConOut->OutputString(EfiConOut, String);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
} }
VOID VOID

View File

@@ -13,14 +13,20 @@ Abstract:
--*/ --*/
#include <ntrtl.h>
#include "bootlib.h" #include "bootlib.h"
#include "bootmgr.h" #include "efi.h"
#include "efilib.h"
BOOT_FIRMWARE_DATA EfiFirmwareData;
PBOOT_FIRMWARE_DATA EfiFirmwareParameters;
EFI_HANDLE EfiImageHandle;
EFI_SYSTEM_TABLE *EfiST; EFI_SYSTEM_TABLE *EfiST;
EFI_BOOT_SERVICES *EfiBS; EFI_BOOT_SERVICES *EfiBS;
EFI_RUNTIME_SERVICES *EfiRT; EFI_RUNTIME_SERVICES *EfiRT;
SIMPLE_TEXT_OUTPUT_INTERFACE *EfiConOut; SIMPLE_TEXT_OUTPUT_INTERFACE *EfiConOut;
SIMPLE_INPUT_INTERFACE *EfiConIn; SIMPLE_INPUT_INTERFACE *EfiConIn;
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *EfiConInEx;
NTSTATUS NTSTATUS
BlpFwInitialize ( BlpFwInitialize (
@@ -36,7 +42,10 @@ Routine Description:
Arguments: Arguments:
Stage - 0 or 1. Stage - Which stage of initialization to perform.
Stage 0: Initialize global firmware-related data and pointers.
Once this stage is complete, ConsolePrint() and ConsolePrintf() can be used.
FirmwareData - Pointer to BOOT_FIRMWARE_DATA. FirmwareData - Pointer to BOOT_FIRMWARE_DATA.
@@ -48,16 +57,43 @@ Return Value:
--*/ --*/
{ {
NTSTATUS Status;
EFI_KEY_TOGGLE_STATE KeyToggleState;
if (FirmwareData == NULL || FirmwareData->Version == 0) { if (FirmwareData == NULL || FirmwareData->Version == 0) {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
if (Stage == 0) { if (Stage == 0) {
RtlCopyMemory(&EfiFirmwareData, FirmwareData, sizeof(BOOT_FIRMWARE_DATA));
EfiFirmwareParameters = &EfiFirmwareData;
EfiImageHandle = FirmwareData->ImageHandle;
EfiST = FirmwareData->SystemTable; EfiST = FirmwareData->SystemTable;
EfiBS = EfiST->BootServices; EfiBS = EfiST->BootServices;
EfiRT = EfiST->RuntimeServices; EfiRT = EfiST->RuntimeServices;
EfiConOut = EfiST->ConOut; EfiConOut = EfiST->ConOut;
EfiConIn = EfiST->ConIn; EfiConIn = EfiST->ConIn;
EfiConInEx = NULL;
} else if (Stage == 1) {
//
// Open the extended console input protocol.
// If successful, tell it to capture partial key events.
//
Status = EfiOpenProtocol(
EfiST->ConsoleInHandle,
&EfiSimpleTextInputExProtocol,
(VOID**)&EfiConInEx
);
if (NT_SUCCESS(Status)) {
KeyToggleState = EFI_KEY_STATE_EXPOSED | EFI_TOGGLE_STATE_VALID;
EfiConInExSetState(EfiConInEx, &KeyToggleState);
}
//
// Disable the watchdog timer.
//
EfiSetWatchdogTimer(0, 0, 0, NULL);
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;

View File

@@ -16,9 +16,7 @@ Abstract:
#include <ntrtl.h> #include <ntrtl.h>
#include <string.h> #include <string.h>
#include <wchar.h> #include <wchar.h>
#include "bootlib.h" #include "efilib.h"
#include "bootmgr.h"
#include "efi.h"
UCHAR EfiInitScratch[2048]; UCHAR EfiInitScratch[2048];
const EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL; const EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
@@ -277,7 +275,7 @@ NTSTATUS
EfiInitpConvertEfiDevicePath ( EfiInitpConvertEfiDevicePath (
IN EFI_DEVICE_PATH *EfiDevicePath, IN EFI_DEVICE_PATH *EfiDevicePath,
IN BCDE_DATA_TYPE OptionType, IN BCDE_DATA_TYPE OptionType,
IN OUT PBOOT_APPLICATION_OPTION Option, IN OUT PBOOT_ENTRY_OPTION Option,
IN ULONG BufferSize IN ULONG BufferSize
) )
@@ -309,23 +307,23 @@ Return Value:
NTSTATUS Status; NTSTATUS Status;
PBCDE_DEVICE DeviceElement; PBCDE_DEVICE DeviceElement;
if (BufferSize < sizeof(BOOT_APPLICATION_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device)) { if (BufferSize < sizeof(BOOT_ENTRY_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device)) {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
RtlZeroMemory(Option, sizeof(BOOT_APPLICATION_OPTION)); RtlZeroMemory(Option, sizeof(BOOT_ENTRY_OPTION));
DeviceElement = (PBCDE_DEVICE)((PUCHAR)Option + sizeof(BOOT_APPLICATION_OPTION)); DeviceElement = (PBCDE_DEVICE)((PUCHAR)Option + sizeof(BOOT_ENTRY_OPTION));
Status = EfiInitTranslateDevicePath( Status = EfiInitTranslateDevicePath(
EfiDevicePath, EfiDevicePath,
&DeviceElement->Device, &DeviceElement->Device,
BufferSize - (sizeof(BOOT_APPLICATION_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device)) BufferSize - (sizeof(BOOT_ENTRY_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device))
); );
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
return Status; return Status;
} }
Option->Type = OptionType; Option->Type = OptionType;
Option->DataOffset = sizeof(BOOT_APPLICATION_OPTION); Option->DataOffset = sizeof(BOOT_ENTRY_OPTION);
Option->DataSize = FIELD_OFFSET(BCDE_DEVICE, Device) + DeviceElement->Device.Size; Option->DataSize = FIELD_OFFSET(BCDE_DEVICE, Device) + DeviceElement->Device.Size;
return STATUS_SUCCESS; return STATUS_SUCCESS;
@@ -335,7 +333,7 @@ NTSTATUS
EfiInitpConvertEfiFilePath ( EfiInitpConvertEfiFilePath (
IN EFI_DEVICE_PATH *EfiFilePath, IN EFI_DEVICE_PATH *EfiFilePath,
IN BCDE_DATA_TYPE OptionType, IN BCDE_DATA_TYPE OptionType,
IN OUT PBOOT_APPLICATION_OPTION Option, IN OUT PBOOT_ENTRY_OPTION Option,
IN ULONG BufferSize IN ULONG BufferSize
) )
@@ -368,19 +366,19 @@ Return Value:
PWCHAR PathStart, Position; PWCHAR PathStart, Position;
ULONG BufferRemaining, Length, Appended; ULONG BufferRemaining, Length, Appended;
if (BufferSize < sizeof(BOOT_APPLICATION_OPTION)) { if (BufferSize < sizeof(BOOT_ENTRY_OPTION)) {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
RtlZeroMemory(Option, sizeof(BOOT_APPLICATION_OPTION)); RtlZeroMemory(Option, sizeof(BOOT_ENTRY_OPTION));
Option->Type = OptionType; Option->Type = OptionType;
Option->DataOffset = sizeof(BOOT_APPLICATION_OPTION); Option->DataOffset = sizeof(BOOT_ENTRY_OPTION);
// //
// Loop through nodes and add one at a time. // Loop through nodes and add one at a time.
// //
Option->DataSize = 0; Option->DataSize = 0;
BufferRemaining = BufferSize - sizeof(BOOT_APPLICATION_OPTION); BufferRemaining = BufferSize - sizeof(BOOT_ENTRY_OPTION);
Node = EfiFilePath; Node = EfiFilePath;
PathStart = (PWCHAR)((PUCHAR)Option + Option->DataOffset); PathStart = (PWCHAR)((PUCHAR)Option + Option->DataOffset);
Position = PathStart; Position = PathStart;
@@ -440,7 +438,7 @@ Return Value:
VOID VOID
EfiInitpCreateApplicationEntry ( EfiInitpCreateApplicationEntry (
IN EFI_SYSTEM_TABLE *SystemTable, IN EFI_SYSTEM_TABLE *SystemTable,
IN OUT PBOOT_INPUT_APPLICATION_ENTRY Entry, IN OUT PBOOT_INIT_APPLICATION_ENTRY Entry,
IN ULONG BufferSize, IN ULONG BufferSize,
IN EFI_DEVICE_PATH *EfiDevicePath, IN EFI_DEVICE_PATH *EfiDevicePath,
IN EFI_DEVICE_PATH *EfiFilePath, IN EFI_DEVICE_PATH *EfiFilePath,
@@ -491,7 +489,7 @@ Return Value:
PWCHAR BcdOptionString; PWCHAR BcdOptionString;
BOOLEAN BcdIdentifierSet; BOOLEAN BcdIdentifierSet;
UNICODE_STRING UnicodeString; UNICODE_STRING UnicodeString;
PBOOT_APPLICATION_OPTION Option, PrevOption; PBOOT_ENTRY_OPTION Option, PrevOption;
PBCDE_DEVICE BootDeviceElement; PBCDE_DEVICE BootDeviceElement;
(VOID)SystemTable; (VOID)SystemTable;
@@ -503,13 +501,13 @@ Return Value:
BcdIdentifierSet = FALSE; BcdIdentifierSet = FALSE;
BufferRemaining = BufferSize; BufferRemaining = BufferSize;
if (BufferRemaining < sizeof(BOOT_INPUT_APPLICATION_ENTRY)) { if (BufferRemaining < sizeof(BOOT_INIT_APPLICATION_ENTRY)) {
return; return;
} }
RtlZeroMemory(Entry, sizeof(BOOT_INPUT_APPLICATION_ENTRY)); RtlZeroMemory(Entry, sizeof(BOOT_INIT_APPLICATION_ENTRY));
Entry->Signature = BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE; Entry->Signature = BOOT_INIT_APPLICATION_ENTRY_SIGNATURE;
BufferRemaining -= FIELD_OFFSET(BOOT_INPUT_APPLICATION_ENTRY, Options); BufferRemaining -= FIELD_OFFSET(BOOT_INIT_APPLICATION_ENTRY, Options);
// //
// Terminate load options. // Terminate load options.
@@ -530,7 +528,7 @@ Return Value:
} }
if (!BcdIdentifierSet) { if (!BcdIdentifierSet) {
Entry->Attributes |= BOOT_INPUT_APPLICATION_ENTRY_NO_BCD_IDENTIFIER; Entry->Attributes |= BOOT_APPLICATION_ENTRY_NO_BCD_IDENTIFIER;
} }
// //
@@ -553,7 +551,7 @@ Return Value:
// TODO: Support UDP/PXE boot. // TODO: Support UDP/PXE boot.
// //
PrevOption = Option; PrevOption = Option;
Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)&Entry->Options + OptionsSize); Option = (PBOOT_ENTRY_OPTION)((PUCHAR)&Entry->Options + OptionsSize);
Status = EfiInitpConvertEfiFilePath(EfiFilePath, BCDE_DATA_TYPE_APPLICATION_PATH, Option, BufferRemaining); Status = EfiInitpConvertEfiFilePath(EfiFilePath, BCDE_DATA_TYPE_APPLICATION_PATH, Option, BufferRemaining);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
goto exit; goto exit;
@@ -567,7 +565,7 @@ Return Value:
// TODO: Parse additional options from LoadOptions. // TODO: Parse additional options from LoadOptions.
// //
PrevOption = Option; PrevOption = Option;
Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)&Entry->Options + OptionsSize); Option = (PBOOT_ENTRY_OPTION)((PUCHAR)&Entry->Options + OptionsSize);
// Status = Unknown(LoadOptions, &Entry->Options, RemainingSize, &OptionsSize, &PrevOption, &Size); // Status = Unknown(LoadOptions, &Entry->Options, RemainingSize, &OptionsSize, &PrevOption, &Size);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
goto exit; goto exit;
@@ -577,10 +575,11 @@ exit:
*BufferUsed = BufferSize - BufferRemaining; *BufferUsed = BufferSize - BufferRemaining;
} }
PBOOT_INPUT_PARAMETERS PBOOT_APPLICATION_PARAMETERS
EfiInitCreateInputParameters ( EfiInitCreateInputParametersEx (
IN EFI_HANDLE ImageHandle, IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable IN EFI_SYSTEM_TABLE *SystemTable,
IN ULONG Flags
) )
/*++ /*++
@@ -595,6 +594,8 @@ Arguments:
SystemTable - Pointer to the EFI system table. SystemTable - Pointer to the EFI system table.
Flags - Unused.
Return Value: Return Value:
Pointer to parameter structure if successful. Pointer to parameter structure if successful.
@@ -603,19 +604,21 @@ Return Value:
--*/ --*/
{ {
ULONG ScratchUsed = 0;
ULONG ApplicationEntrySize = 0;
EFI_STATUS Status; EFI_STATUS Status;
ULONG ScratchUsed;
ULONG ApplicationEntrySize;
EFI_PHYSICAL_ADDRESS BadPageAddress; EFI_PHYSICAL_ADDRESS BadPageAddress;
EFI_LOADED_IMAGE *LoadedImage; EFI_LOADED_IMAGE *LoadedImage;
EFI_DEVICE_PATH *DevicePath; EFI_DEVICE_PATH *DevicePath;
PBOOT_INPUT_PARAMETERS InputParameters; PBOOT_APPLICATION_PARAMETERS InputParameters;
PBOOT_MEMORY_INFO MemoryInfo; PBOOT_MEMORY_INFO MemoryInfo;
PMEMORY_DESCRIPTOR MemoryDescriptor; PMEMORY_DESCRIPTOR MemoryDescriptor;
PBOOT_DEVICE BootDevice; PBOOT_DEVICE BootDevice;
PBOOT_FIRMWARE_DATA FirmwareData; PBOOT_FIRMWARE_DATA FirmwareData;
PBOOT_RETURN_DATA ReturnData; PBOOT_RETURN_DATA ReturnData;
ScratchUsed = 0;
// //
// Page 0x102 may be broken on some machines. // Page 0x102 may be broken on some machines.
// It is mapped here so that it does not get used. // It is mapped here so that it does not get used.
@@ -641,12 +644,12 @@ Return Value:
return NULL; return NULL;
} }
InputParameters = (PBOOT_INPUT_PARAMETERS)(&EfiInitScratch[ScratchUsed]); InputParameters = (PBOOT_APPLICATION_PARAMETERS)(&EfiInitScratch[ScratchUsed]);
ScratchUsed += sizeof(BOOT_INPUT_PARAMETERS); ScratchUsed += sizeof(BOOT_APPLICATION_PARAMETERS);
InputParameters->Signature = BOOT_INPUT_PARAMETERS_SIGNATURE; InputParameters->Signature = BOOT_APPLICATION_PARAMETERS_SIGNATURE;
InputParameters->Version = BOOT_INPUT_PARAMETERS_VERSION; InputParameters->Version = BOOT_APPLICATION_PARAMETERS_VERSION;
InputParameters->MachineType = BOOT_MACHINE_TYPE; InputParameters->MachineType = BOOT_MACHINE_TYPE;
InputParameters->TranslationType = BOOT_TRANSLATION_TYPE_NONE; InputParameters->TranslationType = TRANSLATION_TYPE_NONE;
InputParameters->ImageBase = LoadedImage->ImageBase; InputParameters->ImageBase = LoadedImage->ImageBase;
InputParameters->ImageSize = LoadedImage->ImageSize; InputParameters->ImageSize = LoadedImage->ImageSize;
@@ -669,13 +672,13 @@ Return Value:
InputParameters->ApplicationEntryOffset = ScratchUsed; InputParameters->ApplicationEntryOffset = ScratchUsed;
EfiInitpCreateApplicationEntry( EfiInitpCreateApplicationEntry(
SystemTable, SystemTable,
(PBOOT_INPUT_APPLICATION_ENTRY)(&EfiInitScratch[ScratchUsed]), (PBOOT_INIT_APPLICATION_ENTRY)(&EfiInitScratch[ScratchUsed]),
sizeof(EfiInitScratch) - ScratchUsed, sizeof(EfiInitScratch) - ScratchUsed,
DevicePath, DevicePath,
LoadedImage->FilePath, LoadedImage->FilePath,
LoadedImage->LoadOptions, LoadedImage->LoadOptions,
LoadedImage->LoadOptionsSize, LoadedImage->LoadOptionsSize,
0, Flags,
&ApplicationEntrySize, &ApplicationEntrySize,
&BootDevice &BootDevice
); );
@@ -693,10 +696,14 @@ Return Value:
InputParameters->FirmwareDataOffset = ScratchUsed; InputParameters->FirmwareDataOffset = ScratchUsed;
FirmwareData = (PBOOT_FIRMWARE_DATA)(&EfiInitScratch[ScratchUsed]); FirmwareData = (PBOOT_FIRMWARE_DATA)(&EfiInitScratch[ScratchUsed]);
ScratchUsed += sizeof(BOOT_FIRMWARE_DATA); ScratchUsed += sizeof(BOOT_FIRMWARE_DATA);
RtlZeroMemory(FirmwareData, sizeof(BOOT_FIRMWARE_DATA));
FirmwareData->Version = BOOT_FIRMWARE_DATA_VERSION; FirmwareData->Version = BOOT_FIRMWARE_DATA_VERSION;
FirmwareData->Reserved = 0;
FirmwareData->ImageHandle = ImageHandle; FirmwareData->ImageHandle = ImageHandle;
FirmwareData->SystemTable = SystemTable; FirmwareData->SystemTable = SystemTable;
#if defined(__i386__) || defined(__x86_64__)
asm volatile("mov %%cr3, %0" :"=r"(FirmwareData->Cr3));
#endif
BlpArchGetDescriptorTableContext(&FirmwareData->DescriptorTableContext);
InputParameters->ReturnDataOffset = ScratchUsed; InputParameters->ReturnDataOffset = ScratchUsed;
ReturnData = (PBOOT_RETURN_DATA)(&EfiInitScratch[ScratchUsed]); ReturnData = (PBOOT_RETURN_DATA)(&EfiInitScratch[ScratchUsed]);
@@ -710,3 +717,32 @@ Return Value:
return InputParameters; return InputParameters;
} }
PBOOT_APPLICATION_PARAMETERS
EfiInitCreateInputParameters (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Creates the input parameter structure for the boot application.
Arguments:
ImageHandle - EFI handle for the boot application image.
SystemTable - Pointer to the EFI system table.
Return Value:
Pointer to parameter structure if successful.
NULL on failure.
--*/
{
return EfiInitCreateInputParametersEx(ImageHandle, SystemTable, 0);
}

View File

@@ -13,8 +13,10 @@ Abstract:
--*/ --*/
#include "bootmgr.h" #include "efilib.h"
#include "efi.h" #include "mm.h"
EFI_GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
EFI_STATUS EFI_STATUS
EfiGetEfiStatusCode ( EfiGetEfiStatusCode (
@@ -85,7 +87,6 @@ Return Value:
} }
} }
NTSTATUS NTSTATUS
EfiGetNtStatusCode ( EfiGetNtStatusCode (
IN EFI_STATUS Status IN EFI_STATUS Status
@@ -156,3 +157,380 @@ Return Value:
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
} }
NTSTATUS
EfiGetMemoryMap (
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
IN OUT UINTN *MapKey,
IN OUT UINTN *DescriptorSize,
IN OUT UINT32 *DescriptorVersion
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.GetMemoryMap(). Gets the firmware memory map
and places it into a buffer.
Arguments:
MemoryMapSize - pointer to the size of the buffer.
MemoryMap - pointer to the buffer to store the memory map in.
MapKey - ponter to the memory map key.
DescriptorSize - pointer to the size of each memory map descriptor.
DescriptorVersion - pointer to the version of memory map descriptors.
Return Value:
STATUS_SUCCESS if successful.
STATUS_INVALID_PARAMETER if MemoryMapSize and/or MemoryMap are invalid.
STATUS_BUFFER_TOO_SMALL if MemoryMapSize is too small.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
//
// TODO: Translate addresses here.
// Need MmArchTranslateVirtualAddress().
//
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->GetMemoryMap(
MemoryMapSize,
MemoryMap,
MapKey,
DescriptorSize,
DescriptorVersion
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT EFI_PHYSICAL_ADDRESS *Memory
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.AllocatePages(). Allocates contiguous pages
of physical memory.
Arguments:
Type - the type of allocation.
MemoryType - the type of memory to allocate.
Pages - the number of pages to allocate.
Memory - pointer to a physical address of the allocation.
Return Value:
STATUS_SUCCESS if successful.
STATUS_INVALID_PARAMETER if Type, MemoryType, and/or Memory are invalid.
STATUS_INSUFFICIENT_NVRAM_RESOURCES if the pages could not be allocated.
STATUS_NOT_FOUND if the pages could not be found.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->AllocatePages(
Type,
MemoryType,
Pages,
Memory
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN Pages
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.FreePages(). Frees contiguous pages
of physical memory.
Arguments:
Memory - physical address of the pages to be freed.
Pages - the number of pages to free.
Return Value:
STATUS_SUCCESS if successful.
STATUS_NOT_FOUND if the allocation was not found.
STATUS_INVALID_PARAMETER Memory and/or Pages are invalid.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->FreePages(
Memory,
Pages
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiSetWatchdogTimer (
IN UINTN Timeout,
IN UINT64 WatchdogCode,
IN UINTN DataSize,
IN CHAR16 *WatchdogData
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.SetWatchdogTimer().
Sets the watchdog timer.
Arguments:
Timeout - The number of seconds to set the timer to.
Setting this to 0 disables the timer.
WatchdogCode - The code to set when an event occurs.
DataSize - The size in bytes of WatchdogData.
WatchdogData - Optional pointer to a string containing
a description of the timer, possibly accompanied
by binary data.
Return Value:
STATUS_SUCCESS if successful.
STATUS_INVALID_PARAMETER if WatchdogCode is invalid.
STATUS_NOT_SUPPORTED if there is no Watchdog timer.
STATUS_IO_DEVICE_ERROR if the timer could not be set.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
if (Timeout != 0 && WatchdogCode <= 0xffff) {
return STATUS_INVALID_PARAMETER;
}
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
//
// TODO: Translate addresses here.
// Need MmArchTranslateVirtualAddress().
//
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = EfiBS->SetWatchdogTimer(
Timeout,
WatchdogCode,
DataSize,
WatchdogData
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiOpenProtocol (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN OUT VOID **Interface
)
/*++
Routine Description:
Wrapper that uses either EFI_BOOT_SERVICES.OpenProtocol() or HandleProtocol().
Opens a handle to a protocol and finds its interface.
Arguments:
Handle - The handle to the protocol to open.
Protocol - The GUID of the protocol.
Intercce - Pointer that recieves the address of the interface.
Return Value:
STATUS_SUCCESS if successful.
Error code on failure.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
NTSTATUS Status;
if (MmTranslationType != TRANSLATION_TYPE_NONE) {
//
// TODO: Translate addresses.
// Need EfiVmOpenProtocol().
//
DebugPrint(L"EfiOpenProtocol(): Virtual address translation not supported\r\n");
return STATUS_NOT_IMPLEMENTED;
}
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ExecutionContextFirmware);
}
//
// If supported, use OpenProtocol() (EFI 1.10+).
// It helps ensure the protocol is not uninstalled
// when still in use.
//
if (EfiST->Hdr.Revision >= EFI_MAKE_REVISION(1, 10)) {
EfiStatus = EfiBS->OpenProtocol(
Handle,
Protocol,
Interface,
EfiImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
} else {
EfiStatus = EfiBS->HandleProtocol(
Handle,
Protocol,
Interface
);
}
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
//
// Convert EFI status to NT status.
//
Status = EfiGetNtStatusCode(EfiStatus);
if (!NT_SUCCESS(Status)) {
*Interface = NULL;
}
return Status;
}
NTSTATUS
EfiConInExSetState (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *Protocol,
IN EFI_KEY_TOGGLE_STATE *KeyToggleState
)
/*++
Routine Description:
Wrapper around EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.SetState().
Sets an input protocol's state.
Arguments:
Protocol - The protocol to set the state of.
KeyToggle State - The state to set.
Return Value:
STATUS_SUCCESS if successful.
STATUS_IO_DEVICE_ERROR if the state could not be set.
STATUS_UNSUPPORTED if State is not supported by the device.
--*/
{
EXECUTION_CONTEXT_TYPE ContextType;
EFI_STATUS EfiStatus;
ContextType = CurrentExecutionContext->Type;
if (ContextType != ExecutionContextFirmware) {
//
// TODO: Translate addresses here.
// Need MmArchTranslateVirtualAddress().
//
BlpArchSwitchContext(ExecutionContextFirmware);
}
EfiStatus = Protocol->SetState(
Protocol,
KeyToggleState
);
if (ContextType != ExecutionContextFirmware) {
BlpArchSwitchContext(ContextType);
}
return EfiGetNtStatusCode(EfiStatus);
}

View File

@@ -13,7 +13,7 @@ Abstract:
--*/ --*/
#include "bootmgr.h" #include "bootlib.h"
#include "efi.h" #include "efi.h"
#include "efilib.h" #include "efilib.h"
#include "mm.h" #include "mm.h"
@@ -23,134 +23,6 @@ Abstract:
#define EFI_PAGE(NtPage) (((NtPage) << PAGE_SHIFT) >> EFI_PAGE_SHIFT) #define EFI_PAGE(NtPage) (((NtPage) << PAGE_SHIFT) >> EFI_PAGE_SHIFT)
#define NT_PAGE(EfiPage) (((EfiPage) << EFI_PAGE_SHIFT) >> PAGE_SHIFT) #define NT_PAGE(EfiPage) (((EfiPage) << EFI_PAGE_SHIFT) >> PAGE_SHIFT)
extern EFI_BOOT_SERVICES *EfiBS;
extern PBOOT_DEVICE BlpBootDevice;
NTSTATUS
EfiGetMemoryMap (
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
IN OUT UINTN *MapKey,
IN OUT UINTN *DescriptorSize,
IN OUT UINT32 *DescriptorVersion
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.GetMemoryMap(). Gets the firmware memory map
and places it into a buffer.
Arguments:
MemoryMapSize - pointer to the size of the buffer.
MemoryMap - pointer to the buffer to store the memory map in.
MapKey - ponter to the memory map key.
DescriptorSize - pointer to the size of each memory map descriptor.
DescriptorVersion - pointer to the version of memory map descriptors.
Return Value:
STATUS_SUCCESS if successful,
Other NTSTATUS value if an error occurs.
--*/
{
return EfiGetNtStatusCode(
EfiBS->GetMemoryMap(
MemoryMapSize,
MemoryMap,
MapKey,
DescriptorSize,
DescriptorVersion
)
);
}
NTSTATUS
EfiAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT EFI_PHYSICAL_ADDRESS *Memory
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.AllocatePages(). Allocates contiguous pages
of physical memory.
Arguments:
Type - the type of allocation.
MemoryType - the type of memory to allocate.
Pages - the number of pages to allocate.
Memory - pointer to a physical address of the allocation.
Return Value:
STATUS_SUCCESS if successful,
Other NTSTATUS value if an error occurs.
--*/
{
return EfiGetNtStatusCode(
EfiBS->AllocatePages(
Type,
MemoryType,
Pages,
Memory
)
);
}
NTSTATUS
EfiFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN Pages
)
/*++
Routine Description:
Wrapper for EFI_BOOT_SERVICES.FreePages(). Frees contiguous pages
of physical memory.
Arguments:
Memory - physical address of the pages to be freed.
Pages - the number of pages to free.
Return Value:
STATUS_SUCCESS if successful,
Other NTSTATUS value if an error occurs.
--*/
{
return EfiGetNtStatusCode(
EfiBS->FreePages(
Memory,
Pages
)
);
}
MEMORY_TYPE MEMORY_TYPE
BlMmTranslateEfiMemoryType ( BlMmTranslateEfiMemoryType (
IN EFI_MEMORY_TYPE EfiMemoryType IN EFI_MEMORY_TYPE EfiMemoryType
@@ -421,6 +293,7 @@ Return Value:
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE); Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
MmMdFreeDescriptor(NtDescriptor);
goto exit; goto exit;
} }
@@ -456,6 +329,7 @@ Return Value:
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE); Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
MmMdFreeDescriptor(NtDescriptor);
goto exit; goto exit;
} }
@@ -486,6 +360,7 @@ Return Value:
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE); Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
MmMdFreeDescriptor(NtDescriptor);
goto exit; goto exit;
} }
} }
@@ -507,6 +382,7 @@ Return Value:
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE); Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
MmMdFreeDescriptor(NtDescriptor);
goto exit; goto exit;
} }
@@ -568,6 +444,7 @@ Return Value:
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE); Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
MmMdFreeDescriptor(NtDescriptor);
goto exit; goto exit;
} }
} }
@@ -611,7 +488,7 @@ Return Value:
// //
// Remove the current descriptor. // Remove the current descriptor.
// //
Status = MmMdRemoveRegionFromMdlEx(Mdl, NtStartPage, NtPageCount, MDL_OPERATION_FLAGS_PHYSICAL, 0); Status = MmMdRemoveRegionFromMdl(Mdl, NtStartPage, NtPageCount, MDL_OPERATION_FLAGS_PHYSICAL);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
MmMdFreeDescriptor(NtDescriptor); MmMdFreeDescriptor(NtDescriptor);
goto exit; goto exit;

View File

@@ -17,6 +17,56 @@ Abstract:
#include "bootlib.h" #include "bootlib.h"
#include "mm.h" #include "mm.h"
ULONG MmTranslationType;
NTSTATUS
BlpMmDestroy (
IN ULONG Stage
)
/*++
Routine Description:
Cleans up after any actions performed by the memory manager.
After calling this, the memory manager can no longer be used.
Arguments:
Stage - Which stage of cleanup to perform.
Stage 0: Unknown.
Stage 1: Destroy all MM modules.
Return Value:
STATUS_SUCCESS if successful.
--*/
{
NTSTATUS Status, ExitStatus;
ExitStatus = STATUS_SUCCESS;
if (Stage == 1) {
Status = MmMdDestroy();
if (!NT_SUCCESS(Status)) {
ExitStatus = Status;
}
Status = MmPaDestroy(0);
if (!NT_SUCCESS(Status)) {
ExitStatus = Status;
}
Status = MmPaDestroy(1);
if (!NT_SUCCESS(Status)) {
ExitStatus = Status;
}
}
return ExitStatus;
}
NTSTATUS NTSTATUS
BlpMmInitializeConstraints ( BlpMmInitializeConstraints (
VOID VOID
@@ -34,8 +84,7 @@ Arguments:
Return Value: Return Value:
STATUS_SUCCESS if successful, STATUS_SUCCESS if successful.
--*/ --*/
@@ -79,14 +128,12 @@ Return Value:
{ {
NTSTATUS Status; NTSTATUS Status;
DebugPrint(L"Initializing memory manager...\r\n");
// //
// Check TranslationType. // Check TranslationType.
// //
if ( if (
TranslationType > BOOT_TRANSLATION_TYPE_MAX || TranslationType > TRANSLATION_TYPE_MAX
LibraryParameters->TranslationType > BOOT_TRANSLATION_TYPE_MAX || LibraryParameters->TranslationType > TRANSLATION_TYPE_MAX
) { ) {
DebugPrint(L"BlpMmInitialize(): TranslationType is invalid\r\n"); DebugPrint(L"BlpMmInitialize(): TranslationType is invalid\r\n");
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
@@ -105,5 +152,11 @@ Return Value:
return Status; return Status;
} }
MmTranslationType = LibraryParameters->TranslationType;
//
// TODO: Finish this routine.
//
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View File

@@ -14,7 +14,7 @@ Abstract:
--*/ --*/
#include <ntrtl.h> #include <ntrtl.h>
#include "bootmgr.h" #include "bootlib.h"
#include "mm.h" #include "mm.h"
#define MAX_STATIC_DESCRIPTOR_COUNT 1024 #define MAX_STATIC_DESCRIPTOR_COUNT 1024
@@ -27,6 +27,8 @@ ULONG MmGlobalMemoryDescriptorCount, MmGlobalMemoryDescriptorsUsed;
PMEMORY_DESCRIPTOR MmDynamicMemoryDescriptors; PMEMORY_DESCRIPTOR MmDynamicMemoryDescriptors;
ULONG MmDynamicMemoryDescriptorCount, MmDynamicMemoryDescriptorsUsed; ULONG MmDynamicMemoryDescriptorCount, MmDynamicMemoryDescriptorsUsed;
#define MAX_PRECEDENCE_INDEX sizeof(MmPlatformMemoryTypePrecedence) / sizeof(MmPlatformMemoryTypePrecedence[0])
MEMORY_TYPE MmPlatformMemoryTypePrecedence[] = { MEMORY_TYPE MmPlatformMemoryTypePrecedence[] = {
MEMORY_TYPE_RESERVED, MEMORY_TYPE_RESERVED,
MEMORY_TYPE_UNUSABLE, MEMORY_TYPE_UNUSABLE,
@@ -44,6 +46,40 @@ MEMORY_TYPE MmPlatformMemoryTypePrecedence[] = {
MEMORY_TYPE_FREE_ZEROED MEMORY_TYPE_FREE_ZEROED
}; };
ULONG
GetPrecedenceIndex (
IN MEMORY_TYPE Type
)
/*++
Routine Description:
Finds the index into MmPlatformMemoryTypePrecedence for Type.
Arguments:
Type - The memory type.
Return Value:
The precedence index if found.
MAX_PRECEDENCE_INDEX if not found.
--*/
{
for (ULONG Index = 0;
Index < MAX_PRECEDENCE_INDEX;
Index++) {
if (MmPlatformMemoryTypePrecedence[Index] == Type) {
return Index;
}
}
return MAX_PRECEDENCE_INDEX;
}
BOOLEAN BOOLEAN
MmMdpHasPrecedence ( MmMdpHasPrecedence (
IN MEMORY_TYPE TypeA, IN MEMORY_TYPE TypeA,
@@ -58,9 +94,9 @@ Routine Description:
Arguments: Arguments:
TypeA - memory type A. TypeA - Memory type A.
TypeB - memory type B. TypeB - Memory type B.
Return Value: Return Value:
@@ -71,7 +107,7 @@ Return Value:
{ {
ULONG ClassA, ClassB; ULONG ClassA, ClassB;
ULONG IndexA, IndexB; ULONG PrecedenceIndexA, PrecedenceIndexB;
if (TypeB == MEMORY_TYPE_FREE_ZEROED) { if (TypeB == MEMORY_TYPE_FREE_ZEROED) {
return TRUE; return TRUE;
@@ -103,28 +139,19 @@ Return Value:
return TRUE; return TRUE;
} }
for (IndexA = 0; PrecedenceIndexA = GetPrecedenceIndex(TypeA);
IndexA < sizeof(MmPlatformMemoryTypePrecedence) / sizeof(MmPlatformMemoryTypePrecedence[0]); if (PrecedenceIndexA == MAX_PRECEDENCE_INDEX) {
IndexA++) {
if (TypeA == MmPlatformMemoryTypePrecedence[IndexA]) {
goto CheckTypeBPrecedence;
}
}
return TRUE; return TRUE;
CheckTypeBPrecedence:
for (IndexB = 0;
IndexB < sizeof(MmPlatformMemoryTypePrecedence) / sizeof(MmPlatformMemoryTypePrecedence[0]);
IndexB++) {
if (TypeB == MmPlatformMemoryTypePrecedence[IndexB]) {
return IndexA <= IndexB ? TRUE:FALSE;
}
} }
PrecedenceIndexB = GetPrecedenceIndex(TypeB);
if (PrecedenceIndexB == MAX_PRECEDENCE_INDEX) {
return FALSE; return FALSE;
} }
return PrecedenceIndexA <= PrecedenceIndexB ? TRUE:FALSE;
}
BOOLEAN BOOLEAN
MmMdpTruncateDescriptor ( MmMdpTruncateDescriptor (
IN PMEMORY_DESCRIPTOR_LIST Mdl, IN PMEMORY_DESCRIPTOR_LIST Mdl,
@@ -152,6 +179,7 @@ Return Value:
--*/ --*/
{ {
NTSTATUS Status;
PMEMORY_DESCRIPTOR PrevDescriptor, NextDescriptor, NewDescriptor; PMEMORY_DESCRIPTOR PrevDescriptor, NextDescriptor, NewDescriptor;
ULONGLONG DescriptorEnd, PrevDescriptorEnd, NextDescriptorEnd; ULONGLONG DescriptorEnd, PrevDescriptorEnd, NextDescriptorEnd;
ULONGLONG MappedFirstPage; ULONGLONG MappedFirstPage;
@@ -186,7 +214,10 @@ Return Value:
PrevDescriptor->Type PrevDescriptor->Type
); );
if (NewDescriptor != NULL) { if (NewDescriptor != NULL) {
MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags); Status = MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags);
if (!NT_SUCCESS(Status)) {
MmMdFreeDescriptor(NewDescriptor);
}
} }
} }
@@ -242,7 +273,10 @@ Return Value:
Descriptor->Type Descriptor->Type
); );
if (NewDescriptor != NULL) { if (NewDescriptor != NULL) {
MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags); Status = MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags);
if (!NT_SUCCESS(Status)) {
MmMdFreeDescriptor(NewDescriptor);
}
} }
} }
@@ -310,6 +344,7 @@ Return Value:
PMEMORY_DESCRIPTOR CurrentDescriptor; PMEMORY_DESCRIPTOR CurrentDescriptor;
if (Mdl == NULL || Descriptor == NULL) { if (Mdl == NULL || Descriptor == NULL) {
DebugPrint(L"MmMdAddDescriptorToList(): Mdl and/or Descriptor are NULL\r\n");
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
@@ -454,9 +489,61 @@ Return Value:
{ {
BOOLEAN Mapped;
PMEMORY_DESCRIPTOR Descriptor;
PLIST_ENTRY ListEntry;
ULONGLONG FirstPage;
Mapped = FALSE;
if (Flags & MDL_OPERATION_FLAGS_VIRTUAL) {
if (Mdl->Type == MDL_TYPE_PHYSICAL) {
Mapped = TRUE;
}
} else {
// //
// TODO: Implement this routine. // If the MDL is virtual, the
// virtual flag must be set.
// //
if (Mdl->Type == MDL_TYPE_VIRTUAL) {
DebugPrint(L"MmMdFindDescriptorFromMdl(): Flags is invalid\r\n");
return NULL;
}
}
//
// Check if the cached descriptor is in range.
//
if (!Mapped && Mdl->Current != NULL) {
Descriptor = (PMEMORY_DESCRIPTOR)Mdl->Current;
if (Page < Descriptor->FirstPage) {
ListEntry = Mdl->Head->Flink;
} else {
ListEntry = Mdl->Current;
}
} else {
ListEntry = Mdl->Head->Flink;
}
while (ListEntry != Mdl->Head) {
Descriptor = (PMEMORY_DESCRIPTOR)ListEntry;
if (Mapped) {
FirstPage = Descriptor->MappedFirstPage;
} else {
FirstPage = Descriptor->FirstPage;
}
//
// Check if this descriptor contains Page.
//
if ((!Mapped || FirstPage)
&& Page >= FirstPage
&& Page < FirstPage + Descriptor->PageCount) {
return Descriptor;
}
ListEntry = ListEntry->Flink;
}
return NULL; return NULL;
} }
@@ -464,7 +551,7 @@ Return Value:
NTSTATUS NTSTATUS
MmMdRemoveRegionFromMdlEx ( MmMdRemoveRegionFromMdlEx (
IN PMEMORY_DESCRIPTOR_LIST Mdl, IN PMEMORY_DESCRIPTOR_LIST Mdl,
IN ULONGLONG FirstPage, IN ULONGLONG RemoveStart,
IN ULONGLONG PageCount, IN ULONGLONG PageCount,
IN ULONG Flags, IN ULONG Flags,
OUT PMEMORY_DESCRIPTOR_LIST Unused OUT PMEMORY_DESCRIPTOR_LIST Unused
@@ -480,46 +567,189 @@ Arguments:
Mdl - MDL to remove the region from. Mdl - MDL to remove the region from.
FirstPage - The first page in the region. RemoveStart - The first page in the region.
PageCount - The number of pages in the region. PageCount - The number of pages in the region.
Flags - MDL_OPERATION_FLAGS_*. Flags - MDL_OPERATION_FLAGS_*.
MDL_OPERATION_FLAGS_PHYSICAL if the region is physical.
MDL_OPERATION_FLAGS_VIRTUAL if the region is virtual.
Unused - Unused. Unused - Unused.
Return Value: Return Value:
None. STATUS_SUCCESS if successful,
STATUS_INVALID_PARAMETER if Flags value is invalid.
--*/ --*/
{ {
ULONGLONG RemoveEnd, DescriptorEnd; NTSTATUS Status;
PLIST_ENTRY Entry; ULONG Offset;
PMEMORY_DESCRIPTOR Descriptor; BOOLEAN Mapped;
MEMORY_DESCRIPTOR RemovedDescriptor; ULONGLONG RemoveEnd;
PLIST_ENTRY ListEntry;
ULONGLONG DescriptorStart, DescriptorEnd;
PMEMORY_DESCRIPTOR Descriptor, NewDescriptor;
(VOID)Flags;
(VOID)Unused; (VOID)Unused;
RemoveEnd = FirstPage + PageCount; Mapped = FALSE;
Entry = Mdl->Head->Flink; if (Flags & MDL_OPERATION_FLAGS_VIRTUAL) {
while (Entry != Mdl->Head) { if (Mdl->Type == MDL_TYPE_PHYSICAL) {
Descriptor = (PMEMORY_DESCRIPTOR)Entry; Mapped = TRUE;
DescriptorEnd = Descriptor->FirstPage + Descriptor->PageCount; }
} else {
//
// If the MDL is virtual, the
// virtual flag must be set.
//
if (Mdl->Type == MDL_TYPE_VIRTUAL) {
DebugPrint(L"MmMdRemoveRegionFromMdlEx(): Flags is invalid\r\n");
return STATUS_INVALID_PARAMETER;
}
}
RtlCopyMemory(&RemovedDescriptor, Descriptor, sizeof(MEMORY_DESCRIPTOR)); RemoveEnd = RemoveStart + PageCount;
ListEntry = Mdl->Head->Flink;
while (ListEntry != Mdl->Head) {
Descriptor = (PMEMORY_DESCRIPTOR)ListEntry;
// if (FirstPage <= Descriptor->FirstPage && Descriptor->FirstPage < RemoveEnd) { if (Mapped) {
// } DescriptorStart = Descriptor->MappedFirstPage;
} else {
DescriptorStart = Descriptor->FirstPage;
}
DescriptorEnd = DescriptorStart + Descriptor->PageCount;
//
// Check if the region to be removed
// is inside the current descriptor.
//
if (RemoveStart <= DescriptorStart && RemoveEnd > DescriptorStart) {
//
// The region is around the start of the descriptor, or
// they have identical locations and sizes.
// | RemoveStart | DescriptorStart | RemoveEnd | DescriptorEnd |
// | Lower address ............................ Higher address |
//
if (RemoveEnd < DescriptorEnd) {
Offset = RemoveEnd - DescriptorStart;
} else {
Offset = DescriptorEnd - DescriptorStart;
} }
// //
// TODO: Implement the rest of this routine. // Shrink the descriptor.
//
Descriptor->FirstPage += Offset;
Descriptor->PageCount -= Offset;
if (Descriptor->MappedFirstPage) {
Descriptor->MappedFirstPage += Offset;
}
//
// Remove descriptor if now empty.
//
if (Descriptor->PageCount == 0) {
MmMdRemoveDescriptorFromList(Mdl, Descriptor);
MmMdFreeDescriptor(Descriptor);
}
} else if (RemoveStart < DescriptorEnd && RemoveEnd >= DescriptorEnd) {
//
// The region is around the end of the descriptor.
// | DescriptorStart | RemoveStart | DescriptorEnd | RemoveEnd |
// | Lower address ............................ Higher address |
// //
return STATUS_SUCCESS; //
// Simply shrink the descriptor.
//
Descriptor->PageCount -= DescriptorEnd - RemoveStart;
} else if (RemoveStart > DescriptorStart && RemoveEnd < DescriptorEnd) {
//
// The region is completely inside the descriptor.
// In this case, the descriptor must be split in two.
// | DescriptorStart | RemoveStart | RemoveEnd | DescriptorEnd |
// | Lower address ............................ Higher address |
//
//
// Create a new descriptor before the removed region.
//
NewDescriptor = MmMdInitDescriptor(
Descriptor->FirstPage,
Descriptor->MappedFirstPage,
RemoveStart - DescriptorStart,
Descriptor->Attributes,
Descriptor->Type
);
//
// Shrink and move the current descriptor.
//
Offset = NewDescriptor->PageCount + PageCount;
Descriptor->FirstPage += Offset;
Descriptor->PageCount -= Offset;
if (Descriptor->MappedFirstPage) {
Descriptor->MappedFirstPage += Offset;
}
//
// Now check if MmMdInitDescriptor() actually worked.
//
if (NewDescriptor == NULL) {
return STATUS_NO_MEMORY;
}
Status = MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags);
if (!NT_SUCCESS(Status)) {
MmMdFreeDescriptor(NewDescriptor);
return Status;
}
}
ListEntry = ListEntry->Flink;
}
return Status;
}
NTSTATUS
MmMdRemoveRegionFromMdl (
IN PMEMORY_DESCRIPTOR_LIST Mdl,
IN ULONGLONG RemoveStart,
IN ULONGLONG PageCount,
IN ULONG Flags
)
/*++
Routine Description:
Removes a region from a MDL.
Wrapper around MmMdRemoveRegionFromMdlEx().
Arguments:
Same as MmMdRemoveRegionFromMdlEx(), except for Unused.
Return Value:
Any status code returned by MmMdRemoveRegionFromMdlEx().
--*/
{
return MmMdRemoveRegionFromMdlEx(
Mdl,
RemoveStart,
PageCount,
Flags,
NULL
);
} }
NTSTATUS NTSTATUS
@@ -564,10 +794,10 @@ Return Value:
} }
// //
// Free the descriptor from the heap. // TODO: Free the descriptor from the heap.
// TODO: Use BlMmFreeHeap(). // Need BlMmFreeHeap().
// //
ConsolePrint(L"MmMdFreeDescriptor(): need BlMmFreeHeap() to free descriptor\r\n"); DebugPrint(L"MmMdFreeDescriptor(): Heap not available\r\n");
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
// return BlMmFreeHeap(Descriptor); // return BlMmFreeHeap(Descriptor);
} }
@@ -655,9 +885,38 @@ Return Value:
return Descriptor; return Descriptor;
} }
NTSTATUS
MmMdDestroy (
)
/*++
Routine Description:
Cleans up after any actions performed by the memory descriptor manager.
After calling this, the memory descriptor manager can no longer be used.
Arguments:
None.
Return Value:
STATUS_SUCCESS.
--*/
{
//
// TODO: Implement this routine.
//
return STATUS_SUCCESS;
}
VOID VOID
MmMdInitialize ( MmMdInitialize (
IN ULONG Unused, IN ULONG Stage,
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
) )
@@ -669,9 +928,11 @@ Routine Description:
Arguments: Arguments:
Unused - Ignored. Stage - Which stage of initialization to perform.
LibraryParameters - pointer to the library parameters structure. Stage 0: Initializes the static memory descriptor pool.
LibraryParameters - Pointer to the library parameters structure.
Return Value: Return Value:
@@ -680,17 +941,19 @@ Return Value:
--*/ --*/
{ {
(VOID)Unused;
(VOID)LibraryParameters; (VOID)LibraryParameters;
DebugPrint(L"Initializing memory descriptor manager...\r\n"); if (Stage == 0) {
// //
// Initialize global memory descriptor list. // Initialize static memory descriptor pool.
// //
MmGlobalMemoryDescriptors = &MmStaticMemoryDescriptors[0]; MmGlobalMemoryDescriptors = &MmStaticMemoryDescriptors[0];
MmGlobalMemoryDescriptorCount = MAX_STATIC_DESCRIPTOR_COUNT; MmGlobalMemoryDescriptorCount = MAX_STATIC_DESCRIPTOR_COUNT;
MmGlobalMemoryDescriptorsUsed = 0; MmGlobalMemoryDescriptorsUsed = 0;
RtlZeroMemory(MmGlobalMemoryDescriptors, MAX_STATIC_DESCRIPTOR_COUNT * sizeof(MEMORY_DESCRIPTOR)); RtlZeroMemory(MmGlobalMemoryDescriptors, MAX_STATIC_DESCRIPTOR_COUNT * sizeof(MEMORY_DESCRIPTOR));
DebugPrintf(L"Global memory descriptor count: %x\r\n", MmGlobalMemoryDescriptorCount); }
//
// TODO: Implement stage 1 initialization.
//
} }

View File

@@ -58,6 +58,40 @@ Return Value:
Mdl->Type = MDL_TYPE_PHYSICAL; Mdl->Type = MDL_TYPE_PHYSICAL;
} }
NTSTATUS
MmPaDestroy (
IN ULONG Stage
)
/*++
Routine Description:
Cleans up after any actions performed by the page allocator.
After calling this, the page allocator can no longer be used.
Arguments:
Stage - Which stage of cleanup to perform.
Stage 0: Unknown.
Stage 1: Unknown.
Return Value:
STATUS_SUCCESS.
--*/
{
(VOID)Stage;
//
// TODO: Implement this routine.
//
return STATUS_SUCCESS;
}
NTSTATUS NTSTATUS
MmPaInitialize ( MmPaInitialize (
IN PBOOT_MEMORY_INFO MemoryInfo, IN PBOOT_MEMORY_INFO MemoryInfo,
@@ -88,14 +122,13 @@ Return Value:
NTSTATUS Status; NTSTATUS Status;
PMEMORY_DESCRIPTOR Descriptor, NewDescriptor; PMEMORY_DESCRIPTOR Descriptor, NewDescriptor;
(VOID)MemoryInfo;
DebugPrint(L"Initializing page allocator...\r\n");
PapMinimumAllocationCount = MinimumAllocation; PapMinimumAllocationCount = MinimumAllocation;
PapMinimumPhysicalPage = 1; PapMinimumPhysicalPage = 1;
PapMaximumPhysicalPage = MAXULONGLONG >> PAGE_SHIFT; PapMaximumPhysicalPage = MAXULONGLONG >> PAGE_SHIFT;
//
// Initialize Memory Descriptor Lists
//
InitializeMdl(&MmMdlFwAllocationTracker); InitializeMdl(&MmMdlFwAllocationTracker);
InitializeMdl(&MmMdlBadMemory); InitializeMdl(&MmMdlBadMemory);
InitializeMdl(&MmMdlTruncatedMemory); InitializeMdl(&MmMdlTruncatedMemory);
@@ -116,11 +149,18 @@ Return Value:
// MDL the memory manager will use for allocation. // MDL the memory manager will use for allocation.
// //
Descriptor = (PMEMORY_DESCRIPTOR)((PUCHAR)MemoryInfo + MemoryInfo->MdlOffset); Descriptor = (PMEMORY_DESCRIPTOR)((PUCHAR)MemoryInfo + MemoryInfo->MdlOffset);
for (ULONG DescriptorCount = MemoryInfo->DescriptorCount; DescriptorCount > 0; DescriptorCount--) { for (ULONG DescriptorCount = MemoryInfo->DescriptorCount;
DescriptorCount > 0;
DescriptorCount--) {
// //
// Remove from the usable MDL. // Remove from the usable MDL.
// //
Status = MmMdRemoveRegionFromMdlEx(&MmMdlUnmappedUnallocated, Descriptor->FirstPage, Descriptor->PageCount, MDL_OPERATION_FLAGS_PHYSICAL, NULL); Status = MmMdRemoveRegionFromMdl(
&MmMdlUnmappedUnallocated,
Descriptor->FirstPage,
Descriptor->PageCount,
MDL_OPERATION_FLAGS_PHYSICAL
);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
@@ -139,8 +179,9 @@ Return Value:
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
Status = MmMdAddDescriptorToList(&MmMdlReservedAllocated, NewDescriptor, 0x00); Status = MmMdAddDescriptorToList(&MmMdlReservedAllocated, NewDescriptor, 0);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
MmMdFreeDescriptor(NewDescriptor);
return Status; return Status;
} }

427
BOOT/ENVIRON/LIB/X86/arch.c Normal file
View File

@@ -0,0 +1,427 @@
/*++
Copyright (c) 2024, Quinn Stephens.
Provided under the BSD 3-Clause license.
Module Name:
arch.c
Abstract:
Provides x86 architecture-specific routines.
--*/
#include <ntrtl.h>
#include "bootlib.h"
// TODO: Move these to a header file?
#define CR0_PG (1 << 31)
#define CR4_OSFXSR (1 << 9)
#define CR4_LA57 (1 << 12)
#define IA32_EFER_MSR 0xC0000080
#define IA32_EFER_LME (1 << 10)
EXECUTION_CONTEXT ApplicationExecutionContext;
EXECUTION_CONTEXT FirmwareExecutionContext;
PEXECUTION_CONTEXT CurrentExecutionContext;
VOID
Archpx64EnableInterruptsAsm (
);
/*++
Routine Description:
Enables interrupts.
Implemented in ctx.S.
Arguments:
None.
Return Value:
None.
--*/
VOID
Archpx64DisableInterruptsAsm (
);
/*++
Routine Description:
Disables interrupts.
Implemented in ctx.S.
Arguments:
None.
Return Value:
None.
--*/
VOID
BlpArchGetDescriptorTableContext (
PDESCRIPTOR_TABLE_CONTEXT Context
);
/*++
Routine Description:
Loads current descriptor values into a
descriptor table context structure.
Implemented in ctx.S.
Arguments:
Context - Pointer to the context structure.
Return Value:
None.
--*/
VOID
ArchSetDescriptorTableContext (
PDESCRIPTOR_TABLE_CONTEXT Context
);
/*++
Routine Description:
Loads current descriptor values from a
descriptor table context structure.
Implemented in ctx.S.
Arguments:
Context - Pointer to the context structure.
Return Value:
None.
--*/
BOOLEAN
BlArchIsFiveLevelPagingActive (
)
{
ULONG_PTR Cr0, Cr4;
ULONG Efer;
//
// Paging must be enabled.
//
asm volatile("mov %%cr0, %0" :"=r"(Cr0));
if (!(Cr0 & CR0_PG)) {
return FALSE;
}
//
// Long mode must be enabled.
//
asm volatile("rdmsr" :"=a"(Efer) :"c"(IA32_EFER_MSR));
if (!(Efer & IA32_EFER_LME)) {
return FALSE;
}
//
// 57-bit linear addresses must be enabled.
// If LA57 is enabled, 5-level paging is enabled.
//
asm volatile("mov %%cr4, %0" :"=r"(Cr4));
if (!(Cr4 & CR4_LA57)) {
return FALSE;
}
return TRUE;
}
NTSTATUS
ArchInitializeContext (
IN OUT PEXECUTION_CONTEXT Context
)
/*++
Routine Description:
Initializes an execution context.
Arguments:
Context - Pointer to the context structure.
Return Value:
STATUS_SUCCESS if successful.
--*/
{
ULONG_PTR Cr4;
if (Context->Type == ExecutionContextFirmware) {
Context->Flags &= ~(EXECUTION_CONTEXT_PAGING_ENABLED | 0x01);
Context->Flags |= EXECUTION_CONTEXT_INTERRUPTS_ENABLED;
//
// Use context data from firmware.
//
Context->Cr3 = EfiFirmwareParameters->Cr3;
RtlCopyMemory(&Context->DescriptorTableContext, &EfiFirmwareParameters->DescriptorTableContext, sizeof(DESCRIPTOR_TABLE_CONTEXT));
return STATUS_SUCCESS;
}
Context->Flags &= ~EXECUTION_CONTEXT_INTERRUPTS_ENABLED;
Context->Flags |= 0x01;
//
// Use current context.
//
asm volatile("mov %%cr3, %0" :"=r"(Context->Cr3));
BlpArchGetDescriptorTableContext(&Context->DescriptorTableContext);
//
// Check if 5-level paging is active.
//
if (!BlArchIsFiveLevelPagingActive()) {
Context->Flags &= ~EXECUTION_CONTEXT_PAGING_ENABLED;
//
// Enable SSE and FXSAVE/FXRSTOR.
//
asm volatile("mov %%cr4, %0" :"=r"(Cr4));
Cr4 |= CR4_OSFXSR;
asm volatile("mov %0, %%cr4" ::"r"(Cr4));
return STATUS_SUCCESS;
}
//
// TODO: Not sure what is supposed to happen here.
//
DebugPrint(L"ArchInitializeContext(): 5-level paging support not implemented\r\n");
return STATUS_NOT_IMPLEMENTED;
}
VOID
ArchSetPagingContext(
IN PEXECUTION_CONTEXT NewContext,
IN PEXECUTION_CONTEXT CurrentContext
)
/*++
Routine Description:
Loads the current paging context.
Arguments:
NewContext - The context to switch to.
CurrentContext - The currently loaded context.
Return Value:
None.
--*/
{
BOOLEAN PagingEnabled;
//
// Check if paging is enabled.
//
if (CurrentContext != NULL) {
PagingEnabled = CurrentContext->Flags & EXECUTION_CONTEXT_PAGING_ENABLED ? TRUE:FALSE;
} else {
PagingEnabled = BlArchIsFiveLevelPagingActive() ? TRUE:FALSE;
}
//
// If paging is not being enabled/disabled,
// just switch CR3.
//
if (PagingEnabled == (NewContext->Flags & EXECUTION_CONTEXT_PAGING_ENABLED ? TRUE:FALSE)) {
asm volatile("mov %0, %%cr3" ::"r"(NewContext->Cr3));
return;
}
//
// TODO: Finish this routine.
//
DebugPrint(L"ArchSetPagingContext(): Paging mode enable/disable not implemented\r\n");
}
VOID
ArchSwitchContext (
IN PEXECUTION_CONTEXT NewContext,
IN PEXECUTION_CONTEXT CurrentContext
)
/*++
Routine Description:
Switches to a specified execution context.
Arguments:
NewContext - The context to switch to.
CurrentContext - The currently loaded context.
Return Value:
None.
--*/
{
if (CurrentContext != NULL && CurrentContext->Flags & EXECUTION_CONTEXT_INTERRUPTS_ENABLED) {
Archpx64DisableInterruptsAsm();
}
//
// Set descriptor table and paging contexts,
// in the correct order.
//
if (NewContext->Type == ExecutionContextFirmware) {
ArchSetPagingContext(NewContext, CurrentContext);
ArchSetDescriptorTableContext(&NewContext->DescriptorTableContext);
} else {
ArchSetDescriptorTableContext(&NewContext->DescriptorTableContext);
ArchSetPagingContext(NewContext, CurrentContext);
}
if (NewContext->Flags & EXECUTION_CONTEXT_INTERRUPTS_ENABLED) {
Archpx64EnableInterruptsAsm();
}
}
VOID
BlpArchSwitchContext (
IN EXECUTION_CONTEXT_TYPE Type
)
/*++
Routine Description:
Switches to an execution context of type Type.
Arguments:
Type - The requested context type.
Return Value:
None.
--*/
{
PEXECUTION_CONTEXT NewContext;
if (Type == ExecutionContextFirmware) {
NewContext = &FirmwareExecutionContext;
} else {
NewContext = &ApplicationExecutionContext;
}
if (CurrentExecutionContext->Type == NewContext->Type) {
return;
}
ArchSwitchContext(NewContext, CurrentExecutionContext);
CurrentExecutionContext = NewContext;
}
NTSTATUS
BlpArchInitialize (
IN ULONG Stage
)
/*++
Routine Description:
Internal routine to perform architecture-specific initialization.
Arguments:
Stage - 0.
Return Value:
STATUS_SUCCESS.
--*/
{
NTSTATUS Status;
if (Stage == 0) {
ApplicationExecutionContext.Type = ExecutionContextApplication;
FirmwareExecutionContext.Type = ExecutionContextFirmware;
CurrentExecutionContext = NULL;
//
// Initialize and use application context.
//
Status = ArchInitializeContext(&ApplicationExecutionContext);
if (NT_SUCCESS(Status)) {
CurrentExecutionContext = &ApplicationExecutionContext;
}
//
// Initialize firmware context if supported.
//
if (BlPlatformFlags & FIRMWARE_FLAG_EXECUTION_CONTEXT_SUPPORTED) {
Status = ArchInitializeContext(&FirmwareExecutionContext);
if (!NT_SUCCESS(Status)) {
// TODO: Implement ArchInitializeProcessorFeatures()?
// ArchInitializeProcessorFeatures();
return Status;
}
//
// Use firmware execution context if
// the application context is not
// supported.
//
if (CurrentExecutionContext == NULL) {
CurrentExecutionContext = &FirmwareExecutionContext;
}
}
//
// Switch to the correct context.
//
ArchSwitchContext(CurrentExecutionContext, NULL);
}
return STATUS_SUCCESS;
}

View File

@@ -0,0 +1,41 @@
.text
SetSegmentRegisters:
mov 0x18(%rcx), %ds
mov 0x1a(%rcx), %es
mov 0x1c(%rcx), %fs
mov 0x1e(%rcx), %gs
mov 0x20(%rcx), %ss
ret
.globl Archpx64EnableInterruptsAsm
Archpx64EnableInterruptsAsm:
sti
ret
.globl Archpx64DisableInterruptsAsm
Archpx64DisableInterruptsAsm:
cli
ret
.globl BlpArchGetDescriptorTableContext
BlpArchGetDescriptorTableContext:
sgdt 0x00(%rcx)
sidt 0x0a(%rcx)
sldt 0x14(%rcx)
mov %cs, 0x16(%rcx)
mov %ds, 0x18(%rcx)
mov %es, 0x1a(%rcx)
mov %fs, 0x1c(%rcx)
mov %gs, 0x1e(%rcx)
mov %ss, 0x20(%rcx)
ret
.globl ArchSetDescriptorTableContext
ArchSetDescriptorTableContext:
sgdt 0x00(%rcx)
sidt 0x0a(%rcx)
sldt 0x14(%rcx)
push 0x16(%rcx)
push $SetSegmentRegisters
lretq

View File

@@ -17,19 +17,22 @@ Abstract:
#include "bootlib.h" #include "bootlib.h"
#define MIN_INPUT_PARAMETERS_SIZE ( \ #define MIN_INPUT_PARAMETERS_SIZE ( \
sizeof(BOOT_INPUT_PARAMETERS) + \ sizeof(BOOT_APPLICATION_PARAMETERS) + \
sizeof(BOOT_MEMORY_INFO) + \ sizeof(BOOT_MEMORY_INFO) + \
sizeof(BOOT_INIT_APPLICATION_ENTRY) + \
sizeof(BOOT_FIRMWARE_DATA) + \ sizeof(BOOT_FIRMWARE_DATA) + \
sizeof(BOOT_RETURN_DATA) \ sizeof(BOOT_RETURN_DATA) \
) )
PBOOT_INPUT_PARAMETERS BlpApplicationParameters; ULONG BlPlatformFlags = 0x002a0000 | FIRMWARE_FLAG_EXECUTION_CONTEXT_SUPPORTED;
BOOT_APPLICATION_ENTRY BlpApplicationEntry;
PBOOT_DEVICE BlpBootDevice; PBOOT_DEVICE BlpBootDevice;
PBOOT_APPLICATION_PARAMETERS BlpApplicationParameters;
BOOT_LIBRARY_PARAMETERS BlpLibraryParameters;
BOOT_APPLICATION_ENTRY BlpApplicationEntry;
NTSTATUS NTSTATUS
InitializeLibrary ( InitializeLibrary (
IN PBOOT_INPUT_PARAMETERS InputParameters, IN PBOOT_APPLICATION_PARAMETERS ApplicationParameters,
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
) )
@@ -41,7 +44,7 @@ Routine Description:
Arguments: Arguments:
InputParameters - Pointer to the application's input parameters. ApplicationParameters - Pointer to the application's input parameters.
LibraryParameters - Pointer to the library parameters. LibraryParameters - Pointer to the library parameters.
@@ -54,23 +57,19 @@ Return Value:
{ {
NTSTATUS Status; NTSTATUS Status;
PBOOT_MEMORY_INFO MemoryInfo; PBOOT_MEMORY_INFO MemoryInfo;
PBOOT_INPUT_APPLICATION_ENTRY ApplicationEntry; PBOOT_INIT_APPLICATION_ENTRY ApplicationEntry;
PBOOT_FIRMWARE_DATA FirmwareData; PBOOT_FIRMWARE_DATA FirmwareData;
PBOOT_BLOCK_IDENTIFIER BlockDevice;
PBOOT_APPLICATION_OPTION Option;
(VOID)LibraryParameters; if (ApplicationParameters == NULL ||
ApplicationParameters->Signature != BOOT_APPLICATION_PARAMETERS_SIGNATURE ||
if (InputParameters == NULL || ApplicationParameters->Size < MIN_INPUT_PARAMETERS_SIZE) {
InputParameters->Signature != BOOT_INPUT_PARAMETERS_SIGNATURE ||
InputParameters->Size < MIN_INPUT_PARAMETERS_SIZE) {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
MemoryInfo = (PBOOT_MEMORY_INFO)((PUCHAR)InputParameters + InputParameters->MemoryInfoOffset); MemoryInfo = (PBOOT_MEMORY_INFO)((PUCHAR)ApplicationParameters + ApplicationParameters->MemoryInfoOffset);
ApplicationEntry = (PBOOT_INPUT_APPLICATION_ENTRY)((PUCHAR)InputParameters + InputParameters->ApplicationEntryOffset); ApplicationEntry = (PBOOT_INIT_APPLICATION_ENTRY)((PUCHAR)ApplicationParameters + ApplicationParameters->ApplicationEntryOffset);
BlpBootDevice = (PBOOT_DEVICE)((PUCHAR)InputParameters + InputParameters->BootDeviceOffset); BlpBootDevice = (PBOOT_DEVICE)((PUCHAR)ApplicationParameters + ApplicationParameters->BootDeviceOffset);
FirmwareData = (PBOOT_FIRMWARE_DATA)((PUCHAR)InputParameters + InputParameters->FirmwareDataOffset); FirmwareData = (PBOOT_FIRMWARE_DATA)((PUCHAR)ApplicationParameters + ApplicationParameters->FirmwareDataOffset);
// //
// Initialize firmware library. // Initialize firmware library.
@@ -79,95 +78,60 @@ Return Value:
// //
Status = BlpFwInitialize(0, FirmwareData); Status = BlpFwInitialize(0, FirmwareData);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
return Status; goto Stage0Failed;
} }
ConsolePrint(L"> Alcyone EFI Boot Manager\r\n"); ConsolePrint(L"> Alcyone EFI Boot Manager\r\n");
ConsolePrintf(L"Image base: %x %x\r\nImage size: %x\r\n", HIDWORD((ULONG_PTR)InputParameters->ImageBase), LODWORD((ULONG_PTR)InputParameters->ImageBase), InputParameters->ImageSize); ConsolePrintf(L"Image base: %x %x\r\nImage size: %x\r\n", HIDWORD((ULONG_PTR)ApplicationParameters->ImageBase), LODWORD((ULONG_PTR)ApplicationParameters->ImageBase), ApplicationParameters->ImageSize);
DebugPrint(L"Initializing boot library...\r\n"); if (ApplicationEntry->Signature != BOOT_INIT_APPLICATION_ENTRY_SIGNATURE) {
if (ApplicationEntry->Signature != BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE) {
DebugPrint(L"InitializeLibrary(): ApplicationEntry Signature is invalid\r\n"); DebugPrint(L"InitializeLibrary(): ApplicationEntry Signature is invalid\r\n");
return STATUS_INVALID_PARAMETER_9; Status = STATUS_INVALID_PARAMETER_9;
goto Stage0Failed;
} }
// //
// Save input parameters and application entry. // Save library and application parameters.
//
BlpApplicationParameters = ApplicationParameters;
RtlCopyMemory(&BlpLibraryParameters, LibraryParameters, sizeof(BOOT_LIBRARY_PARAMETERS));
//
// Save application entry.
// //
BlpApplicationParameters = InputParameters;
BlpApplicationEntry.Attributes = ApplicationEntry->Attributes; BlpApplicationEntry.Attributes = ApplicationEntry->Attributes;
RtlCopyMemory(&BlpApplicationEntry.BcdIdentifier, &ApplicationEntry->BcdIdentifier, sizeof(GUID)); RtlCopyMemory(&BlpApplicationEntry.BcdIdentifier, &ApplicationEntry->BcdIdentifier, sizeof(GUID));
BlpApplicationEntry.Options = &ApplicationEntry->Options; BlpApplicationEntry.Options = &ApplicationEntry->Options;
Status = BlpMmInitialize(MemoryInfo, InputParameters->TranslationType, LibraryParameters); Status = BlpArchInitialize(0);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
return Status; goto Stage0Failed;
} }
// Status = BlpMmInitialize(MemoryInfo, ApplicationParameters->TranslationType, LibraryParameters);
// Print debug information. if (!NT_SUCCESS(Status)) {
// TODO: Remove this once the project is more stable? goto Stage0Failed;
//
#ifdef _DEBUG
DebugPrint(L"Boot device type: ");
switch (BlpBootDevice->Type) {
case BOOT_DEVICE_TYPE_PARTITION:
DebugPrint(L"partition\r\n");
BlockDevice = &BlpBootDevice->Partition.Parent;
break;
case BOOT_DEVICE_TYPE_PARTITION_EX:
DebugPrint(L"partition\r\n");
BlockDevice = &BlpBootDevice->PartitionEx.Parent;
break;
default:
DebugPrint(L"generic block device\r\n");
BlockDevice = &BlpBootDevice->Block;
break;
} }
DebugPrint(L"Boot device parent type: "); Status = BlpFwInitialize(1, FirmwareData);
switch (BlockDevice->Type) { if (!NT_SUCCESS(Status)) {
case BOOT_BLOCK_DEVICE_TYPE_HARDDRIVE: goto Stage1Failed;
DebugPrint(L"hard drive\r\n");
break;
case BOOT_BLOCK_DEVICE_TYPE_CDROM:
DebugPrint(L"CD-ROM\r\n");
break;
case BOOT_BLOCK_DEVICE_TYPE_RAMDISK:
DebugPrint(L"RAM disk\r\n");
break;
default:
DebugPrint(L"generic block device\r\n");
break;
} }
Option = &ApplicationEntry->Options; Status = BlpArchInitialize(1);
for (ULONG Index = 0; !Option->IsInvalid; Index++) { if (!NT_SUCCESS(Status)) {
DebugPrintf(L"Boot entry option %x: ", Index); goto Stage1Failed;
if (Option->Type == BCDE_DATA_TYPE_APPLICATION_PATH) {
DebugPrint(L"application path \"");
DebugPrint((PWSTR)((PUCHAR)Option + Option->DataOffset));
DebugPrint(L"\"\r\n");
} else {
DebugPrintf(L"type %x, data size %x\r\n", Option->Type, Option->DataSize);
} }
if (Option->NextOptionOffset == 0) { Stage1Failed:
break; BlpMmDestroy(1);
} Stage0Failed:
Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)Option + Option->NextOptionOffset);
}
#endif
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
BlInitializeLibrary ( BlInitializeLibrary (
IN PBOOT_INPUT_PARAMETERS InputParameters, IN PBOOT_APPLICATION_PARAMETERS ApplicationParameters,
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
) )
@@ -179,7 +143,7 @@ Routine Description:
Arguments: Arguments:
InputParameters - Pointer to the application's input parameters. ApplicationParameters - Pointer to the application's input parameters.
LibraryParameters - Pointer to the library parameters. LibraryParameters - Pointer to the library parameters.
@@ -190,7 +154,7 @@ Return Value:
--*/ --*/
{ {
return InitializeLibrary(InputParameters, LibraryParameters); return InitializeLibrary(ApplicationParameters, LibraryParameters);
} }
NTSTATUS NTSTATUS
@@ -210,10 +174,25 @@ Arguments:
Return Value: Return Value:
STATUS_SUCCESS. STATUS_SUCCESS if successful.
Error code on failure.
--*/ --*/
{ {
return STATUS_SUCCESS; NTSTATUS Status, ExitStatus;
ExitStatus = STATUS_SUCCESS;
Status = BlpMmDestroy(0);
if (!NT_SUCCESS(Status)) {
ExitStatus = Status;
}
Status = BlpMmDestroy(1);
if (!NT_SUCCESS(Status)) {
ExitStatus = Status;
}
return ExitStatus;
} }

View File

@@ -17,7 +17,7 @@ Abstract:
ULONG ULONG
BlGetBootOptionSize ( BlGetBootOptionSize (
IN PBOOT_APPLICATION_OPTION Option IN PBOOT_ENTRY_OPTION Option
) )
/*++ /*++
@@ -42,11 +42,11 @@ Return Value:
if (Option->DataOffset != 0) { if (Option->DataOffset != 0) {
TotalSize = Option->DataOffset + Option->DataSize; TotalSize = Option->DataOffset + Option->DataSize;
} else { } else {
TotalSize = sizeof(BOOT_APPLICATION_OPTION); TotalSize = sizeof(BOOT_ENTRY_OPTION);
} }
if (Option->OtherOptionsOffset != 0) { if (Option->OtherOptionsOffset != 0) {
TotalSize += BlGetBootOptionListSize((PBOOT_APPLICATION_OPTION)((PUCHAR)Option + Option->OtherOptionsOffset)); TotalSize += BlGetBootOptionListSize((PBOOT_ENTRY_OPTION)((PUCHAR)Option + Option->OtherOptionsOffset));
} }
return TotalSize; return TotalSize;
@@ -54,7 +54,7 @@ Return Value:
ULONG ULONG
BlGetBootOptionListSize ( BlGetBootOptionListSize (
IN PBOOT_APPLICATION_OPTION Options IN PBOOT_ENTRY_OPTION Options
) )
/*++ /*++
@@ -75,12 +75,12 @@ Return Value:
{ {
ULONG TotalSize, NextOffset; ULONG TotalSize, NextOffset;
PBOOT_APPLICATION_OPTION Option; PBOOT_ENTRY_OPTION Option;
TotalSize = 0; TotalSize = 0;
NextOffset = 0; NextOffset = 0;
do { do {
Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)Options + NextOffset); Option = (PBOOT_ENTRY_OPTION)((PUCHAR)Options + NextOffset);
NextOffset = Option->NextOptionOffset; NextOffset = Option->NextOptionOffset;
TotalSize += BlGetBootOptionSize(Option); TotalSize += BlGetBootOptionSize(Option);
} while (NextOffset != 0); } while (NextOffset != 0);

View File

@@ -5,14 +5,16 @@
| File | Public Routines | | File | Public Routines |
|-|-| |-|-|
| APP/BOOTMGR/EFI/efientry.c | EfiMain() | | APP/BOOTMGR/EFI/efientry.c | EfiMain() |
| APP/BOOTMGR/bootmgr.c | BmMain() |
| APP/BOOTMGR/bcd.c | BmXXDataStore() | | APP/BOOTMGR/bcd.c | BmXXDataStore() |
| LIB/EFI/efifw.c | BlpFwXX() | | APP/BOOTMGR/bootmgr.c | BmMain() |
| LIB/EFI/efimm.c | MmFwXX() |
| LIB/EFI/efiinit.c | EfiInitXX() |
| LIB/EFI/eficon.c | ConsoleXX() | | LIB/EFI/eficon.c | ConsoleXX() |
| LIB/EFI/efilib.c | EfiGetEfiStatusCode() | | LIB/EFI/efifw.c | BlpFwXX() |
| LIB/EFI/efiinit.c | EfiInitXX() |
| LIB/EFI/efilib.c | EfiGetXXStatusCode() |
| LIB/EFI/efimm.c | MmFwXX() |
| LIB/MM/mm.c | BlpMmXX() | | LIB/MM/mm.c | BlpMmXX() |
| LIB/MM/mmmd.c | MmMdXX() |
| LIB/MM/mmpa.c | MmPaXX() | | LIB/MM/mmpa.c | MmPaXX() |
| LIB/bootlib.c | BlXXLibrary() | | LIB/bootlib.c | BlXXLibrary() |
| LIB/bootopt.c | BlXXBootOptionXX() | | LIB/bootopt.c | BlXXBootOptionXX() |
| LIB/XX/arch.c | BlpArchXX() |

View File

@@ -105,6 +105,31 @@ private:
KIRQL m_OldIrql; KIRQL m_OldIrql;
}; };
class QueuedSpinlockAtDPC {
public:
// Constructor to acquire the lock
explicit QueuedSpinlockAtDPC(KSPIN_LOCK_QUEUE_NUMBER lockNumber)
: m_lockNumber(lockNumber) {
// Acquire the lock at DPC level
m_lockHandle = KeAcquireQueuedSpinLockAtDpcLevel(&KeGetCurrentPrcb()->LockQueue[m_lockNumber]);
}
// Destructor to release the lock automatically
~QueuedSpinlockAtDPC() {
// Release the lock at DPC level
KeReleaseQueuedSpinLockFromDpcLevel(&KeGetCurrentPrcb()->LockQueue[m_lockNumber], m_lockHandle);
}
// Deleting copy and move constructors to prevent unintended copying
QueuedSpinlockAtDPC(const QueuedSpinlockAtDPC&) = delete;
QueuedSpinlockAtDPC& operator=(const QueuedSpinlockAtDPC&) = delete;
private:
KSPIN_LOCK_QUEUE_NUMBER m_lockNumber; // Spinlock queue number
KIRQL m_lockHandle; // Lock handle returned by KeAcquireQueuedSpinLockAtDpcLevel
};
template <typename T> template <typename T>
class Array { class Array {
public: public:

486
NTOSKRNL/CC/ccutil.cpp Normal file
View File

@@ -0,0 +1,486 @@
/*
* PROJECT: Alcyone System Kernel
* LICENSE: BSD Clause 3
* PURPOSE: Cache Controllerm, Cache Utility Handler.
* NT KERNEL: 5.11.9360
* COPYRIGHT: 2023-2029 Dibymartanda Samanta <>
*/
constexpr ULONG LastpageLimit = {0x200};
constexpr LONGLONG BASE_PAGE_INITIALIZER = {-1};
constexpr ULONG DIRTY_PAGE_INITIALIZER = {-1};
constexpr ULONG DIRTY_PAGE_INIT = {0};
class BitmapRangeManager {
private:
static constexpr LONGLONG CalculateBasePage(LONGLONG InputPage) {
return (InputPage & ~(0x1000 - 1));
}
public:
static PBITMAP_RANGE FindBitmapRangeToDirty(PMBCB Mbcb, LONGLONG InputPage, PULONG* pBitmap) {
PBITMAP_RANGE CurrentRange = nullptr;
PBITMAP_RANGE NewRange = nullptr;
PLIST_ENTRY HeadList = nullptr;
LONGLONG BasePage = {0};
HeadList = &Mbcb->BitmapRanges;
BasePage = CalculateBasePage(InputPage);
CurrentRange = CONTAINING_RECORD(Mbcb->BitmapRanges.Flink, BITMAP_RANGE, Links);
while(true){
if (BasePage == CurrentRange->BasePage)
return CurrentRange;
if (CurrentRange->DirtyPages || NewRange) {
if (BasePage > CurrentRange->BasePage)
HeadList = &CurrentRange->Links;
}
else {
NewRange = CurrentRange;
}
if (CurrentRange->Links.Flink == &Mbcb->BitmapRanges)
break;
CurrentRange = CONTAINING_RECORD(CurrentRange->Links.Flink, BITMAP_RANGE, Links);
if (CurrentRange->BasePage > BasePage && NewRange)
break;
}
if (NewRange) {
RemoveEntryList(&NewRange->Links);
}
else {
NewRange = reinterpret_cast<PBITMAP_RANGE>(ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewRange), 'rBcC'));
if (!NewRange) {
return nullptr;
}
RtlZeroMemory(NewRange, sizeof(*NewRange));
}
InsertHeadList(HeadList, &NewRange->Links);
NewRange->BasePage = BasePage;
NewRange->FirstDirtyPage = DIRTY_PAGE_INITIALIZER;
NewRange->LastDirtyPage = 0;
if (!NewRange->Bitmap) {
NewRange->Bitmap = *pBitmap;
*pBitmap = nullptr;
}
return NewRange;
}
};
/* Internal Functions */
LONG
CcCopyReadExceptionFilter(
_In_ PEXCEPTION_POINTERS ExceptionInfo,
_Out_ NTSTATUS* OutStatus)
{
NT_ASSERT(!NT_SUCCESS(*OutStatus));
return EXCEPTION_EXECUTE_HANDLER;
}
PBITMAP_RANGE
NTAPI
CcFindBitmapRangeToDirty(
_In_ PMBCB Mbcb,
_In_ LONGLONG InputPage,
_Inout_ PULONG* PBITMAP)
{
return BitmapRangeManager::FindBitmapRangeToDirty(Mbcb, InputPage, pBitmap);
}
VOID
NTAPI
CcSetDirtyInMask(
_In_ PSHARED_CACHE_MAP SharedCacheMap,
_In_ PLARGE_INTEGER FileOffset,
_In_ ULONG Length)
{
KLOCK_QUEUE_HANDLE LockHandle = {0};
LARGE_INTEGER EndOffset = {0};
ULONGLONG StartPage ={0};
ULONGLONG EndPage = {0};
ULONG CurrentPage = {0};
PMBCB Mbcb = nullptr;
PBITMAP_RANGE BitmapRange = nullptr;
PULONG Bitmap = nullptr;
PULONG VacbLevel = nullptr;
ULONG BitMask = {0};
// Calculate start and end pages
StartPage = FileOffset->QuadPart >> PAGE_SHIFT;
EndOffset.QuadPart = FileOffset->QuadPart + Length;
EndPage = (EndOffset.QuadPart - 1) >> PAGE_SHIFT;
for(;;)
{
if (SharedCacheMap->SectionSize.QuadPart > VACB_MAPPING_GRANULARITY)
{
if (!CcPrefillVacbLevelZone(1, &LockHandle, 0, 0, 0))
return;
VacbLevel = CcAllocateVacbLevel(0);
KeLowerIrql(LockHandle.OldIrql);
}
KeAcquireInStackQueuedSpinLock(&SharedCacheMap->BcbSpinLock, &LockHandle);
Mbcb = SharedCacheMap->Mbcb;
if (Mbcb == nullptr)
{
Mbcb = CcAllocateInitializeBcb();
if (Mbcb == nullptr)
goto ReleaseAndExit;
Mbcb->NodeTypeCode = CACHE_NTC_BCB;
InitializeListHead(&Mbcb->BitmapRanges);
InsertHeadList(&Mbcb->BitmapRanges, &Mbcb->BitmapRange1.Links);
Mbcb->BitmapRange1.FirstDirtyPage = (ULONG)-1;
Mbcb->BitmapRange1.Bitmap = (PULONG)&Mbcb->BitmapRange2;
SharedCacheMap->Mbcb = Mbcb;
}
if (EndPage < 512 || Mbcb->NodeTypeCode == 0x02F9)
{
BitmapRange = CcFindBitmapRangeToDirty(Mbcb, StartPage, &Bitmap);
if (BitmapRange == nullptr)
break;
if (StartPage < BitmapRange->BasePage + BitmapRange->FirstDirtyPage)
BitmapRange->FirstDirtyPage = StartPage - BitmapRange->BasePage;
if (EndPage > BitmapRange->BasePage + BitmapRange->LastDirtyPage)
BitmapRange->LastDirtyPage = EndPage - BitmapRange->BasePage;
if (SharedCacheMap->DirtyPages == 0)
{
CcScheduleLazyWriteScan(FALSE);
RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
InsertTailList(&CcDirtySharedCacheMapList, &SharedCacheMap->SharedCacheMapLinks);
Mbcb->ResumeWritePage = StartPage;
}
Bitmap = &BitmapRange->Bitmap[(StartPage - BitmapRange->BasePage) >> 5];
BitMask = 1 << (StartPage & 0x1F);
for (CurrentPage = StartPage; CurrentPage <= EndPage; CurrentPage++)
{
if ((*Bitmap & BitMask) == 0)
{
CcTotalDirtyPages++;
Mbcb->DirtyPages++;
BitmapRange->DirtyPages++;
SharedCacheMap->DirtyPages++;
*Bitmap |= BitMask;
}
BitMask <<= 1;
if (BitMask == 0)
{
Bitmap++;
BitMask = 1;
}
}
}
else
{
// Handle large files (>2MB)
if (Mbcb->BitmapRange1.DirtyPages)
{
RtlCopyMemory(VacbLevel, Mbcb->BitmapRange1.Bitmap, (2 * sizeof(BITMAP_RANGE)));
RtlZeroMemory(Mbcb->BitmapRange1.Bitmap, (2 * sizeof(BITMAP_RANGE)));
}
Mbcb->BitmapRange1.Bitmap = VacbLevel;
// Initialize BitmapRange2
InsertTailList(&Mbcb->BitmapRanges, &Mbcb->BitmapRange2.Links);
Mbcb->BitmapRange2.BasePage = BASE_PAGE_INITIALIZER;
Mbcb->BitmapRange2.FirstDirtyPage = DIRTY_PAGE_INITIALIZER;
// Initialize BitmapRange3
InsertTailList(&Mbcb->BitmapRanges, &Mbcb->BitmapRange3.Links);
Mbcb->BitmapRange3.BasePage = BASE_PAGE_INITIALIZER;
Mbcb->BitmapRange3.FirstDirtyPage = DIRTY_PAGE_INITIALIZER;
VacbLevel = nullptr;
Mbcb->NodeTypeCode = 0x02F9;
KeReleaseInStackQueuedSpinLock(&LockHandle);
continue;
}
// Update ValidDataGoal if necessary
if (EndOffset.QuadPart > SharedCacheMap->ValidDataGoal.QuadPart)
{
SharedCacheMap->ValidDataGoal = EndOffset;
}
break;
}
ReleaseAndExit:
if (VacbLevel != nullptr)
{
*VacbLevel = (ULONG)CcVacbLevelFreeList;
CcVacbLevelEntries++;
CcVacbLevelFreeList = VacbLevel;
}
KeReleaseInStackQueuedSpinLock(&LockHandle);
}
BOOLEAN
NTAPI
CcMapAndCopy(
_In_ PSHARED_CACHE_MAP SharedCacheMap,
_In_ PVOID Buffer,
_In_ PLARGE_INTEGER FileOffset,
_In_ ULONG Length,
_In_ ULONG Flags,
_In_ PFILE_OBJECT FileObject,
_In_ PLARGE_INTEGER ValidDataLength,
_In_ BOOLEAN Wait)
{
NT_DBGBREAK("UNIMPLEMENTED\n");
}
/* EXTERNAL API FUNCTIONS */
BOOLEAN
NTAPI
CcCanIWrite(
_In_ PFILE_OBJECT FileObject,
_In_ ULONG BytesToWrite,
_In_ BOOLEAN Wait,
_In_ UCHAR Retrying)
{
PFSRTL_COMMON_FCB_HEADER FsContext = nullptr;
PSHARED_CACHE_MAP SharedCacheMap = nullptr;
DEFERRED_WRITE DeferredWrite = {0};
KEVENT Event = {0};
ULONG WriteSize = {0};
ULONG Pages = {0};
KIRQL OldIrql = {0};
BOOLEAN IsSmallThreshold = false;
/* Quick checks for immediate return */
if (FileObject->Flags & FO_WRITE_THROUGH)
return true;
if (IoIsFileOriginRemote(FileObject) && Retrying < 0xFD)
return true;
/* Calculate size and pages */
WriteSize = min(BytesToWrite, 0x40000);
Pages = ROUND_UP(WriteSize, PAGE_SIZE) / PAGE_SIZE;
FsContext = FileObject->FsContext;
/* Check threshold conditions */
if (Retrying >= 0xFE || (FsContext->Flags & FSRTL_FLAG_LIMIT_MODIFIED_PAGES))
{
if (Retrying != 0xFF)
{
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
}
if (FileObject->SectionObjectPointer)
{
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
if (SharedCacheMap &&
SharedCacheMap->DirtyPageThreshold &&
SharedCacheMap->DirtyPages)
{
if (SharedCacheMap->DirtyPageThreshold < (SharedCacheMap->DirtyPages + Pages))
{
IsSmallThreshold = true;
}
}
}
if (Retrying != 0xFF)
{
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
}
}
/* Check if we can write immediately */
if ((Retrying || IsListEmpty(&CcDeferredWrites)) &&
(CcDirtyPageThreshold > (CcTotalDirtyPages + Pages)))
{
if ((MmAvailablePages > MmThrottleTop && !IsSmallThreshold) ||
(MmModifiedPageListHead.Total < 1000 &&
MmAvailablePages > MmThrottleBottom &&
!IsSmallThreshold))
{
return true;
}
}
if (!Wait)
return FALSE;
/* Initialize deferred write */
if (IsListEmpty(&CcDeferredWrites))
{
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
CcScheduleLazyWriteScan(TRUE);
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
}
KeInitializeEvent(&Event, NotificationEvent, false);
DeferredWrite.NodeTypeCode = NODE_TYPE_DEFERRED_WRITE;
DeferredWrite.NodeByteSize = sizeof(DEFERRED_WRITE);
DeferredWrite.FileObject = FileObject;
DeferredWrite.BytesToWrite = BytesToWrite;
DeferredWrite.Event = &Event;
DeferredWrite.LimitModifiedPages = (FsContext->Flags & FSRTL_FLAG_LIMIT_MODIFIED_PAGES) != 0;
/* Insert into deferred writes list */
/* Insert into deferred writes list */
if (Retrying)
{
ExInterlockedInsertHeadList(&CcDeferredWrites,
&DeferredWrite.DeferredWriteLinks,
&CcDeferredWriteSpinLock);
}
else
{
ExInterlockedInsertTailList(&CcDeferredWrites,
&DeferredWrite.DeferredWriteLinks,
&CcDeferredWriteSpinLock);
}
/* Wait for the write to complete */
do
{
CcPostDeferredWrites();
} while (KeWaitForSingleObject(&Event,
Executive,
KernelMode,
false,
&CcIdleDelay) != STATUS_SUCCESS);
return TRUE;
}
BOOLEAN
NTAPI
CcCopyRead(
_In_ PFILE_OBJECT FileObject,
_In_ PLARGE_INTEGER FileOffset,
_In_ ULONG Length,
_In_ BOOLEAN Wait,
_Out_ PVOID Buffer,
_Out_ IO_STATUS_BLOCK* OutIoStatus)
{
NT_DBGBREAK("UNIMPLEMENTED\n");
}
BOOLEAN
NTAPI
CcCopyWrite(
_In_ PFILE_OBJECT FileObject,
_In_ PLARGE_INTEGER FileOffset,
_In_ ULONG Length,
_In_ BOOLEAN Wait,
_In_ PVOID Buffer)
{
NT_DBGBREAK("UNIMPLEMENTED\n");
}
VOID
CcDeferWrite(
_In_ PFILE_OBJECT FileObject,
_In_ PCC_POST_DEFERRED_WRITE PostRoutine,
_In_ PVOID Context1,
_In_ PVOID Context2,
_In_ ULONG BytesToWrite,
_In_ BOOLEAN Retrying
)
{
KIRQL OldIrql;
PDEFERRED_WRITE DeferredWrite = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(DEFERRED_WRITE), 'wDcC');
if (DeferredWrite != nullptr)
{
RtlZeroMemory(DeferredWrite, sizeof(DEFERRED_WRITE));
DeferredWrite->NodeTypeCode = NODE_TYPE_DEFERRED_WRITE;
DeferredWrite->NodeByteSize = sizeof(DEFERRED_WRITE);
DeferredWrite->FileObject = FileObject;
DeferredWrite->BytesToWrite = BytesToWrite;
DeferredWrite->PostRoutine = PostRoutine;
DeferredWrite->Context1 = Context1;
DeferredWrite->Context2 = Context2;
if (Retrying)
ExInterlockedInsertHeadList(&CcDeferredWrites,
&DeferredWrite->DeferredWriteLinks,
&CcDeferredWriteSpinLock);
else
ExInterlockedInsertTailList(&CcDeferredWrites,
&DeferredWrite->DeferredWriteLinks,
&CcDeferredWriteSpinLock);
CcPostDeferredWrites();
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
CcScheduleLazyWriteScan(TRUE);
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
}
else
{
PostRoutine(Context1, Context2);
}
}
VOID
NTAPI
CcFastCopyRead(
_In_ PFILE_OBJECT FileObject,
_In_ ULONG FileOffset,
_In_ ULONG Length,
_In_ ULONG PageCount,
_Out_ PVOID Buffer,
_Out_ PIO_STATUS_BLOCK IoStatus)
{
NT_DBGBREAK("UNIMPLEMENTED\n");
}
VOID
NTAPI
CcFastCopyWrite(
_In_ PFILE_OBJECT FileObject,
_In_ ULONG FileOffset,
_In_ ULONG Length,
_In_ PVOID InBuffer)
{
NT_DBGBREAK("UNIMPLEMENTED\n");
}

View File

@@ -3,127 +3,110 @@
* LICENSE: BSD Clause 3 * LICENSE: BSD Clause 3
* PURPOSE: Mutexes * PURPOSE: Mutexes
* NT KERNEL: 5.11.9360 * NT KERNEL: 5.11.9360
* COPYRIGHT: 2023-2029 Dibymartanda Samanta <> * COPYRIGHT: 2023-2029 Dibymartanda Samanta <dibya.samanta@neverseen.de>
*/ */
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NTDEBUG #define NTDEBUG
extern "C" extern "C"
/*Mutex Count :
0 => Can Be aquired,
1 => Is Aquired by a Thread
In Negative Indigates, Number of Threads waiting*/
constexpr ULONG MUTEX_READY_TO_BE_AQUIRED = 0; /*Mutex Count :
0 => Can Be acquired,
1 => Is Acquired by a Thread
In Negative Indicates, Number of Threads waiting*/
constexpr ULONG MUTEX_READY_TO_BE_ACQUIRED = 0;
/*Internal Function*/ /*Internal Function*/
/* Fast Mutex definitions */ // Fast Mutex definitions
#define FM_LOCK_BIT 0x1 #define FM_LOCK_BIT 0x1
#define FM_LOCK_BIT_V 0x0
#define FM_LOCK_WAITER_WOKEN 0x2 #define FM_LOCK_WAITER_WOKEN 0x2
#define FM_LOCK_WAITER_INC 0x4 #define FM_LOCK_WAITER_INC 0x4
#define FM_RECURSIVE_BIT 0x8
typedef struct _FAST_MUTEX typedef struct _FAST_MUTEX {
{ LONG Count; // 0x0: 0 = free, 1 = owned, negative = waiters
LONG Count; //0x0 PVOID Owner; // 0x4: Owning thread
VOID* Owner; //0x4 ULONG Contention; // 0x8: Contention count
ULONG Contention; //0x8 KEVENT Event; // 0xC: Wait event
struct _KEVENT Event; //0xc ULONG OldIrql; // 0x1C: Saved IRQL
ULONG OldIrql; //0x1c LONG RecursionDepth; // 0x20: For recursive mutexes
} FAST_MUTEX, *PFAST_MUTEX; //0x20 bytes (sizeof) } FAST_MUTEX, *PFAST_MUTEX; // 0x24 bytes (sizeof)
typedef PFAST_MUTEX PKGUARDED_MUTEX; typedef PFAST_MUTEX PKGUARDED_MUTEX;
/*Internal Functio*/ /*Internal Function*/
VOID VOID
FASTCALL FASTCALL
KiAcquireFastMutex( KiAcquireFastMutex(
_Inout_ PFAST_MUTEX Mutex _Inout_ PFAST_MUTEX Mutex
) )
{ {
LONG AcquireMarker = {0}; LONG OldCount;
LONG AcquireBit = {0}; LONG NewCount;
LONG OldCount = {0};
PAGED_CODE(); PAGED_CODE();
/* Increment contention count */ /* Increment contention count */
InterlockedIncrement(&Mutex->Contention); InterlockedIncrement(&Mutex->Contention);
/* Initialize loop variables */ while (TRUE)
AcquireMarker = 4;
AcquireBit = 1;
while(true)
{ {
/* Read current count */ /* Read current count */
OldCount = ReadForWriteAccess(&Mutex->Count); OldCount = ReadForWriteAccess(&Mutex->Count);
/* Check if mutex is free */ /* Check if mutex is free (count == 0) */
if ((OldCount & 1) == 0) if (OldCount == 0)
{ {
/* Attempt to acquire by incrementing count */ /* Attempt to acquire by setting count to 1 */
if (InterlockedCompareExchange(&Mutex->Count, OldCount + AcquireMarker,OldCount) == OldCount) if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0)
{
/* Wait for the mutex event */
KeWaitForSingleObject(&Mutex->Event,WrFastMutex,KernelMode,false,0);
AcquireMarker = 2;
AcquireBit = 3;
continue;
}
}
else
{
/* Attempt to mark mutex as owned */
if (InterlockedCompareExchange(&Mutex->Count, AcquireBit ^ OldCount,OldCount) == OldCount)
{ {
/* Mutex acquired successfully */ /* Mutex acquired successfully */
break; break;
} }
} }
else
{
/* Mutex is owned, increment waiter count (make it more negative) */
NewCount = OldCount - 1;
if (InterlockedCompareExchange(&Mutex->Count, NewCount, OldCount) == OldCount)
{
/* Wait for the mutex event */
KeWaitForSingleObject(&Mutex->Event, WrFastMutex, KernelMode, FALSE, NULL);
/* Continue loop to try acquiring again */
}
}
} }
} }
VOID
FASTCALL FASTCALL
KeReleaseFastMutexContended( KeReleaseFastMutexContended(
IN PFAST_MUTEX FastMutex, IN PFAST_MUTEX FastMutex,
IN LONG OldValue) IN LONG OldValue)
{ {
BOOLEAN WakeWaiter = false; LONG NewValue;
LONG NewValue = {0};
PKTHREAD WokenThread = nullptr;
KPRIORITY HandoffPriority = {0};
/* Loop until we successfully update the mutex state */ /* If there are waiters (negative count), wake one up */
for (;;) if (OldValue < 0)
{ {
WakeWaiter = false; /* Increment count (reduce number of waiters) but keep it owned */
NewValue = OldValue + FM_LOCK_BIT; NewValue = OldValue + 1;
if (NewValue == 0)
if (!(OldValue & FM_LOCK_WAITER_WOKEN))
{ {
NewValue = OldValue - FM_LOCK_BIT; /* No more waiters, mutex becomes free */
WakeWaiter = true; NewValue = 0;
} }
LONG PreviousValue = InterlockedCompareExchange(&FastMutex->Lock, NewValue, OldValue); if (InterlockedCompareExchange(&FastMutex->Count, NewValue, OldValue) == OldValue)
if (PreviousValue == OldValue)
break;
OldValue = PreviousValue;
}
if (WakeWaiter)
{ {
/* Wake up a waiter */ /* Wake up a waiter */
KeSetEventBoostPriority(&FastMutex->Event); KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE);
}
} }
} }
/* Exported Function */ /* Exported Function */
@@ -133,14 +116,14 @@ KeInitializeFastMutex(
_Out_ PFAST_MUTEX Mutex _Out_ PFAST_MUTEX Mutex
) )
{ {
/* Initialize the mutex structure */ /* Initialize the mutex structure */
RtlZeroMemory(Mutex, sizeof(FAST_MUTEX)); RtlZeroMemory(Mutex, sizeof(FAST_MUTEX));
/* Set initial values */ /* Set initial values - 0 means free/available */
Mutex->Owner = nullptr; Mutex->Owner = NULL;
Mutex->Contention = 0; Mutex->Contention = 0;
Mutex->Count = 1; Mutex->Count = 0; // 0 = free
Mutex->RecursionDepth = 0;
/* Initialize the Mutex Gate */ /* Initialize the Mutex Gate */
KeInitializeEvent(&Mutex->Event, SynchronizationEvent, FALSE); KeInitializeEvent(&Mutex->Event, SynchronizationEvent, FALSE);
@@ -151,23 +134,25 @@ VECTORCALL
KeTryToAcquireFastMutex( KeTryToAcquireFastMutex(
_Inout_ PFAST_MUTEX Mutex) _Inout_ PFAST_MUTEX Mutex)
{ {
KIRQL CurrentIrql = KeGetCurrentIrql(); KIRQL OldIrql;
BOOLEAN Result = false;
if(_InterlockedBitTestAndReset(&FastMutex->Count, MUTEX_READY_TO_BE_AQUIRED)) /* Raise IRQL to APC_LEVEL */
OldIrql = KeRaiseIrqlToSynchLevel();
/* Try to acquire the mutex atomically */
if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0)
{ {
FastMutex->Owner = (PVOID)KeGetCurrentThread(); /* Successfully acquired */
Mutex->OldIrql = KeRaiseIrql(APC_LEVEL); Mutex->Owner = (PVOID)KeGetCurrentThread();
Result = TRUE; Mutex->OldIrql = OldIrql;
return TRUE;
} }
else else
{ {
/* Failed to acquire the mutex */ /* Failed to acquire the mutex */
KeLowerIrql(CurrentIrql); KeLowerIrql(OldIrql);
KeYieldProcessor(); return FALSE;
Result = FALSE;
} }
return Result;
} }
VOID VOID
@@ -175,24 +160,21 @@ NTAPI
KeEnterCriticalRegionAndAcquireFastMutexUnsafe( KeEnterCriticalRegionAndAcquireFastMutexUnsafe(
_In_ PFAST_MUTEX FastMutex) _In_ PFAST_MUTEX FastMutex)
{ {
PKTHREAD OwnerThread = nullptr; PKTHREAD OwnerThread;
KeEnterCriticalRegion(); KeEnterCriticalRegion();
/* Get the current thread again (following the pseudocode) */ /* Get the current thread */
OwnerThread = KeGetCurrentThread(); OwnerThread = KeGetCurrentThread();
/* Try to acquire the FastMutex */ /* Try to acquire the FastMutex */
if (_InterlockedBitTestAndReset(&FastMutex->Lock, 0)) if (InterlockedCompareExchange(&FastMutex->Count, 1, 0) != 0)
{
/* FastMutex was free, we acquired it */
FastMutex->Owner = OwnerThread;
}
else
{ {
/* FastMutex was locked, we need to wait */ /* FastMutex was locked, we need to wait */
KiAcquireFastMutex(FastMutex); KiAcquireFastMutex(FastMutex);
FastMutex->Owner = OwnerThread;
} }
FastMutex->Owner = OwnerThread;
} }
VOID VOID
@@ -200,38 +182,36 @@ FASTCALL
KeReleaseFastMutexUnsafeAndLeaveCriticalRegion( KeReleaseFastMutexUnsafeAndLeaveCriticalRegion(
_In_ PFAST_MUTEX FastMutex) _In_ PFAST_MUTEX FastMutex)
{ {
LONG OldValue = {0}; LONG OldValue;
PKTHREAD CurrentThread = nullptr ;
SHORT NewValue ={0};
/* Clear the owner */ /* Clear the owner */
FastMutex->Owner = nullptr; FastMutex->Owner = NULL;
/* Try to release the FastMutex */ /* Release the FastMutex */
OldValue = InterlockedCompareExchange(&FastMutex->Lock, 1, 0); OldValue = InterlockedExchange(&FastMutex->Count, 0);
if (OldValue != 0)
if (OldValue < 0)
{ {
/* Contended case, call the contended release function */ /* There were waiters, call the contended release function */
KeReleaseFastMutexContended(FastMutex, OldValue); KeReleaseFastMutexContended(FastMutex, OldValue);
} }
/* leave critical region*/ /* Leave critical region */
KeLeaveCriticalRegion(); KeLeaveCriticalRegion();
} }
VOID VOID
NTAPI NTAPI
KeAcquireFastMutex( KeAcquireFastMutex(
_In_ PFAST_MUTEX FastMutex) _In_ PFAST_MUTEX FastMutex)
{ {
KIRQL OldIrql = {0}; KIRQL OldIrql;
/* Raise IRQL to APC_LEVEL */ /* Raise IRQL to APC_LEVEL */
OldIrql = KeRaiseIrqlToSynchLevel(); OldIrql = KeRaiseIrqlToSynchLevel();
/* Try to acquire the FastMutex */ /* Try to acquire the FastMutex */
if (InterlockedBitTestAndReset(&FastMutex->Lock, 0) == 0) if (InterlockedCompareExchange(&FastMutex->Count, 1, 0) != 0)
{ {
/* We didn't acquire it, we'll have to wait */ /* We didn't acquire it, we'll have to wait */
KiAcquireFastMutex(FastMutex); KiAcquireFastMutex(FastMutex);
@@ -247,13 +227,13 @@ NTAPI
KeAcquireFastMutexUnsafe( KeAcquireFastMutexUnsafe(
_In_ PFAST_MUTEX FastMutex) _In_ PFAST_MUTEX FastMutex)
{ {
PKTHREAD CurrentThread = nullptr; PKTHREAD CurrentThread;
/* Get the current thread */ /* Get the current thread */
CurrentThread = KeGetCurrentThread(); CurrentThread = KeGetCurrentThread();
/* Try to acquire the FastMutex */ /* Try to acquire the FastMutex */
if (!InterlockedBitTestAndReset(&FastMutex->Lock, 0)) if (InterlockedCompareExchange(&FastMutex->Count, 1, 0) != 0)
{ {
/* FastMutex was locked, we need to wait */ /* FastMutex was locked, we need to wait */
KiAcquireFastMutex(FastMutex); KiAcquireFastMutex(FastMutex);
@@ -269,21 +249,24 @@ KeReleaseFastMutex(
_Inout_ PFAST_MUTEX FastMutex _Inout_ PFAST_MUTEX FastMutex
) )
{ {
KIRQL OldIrql ={0}; KIRQL OldIrql;
LONG OldCount ={0}; LONG OldCount;
FastMutex->Owner = nullptr; /* Clear owner and get saved IRQL */
FastMutex->Owner = NULL;
OldIrql = FastMutex->OldIrql; OldIrql = FastMutex->OldIrql;
OldCount = InterlockedExchangeAdd(&FastMutex->Count, 1); /* Release the mutex */
OldCount = InterlockedExchange(&FastMutex->Count, 0);
if (OldCount != 0 && /* Check if there were waiters */
(OldCount & 2) == 0 && if (OldCount < 0)
InterlockedCompareExchange(&FastMutex->Count, OldCount - 1, OldCount + 1) == OldCount + 1)
{ {
/* Wake up waiters */
KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE);
} }
/* Restore IRQL */
KeLowerIrql(OldIrql); KeLowerIrql(OldIrql);
} }
@@ -292,31 +275,21 @@ NTAPI
KeReleaseFastMutexUnsafe( KeReleaseFastMutexUnsafe(
_In_ PFAST_MUTEX FastMutex) _In_ PFAST_MUTEX FastMutex)
{ {
LONG OldValue = {0}; LONG OldValue;
/* Clear the owner */ /* Clear the owner */
FastMutex->Owner = nullptr; FastMutex->Owner = NULL;
/* Release the lock and get the old value */ /* Release the lock and get the old value */
OldValue = InterlockedExchangeAdd(&FastMutex->Lock, 1); OldValue = InterlockedExchange(&FastMutex->Count, 0);
/* Check if there were waiters */ /* Check if there were waiters */
if (OldValue != 0) if (OldValue < 0)
{ {
/* Check if no waiter has been woken up yet */ /* Wake up waiters */
if ((OldValue & FM_LOCK_WAITER_WOKEN) == 0)
{
/* Try to wake up a waiter */
if (OldValue + 1 == InterlockedCompareExchange(&FastMutex->Lock,
OldValue - 1,
OldValue + 1))
{
/* Wake up one waiter */
KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE);
} }
} }
}
}
/*Guarded Mutexes in Modern NT behave just like Fast Mutexes with bit of protection */ /*Guarded Mutexes in Modern NT behave just like Fast Mutexes with bit of protection */
@@ -325,11 +298,13 @@ NTAPI
KeInitializeGuardedMutex(_Out_ PKGUARDED_MUTEX GuardedMutex) KeInitializeGuardedMutex(_Out_ PKGUARDED_MUTEX GuardedMutex)
{ {
/* Initialize the GuardedMutex */ /* Initialize the GuardedMutex */
GuardedMutex->Count = 1; GuardedMutex->Count = 0; // 0 = free
GuardedMutex->Owner = nullptr; GuardedMutex->Owner = NULL;
GuardedMutex->Contention = 0; GuardedMutex->Contention = 0;
GuardedMutex->RecursionDepth = 0;
/* Initialize the Mutex Gate */ /* Initialize the Mutex Gate */
KeInitializeEvent(&Mutex->Event, SynchronizationEvent, FALSE); KeInitializeEvent(&GuardedMutex->Event, SynchronizationEvent, FALSE);
} }
VOID VOID
@@ -337,10 +312,19 @@ NTAPI
KeAcquireGuardedMutex(_Inout_ PKGUARDED_MUTEX Mutex) KeAcquireGuardedMutex(_Inout_ PKGUARDED_MUTEX Mutex)
{ {
PKTHREAD OwnerThread = KeGetCurrentThread(); PKTHREAD OwnerThread = KeGetCurrentThread();
KIRQL OldIrql;
/* Raise IRQL and enter guarded region */
OldIrql = KeRaiseIrqlToSynchLevel();
KeEnterGuardedRegion(); KeEnterGuardedRegion();
if (!_Interlockedbittestandreset(&Mutex->Count, 0) )
if (InterlockedCompareExchange(&Mutex->Count, 1, 0) != 0)
{
KiAcquireFastMutex(Mutex); KiAcquireFastMutex(Mutex);
}
Mutex->Owner = OwnerThread; Mutex->Owner = OwnerThread;
Mutex->OldIrql = OldIrql;
} }
VOID VOID
@@ -349,11 +333,12 @@ KeAcquireGuardedMutexUnsafe(
_Inout_ PKGUARDED_MUTEX FastMutex _Inout_ PKGUARDED_MUTEX FastMutex
) )
{ {
PKTHREAD CurrentThread = nullptr; PKTHREAD CurrentThread;
KeEnterGuardedRegion(); KeEnterGuardedRegion();
CurrentThread = KeGetCurrentThread(); CurrentThread = KeGetCurrentThread();
if (!_InterlockedBitTestAndReset(&FastMutex->Count, 0)) if (InterlockedCompareExchange(&FastMutex->Count, 1, 0) != 0)
{ {
KiAcquireFastMutex(FastMutex); KiAcquireFastMutex(FastMutex);
} }
@@ -367,18 +352,17 @@ KeReleaseGuardedMutexUnsafe(
_Inout_ PKGUARDED_MUTEX FastMutex _Inout_ PKGUARDED_MUTEX FastMutex
) )
{ {
LONG OldCount ={0}; LONG OldCount;
FastMutex->Owner = nullptr; FastMutex->Owner = NULL;
OldCount = _InterlockedExchangeAdd(&FastMutex->Count, 1); OldCount = InterlockedExchange(&FastMutex->Count, 0);
if (OldCount != 0 && if (OldCount < 0)
(OldCount & FM_LOCK_WAITER_WOKEN) == 0 &&
OldCount + 1 == InterlockedCompareExchange(&FastMutex->Count, OldCount - 1, OldCount + 1))
{ {
KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE);
} }
KeLeaveGuardedRegion(); KeLeaveGuardedRegion();
} }
@@ -387,23 +371,299 @@ NTAPI
KeReleaseGuardedMutex( KeReleaseGuardedMutex(
_In_ PKGUARDED_MUTEX FastMutex) _In_ PKGUARDED_MUTEX FastMutex)
{ {
KIRQL OldIrql ={0}; KIRQL OldIrql;
LONG OldValue ={0}; LONG OldValue;
/* Save the old IRQL and clear the owner */ /* Save the old IRQL and clear the owner */
OldIrql = FastMutex->OldIrql; OldIrql = FastMutex->OldIrql;
FastMutex->Owner = nullptr; FastMutex->Owner = NULL;
/* Try to release the FastMutex */ /* Try to release the FastMutex */
OldValue = _InterlockedExchangeAdd(&Mutex->Count, 1); OldValue = InterlockedExchange(&FastMutex->Count, 0);
if (OldCount != 0 &&
(OldCount & FM_LOCK_WAITER_WOKEN) == 0 && if (OldValue < 0)
OldCount + 1 == InterlockedCompareExchange(&FastMutex->Count, OldCount - 1, OldCount + 1))
{ {
KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE);
} }
/* Lower IRQL */ /* Lower IRQL and leave guarded region */
KeLowerIrql(OldIrql); KeLowerIrql(OldIrql);
KeLeaveGuardedRegion(); KeLeaveGuardedRegion();
} }
/* Specific to Alcyone, Not found in Windows NT */
VOID
NTAPI
KeInitializeRecursiveFastMutex(_Out_ PFAST_MUTEX Mutex)
{
KeInitializeFastMutex(Mutex);
/* Mark as recursive by setting the recursive bit in a separate field */
Mutex->RecursionDepth = -1; // Use -1 to indicate recursive capability
}
NTSTATUS
NTAPI
KeAcquireFastMutexTimeout(_Inout_ PFAST_MUTEX Mutex, _In_ PLARGE_INTEGER Timeout)
{
KIRQL OldIrql;
NTSTATUS Status;
/* Raise IRQL */
OldIrql = KeRaiseIrqlToSynchLevel();
/* Try to acquire immediately */
if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0)
{
Mutex->Owner = KeGetCurrentThread();
Mutex->OldIrql = OldIrql;
return STATUS_SUCCESS;
}
/* Increment waiter count */
InterlockedDecrement(&Mutex->Count);
/* Wait with timeout */
Status = KeWaitForSingleObject(&Mutex->Event, WrFastMutex, KernelMode, FALSE, Timeout);
if (Status == STATUS_SUCCESS)
{
/* Try to acquire after being woken up */
if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0)
{
Mutex->Owner = KeGetCurrentThread();
Mutex->OldIrql = OldIrql;
}
else
{
/* Someone else got it, this shouldn't happen normally */
KeLowerIrql(OldIrql);
Status = STATUS_TIMEOUT;
}
}
else
{
/* Timeout or other error - remove ourselves from waiter count */
InterlockedIncrement(&Mutex->Count);
KeLowerIrql(OldIrql);
}
return Status;
}
BOOLEAN
NTAPI
KeIsMutexOwned(_In_ PFAST_MUTEX Mutex)
{
return (Mutex->Owner == KeGetCurrentThread());
}
NTSTATUS
NTAPI
KeAcquireGuardedMutexTimeout(_Inout_ PKGUARDED_MUTEX Mutex, _In_ PLARGE_INTEGER Timeout)
{
KIRQL OldIrql;
NTSTATUS Status;
/* Raise IRQL and enter guarded region */
OldIrql = KeRaiseIrqlToSynchLevel();
KeEnterGuardedRegion();
/* Try to acquire immediately */
if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0)
{
Mutex->Owner = KeGetCurrentThread();
Mutex->OldIrql = OldIrql;
return STATUS_SUCCESS;
}
/* Increment waiter count */
InterlockedDecrement(&Mutex->Count);
/* Wait with timeout */
Status = KeWaitForSingleObject(&Mutex->Event, WrGuardedMutex, KernelMode, FALSE, Timeout);
if (Status == STATUS_SUCCESS)
{
/* Try to acquire after being woken up */
if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0)
{
Mutex->Owner = KeGetCurrentThread();
Mutex->OldIrql = OldIrql;
}
else
{
/* Someone else got it, this shouldn't happen normally */
KeLowerIrql(OldIrql);
KeLeaveGuardedRegion();
Status = STATUS_TIMEOUT;
}
}
else
{
/* Timeout or other error - remove ourselves from waiter count */
InterlockedIncrement(&Mutex->Count);
KeLowerIrql(OldIrql);
KeLeaveGuardedRegion();
}
return Status;
}
/* Additional Alcyone-specific recursive mutex functions */
VOID
NTAPI
KeAcquireRecursiveFastMutex(_Inout_ PFAST_MUTEX Mutex)
{
PKTHREAD CurrentThread = KeGetCurrentThread();
KIRQL OldIrql;
/* Check if this is a recursive mutex */
if (Mutex->RecursionDepth == -1)
{
/* Check if current thread already owns it */
if (Mutex->Owner == CurrentThread)
{
/* Increment recursion depth */
InterlockedIncrement(&Mutex->RecursionDepth);
return;
}
}
/* Not recursive or not owned by current thread - acquire normally */
OldIrql = KeRaiseIrqlToSynchLevel();
if (InterlockedCompareExchange(&Mutex->Count, 1, 0) != 0)
{
KiAcquireFastMutex(Mutex);
}
Mutex->Owner = CurrentThread;
Mutex->OldIrql = OldIrql;
/* Set recursion depth to 1 for recursive mutexes */
if (Mutex->RecursionDepth == -1)
{
Mutex->RecursionDepth = 1;
}
}
VOID
NTAPI
KeReleaseRecursiveFastMutex(_Inout_ PFAST_MUTEX Mutex)
{
PKTHREAD CurrentThread = KeGetCurrentThread();
KIRQL OldIrql;
LONG OldCount;
/* Verify ownership */
if (Mutex->Owner != CurrentThread)
{
KeBugCheckEx(MUTEX_LEVEL_NUMBER_VIOLATION,
(ULONG_PTR)Mutex,
(ULONG_PTR)CurrentThread,
(ULONG_PTR)Mutex->Owner,
0);
return;
}
/* Handle recursive case */
if (Mutex->RecursionDepth > 1)
{
InterlockedDecrement(&Mutex->RecursionDepth);
return;
}
/* Clear owner and get saved IRQL */
Mutex->Owner = NULL;
OldIrql = Mutex->OldIrql;
/* Reset recursion depth for recursive mutexes */
if (Mutex->RecursionDepth != 0)
{
Mutex->RecursionDepth = -1; // Mark as recursive but not owned
}
/* Release the mutex */
OldCount = InterlockedExchange(&Mutex->Count, 0);
/* Check if there were waiters */
if (OldCount < 0)
{
KeSetEvent(&Mutex->Event, IO_NO_INCREMENT, FALSE);
}
/* Restore IRQL */
KeLowerIrql(OldIrql);
}
/* Utility functions for debugging and monitoring */
ULONG
NTAPI
KeGetMutexContentionCount(_In_ PFAST_MUTEX Mutex)
{
return Mutex->Contention;
}
PKTHREAD
NTAPI
KeGetMutexOwner(_In_ PFAST_MUTEX Mutex)
{
return (PKTHREAD)Mutex->Owner;
}
LONG
NTAPI
KeGetMutexRecursionDepth(_In_ PFAST_MUTEX Mutex)
{
return Mutex->RecursionDepth;
}
BOOLEAN
NTAPI
KeIsMutexRecursive(_In_ PFAST_MUTEX Mutex)
{
return (Mutex->RecursionDepth == -1 || Mutex->RecursionDepth > 0);
}
/* Enhanced try-acquire with recursion support */
BOOLEAN
NTAPI
KeTryToAcquireRecursiveFastMutex(_Inout_ PFAST_MUTEX Mutex)
{
PKTHREAD CurrentThread = KeGetCurrentThread();
KIRQL OldIrql;
/* Check if this is a recursive mutex and current thread owns it */
if (Mutex->RecursionDepth != 0 && Mutex->Owner == CurrentThread)
{
/* Increment recursion depth */
InterlockedIncrement(&Mutex->RecursionDepth);
return TRUE;
}
/* Try normal acquisition */
OldIrql = KeRaiseIrqlToSynchLevel();
if (InterlockedCompareExchange(&Mutex->Count, 1, 0) == 0)
{
Mutex->Owner = CurrentThread;
Mutex->OldIrql = OldIrql;
/* Set recursion depth to 1 for recursive mutexes */
if (Mutex->RecursionDepth == -1)
{
Mutex->RecursionDepth = 1;
}
return TRUE;
}
else
{
KeLowerIrql(OldIrql);
return FALSE;
}
}

View File

@@ -1,11 +1,11 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
printf.c wprintf.c
Abstract: Abstract:
@@ -33,7 +33,7 @@ print_hex (
n = 0; n = 0;
shift = 28; shift = 28;
while (n < maxlen && shift >= 0) { while (n < maxlen && shift >= 0) {
x = (num >> shift) & 0xf; x = (num >> shift) & 0xF;
if (x >= 0xa) { if (x >= 0xa) {
*dest = 'a' + (x - 0xa); *dest = 'a' + (x - 0xa);
} else { } else {

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -64,13 +64,10 @@ memmove (
/* Check for overlap */ /* Check for overlap */
if (src > dest || ((char *)src + count) < (char *)dest) { if (src > dest || ((char *)src + count) < (char *)dest) {
/* Low-to-high copy, like memcpy() */ /* Low-to-high copy */
while (count--) { return memcpy(dest, src, count);
*(char *)dest = *(char *)src;
dest = (char *)dest + 1;
src = (char *)src + 1;
} }
} else {
/* High-to-low copy */ /* High-to-low copy */
dest = (char *)dest + count - 1; dest = (char *)dest + count - 1;
src = (char *)src + count - 1; src = (char *)src + count - 1;
@@ -79,7 +76,6 @@ memmove (
dest = (char *)dest - 1; dest = (char *)dest - 1;
src = (char *)src - 1; src = (char *)src - 1;
} }
}
return ptr; return ptr;
} }

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -24,9 +24,11 @@ strlen (
const char *ptr; const char *ptr;
ptr = str; ptr = str;
while (*ptr++); while (*ptr) {
ptr++;
}
return ptr - str - sizeof(char); return ptr - str;
} }
size_t size_t
@@ -36,12 +38,14 @@ strnlen (
) )
{ {
size_t len; const char *ptr;
len = 0; ptr = str;
while (len < maxlen && str[len++]); while (maxlen-- && *ptr) {
ptr++;
}
return len - sizeof(char); return ptr - str;
} }
int int

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -26,8 +26,7 @@ wmemset (
wchar_t *ptr = dest; wchar_t *ptr = dest;
while (count--) { while (count--) {
*(wchar_t *)dest = c; *dest++ = c;
dest = (wchar_t *)dest + 1;
} }
return ptr; return ptr;
@@ -44,9 +43,7 @@ wmemcpy (
wchar_t *ptr = dest; wchar_t *ptr = dest;
while (count--) { while (count--) {
*(wchar_t *)dest = *(wchar_t *)src; *dest++ = *src++;
dest = (wchar_t *)dest + 1;
src = (wchar_t *)src + 1;
} }
return ptr; return ptr;
@@ -64,13 +61,10 @@ wmemmove (
/* Check for overlap */ /* Check for overlap */
if (src > dest || ((wchar_t *)src + count) < (wchar_t *)dest) { if (src > dest || ((wchar_t *)src + count) < (wchar_t *)dest) {
/* Low-to-high copy, like memcpy() */ /* Low-to-high copy */
while (count--) { return wmemcpy(dest, src, count);
*(wchar_t *)dest = *(wchar_t *)src;
dest = (wchar_t *)dest + 1;
src = (wchar_t *)src + 1;
} }
} else {
/* High-to-low copy */ /* High-to-low copy */
dest = (wchar_t *)dest + count - 1; dest = (wchar_t *)dest + count - 1;
src = (wchar_t *)src + count - 1; src = (wchar_t *)src + count - 1;
@@ -79,7 +73,6 @@ wmemmove (
dest = (wchar_t *)dest - 1; dest = (wchar_t *)dest - 1;
src = (wchar_t *)src - 1; src = (wchar_t *)src - 1;
} }
}
return ptr; return ptr;
} }

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -24,9 +24,11 @@ wcslen (
const wchar_t *ptr; const wchar_t *ptr;
ptr = str; ptr = str;
while (*ptr++); while (*ptr) {
ptr++;
}
return (const char*)ptr - (const char*)str - sizeof(wchar_t); return ptr - str;
} }
size_t size_t
@@ -36,12 +38,14 @@ wcsnlen (
) )
{ {
size_t len; const wchar_t *ptr;
len = 0; ptr = str;
while (len < maxlen && str[len++]); while (maxlen-- && *ptr) {
ptr++;
}
return len - sizeof(wchar_t); return ptr - str;
} }
int int
@@ -127,3 +131,41 @@ wcsstr (
return NULL; return NULL;
} }
wchar_t *
wcscpy_s (
wchar_t *dest,
size_t maxlen,
const wchar_t *src
)
{
for (size_t i = 0; i < maxlen; i++, src++) {
dest[i] = *src;
if (!*src) {
break;
}
}
return dest;
}
wchar_t *
wcscat_s (
wchar_t *dest,
size_t maxlen,
const wchar_t *src
)
{
for (size_t i = wcsnlen(dest, maxlen); i < maxlen; i++, src++) {
dest[i] = *src;
if (!*src) {
break;
}
}
return dest;
}

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -9,16 +9,16 @@ Module Name:
Abstract: Abstract:
Provides variable arguments definitions. Provides variable argument list definitions.
--*/ --*/
#pragma once #pragma once
#ifndef _STDARG_H #ifndef _STDARG_H
#define _STDARG_H #define _STDARG_H 1
#ifdef __cplusplus #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
@@ -29,7 +29,7 @@ typedef __builtin_va_list va_list;
#define va_copy(ap, s) __builtin_va_copy(ap, s) #define va_copy(ap, s) __builtin_va_copy(ap, s)
#define va_end(ap) __builtin_va_end(ap) #define va_end(ap) __builtin_va_end(ap)
#ifdef __cplusplus #if defined(__cplusplus)
} }
#endif #endif

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -16,14 +16,16 @@ Abstract:
#pragma once #pragma once
#ifndef _STDDEF_H #ifndef _STDDEF_H
#define _STDDEF_H #define _STDDEF_H 1
#ifdef __cplusplus #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
#ifndef NULL #ifndef NULL
#ifdef __cplusplus #if defined(__cplusplus) && __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__cplusplus)
#define NULL 0 #define NULL 0
#else #else
#define NULL ((void*)0) #define NULL ((void*)0)
@@ -32,7 +34,7 @@ extern "C" {
#ifndef _SIZE_T_DEFINED #ifndef _SIZE_T_DEFINED
#define _SIZE_T_DEFINED #define _SIZE_T_DEFINED
#ifdef _WIN64 #if defined(_WIN64)
typedef unsigned __int64 size_t; typedef unsigned __int64 size_t;
#else #else
typedef unsigned int size_t; typedef unsigned int size_t;
@@ -41,7 +43,7 @@ typedef unsigned int size_t;
#ifndef _PTRDIFF_T_DEFINED #ifndef _PTRDIFF_T_DEFINED
#define _PTRDIFF_T_DEFINED #define _PTRDIFF_T_DEFINED
#ifdef _WIN64 #if defined(_WIN64)
typedef __int64 ptrdiff_t; typedef __int64 ptrdiff_t;
#else #else
typedef long int ptrdiff_t; typedef long int ptrdiff_t;
@@ -53,7 +55,9 @@ typedef long int ptrdiff_t;
typedef unsigned short wchar_t; typedef unsigned short wchar_t;
#endif #endif
#ifdef __cplusplus #define offsetof(type, member) __builtin_offsetof(type, member)
#if defined(__cplusplus)
} }
#endif #endif

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -16,13 +16,17 @@ Abstract:
#pragma once #pragma once
#ifndef _STRING_H #ifndef _STRING_H
#define _STRING_H #define _STRING_H 1
#ifdef __cplusplus #include <stddef.h>
#if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
#include <stddef.h> void *memset(void *dest, int c, size_t count);
void *memcpy(void *dest, const void *src, size_t count);
void *memmove(void *dest, const void *src, size_t count);
size_t strlen(const char *str); size_t strlen(const char *str);
size_t strnlen(const char *str, size_t maxlen); size_t strnlen(const char *str, size_t maxlen);
@@ -31,11 +35,7 @@ int strncmp(const char* s1, const char* s2, size_t n);
char *strchr(const char *s, int c); char *strchr(const char *s, int c);
char *strstr(const char *haystack, const char *needle); char *strstr(const char *haystack, const char *needle);
void *memset(void *dest, int c, size_t count); #if defined(__cplusplus)
void *memcpy(void *dest, const void *src, size_t count);
void *memmove(void *dest, const void *src, size_t count);
#ifdef __cplusplus
} }
#endif #endif

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -16,14 +16,18 @@ Abstract:
#pragma once #pragma once
#ifndef _WCHAR_H #ifndef _WCHAR_H
#define _WCHAR_H #define _WCHAR_H 1
#ifdef __cplusplus #include <stdarg.h>
#include <stddef.h>
#if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
#include <stdarg.h> wchar_t *wmemset(wchar_t *dest, wchar_t c, size_t count);
#include <string.h> wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count);
wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t count);
size_t wcslen(const wchar_t *str); size_t wcslen(const wchar_t *str);
size_t wcsnlen(const wchar_t *str, size_t maxlen); size_t wcsnlen(const wchar_t *str, size_t maxlen);
@@ -31,14 +35,12 @@ int wcscmp(const wchar_t* s1, const wchar_t* s2);
int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n); int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n);
wchar_t *wcschr(const wchar_t *wcs, wchar_t wc); wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
wchar_t *wcsstr(const wchar_t *haystack, const wchar_t *needle); wchar_t *wcsstr(const wchar_t *haystack, const wchar_t *needle);
wchar_t *wcscpy_s(wchar_t *dest, size_t maxlen, const wchar_t *src);
wchar_t *wmemset(wchar_t *dest, wchar_t c, size_t count); wchar_t *wcscat_s(wchar_t *dest, size_t maxlen, const wchar_t *src);
wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count);
wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t count);
int vswprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, va_list args); int vswprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, va_list args);
#ifdef __cplusplus #if defined(__cplusplus)
} }
#endif #endif

78
SDK/INC/EFI/X64/efibind.h Normal file
View File

@@ -0,0 +1,78 @@
/*++
Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license.
Module Name:
efibind.h
Abstract:
Provides processor/compiler-specific EFI definitions for x64 systems.
--*/
#pragma once
#ifndef _EFIBIND_H
#define _EFIBIND_H
//
// Calling conventions.
//
#ifndef EFIAPI
#if defined_(MSC_EXTENSIONS)
#define EFIAPI __cdecl
#elif defined(__clang__) || defined(__GNUC__)
#define EFIAPI __attribute__((ms_abi))
#else
#define EFIAPI
#endif
#endif
//
// Error masks.
//
#define EFI_ERROR_MASK 0x8000000000000000
#define EFI_ERROR_MASK_OEM 0xC000000000000000
//
// Integer types.
//
#if defined(_MSC_EXTENSIONS)
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
#elif defined(UNIX_LP64)
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long uint64_t;
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long int64_t;
#else
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
#endif
//
// Word-sized integers.
//
typedef uint64_t UINTN;
typedef int64_t INTN;
#endif /* !_EFIBIND_H */

34
SDK/INC/EFI/efi.h Normal file
View File

@@ -0,0 +1,34 @@
/*++
Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license.
Module Name:
efi.h
Abstract:
Provides EFI header files.
--*/
#pragma once
#ifndef _EFI_H
#define _EFI_H
#if defined(__x86_64__)
#include "X64/efibind.h"
#else
#error Unsupported architecture
#endif
#include "efidef.h"
#include "efidevp.h"
#include "eficon.h"
#include "efiprot.h"
#include "efiapi.h"
#include "efierr.h"
#endif /* !_EFI_H */

1006
SDK/INC/EFI/efiapi.h Normal file

File diff suppressed because it is too large Load Diff

436
SDK/INC/EFI/eficon.h Normal file
View File

@@ -0,0 +1,436 @@
/*++
Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license.
Module Name:
eficon.h
Abstract:
Provides EFI console protocol definitions.
--*/
#pragma once
#ifndef _EFICON_H
#define _EFICON_H
#pragma pack(1)
//
// EFI Simple Text Output Protocol.
//
#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \
{ 0x387477C2, 0x69C7, 0x11D2, {0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} }
#define SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID
typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
typedef EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SIMPLE_TEXT_OUTPUT_INTERFACE;
//
// Text attributes.
//
#define EFI_TEXT_ATTR(Foreground, Background) ((Foreground) | ((Background) << 4))
#define EFI_BLACK 0x00
#define EFI_BLUE 0x01
#define EFI_GREEN 0x02
#define EFI_RED 0x04
#define EFI_BRIGHT 0x08
#define EFI_CYAN (EFI_BLUE | EFI_GREEN)
#define EFI_MAGENTA (EFI_BLUE | EFI_RED)
#define EFI_BROWN (EFI_GREEN | EFI_RED)
#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED)
#define EFI_DARKGRAY (EFI_BRIGHT)
#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT)
#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT)
#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT)
#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT)
#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT)
#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT)
#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT)
#define EFI_BACKGROUND_BLACK 0x00
#define EFI_BACKGROUND_BLUE 0x10
#define EFI_BACKGROUND_GREEN 0x20
#define EFI_BACKGROUND_RED 0x40
#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN)
#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED)
#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
//
// Unicode Box Draw characters.
//
#define BOXDRAW_HORIZONTAL 0x2500
#define BOXDRAW_VERTICAL 0x2502
#define BOXDRAW_DOWN_RIGHT 0x250C
#define BOXDRAW_DOWN_LEFT 0x2510
#define BOXDRAW_UP_RIGHT 0x2514
#define BOXDRAW_UP_LEFT 0x2518
#define BOXDRAW_VERTICAL_RIGHT 0x251C
#define BOXDRAW_VERTICAL_LEFT 0x2524
#define BOXDRAW_DOWN_HORIZONTAL 0x252C
#define BOXDRAW_UP_HORIZONTAL 0x2534
#define BOXDRAW_VERTICAL_HORIZONTAL 0x253C
#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550
#define BOXDRAW_DOUBLE_VERTICAL 0x2551
#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552
#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553
#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554
#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555
#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556
#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557
#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558
#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559
#define BOXDRAW_DOUBLE_UP_RIGHT 0x255A
#define BOXDRAW_UP_LEFT_DOUBLE 0x255B
#define BOXDRAW_UP_DOUBLE_LEFT 0x255C
#define BOXDRAW_DOUBLE_UP_LEFT 0x255D
#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255E
#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255F
#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560
#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561
#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562
#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563
#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564
#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565
#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566
#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567
#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568
#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569
#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256A
#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256B
#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256C
//
// Required Block Elements.
//
#define BLOCKELEMENT_FULL_BLOCK 0x2588
#define BLOCKELEMENT_LIGHT_SHADE 0x2591
//
// Required Geometric Shapes.
//
#define GEOMETRICSHAPE_UP_TRIANGLE 0x25B2
#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25BA
#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25BC
#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25C4
//
// Required Arrow Shapes.
//
#define ARROW_LEFT 0x2190
#define ARROW_UP 0x2191
#define ARROW_RIGHT 0x2192
#define ARROW_DOWN 0x2193
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_RESET) (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_OUTPUT_STRING) (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *String
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_TEST_STRING) (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *String
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_SET_ATTRIBUTE) (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN Attribute
);
//
// Mode/cursor.
//
typedef struct {
INT32 MaxMode;
INT32 Mode;
INT32 Attribute;
INT32 CursorColumn;
INT32 CursorRow;
BOOLEAN CursorVisible;
} SIMPLE_TEXT_OUTPUT_MODE;
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_QUERY_MODE) (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN ModeNumber,
OUT UINTN *Columns,
OUT UINTN *Rows
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_SET_MODE) (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN ModeNumber
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_CLEAR_SCREEN) (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION) (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN Column,
IN UINTN Row
);
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_ENABLE_CURSOR) (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN BOOLEAN Visible
);
struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
EFI_TEXT_RESET Reset;
EFI_TEXT_OUTPUT_STRING OutputString;
EFI_TEXT_TEST_STRING TestString;
EFI_TEXT_QUERY_MODE QueryMode;
EFI_TEXT_SET_MODE SetMode;
EFI_TEXT_SET_ATTRIBUTE SetAttribute;
EFI_TEXT_CLEAR_SCREEN ClearScreen;
EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition;
EFI_TEXT_ENABLE_CURSOR EnableCursor;
SIMPLE_TEXT_OUTPUT_MODE *Mode;
};
//
// EFI Simple Text Input Protocol.
//
#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \
{ 0x387477C1, 0x69C7, 0x11D2, {0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} }
#define SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID
typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
typedef EFI_SIMPLE_TEXT_INPUT_PROTOCOL SIMPLE_INPUT_INTERFACE;
//
// Required Unicode control characters.
//
#define CHAR_NULL 0x0000
#define CHAR_BACKSPACE 0x0008
#define CHAR_TAB 0x0009
#define CHAR_LINEFEED 0x000A
#define CHAR_CARRIAGE_RETURN 0x000D
//
// Scan codes.
//
#define SCAN_NULL 0x0000
#define SCAN_UP 0x0001
#define SCAN_DOWN 0x0002
#define SCAN_RIGHT 0x0003
#define SCAN_LEFT 0x0004
#define SCAN_HOME 0x0005
#define SCAN_END 0x0006
#define SCAN_INSERT 0x0007
#define SCAN_DELETE 0x0008
#define SCAN_PAGE_UP 0x0009
#define SCAN_PAGE_DOWN 0x000A
#define SCAN_F1 0x000B
#define SCAN_F2 0x000C
#define SCAN_F3 0x000D
#define SCAN_F4 0x000E
#define SCAN_F5 0x000F
#define SCAN_F6 0x0010
#define SCAN_F7 0x0011
#define SCAN_F8 0x0012
#define SCAN_F9 0x0013
#define SCAN_F10 0x0014
#define SCAN_ESC 0x0017
typedef struct {
UINT16 ScanCode;
CHAR16 UnicodeChar;
} EFI_INPUT_KEY;
typedef
EFI_STATUS
(EFIAPI *EFI_INPUT_RESET) (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
typedef
EFI_STATUS
(EFIAPI *EFI_INPUT_READ_KEY) (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
OUT EFI_INPUT_KEY *Key
);
struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
EFI_INPUT_RESET Reset;
EFI_INPUT_READ_KEY ReadKeyStroke;
EFI_EVENT WaitForKey;
};
//
// EFI Extended Simple Text Input Protocol.
//
#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
{ 0xDD9E7534, 0x7762, 0x4698, {0x8C, 0x14, 0xF5, 0x85, 0x17, 0xA6, 0x25, 0xAA} }
#define SIMPLE_TEXT_INPUT_EX_PROTOCOL EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID
typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
//
// Shift state.
//
#define EFI_SHIFT_STATE_VALID 0x80000000
#define EFI_RIGHT_SHIFT_PRESSED 0x00000001
#define EFI_LEFT_SHIFT_PRESSED 0x00000002
#define EFI_RIGHT_CONTROL_PRESSED 0x00000004
#define EFI_LEFT_CONTROL_PRESSED 0x00000008
#define EFI_RIGHT_ALT_PRESSED 0x00000010
#define EFI_LEFT_ALT_PRESSED 0x00000020
#define EFI_RIGHT_LOGO_PRESSED 0x00000040
#define EFI_LEFT_LOGO_PRESSED 0x00000080
#define EFI_MENU_KEY_PRESSED 0x00000100
#define EFI_SYS_REQ_PRESSED 0x00000200
//
// Toggle state.
//
#define EFI_SCROLL_LOCK_ACTIVE 0x01
#define EFI_NUM_LOCK_ACTIVE 0x02
#define EFI_CAPS_LOCK_ACTIVE 0x04
#define EFI_KEY_STATE_EXPOSED 0x40
#define EFI_TOGGLE_STATE_VALID 0x80
//
// Additional scan codes.
//
#define SCAN_PAUSE 0x0048
#define SCAN_F13 0x0068
#define SCAN_F14 0x0069
#define SCAN_F15 0x006A
#define SCAN_F16 0x006B
#define SCAN_F17 0x006C
#define SCAN_F18 0x006D
#define SCAN_F19 0x006E
#define SCAN_F20 0x006F
#define SCAN_F21 0x0070
#define SCAN_F22 0x0071
#define SCAN_F23 0x0072
#define SCAN_F24 0x0073
#define SCAN_MUTE 0x007F
#define SCAN_VOLUME_UP 0x0080
#define SCAN_VOLUME_DOWN 0x0081
#define SCAN_BRIGHTNESS_UP 0x0100
#define SCAN_BRIGHTNESS_DOWN 0x0101
#define SCAN_SUSPEND 0x0102
#define SCAN_HIBERNATE 0x0103
#define SCAN_TOGGLE_DISPLAY 0x0104
#define SCAN_RECOVERY 0x0105
#define SCAN_EJECT 0x0106
typedef UINT8 EFI_KEY_TOGGLE_STATE;
typedef struct {
UINT32 KeyShiftState;
EFI_KEY_TOGGLE_STATE KeyToggleState;
} EFI_KEY_STATE;
typedef struct {
EFI_INPUT_KEY Key;
EFI_KEY_STATE KeyState;
} EFI_KEY_DATA;
typedef
EFI_STATUS
(EFIAPI *EFI_INPUT_RESET_EX) (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
typedef
EFI_STATUS
(EFIAPI *EFI_INPUT_READ_KEY_EX) (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
OUT EFI_KEY_DATA *KeyData
);
typedef
EFI_STATUS
(EFIAPI *EFI_SET_STATE) (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN EFI_KEY_TOGGLE_STATE *KeyToggleState
);
typedef
EFI_STATUS
(EFIAPI *EFI_KEY_NOTIFY_FUNCTION) (
IN EFI_KEY_DATA *KeyData
);
typedef
EFI_STATUS
(EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY) (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN EFI_KEY_DATA *KeyData,
IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
OUT VOID **NotifyHandle
);
typedef
EFI_STATUS
(EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY) (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN VOID *NotificationHandle
);
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL {
EFI_INPUT_RESET_EX Reset;
EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx;
EFI_EVENT WaitForKeyEx;
EFI_SET_STATE SetState;
EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify;
EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify;
};
#pragma pack()
#endif /* !_EFICON_H */

377
SDK/INC/EFI/efidef.h Normal file
View File

@@ -0,0 +1,377 @@
/*++
Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license.
Module Name:
efidef.h
Abstract:
Provides basic EFI type/structure definitions.
--*/
#pragma once
#ifndef _EFIDEF_H
#define _EFIDEF_H
#pragma pack(1)
#ifndef VOID
#define VOID void
#endif
#ifndef CONST
#define CONST const
#endif
#ifndef VOLATILE
#define VOLATILE volatile
#endif
//
// Decorators to show parameter usage.
// IN - Argument passed into routine.
// OUT - Pointed-to value set by routine.
// OPTIONAL - Argument is not required.
//
#ifndef IN
#define IN
#define OUT
#define OPTIONAL
#endif
#ifndef NULL
#if defined(__cplusplus)
#if __cplusplus >= 201103L
#define NULL nullptr
#else
#define NULL 0
#endif
#else
#define NULL ((VOID *) 0)
#endif
#endif
#ifndef TRUE
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || defined(__cplusplus)
#define TRUE true
#define FALSE false
#else
#define TRUE ((BOOLEAN) 1)
#define FALSE ((BOOLEAN) 0)
#endif
#endif
#ifndef FORCEINLINE
#if defined(_MSC_EXTENSIONS)
#define FORCEINLINE __forceinline
#elif defined(__clang__) || defined(__GNUC__)
#define FORCEINLINE __attribute__((always_inline))
#else
#define FORCEINLINE static inline
#endif
#endif
//
// Error code helpers.
//
#define EFIERR(e) (EFI_ERROR_MASK | e)
#define EFIERR_OEM(e) (EFI_ERROR_MASK_OEM | e)
//
// Unsigned integer types.
//
typedef uint8_t UINT8;
typedef uint16_t UINT16;
typedef uint32_t UINT32;
typedef uint64_t UINT64;
//
// Signed integer types.
//
typedef int8_t INT8;
typedef int16_t INT16;
typedef int32_t INT32;
typedef int64_t INT64;
//
// Boolean types.
//
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || defined(__cplusplus)
typedef bool BOOLEAN;
#else
typedef UINT8 BOOLEAN;
#endif
//
// Character types.
//
typedef UINT8 CHAR8;
typedef UINT16 CHAR16;
//
// Miscellaneous types.
//
typedef UINTN EFI_STATUS;
typedef UINT64 EFI_LBA;
typedef UINTN EFI_TPL;
typedef VOID *EFI_HANDLE;
typedef VOID *EFI_EVENT;
//
// Static assertion helper.
//
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || (defined(__cplusplus) && __cplusplus >= 201103L)
#define STATIC_ASSERT static_assert
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define STATIC_ASSERT _Static_assert
#else
#warning Static assertion not available. Compilation problems may not be detected!
#define STATIC_ASSERT(expression, message)
#endif
//
// Ensure that types are of the correct size.
//
STATIC_ASSERT(sizeof(UINT8) == 1, "sizeof(UINT8) must equal 1");
STATIC_ASSERT(sizeof(UINT16) == 2, "sizeof(UINT16) must equal 2");
STATIC_ASSERT(sizeof(UINT32) == 4, "sizeof(UINT32) must equal 4");
STATIC_ASSERT(sizeof(UINT64) == 8, "sizeof(UINT64) must equal 8");
STATIC_ASSERT(sizeof(INT8) == 1, "sizeof(INT8) must equal 1");
STATIC_ASSERT(sizeof(INT16) == 2, "sizeof(INT16) must equal 2");
STATIC_ASSERT(sizeof(INT32) == 4, "sizeof(INT32) must equal 4");
STATIC_ASSERT(sizeof(INT64) == 8, "sizeof(INT64) must equal 8");
STATIC_ASSERT(sizeof(BOOLEAN) == 1, "sizeof(BOOLEAN) must equal 1");
STATIC_ASSERT(sizeof(CHAR8) == 1, "sizeof(CHAR8) must equal 1");
STATIC_ASSERT(sizeof(CHAR16) == 2, "sizeof(CHAR16) must equal 2");
//
// GUID (Globally Unique IDentifier).
//
typedef struct {
UINT32 Data1;
UINT16 Data2;
UINT16 Data3;
UINT8 Data4[8];
} EFI_GUID;
//
// Time.
//
typedef struct {
UINT16 Year;
UINT8 Month;
UINT8 Day;
UINT8 Hour;
UINT8 Minute;
UINT8 Second;
UINT8 Pad1;
UINT32 Nanosecond;
INT16 Timezone;
UINT8 Daylight;
UINT8 Pad2;
} EFI_TIME;
//
// For EFI_TIME.Daylight.
//
#define EFI_TIME_ADJUST_DAYLIGHT 0x01
#define EFI_TIME_IN_DAYLIGHT 0x02
//
// For EFI_TIME.TimeZone.
//
#define EFI_UNSPECIFIED_TIMEZONE 0x07FF
//
// Network addresses.
//
typedef struct {
UINT8 Addr[4];
} EFI_IPv4_ADDRESS;
typedef struct {
UINT8 Addr[16];
} EFI_IPv6_ADDRESS;
typedef union {
UINT32 Addr[4];
EFI_IPv4_ADDRESS v4;
EFI_IPv6_ADDRESS v6;
} EFI_IP_ADDRESS;
typedef struct {
UINT8 Addr[32];
} EFI_MAC_ADDRESS;
typedef struct {
UINT8 Address[6];
} BLUETOOTH_ADDRESS;
typedef struct {
UINT8 Address[6];
UINT8 Type;
} BLUETOOTH_LE_ADDRESS;
//
// Memory addresses.
//
typedef UINT64 EFI_PHYSICAL_ADDRESS;
typedef UINT64 EFI_VIRTUAL_ADDRESS;
//
// Memory allocation methods.
//
typedef enum {
//
// Allocate range at any address.
//
AllocateAnyPages,
//
// Allocate range ending at a specific address.
//
AllocateMaxAddress,
//
// Allocate range starting at a specific address.
//
AllocateAddress,
//
// For bounds checking.
//
MaxAllocateType
} EFI_ALLOCATE_TYPE;
//
// Memory types.
//
typedef enum {
EfiReservedMemoryType,
EfiLoaderCode,
EfiLoaderData,
EfiBootServicesCode,
EfiBootServicesData,
EfiRuntimeServicesCode,
EfiRuntimeServicesData,
EfiConventionalMemory,
EfiUnusableMemory,
EfiACPIReclaimMemory,
EfiACPIMemoryNVS,
EfiMemoryMappedIO,
EfiMemoryMappedIOPortSpace,
EfiPalCode,
EfiPersistentMemory,
EfiUnacceptedMemoryType,
EfiMaxMemoryType,
MEMORY_TYPE_OEM_RESERVED_MIN = 0x70000000,
MEMORY_TYPE_OEM_RESERVED_MAX = 0x7FFFFFFF,
MEMORY_TYPE_OS_RESERVED_MIN = 0x80000000,
MEMORY_TYPE_OS_RESERVED_MAX = 0xFFFFFFFF
} EFI_MEMORY_TYPE;
//
// Memory caching attributes.
//
#define EFI_MEMORY_UC 0x0000000000000001
#define EFI_MEMORY_WC 0x0000000000000002
#define EFI_MEMORY_WT 0x0000000000000004
#define EFI_MEMORY_WB 0x0000000000000008
#define EFI_MEMORY_UCE 0x0000000000000010
//
// Memory protection attributes.
//
#define EFI_MEMORY_WP 0x0000000000001000
#define EFI_MEMORY_RP 0x0000000000002000
#define EFI_MEMORY_XP 0x0000000000004000
#define EFI_MEMORY_RO 0x0000000000020000
//
// Miscellaneous memory attributes.
//
#define EFI_MEMORY_NV 0x0000000000008000
#define EFI_MEMORY_MORE_RELIABLE 0x0000000000010000
#define EFI_MEMORY_SP 0x0000000000040000
#define EFI_MEMORY_CPU_CRYPTO 0x0000000000080000
#define EFI_MEMORY_HOT_PLUGGABLE 0x0000000000100000
#define EFI_MEMORY_ISA_VALID 0x4000000000000000
#define EFI_MEMORY_RUNTIME 0x8000000000000000
//
// Memory type/attribute masks.
//
#define EFI_MEMORY_ISA_MASK 0x0FFFF00000000000
#define EFI_CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP)
#define EFI_MEMORY_ACCESS_MASK (EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RO)
#define EFI_MEMORY_ATTRIBUTE_MASK (EFI_MEMORY_ACCESS_MASK | EFI_MEMORY_SP | EFI_MEMORY_CPU_CRYPTO)
//
// Memory descriptor.
//
#define EFI_MEMORY_DESCRIPTOR_VERSION 1
typedef struct {
//
// Memory type (EFI_MEMORY_TYPE) of the region.
//
UINT32 Type;
UINT32 Pad;
//
// Must be aligned on an EFI_PAGE_SIZE-byte boundary.
// Must not be above 0xFFFFFFFFFFFFF000.
//
EFI_PHYSICAL_ADDRESS PhysicalStart;
EFI_VIRTUAL_ADDRESS VirtualStart;
//
// Number of EFI_PAGE_SIZE-byte pages.
// Must not be zero.
//
UINT64 NumberOfPages;
//
// Capabilities of the memory region.
//
UINT64 Attribute;
} EFI_MEMORY_DESCRIPTOR;
//
// International language.
//
typedef CHAR8 ISO_639_2;
#define ISO_639_2_ENTRY_SIZE 3
//
// Memory units & address helpers.
//
#define EFI_PAGE_SIZE 4096
#define EFI_PAGE_MASK 0xFFF
#define EFI_PAGE_SHIFT 12
#define EFI_SIZE_TO_PAGES(s) (((s) >> EFI_PAGE_SHIFT) + ((s) & EFI_PAGE_MASK ? 1:0))
//
// OS indications.
//
#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
#define EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION 0x0000000000000002
#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED 0x0000000000000004
#define EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED 0x0000000000000008
#define EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED 0x0000000000000010
#define EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY 0x0000000000000040
#define EFI_OS_INDICATIONS_JSON_CONFIG_DATA_REFRESH 0x0000000000000080
#pragma pack()
#endif /* !_EFIDEF_H */

1058
SDK/INC/EFI/efidevp.h Normal file

File diff suppressed because it is too large Load Diff

88
SDK/INC/EFI/efierr.h Normal file
View File

@@ -0,0 +1,88 @@
/*++
Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license.
Module Name:
efierr.h
Abstract:
Provides EFI error definitions.
--*/
#pragma once
#ifndef _EFIERR_H
#define _EFIERR_H
#define EFIWARN(a) (a)
#define EFI_ERROR(a) (((INTN) (a)) < 0)
//
// Standard errors.
//
#define EFI_SUCCESS 0
#define EFI_LOAD_ERROR EFIERR(1)
#define EFI_INVALID_PARAMETER EFIERR(2)
#define EFI_UNSUPPORTED EFIERR(3)
#define EFI_BAD_BUFFER_SIZE EFIERR(4)
#define EFI_BUFFER_TOO_SMALL EFIERR(5)
#define EFI_NOT_READY EFIERR(6)
#define EFI_DEVICE_ERROR EFIERR(7)
#define EFI_WRITE_PROTECTED EFIERR(8)
#define EFI_OUT_OF_RESOURCES EFIERR(9)
#define EFI_VOLUME_CORRUPTED EFIERR(10)
#define EFI_VOLUME_FULL EFIERR(11)
#define EFI_NO_MEDIA EFIERR(12)
#define EFI_MEDIA_CHANGED EFIERR(13)
#define EFI_NOT_FOUND EFIERR(14)
#define EFI_ACCESS_DENIED EFIERR(15)
#define EFI_NO_RESPONSE EFIERR(16)
#define EFI_NO_MAPPING EFIERR(17)
#define EFI_TIMEOUT EFIERR(18)
#define EFI_NOT_STARTED EFIERR(19)
#define EFI_ALREADY_STARTED EFIERR(20)
#define EFI_ABORTED EFIERR(21)
#define EFI_ICMP_ERROR EFIERR(22)
#define EFI_TFTP_ERROR EFIERR(23)
#define EFI_PROTOCOL_ERROR EFIERR(24)
#define EFI_INCOMPATIBLE_VERSION EFIERR(25)
#define EFI_SECURITY_VIOLATION EFIERR(26)
#define EFI_CRC_ERROR EFIERR(27)
#define EFI_END_OF_MEDIA EFIERR(28)
#define EFI_END_OF_FILE EFIERR(31)
#define EFI_INVALID_LANGUAGE EFIERR(32)
#define EFI_COMPROMISED_DATA EFIERR(33)
#define EFI_IP_ADDRESS_CONFLICT EFIERR(34)
#define EFI_HTTP_ERROR EFIERR(35)
//
// Standard warnings.
//
#define EFI_WARN_UNKOWN_GLYPH EFIWARN(1)
#define EFI_WARN_DELETE_FAILURE EFIWARN(2)
#define EFI_WARN_WRITE_FAILURE EFIWARN(3)
#define EFI_WARN_BUFFER_TOO_SMALL EFIWARN(4)
#define EFI_WARN_STALE_DATA EFIWARN(5)
#define EFI_WARN_FILE_SYSTEM EFIWARN(6)
#define EFI_WARN_RESET_REQUESTED EFIWARN(7)
//
// ICMP errors.
//
#define EFI_NETWORK_UNREACHABLE EFIERR(100)
#define EFI_HOST_UNREACHABLE EFIERR(101)
#define EFI_PROTOCOL_UNREACHABLE EFIERR(102)
#define EFI_PORT_UNREACHABLE EROERR(103)
//
// TCP errors.
//
#define EFI_CONNECTION_FIN EFIERR(104)
#define EFI_CONNECTION_RESET EFIERR(105)
#define EFI_CONNECTION_REFUSED EFIERR(106)
#endif /* !_EFIERR_H */

72
SDK/INC/EFI/efiprot.h Normal file
View File

@@ -0,0 +1,72 @@
/*++
Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license.
Module Name:
efiprot.h
Abstract:
Provides EFI protocol definitions.
--*/
#pragma once
#ifndef _EFIPROT_H
#define _EFIPROT_H
#pragma pack(1)
//
// Device Path Protocol.
//
#define EFI_DEVICE_PATH_PROTOCOL_GUID \
{ 0x9576E91, 0x6D3F, 0x11D2, {0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} }
#define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID
//
// Loaded Image Protocol.
//
#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
{ 0x5B1B31A1, 0x9562, 0x11D2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} }
#define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID
#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \
{ 0xBC62157E, 0x3E33, 0x4FEC, {0x99, 0x20, 0x2D, 0x3B, 0x36, 0xD7, 0x50, 0xDF} }
#define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000
#define EFI_IMAGE_INFORMATION_REVISION EFI_LOADED_IMAGE_PROTOCOL_REVISION
typedef
EFI_STATUS
(EFIAPI *EFI_IMAGE_UNLOAD) (
IN EFI_HANDLE ImageHandle
);
typedef struct {
UINT32 Revision;
EFI_HANDLE ParentHandle;
struct _EFI_SYSTEM_TABLE *SystemTable;
EFI_HANDLE DeviceHandle;
EFI_DEVICE_PATH *FilePath;
VOID *Reserved;
UINT32 LoadOptionsSize;
VOID *LoadOptions;
VOID *ImageBase;
UINT64 ImageSize;
EFI_MEMORY_TYPE ImageCodeType;
EFI_MEMORY_TYPE ImageDataType;
EFI_IMAGE_UNLOAD Unload;
} EFI_LOADED_IMAGE_PROTOCOL, EFI_LOADED_IMAGE;
#pragma pack()
#endif /* !_EFIPROT_H */

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -13,6 +13,8 @@ Abstract:
--*/ --*/
#pragma once
#ifndef _GUIDDEF_H #ifndef _GUIDDEF_H
#define _GUIDDEF_H #define _GUIDDEF_H

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -13,6 +13,8 @@ Abstract:
--*/ --*/
#pragma once
#ifndef _NT_H #ifndef _NT_H
#define _NT_H #define _NT_H

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -13,6 +13,8 @@ Abstract:
--*/ --*/
#pragma once
#ifndef _NTDEF_H #ifndef _NTDEF_H
#define _NTDEF_H #define _NTDEF_H
@@ -44,7 +46,11 @@ Abstract:
#ifndef NULL #ifndef NULL
#if defined(__cplusplus) #if defined(__cplusplus)
#if __cplusplus >= 201103L
#define NULL nullptr
#else
#define NULL 0 #define NULL 0
#endif
#else #else
#define NULL ((VOID *) 0) #define NULL ((VOID *) 0)
#endif #endif
@@ -53,7 +59,10 @@ Abstract:
#ifndef FORCEINLINE #ifndef FORCEINLINE
#if defined(_MSC_EXTENSIONS) #if defined(_MSC_EXTENSIONS)
#define FORCEINLINE __forceinline #define FORCEINLINE __forceinline
#elif defined(__clang__) || defined(__GNUC__)
#define FORCEINLINE __attribute__((always_inline))
#else #else
#warning Unable to define FORCEINLINE
#define FORCEINLINE static inline #define FORCEINLINE static inline
#endif #endif
#endif #endif
@@ -61,14 +70,24 @@ Abstract:
#ifndef FASTCALL #ifndef FASTCALL
#if defined(_M_IX86) #if defined(_M_IX86)
#define FASTCALL __fastcall #define FASTCALL __fastcall
#elif defined(__clang__) || defined(__GNUC__)
#define FASTCALL __attribute__((fastcall))
#else #else
#warning Unable to defined FASTCALL
#define FASTCALL #define FASTCALL
#endif #endif
#endif #endif
#ifndef NTAPI #ifndef NTAPI
#if !defined(_M_AMD64) #if !defined(_M_AMD64)
#if defined(_MSC_EXTENSIONS)
#define NTAPI __stdcall #define NTAPI __stdcall
#elif defined(__clang__) || defined(__GNUC__)
#define NTAPI __attribute__((stdcall))
#else
#warning Unable to define NTAPI
#define NTAPI
#endif
#else #else
#define NTAPI #define NTAPI
#endif #endif
@@ -88,14 +107,14 @@ typedef unsigned long ULONG;
// Minimum/maximum values of basic types. // Minimum/maximum values of basic types.
// //
#define MINCHAR 0x80 #define MINCHAR 0x80
#define MAXCHAR 0x7f #define MAXCHAR 0x7F
#define MINSHORT 0x8000 #define MINSHORT 0x8000
#define MAXSHORT 0x7fff #define MAXSHORT 0x7FFF
#define MINLONG 0x80000000 #define MINLONG 0x80000000
#define MAXLONG 0x7fffffff #define MAXLONG 0x7FFFFFFF
#define MAXUCHAR 0xff #define MAXUCHAR 0xFF
#define MAXUSHORT 0xffff #define MAXUSHORT 0xFFFF
#define MAXULONG 0xffffffff #define MAXULONG 0xFFFFFFFF
// //
// Long long types. // Long long types.
@@ -111,36 +130,32 @@ typedef long long LONGLONG;
typedef unsigned long long ULONGLONG; typedef unsigned long long ULONGLONG;
#endif #endif
typedef LONGLONG *PLONGLONG; #define MAXLONGLONG 0x7FFFFFFFFFFFFFFF
typedef ULONGLONG *PULONGLONG; #define MAXULONGLONG 0xFFFFFFFFFFFFFFFF
#define MAXLONGLONG 0x7fffffffffffffff
#define MAXULONGLONG 0xffffffffffffffff
#define LODWORD(x) ((ULONG)(x))
#define HIDWORD(x) ((ULONG)((x) >> 32))
#define LOWORD(x) ((USHORT)(x))
#define HIWORD(x) ((USHORT)((x) >> 16))
#define LOBYTE(x) ((UCHAR)(x))
#define HIBYTE(x) ((UCHAR)((x) >> 8))
// //
// Logical/boolean value types. // Logical/boolean value types.
// //
typedef ULONG LOGICAL; typedef ULONG LOGICAL;
typedef ULONG *PLOGICAL;
typedef int BOOL; typedef int BOOL;
typedef BOOL *PBOOL;
typedef UCHAR BOOLEAN; typedef UCHAR BOOLEAN;
typedef BOOLEAN *PBOOLEAN;
#define TRUE 1 #define TRUE 1
#define FALSE 0 #define FALSE 0
// //
// Basic pointer types. // Numeric pointer types.
//
#if defined(_WIN64)
typedef LONGLONG LONG_PTR;
typedef ULONGLONG ULONG_PTR;
#else
typedef LONG LONG_PTR;
typedef ULONG ULONG_PTR;
#endif
//
// Basic type pointers.
// //
typedef VOID *PVOID; typedef VOID *PVOID;
typedef CHAR *PCHAR; typedef CHAR *PCHAR;
@@ -150,15 +165,17 @@ typedef USHORT *PUSHORT;
typedef ULONG *PULONG; typedef ULONG *PULONG;
// //
// Numeric pointer types. // Long long type pointers.
// //
#ifdef _WIN64 typedef LONGLONG *PLONGLONG;
typedef LONGLONG LONG_PTR; typedef ULONGLONG *PULONGLONG;
typedef ULONGLONG ULONG_PTR;
#else //
typedef LONG LONG_PTR; // Logical/boolean type pointers.
typedef ULONG ULONG_PTR; //
#endif typedef ULONG *PLOGICAL;
typedef BOOL *PBOOL;
typedef BOOLEAN *PBOOLEAN;
// //
// String types. // String types.
@@ -210,6 +227,16 @@ typedef NTSTATUS *PNTSTATUS;
#define ALIGN_DOWN(x, a) ((x) & ~((a) - 1)) #define ALIGN_DOWN(x, a) ((x) & ~((a) - 1))
#define ALIGN_UP(x, a) ALIGN_DOWN((x) + (a) - 1, a) #define ALIGN_UP(x, a) ALIGN_DOWN((x) + (a) - 1, a)
//
// Bit extraction helpers.
//
#define LODWORD(x) ((ULONG)(x))
#define HIDWORD(x) ((ULONG)((x) >> 32))
#define LOWORD(x) ((USHORT)(x))
#define HIWORD(x) ((USHORT)((x) >> 16))
#define LOBYTE(x) ((UCHAR)(x))
#define HIBYTE(x) ((UCHAR)((x) >> 8))
// //
// Large (64-bit) integer value. // Large (64-bit) integer value.
// //
@@ -234,135 +261,6 @@ typedef union ULARGE_INTEGER {
ULONGLONG QuadPart; ULONGLONG QuadPart;
} ULARGE_INTEGER, *PULARGE_INTEGER; } ULARGE_INTEGER, *PULARGE_INTEGER;
//
// Doubly-linked list entry.
//
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY;
FORCEINLINE
VOID
InitializeListHead (
IN PLIST_ENTRY Head
)
/*++
Routine Description:
Initializes a list head.
Arguments:
Head - the list head.
Return Value:
None.
--*/
{
Head->Blink = Head;
Head->Flink = Head;
}
FORCEINLINE
VOID
InsertHeadList (
IN PLIST_ENTRY Head,
IN PLIST_ENTRY Entry
)
/*++
Routine Description:
Inserts a list entry at the head of a list.
Arguments:
Entry - The list entry.
Return Value:
None.
--*/
{
Entry->Flink = Head->Flink;
Entry->Blink = Head;
Head->Flink->Blink = Entry;
Head->Flink = Entry;
}
FORCEINLINE
VOID
InsertTailList (
IN PLIST_ENTRY Head,
IN PLIST_ENTRY Entry
)
/*++
Routine Description:
Inserts a list entry at the tail of a list.
Arguments:
Entry - The list entry.
Return Value:
None.
--*/
{
Entry->Blink = Head->Blink;
Entry->Flink = Head;
Head->Blink->Flink = Entry;
Head->Blink = Entry;
}
FORCEINLINE
BOOLEAN
RemoveEntryList (
IN PLIST_ENTRY Entry
)
/*++
Routine Description:
Removes a list entry from a list.
Arguments:
Entry - the entry to remove.
Return Value:
True if the list is now empty,
False if the list still has at least one entry.
--*/
{
PLIST_ENTRY Blink, Flink;
Blink = Entry->Blink;
Flink = Entry->Flink;
Blink->Flink = Flink;
Flink->Blink = Blink;
return (BOOLEAN)(Flink == Blink);
}
// //
// Unicode string. // Unicode string.
// //
@@ -377,6 +275,14 @@ typedef CONST UNICODE_STRING *PCUNICODE_STRING;
#define MAX_USTRING ALIGN_DOWN(MAXUSHORT, sizeof(WCHAR)) #define MAX_USTRING ALIGN_DOWN(MAXUSHORT, sizeof(WCHAR))
//
// Doubly-linked list entry.
//
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY;
#include <guiddef.h> #include <guiddef.h>
#endif /* !_NTDEF_H */ #endif /* !_NTDEF_H */

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -13,14 +13,36 @@ Abstract:
--*/ --*/
#pragma once
#ifndef _NTIMAGE_H #ifndef _NTIMAGE_H
#define _NTIMAGE_H #define _NTIMAGE_H
// //
// Machine type values. // Machine types.
// //
#define IMAGE_FILE_MACHINE_UNKNOWN 0 #define IMAGE_FILE_MACHINE_UNKNOWN 0x0000
#define IMAGE_FILE_MACHINE_I386 0x014c #define IMAGE_FILE_MACHINE_I386 0x014C
#define IMAGE_FILE_MACHINE_AMD64 0x8664 #define IMAGE_FILE_MACHINE_AMD64 0x8664
//
// Subsystem types.
//
#define IMAGE_SUBSYSTEM_UNKNOWN 0
#define IMAGE_SUBSYSTEM_NATIVE 1
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
#define IMAGE_SUBSYSTEM_WINDOWS_CE_OLD 4
#define IMAGE_SUBSYSTEM_OS2_CUI 5
#define IMAGE_SUBSYSTEM_POSIX_CUI 7
#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
#define IMAGE_SUBSYSTEM_EFI_ROM 13
#define IMAGE_SUBSYSTEM_XBOX 14
#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16
#define IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG 17
#endif /* !_NTIMAGE_H */ #endif /* !_NTIMAGE_H */

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -13,12 +13,14 @@ Abstract:
--*/ --*/
#pragma once
#ifndef _NTRTL_H #ifndef _NTRTL_H
#define _NTRTL_H #define _NTRTL_H
#include <string.h> #if defined(__cplusplus)
#include <ntdef.h> extern "C" {
#include <ntstatus.h> #endif
// //
// Memory operations. // Memory operations.
@@ -28,6 +30,127 @@ Abstract:
#define RtlFillMemory(Destination, Length, Fill) memset((Destination), (Fill), (Length)) #define RtlFillMemory(Destination, Length, Fill) memset((Destination), (Fill), (Length))
#define RtlZeroMemory(Destination, Length) memset((Destination), 0, (Length)) #define RtlZeroMemory(Destination, Length) memset((Destination), 0, (Length))
FORCEINLINE
VOID
InitializeListHead (
IN PLIST_ENTRY Head
)
/*++
Routine Description:
Initializes a list head.
Arguments:
Head - Pointer to the list's head.
Return Value:
None.
--*/
{
Head->Blink = Head;
Head->Flink = Head;
}
FORCEINLINE
VOID
InsertHeadList (
IN PLIST_ENTRY Head,
IN PLIST_ENTRY Entry
)
/*++
Routine Description:
Inserts an entry at the head of a list.
Arguments:
Entry - Pointer to the list entry to insert.
Return Value:
None.
--*/
{
Entry->Flink = Head->Flink;
Entry->Blink = Head;
Head->Flink->Blink = Entry;
Head->Flink = Entry;
}
FORCEINLINE
VOID
InsertTailList (
IN PLIST_ENTRY Head,
IN PLIST_ENTRY Entry
)
/*++
Routine Description:
Inserts an entry at the tail of a list.
Arguments:
Entry - Pointer to the list entry to insert.
Return Value:
None.
--*/
{
Entry->Blink = Head->Blink;
Entry->Flink = Head;
Head->Blink->Flink = Entry;
Head->Blink = Entry;
}
FORCEINLINE
BOOLEAN
RemoveEntryList (
IN PLIST_ENTRY Entry
)
/*++
Routine Description:
Removes an entry from a list.
Arguments:
Entry - Pointer to the entry to remove.
Return Value:
TRUE if the list is now empty,
FALSE if the list still has at least one entry.
--*/
{
PLIST_ENTRY Blink, Flink;
Blink = Entry->Blink;
Flink = Entry->Flink;
Blink->Flink = Flink;
Flink->Blink = Blink;
return (BOOLEAN)(Flink == Blink);
}
#define ULONG_ERROR 0xFFFFFFFFUL #define ULONG_ERROR 0xFFFFFFFFUL
FORCEINLINE FORCEINLINE
@@ -83,4 +206,8 @@ RtlGUIDFromString (
OUT GUID *Guid OUT GUID *Guid
); );
#if defined(__cplusplus)
}
#endif
#endif /* !_NTRTL_H */ #endif /* !_NTRTL_H */

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -13,14 +13,12 @@ Abstract:
--*/ --*/
#pragma once
#ifndef _NTSTATUS_H #ifndef _NTSTATUS_H
#define _NTSTATUS_H #define _NTSTATUS_H
#define STATUS_SUCCESS ((NTSTATUS) 0x00000000L) #define STATUS_SUCCESS ((NTSTATUS) 0x00000000L)
//
// TODO: There are an insane amount of status values.
//
#define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL) #define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL)
#define STATUS_UNSUCCESSFUL ((NTSTATUS) 0xC0000001L) #define STATUS_UNSUCCESSFUL ((NTSTATUS) 0xC0000001L)
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L) #define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L)

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -13,8 +13,7 @@ Abstract:
--*/ --*/
#include <ntrtl.h> #include <nt.h>
#include <ntstatus.h>
#include <stdarg.h> #include <stdarg.h>
int int
@@ -29,13 +28,17 @@ ScanHexFormat (
Routine Description: Routine Description:
Turns a text representation of a GUID into the binary format. Parses a formatted hex string.
Arguments: Arguments:
String - A GUID string in the format {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}. Buffer - The source string to parse.
Guid - The GUID structure which is to recieve the data. MaximumLength - The length of the source string.
Format - The format of the source string.
... - Pointers to data destinations.
Return Value: Return Value:
@@ -94,10 +97,10 @@ Return Value:
if (*Buffer >= '0' && *Buffer <= '9') { if (*Buffer >= '0' && *Buffer <= '9') {
Number += *Buffer - '0'; Number += *Buffer - '0';
} else if (*Buffer >= 'a' && *Buffer <= 'f') {
Number += *Buffer - 'a' + 0xa;
} else if (*Buffer >= 'A' && *Buffer <= 'F') { } else if (*Buffer >= 'A' && *Buffer <= 'F') {
Number += *Buffer - 'A' + 0xA; Number += *Buffer - 'A' + 0xA;
} else if (*Buffer >= 'a' && *Buffer <= 'f') {
Number += *Buffer - 'a' + 0xa;
} else { } else {
return -1; return -1;
} }

View File

@@ -1,6 +1,6 @@
/*++ /*++
Copyright (c) 2024, Quinn Stephens. Copyright (c) 2024-2025, Quinn Stephens.
Provided under the BSD 3-Clause license. Provided under the BSD 3-Clause license.
Module Name: Module Name:
@@ -13,7 +13,7 @@ Abstract:
--*/ --*/
#include <ntrtl.h> #include <nt.h>
#include <wchar.h> #include <wchar.h>
VOID VOID
@@ -32,9 +32,9 @@ Routine Description:
Arguments: Arguments:
Destination - A pointer to the unicode string structure. Destination - Pointer to the unicode string structure.
Source - Optionally, a pointer to a null-terminated string to initialize Source - Optionally, a pointer to a NULL-terminated string to initialize
the unicode string structure with. the unicode string structure with.
Return Value: Return Value:

View File

@@ -1,5 +1,5 @@
--- ---
--- Copyright (c) 2024, Quinn Stephens. --- Copyright (c) 2024-2025, Quinn Stephens.
--- Provided under the BSD 3-Clause license. --- Provided under the BSD 3-Clause license.
--- ---
@@ -44,12 +44,14 @@ project("RTL")
project("BOOTMGR") project("BOOTMGR")
kind("ConsoleApp") kind("ConsoleApp")
location("BOOT/ENVIRON/APP/BOOTMGR") location("BOOT/ENVIRON/APP/BOOTMGR")
files({ "BOOT/ENVIRON/INC/**.h", "BOOT/ENVIRON/LIB/**.c", "BOOT/ENVIRON/LIB/**.S", "BOOT/ENVIRON/APP/BOOTMGR/**.c" })
includedirs({ "BOOT/ENVIRON/INC", "SDK/INC/CRT", "SDK/INC/NT" }) includedirs({ "BOOT/ENVIRON/INC", "SDK/INC/CRT", "SDK/INC/NT", "SDK/INC/EFI" })
libdirs({ "BUILD/SDK" }) libdirs({ "BUILD/SDK" })
objdir("BUILD/BOOT") objdir("BUILD/BOOT")
targetdir("BUILD/BOOT") targetdir("BUILD/BOOT")
files({ "BOOT/ENVIRON/INC/**.h", "BOOT/ENVIRON/LIB/**.c", "BOOT/ENVIRON/APP/BOOTMGR/**.c" })
defines({ "_EFI" })
filter("toolset:clang") filter("toolset:clang")
buildoptions({ "-fshort-wchar", "-fno-strict-aliasing", "-fno-stack-protector", "-fno-stack-check", "-mno-red-zone" }) buildoptions({ "-fshort-wchar", "-fno-strict-aliasing", "-fno-stack-protector", "-fno-stack-check", "-mno-red-zone" })