Compare commits
6 Commits
main
...
LazyWriter
Author | SHA1 | Date | |
---|---|---|---|
11683762c3 | |||
3ae19eaf01 | |||
e75a2adeec | |||
1c173364a1 | |||
104a0212e0 | |||
1dec536c4d |
5
.gitignore
vendored
5
.gitignore
vendored
@ -9,7 +9,6 @@
|
||||
Makefile
|
||||
/BUILD/
|
||||
/UNUSED/
|
||||
/DISK/
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
@ -44,7 +43,3 @@ Makefile
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Disk image files
|
||||
*.img
|
||||
*.iso
|
||||
*.fd
|
||||
|
@ -31,20 +31,20 @@ Routine Description:
|
||||
|
||||
Arguments:
|
||||
|
||||
ImageHandle - EFI handle for the boot manager image.
|
||||
ImageHandle - Handle for the boot manager image.
|
||||
|
||||
SystemTable - Pointer to the EFI system table.
|
||||
|
||||
Return Value:
|
||||
|
||||
EFI_SUCCESS if successful.
|
||||
EFI_INVALID_PARAMETER if EfiInitCreateInputParameters() fails.
|
||||
Any other error code if BmMain() fails.
|
||||
EFI_INVALID_PARAMEER if input parameter structure creation fails.
|
||||
Any other value defined in efierr.h.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PBOOT_APPLICATION_PARAMETERS InputParameters;
|
||||
PBOOT_INPUT_PARAMETERS InputParameters;
|
||||
|
||||
//
|
||||
// Create firmware-independent input structure from EFI parameters.
|
||||
@ -55,7 +55,7 @@ Return Value:
|
||||
}
|
||||
|
||||
//
|
||||
// Transfer control to the firmware-independent boot manager code.
|
||||
// Transfer control to the firmware-independent boot manager.
|
||||
//
|
||||
return EfiGetEfiStatusCode(BmMain(InputParameters));
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
|
||||
bcd.c
|
||||
|
||||
Abstract:
|
||||
|
||||
BCD (Boot Configuration Data, aka Boot Data Store) routines.
|
||||
|
||||
--*/
|
||||
|
||||
#include "bootmgr.h"
|
||||
|
||||
NTSTATUS
|
||||
BmOpenDataStore (
|
||||
IN OUT PHANDLE Handle
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Opens the boot configuration data store.
|
||||
|
||||
Arguments:
|
||||
|
||||
Handle - Pointer to a HANDLE that recieves the data store handle.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
*Handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
/*
|
||||
NTSTATUS Status;
|
||||
PBOOT_DEVICE Device;
|
||||
PWSTR FilePath;
|
||||
BOOLEAN FilePathSet;
|
||||
|
||||
Device = NULL;
|
||||
FilePath = NULL;
|
||||
FilePathSet = FALSE;
|
||||
|
||||
return BmGetDataStorePath(&Device, &FilePath, &FilePathSet);
|
||||
*/
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
@ -9,15 +9,16 @@ Module Name:
|
||||
|
||||
Abstract:
|
||||
|
||||
Boot manager main routine.
|
||||
Main functions of the boot manager.
|
||||
|
||||
--*/
|
||||
|
||||
#include "bootmgr.h"
|
||||
#include "bootlib.h"
|
||||
|
||||
NTSTATUS
|
||||
BmMain (
|
||||
IN PBOOT_APPLICATION_PARAMETERS ApplicationParameters
|
||||
IN PBOOT_INPUT_PARAMETERS InputParameters
|
||||
)
|
||||
|
||||
/*++
|
||||
@ -28,7 +29,7 @@ Routine Description:
|
||||
|
||||
Arguments:
|
||||
|
||||
ApplicationParameters - Input parameters for the boot manager.
|
||||
InputParameters - Input parameters for the boot manager.
|
||||
|
||||
Return Value:
|
||||
|
||||
@ -40,36 +41,17 @@ Return Value:
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOT_LIBRARY_PARAMETERS LibraryParameters;
|
||||
HANDLE DataStoreHandle;
|
||||
|
||||
LibraryParameters.Flags = 0;
|
||||
LibraryParameters.TranslationType = TRANSLATION_TYPE_NONE;
|
||||
LibraryParameters.MinimumPageAllocation = 16;
|
||||
|
||||
//
|
||||
// Initialize the boot library.
|
||||
//
|
||||
Status = BlInitializeLibrary(ApplicationParameters, &LibraryParameters);
|
||||
Status = BlInitializeLibrary(InputParameters, &LibraryParameters);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ConsolePrintf(L"BlInitializeLibrary() failed: 0x%x\r\n", Status);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Open the boot data store.
|
||||
//
|
||||
(VOID)BmOpenDataStore(&DataStoreHandle);
|
||||
|
||||
//
|
||||
// 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:
|
||||
BlDestroyLibrary();
|
||||
return Status;
|
||||
|
@ -17,505 +17,15 @@ Abstract:
|
||||
#define _BOOTLIB_H
|
||||
|
||||
#include <nt.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.
|
||||
//
|
||||
#include "bootmgr.h"
|
||||
|
||||
typedef struct {
|
||||
ULONG Flags;
|
||||
ULONG TranslationType;
|
||||
ULONG MinimumPageAllocation;
|
||||
} 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
|
||||
ConsolePrint (
|
||||
IN PWSTR String
|
||||
);
|
||||
|
||||
VOID
|
||||
ConsolePrintf (
|
||||
IN PWSTR Format,
|
||||
...
|
||||
);
|
||||
|
||||
VOID
|
||||
BlpArchGetDescriptorTableContext (
|
||||
PDESCRIPTOR_TABLE_CONTEXT Context
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
BlArchIsFiveLevelPagingActive (
|
||||
);
|
||||
|
||||
VOID
|
||||
BlpArchSwitchContext (
|
||||
IN EXECUTION_CONTEXT_TYPE Type
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlpArchInitialize (
|
||||
IN ULONG Stage
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlpFwInitialize (
|
||||
IN ULONG Stage,
|
||||
IN PBOOT_FIRMWARE_DATA FirmwareData
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlpMmDestroy (
|
||||
IN ULONG Stage
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlpMmInitializeConstraints (
|
||||
VOID
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
BlpMmInitialize (
|
||||
IN PBOOT_MEMORY_INFO MemoryInfo,
|
||||
IN ULONG TranslationType,
|
||||
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
|
||||
BlInitializeLibrary (
|
||||
IN PBOOT_APPLICATION_PARAMETERS ApplicationParameters,
|
||||
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
||||
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
|
||||
);
|
||||
|
||||
|
@ -16,16 +16,119 @@ Abstract:
|
||||
#ifndef _BOOTMGR_H
|
||||
#define _BOOTMGR_H
|
||||
|
||||
#include "bootlib.h"
|
||||
#include <nt.h>
|
||||
#include "efi.h"
|
||||
|
||||
NTSTATUS
|
||||
BmOpenDataStore (
|
||||
IN OUT PHANDLE Handle
|
||||
);
|
||||
//
|
||||
// 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
|
||||
|
||||
//
|
||||
// No address translation.
|
||||
//
|
||||
#define BOOT_TRANSLATION_TYPE 0
|
||||
|
||||
//
|
||||
// Use EFI page size.
|
||||
//
|
||||
#define PAGE_SIZE EFI_PAGE_SIZE
|
||||
#define PAGE_SHIFT EFI_PAGE_SHIFT
|
||||
|
||||
#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;
|
||||
|
||||
#define BOOT_APPLICATION_ENTRY_SIGNATURE 0x544e4550415442 /* "BTAPENT" */
|
||||
|
||||
#define BOOT_APPLICATION_ENTRY_BCD_IDENTIFIER_NOT_SET 0x01
|
||||
|
||||
typedef struct {
|
||||
ULONGLONG Signature;
|
||||
ULONG Attributes;
|
||||
GUID BcdIdentifier;
|
||||
} BOOT_APPLICATION_ENTRY, *PBOOT_APPLICATION_ENTRY;
|
||||
|
||||
#define BOOT_MEMORY_INFO_VERSION 1
|
||||
|
||||
typedef struct {
|
||||
ULONG Version;
|
||||
ULONG MdlOffset;
|
||||
ULONG DescriptorCount;
|
||||
ULONG DescriptorSize;
|
||||
ULONG BasePageOffset;
|
||||
} BOOT_MEMORY_INFO, *PBOOT_MEMORY_INFO;
|
||||
|
||||
#define MEMORY_ATTRIBUTE_CACHE_WB 0x08
|
||||
|
||||
#define MEMORY_TYPE_BOOT_APPLICATION 0xd0000002
|
||||
|
||||
typedef struct {
|
||||
LIST_ENTRY ListEntry;
|
||||
|
||||
ULONGLONG BasePage;
|
||||
ULONG Pages;
|
||||
|
||||
ULONG Attributes;
|
||||
ULONG Type;
|
||||
} BOOT_MEMORY_DESCRIPTOR, *PBOOT_MEMORY_DESCRIPTOR;
|
||||
|
||||
#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 {
|
||||
ULONG Size;
|
||||
} BOOT_DEVICE, *PBOOT_DEVICE;
|
||||
|
||||
NTSTATUS
|
||||
BmMain (
|
||||
IN PBOOT_APPLICATION_PARAMETERS ApplicationParameters
|
||||
IN PBOOT_INPUT_PARAMETERS InputParameters
|
||||
);
|
||||
|
||||
#endif
|
||||
|
@ -16,13 +16,48 @@ Abstract:
|
||||
#ifndef _EFIAPI_H
|
||||
#define _EFIAPI_H
|
||||
|
||||
#define EFI_MAKE_REVISION(Major, Minor) (((Major) << 16) | (Minor))
|
||||
#define EFI_SPECIFICATION_MAJOR_REVISION 1
|
||||
#define EFI_SPECIFICATION_MINOR_REVISION 02
|
||||
#define EFI_SPECIFICATION_VERSION EFI_MAKE_REVISION(EFI_SPECIFICATION_MAJOR_REVISION, EFI_SPECIFICATION_MINOR_REVISION)
|
||||
#define EFI_SPECIFICATION_VERSION ((EFI_SPECIFICATION_MAJOR_REVISION << 16) || EFI_SPECIFICATION_MINOR_REVISION)
|
||||
|
||||
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.
|
||||
*/
|
||||
@ -88,16 +123,6 @@ EFI_STATUS
|
||||
IN UINTN Pages
|
||||
);
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_GET_MEMORY_MAP) (
|
||||
IN OUT UINTN *MemoryMapSize,
|
||||
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
|
||||
IN OUT UINTN *MapKey,
|
||||
IN OUT UINTN *DescriptorSize,
|
||||
IN OUT UINT32 *DescriptorVersion
|
||||
);
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_HANDLE_PROTOCOL) (
|
||||
@ -106,42 +131,6 @@ EFI_STATUS
|
||||
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 {
|
||||
EFI_TABLE_HEADER Hdr;
|
||||
|
||||
@ -150,7 +139,7 @@ typedef struct _EFI_BOOT_SERVICES {
|
||||
|
||||
EFI_ALLOCATE_PAGES AllocatePages;
|
||||
EFI_FREE_PAGES FreePages;
|
||||
EFI_GET_MEMORY_MAP GetMemoryMap;
|
||||
EFI_HANDLE GetMemoryMap;
|
||||
EFI_HANDLE AllocatePool;
|
||||
EFI_HANDLE FreePool;
|
||||
|
||||
@ -179,13 +168,13 @@ typedef struct _EFI_BOOT_SERVICES {
|
||||
|
||||
EFI_HANDLE GetNextHighMonotonicCount;
|
||||
EFI_HANDLE Stall;
|
||||
EFI_SET_WATCHDOG_TIMER SetWatchdogTimer;
|
||||
EFI_HANDLE SetWatchdogTimer;
|
||||
|
||||
EFI_HANDLE ConnectController;
|
||||
EFI_HANDLE DisconnectController;
|
||||
|
||||
EFI_OPEN_PROTOCOL OpenProtocol;
|
||||
EFI_CLOSE_PROTOCOL CloseProtocol;
|
||||
EFI_HANDLE OpenProtocol;
|
||||
EFI_HANDLE CloseProtocol;
|
||||
EFI_HANDLE OpenProtocolInformation;
|
||||
|
||||
EFI_HANDLE ProtocolsPerHandle;
|
||||
|
@ -300,85 +300,9 @@ EFI_STATUS
|
||||
);
|
||||
|
||||
typedef struct _SIMPLE_INPUT_INTERFACE {
|
||||
EFI_INPUT_RESET Reset;
|
||||
EFI_INPUT_RESET Reset;
|
||||
EFI_INPUT_READ_KEY ReadKeyStroke;
|
||||
EFI_EVENT WaitForKey;
|
||||
EFI_EVENT WaitForKey;
|
||||
} 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
|
||||
|
@ -24,40 +24,8 @@ typedef struct _EFI_DEVICE_PATH_PROTOCOL {
|
||||
typedef struct _EFI_DEVICE_PATH_PROTOCOL _EFI_DEVICE_PATH;
|
||||
typedef EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH;
|
||||
|
||||
#define END_DEVICE_PATH_TYPE 0x7f
|
||||
|
||||
#define HARDWARE_DEVICE_PATH 0x01
|
||||
|
||||
#define HW_MEMMAP_DP 0x03
|
||||
|
||||
typedef struct {
|
||||
EFI_DEVICE_PATH Header;
|
||||
UINT32 MemoryType;
|
||||
EFI_PHYSICAL_ADDRESS StartingAddress;
|
||||
EFI_PHYSICAL_ADDRESS EndingAddress;
|
||||
} MEMMAP_DEVICE_PATH;
|
||||
|
||||
#define MEDIA_DEVICE_PATH 0x04
|
||||
|
||||
#define MEDIA_HARDDRIVE_DP 0x01
|
||||
|
||||
typedef struct {
|
||||
EFI_DEVICE_PATH Header;
|
||||
UINT32 PartitionNumber;
|
||||
UINT64 PartitionStart;
|
||||
UINT64 PartitionSize;
|
||||
UINT8 Signature[16];
|
||||
UINT8 MBRType;
|
||||
UINT8 SignatureType;
|
||||
} HARDDRIVE_DEVICE_PATH;
|
||||
|
||||
#define MBR_TYPE_PCAT 0x01
|
||||
#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
|
||||
|
||||
#define NO_DISK_SIGNATURE 0x00
|
||||
#define SIGNATURE_TYPE_MBR 0x01
|
||||
#define SIGNATURE_TYPE_GUID 0x02
|
||||
|
||||
#define MEDIA_CDROM_DP 0x02
|
||||
|
||||
typedef struct {
|
||||
@ -67,13 +35,6 @@ typedef struct {
|
||||
UINT64 PartitionSize;
|
||||
} CDROM_DEVICE_PATH;
|
||||
|
||||
#define MEDIA_FILEPATH_DP 0x04
|
||||
|
||||
typedef struct {
|
||||
EFI_DEVICE_PATH Header;
|
||||
CHAR16 PathName[1];
|
||||
} FILEPATH_DEVICE_PATH;
|
||||
|
||||
FORCEINLINE
|
||||
UINT8
|
||||
DevicePathType (
|
||||
|
@ -16,19 +16,11 @@ Abstract:
|
||||
#ifndef _EFILIB_H
|
||||
#define _EFILIB_H
|
||||
|
||||
#include "bootlib.h"
|
||||
#include <nt.h>
|
||||
#include "bootmgr.h"
|
||||
#include "efi.h"
|
||||
|
||||
extern EFI_GUID EfiSimpleTextInputExProtocol;
|
||||
|
||||
PBOOT_APPLICATION_PARAMETERS
|
||||
EfiInitCreateInputParametersEx (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable,
|
||||
IN ULONG Flags
|
||||
);
|
||||
|
||||
PBOOT_APPLICATION_PARAMETERS
|
||||
PBOOT_INPUT_PARAMETERS
|
||||
EfiInitCreateInputParameters (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
@ -39,53 +31,4 @@ EfiGetEfiStatusCode (
|
||||
IN NTSTATUS Status
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
EfiGetNtStatusCode (
|
||||
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
|
||||
|
@ -17,41 +17,9 @@ Abstract:
|
||||
#define _EFIPROT_H
|
||||
|
||||
/*
|
||||
* Loaded image protocol definitions.
|
||||
* Device path 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 \
|
||||
{ 0x9576e91, 0x6d3f, 0x11d2, { 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } }
|
||||
#define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID
|
||||
|
@ -1,123 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
|
||||
mm.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Boot memory manager definitions.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _MM_H
|
||||
#define _MM_H
|
||||
|
||||
#include "bootlib.h"
|
||||
|
||||
#define MDL_OPERATION_FLAGS_TRUNCATE 0x00000002
|
||||
#define MDL_OPERATION_FLAGS_PHYSICAL 0x40000000
|
||||
#define MDL_OPERATION_FLAGS_VIRTUAL 0x80000000
|
||||
|
||||
extern ULONG MmTranslationType;
|
||||
|
||||
NTSTATUS
|
||||
MmFwGetMemoryMap (
|
||||
IN OUT PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN ULONG Flags
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
MmMdpHasPrecedence (
|
||||
IN MEMORY_TYPE A,
|
||||
IN MEMORY_TYPE B
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
MmMdpTruncateDescriptor (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN PMEMORY_DESCRIPTOR Descriptor,
|
||||
IN ULONG Flags
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmMdAddDescriptorToList (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN PMEMORY_DESCRIPTOR Descriptor,
|
||||
IN ULONG Flags
|
||||
);
|
||||
|
||||
VOID
|
||||
MmMdRemoveDescriptorFromList (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN PMEMORY_DESCRIPTOR Descriptor
|
||||
);
|
||||
|
||||
PMEMORY_DESCRIPTOR
|
||||
MmMdFindDescriptorFromMdl (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN ULONGLONG Page,
|
||||
IN ULONG Flags
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmMdRemoveRegionFromMdlEx (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN ULONGLONG FirstPage,
|
||||
IN ULONGLONG PageCount,
|
||||
IN ULONG Flags,
|
||||
OUT PMEMORY_DESCRIPTOR_LIST Unused
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmMdRemoveRegionFromMdl (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN ULONGLONG RemoveStart,
|
||||
IN ULONGLONG PageCount,
|
||||
IN ULONG Flags
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmMdFreeDescriptor (
|
||||
IN PMEMORY_DESCRIPTOR Descriptor
|
||||
);
|
||||
|
||||
VOID
|
||||
MmMdFreeList (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl
|
||||
);
|
||||
|
||||
PMEMORY_DESCRIPTOR
|
||||
MmMdInitDescriptor (
|
||||
IN ULONGLONG FirstPage,
|
||||
IN ULONGLONG MappedFirstPage,
|
||||
IN ULONGLONG PageCount,
|
||||
IN ULONG Attributes,
|
||||
IN MEMORY_TYPE Type
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmMdDestroy (
|
||||
);
|
||||
|
||||
VOID
|
||||
MmMdInitialize (
|
||||
IN ULONG Unused,
|
||||
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmPaDestroy (
|
||||
IN ULONG Stage
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MmPaInitialize (
|
||||
IN PBOOT_MEMORY_INFO MemoryInfo,
|
||||
IN ULONG MinimumAllocation
|
||||
);
|
||||
|
||||
#endif
|
@ -1,91 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
|
||||
eficon.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides EFI console utilities.
|
||||
|
||||
--*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <wchar.h>
|
||||
#include "bootlib.h"
|
||||
|
||||
VOID
|
||||
ConsolePrint (
|
||||
IN PWSTR String
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Prints a string to the console.
|
||||
|
||||
Arguments:
|
||||
|
||||
String.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
EXECUTION_CONTEXT_TYPE ContextType;
|
||||
|
||||
ContextType = CurrentExecutionContext->Type;
|
||||
if (ContextType != ExecutionContextFirmware) {
|
||||
BlpArchSwitchContext(ExecutionContextFirmware);
|
||||
}
|
||||
|
||||
EfiConOut->OutputString(EfiConOut, String);
|
||||
|
||||
if (ContextType != ExecutionContextFirmware) {
|
||||
BlpArchSwitchContext(ContextType);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
ConsolePrintf (
|
||||
IN PWSTR Format,
|
||||
...
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Prints a formatted string to the console.
|
||||
|
||||
Arguments:
|
||||
|
||||
Format - Format string handled by vswprintf().
|
||||
|
||||
... - Arguments.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
int Status;
|
||||
va_list Args;
|
||||
WCHAR Buffer[256];
|
||||
|
||||
va_start(Args, Format);
|
||||
Status = vswprintf(Buffer, sizeof(Buffer) / sizeof(WCHAR) - 1, Format, Args);
|
||||
va_end(Args);
|
||||
if (Status > 0) {
|
||||
ConsolePrint(Buffer);
|
||||
}
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
|
||||
efifw.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides EFI firmware utilities.
|
||||
|
||||
--*/
|
||||
|
||||
#include <ntrtl.h>
|
||||
#include "bootlib.h"
|
||||
#include "efi.h"
|
||||
#include "efilib.h"
|
||||
|
||||
BOOT_FIRMWARE_DATA EfiFirmwareData;
|
||||
PBOOT_FIRMWARE_DATA EfiFirmwareParameters;
|
||||
EFI_HANDLE EfiImageHandle;
|
||||
EFI_SYSTEM_TABLE *EfiST;
|
||||
EFI_BOOT_SERVICES *EfiBS;
|
||||
EFI_RUNTIME_SERVICES *EfiRT;
|
||||
SIMPLE_TEXT_OUTPUT_INTERFACE *EfiConOut;
|
||||
SIMPLE_INPUT_INTERFACE *EfiConIn;
|
||||
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *EfiConInEx;
|
||||
|
||||
NTSTATUS
|
||||
BlpFwInitialize (
|
||||
IN ULONG Stage,
|
||||
IN PBOOT_FIRMWARE_DATA FirmwareData
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Internal routine to initialize the boot library.
|
||||
|
||||
Arguments:
|
||||
|
||||
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.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful,
|
||||
STATUS_INVALID_PARAMETER if FirmwareData is invalid.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
EFI_KEY_TOGGLE_STATE KeyToggleState;
|
||||
|
||||
if (FirmwareData == NULL || FirmwareData->Version == 0) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Stage == 0) {
|
||||
RtlCopyMemory(&EfiFirmwareData, FirmwareData, sizeof(BOOT_FIRMWARE_DATA));
|
||||
EfiFirmwareParameters = &EfiFirmwareData;
|
||||
|
||||
EfiImageHandle = FirmwareData->ImageHandle;
|
||||
EfiST = FirmwareData->SystemTable;
|
||||
EfiBS = EfiST->BootServices;
|
||||
EfiRT = EfiST->RuntimeServices;
|
||||
EfiConOut = EfiST->ConOut;
|
||||
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;
|
||||
}
|
@ -16,435 +16,22 @@ Abstract:
|
||||
#include <ntrtl.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "efilib.h"
|
||||
#include "bootmgr.h"
|
||||
#include "efi.h"
|
||||
|
||||
UCHAR EfiInitScratch[2048];
|
||||
const EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
|
||||
const EFI_GUID EfiDevicePathProtocol = DEVICE_PATH_PROTOCOL;
|
||||
|
||||
NTSTATUS
|
||||
EfiInitpAppendPathString (
|
||||
IN PWCHAR Destination,
|
||||
IN ULONG BufferSize,
|
||||
IN PWCHAR Source,
|
||||
IN ULONG SourceSize,
|
||||
IN OUT PULONG BufferUsed
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Appends a soure path to a destination path.
|
||||
|
||||
Arguments:
|
||||
|
||||
Destination - Path to append Source to.
|
||||
|
||||
BufferSize - Maximum number of bytes to append to Destination.
|
||||
|
||||
Source - Source path to append to Destination.
|
||||
|
||||
SourceSize - Size of Source, in bytes.
|
||||
|
||||
BufferUsed - Pointer to a ULONG recieving the number of bytes appended in.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful,
|
||||
STATUS_INVALID_PARAMETER if Destination is not valid,
|
||||
STATUS_BUFFER_TOO_SMALL if BufferSize is too small.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
ULONG Position;
|
||||
|
||||
//
|
||||
// Verify that Source uses wide characters.
|
||||
//
|
||||
if (SourceSize % sizeof(WCHAR) != 0) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove NULL terminator.
|
||||
//
|
||||
if (SourceSize >= sizeof(WCHAR)) {
|
||||
Position = (SourceSize / sizeof(WCHAR)) - 1;
|
||||
if (Source[Position] == UNICODE_NULL) {
|
||||
SourceSize -= sizeof(UNICODE_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Remove leading separator.
|
||||
//
|
||||
if (SourceSize >= sizeof(WCHAR)) {
|
||||
if (Source[0] == L'\\') {
|
||||
Source++;
|
||||
SourceSize -= sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Remove trailing separator.
|
||||
//
|
||||
if (SourceSize >= sizeof(WCHAR)) {
|
||||
Position = (SourceSize / sizeof(WCHAR)) - 1;
|
||||
if (Source[Position] == L'\\') {
|
||||
SourceSize -= sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check if Source is empty.
|
||||
//
|
||||
if (SourceSize == 0) {
|
||||
*BufferUsed = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure the buffer is large enough.
|
||||
//
|
||||
if (BufferSize < SourceSize + sizeof(WCHAR)) {
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
//
|
||||
// Append separator and Source to Destination.
|
||||
//
|
||||
Destination[0] = L'\\';
|
||||
RtlCopyMemory(Destination + 1, Source, SourceSize);
|
||||
|
||||
*BufferUsed = SourceSize + sizeof(WCHAR);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_DEVICE_PATH *
|
||||
EfiInitpGetDeviceNode (
|
||||
IN EFI_DEVICE_PATH *DevicePath
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Searches an EFI device path for the last device path node
|
||||
before a file path node.
|
||||
|
||||
Arguments:
|
||||
|
||||
DevicePath - EFI_DEVICE_PATH *.
|
||||
|
||||
Return Value:
|
||||
|
||||
EFI_DEVICE_PATH *.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
EFI_DEVICE_PATH *Node;
|
||||
|
||||
if (IsDevicePathEndType(DevicePath)) {
|
||||
return DevicePath;
|
||||
}
|
||||
|
||||
Node = NextDevicePathNode(DevicePath);
|
||||
while (!IsDevicePathEndType(Node)) {
|
||||
if (DevicePathType(Node) == MEDIA_DEVICE_PATH && DevicePathSubType(Node) == MEDIA_FILEPATH_DP) {
|
||||
break;
|
||||
}
|
||||
|
||||
DevicePath = Node;
|
||||
Node = NextDevicePathNode(Node);
|
||||
}
|
||||
|
||||
return DevicePath;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
EfiInitTranslateDevicePath (
|
||||
IN EFI_DEVICE_PATH *EfiDevicePath,
|
||||
IN OUT PBOOT_DEVICE BootDevice,
|
||||
IN ULONG BufferSize
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Translates an EFI_DEVICE_PATH into a BOOT_DEVICE.
|
||||
|
||||
Arguments:
|
||||
|
||||
EfiDevicePath - Path to be translated.
|
||||
|
||||
BootDevice - Pointer to a buffer that recieves the device.
|
||||
|
||||
BufferSize - Amount of available bytes in the buffer.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful.
|
||||
STATUS_INVALID_PARAMETER if the buffer is too small.
|
||||
STATUS_UNSUCCESSFUL if the path could not be translated.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
EFI_DEVICE_PATH *DeviceNode;
|
||||
MEMMAP_DEVICE_PATH *MemmapNode;
|
||||
HARDDRIVE_DEVICE_PATH *HarddriveNode;
|
||||
PBOOT_BLOCK_IDENTIFIER BlockDevice;
|
||||
|
||||
if (BufferSize < sizeof(BOOT_DEVICE)) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
BootDevice->Size = sizeof(BOOT_DEVICE);
|
||||
|
||||
//
|
||||
// Memory map devices are treated as ramdisks.
|
||||
//
|
||||
if (DevicePathType(EfiDevicePath) == HARDWARE_DEVICE_PATH && DevicePathSubType(EfiDevicePath) == HW_MEMMAP_DP) {
|
||||
MemmapNode = (MEMMAP_DEVICE_PATH *)EfiDevicePath;
|
||||
BlockDevice = &BootDevice->Block;
|
||||
BootDevice->Type = BOOT_DEVICE_TYPE_BLOCK;
|
||||
BlockDevice->Type = BOOT_BLOCK_DEVICE_TYPE_RAMDISK;
|
||||
BlockDevice->Ramdisk.ImageBase.QuadPart = MemmapNode->StartingAddress;
|
||||
BlockDevice->Ramdisk.ImageSize = MemmapNode->EndingAddress - MemmapNode->StartingAddress;
|
||||
BlockDevice->Ramdisk.ImageOffset = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: Support more devices than just HDD/CD-ROM and ramdisks.
|
||||
//
|
||||
DeviceNode = EfiInitpGetDeviceNode(EfiDevicePath);
|
||||
if (DevicePathType(DeviceNode) != MEDIA_DEVICE_PATH) {
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
switch (DevicePathSubType(DeviceNode)) {
|
||||
case MEDIA_HARDDRIVE_DP:
|
||||
HarddriveNode = (HARDDRIVE_DEVICE_PATH *)DeviceNode;
|
||||
|
||||
//
|
||||
// MBR disks still use the old partition struct.
|
||||
//
|
||||
if (HarddriveNode->SignatureType != SIGNATURE_TYPE_MBR) {
|
||||
BlockDevice = &BootDevice->PartitionEx.Parent;
|
||||
BootDevice->Type = BOOT_DEVICE_TYPE_PARTITION_EX;
|
||||
} else {
|
||||
BlockDevice = &BootDevice->Partition.Parent;
|
||||
BootDevice->Type = BOOT_DEVICE_TYPE_PARTITION;
|
||||
}
|
||||
BlockDevice->Type = BOOT_BLOCK_DEVICE_TYPE_HARDDRIVE;
|
||||
|
||||
switch (HarddriveNode->SignatureType) {
|
||||
case SIGNATURE_TYPE_MBR:
|
||||
BlockDevice->Harddrive.PartitionType = BOOT_HARDDRIVE_PARTITION_TYPE_MBR;
|
||||
BlockDevice->Harddrive.Mbr.Signature = *((ULONG *)HarddriveNode->Signature);
|
||||
BootDevice->Partition.Mbr.PartitionNumber = HarddriveNode->PartitionNumber;
|
||||
break;
|
||||
case SIGNATURE_TYPE_GUID:
|
||||
BootDevice->Attributes |= BOOT_DEVICE_ATTRIBUTE_NO_PARENT_SIGNATURE;
|
||||
BlockDevice->Harddrive.PartitionType = BOOT_HARDDRIVE_PARTITION_TYPE_GPT;
|
||||
RtlCopyMemory(&BootDevice->PartitionEx.Gpt.PartitionIdentifier, &HarddriveNode->Signature, sizeof(HarddriveNode->Signature));
|
||||
break;
|
||||
default:
|
||||
BlockDevice->Harddrive.PartitionType = BOOT_HARDDRIVE_PARTITION_TYPE_RAW;
|
||||
BlockDevice->Harddrive.Raw.DriveNumber = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case MEDIA_CDROM_DP:
|
||||
BootDevice->Type = BOOT_DEVICE_TYPE_BLOCK;
|
||||
BootDevice->Block.Type = BOOT_BLOCK_DEVICE_TYPE_CDROM;
|
||||
BootDevice->Block.Cdrom.DriveNumber = 0;
|
||||
break;
|
||||
default:
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
EfiInitpConvertEfiDevicePath (
|
||||
IN EFI_DEVICE_PATH *EfiDevicePath,
|
||||
IN BCDE_DATA_TYPE OptionType,
|
||||
IN OUT PBOOT_ENTRY_OPTION Option,
|
||||
IN ULONG BufferSize
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Converts an EFI device path into option format.
|
||||
|
||||
Arguments:
|
||||
|
||||
EfiDevicePath - Path to be converted.
|
||||
|
||||
OptionType - The data type to be assigned to Option->Type.
|
||||
|
||||
Option - Pointer to a buffer that recieves the option.
|
||||
|
||||
BufferSize - The amount of available bytes in the buffer.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful.
|
||||
STATUS_INVALID_PARAMETER if the buffer is too small.
|
||||
Any status code returned by EfiInitTranslateDevicePath().
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PBCDE_DEVICE DeviceElement;
|
||||
|
||||
if (BufferSize < sizeof(BOOT_ENTRY_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device)) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
RtlZeroMemory(Option, sizeof(BOOT_ENTRY_OPTION));
|
||||
DeviceElement = (PBCDE_DEVICE)((PUCHAR)Option + sizeof(BOOT_ENTRY_OPTION));
|
||||
Status = EfiInitTranslateDevicePath(
|
||||
EfiDevicePath,
|
||||
&DeviceElement->Device,
|
||||
BufferSize - (sizeof(BOOT_ENTRY_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device))
|
||||
);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Option->Type = OptionType;
|
||||
Option->DataOffset = sizeof(BOOT_ENTRY_OPTION);
|
||||
Option->DataSize = FIELD_OFFSET(BCDE_DEVICE, Device) + DeviceElement->Device.Size;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
EfiInitpConvertEfiFilePath (
|
||||
IN EFI_DEVICE_PATH *EfiFilePath,
|
||||
IN BCDE_DATA_TYPE OptionType,
|
||||
IN OUT PBOOT_ENTRY_OPTION Option,
|
||||
IN ULONG BufferSize
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Converts an EFI file path into option format.
|
||||
|
||||
Arguments:
|
||||
|
||||
EfiFilePath - Path to be converted.
|
||||
|
||||
OptionType - The data type to be assigned to Option->Type.
|
||||
|
||||
Option - Pointer to a buffer that recieves the option.
|
||||
|
||||
BufferSize - The amount of available bytes in the buffer.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful.
|
||||
STATUS_INVALID_PARAMETER if the buffer is too small.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
EFI_DEVICE_PATH *Node;
|
||||
PWCHAR PathStart, Position;
|
||||
ULONG BufferRemaining, Length, Appended;
|
||||
|
||||
if (BufferSize < sizeof(BOOT_ENTRY_OPTION)) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
RtlZeroMemory(Option, sizeof(BOOT_ENTRY_OPTION));
|
||||
Option->Type = OptionType;
|
||||
Option->DataOffset = sizeof(BOOT_ENTRY_OPTION);
|
||||
|
||||
//
|
||||
// Loop through nodes and add one at a time.
|
||||
//
|
||||
Option->DataSize = 0;
|
||||
BufferRemaining = BufferSize - sizeof(BOOT_ENTRY_OPTION);
|
||||
Node = EfiFilePath;
|
||||
PathStart = (PWCHAR)((PUCHAR)Option + Option->DataOffset);
|
||||
Position = PathStart;
|
||||
while (!IsDevicePathEndType(Node)) {
|
||||
//
|
||||
// Ignore non-filepath nodes.
|
||||
//
|
||||
if (DevicePathType(Node) != MEDIA_DEVICE_PATH || DevicePathSubType(Node) != MEDIA_FILEPATH_DP) {
|
||||
Node = NextDevicePathNode(Node);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the length of this path.
|
||||
//
|
||||
Status = RtlULongSub(DevicePathNodeLength(Node), FIELD_OFFSET(FILEPATH_DEVICE_PATH, PathName), &Length);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Append this path to the path string.
|
||||
//
|
||||
Status = EfiInitpAppendPathString(Position, BufferRemaining, &((FILEPATH_DEVICE_PATH *)Node)->PathName[0], Length, &Appended);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Update counters & position.
|
||||
//
|
||||
Option->DataSize += Appended;
|
||||
BufferRemaining -= Appended;
|
||||
Position = (PWCHAR)((PUCHAR)Position + Appended);
|
||||
Node = NextDevicePathNode(Node);
|
||||
}
|
||||
|
||||
//
|
||||
// NULL-terminate path string.
|
||||
//
|
||||
if (BufferRemaining < sizeof(UNICODE_NULL)) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
*Position = L'\0';
|
||||
Option->DataSize += sizeof(UNICODE_NULL);
|
||||
|
||||
//
|
||||
// The option is invalid if the path is empty.
|
||||
//
|
||||
if (Position == PathStart) {
|
||||
Option->IsInvalid = TRUE;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
EfiInitpCreateApplicationEntry (
|
||||
IN EFI_SYSTEM_TABLE *SystemTable,
|
||||
IN OUT PBOOT_INIT_APPLICATION_ENTRY Entry,
|
||||
IN OUT PBOOT_APPLICATION_ENTRY Entry,
|
||||
IN ULONG BufferSize,
|
||||
IN EFI_DEVICE_PATH *EfiDevicePath,
|
||||
IN EFI_DEVICE_PATH *EfiFilePath,
|
||||
IN EFI_DEVICE_PATH *DevicePath,
|
||||
IN EFI_DEVICE_PATH *FilePath,
|
||||
IN PWCHAR LoadOptions,
|
||||
IN ULONG LoadOptionsSize,
|
||||
IN ULONG Flags,
|
||||
OUT PULONG BufferUsed,
|
||||
OUT PBOOT_DEVICE *BootDevice
|
||||
)
|
||||
@ -453,29 +40,27 @@ EfiInitpCreateApplicationEntry (
|
||||
|
||||
Routine Description:
|
||||
|
||||
Creates an application entry for the boot application.
|
||||
Creates an application entry structure for the boot application.
|
||||
|
||||
Arguments:
|
||||
|
||||
SystemTable - Pointer to the EFI system table.
|
||||
|
||||
Entry - Pointer to a buffer that recieves the entry.
|
||||
Entry - A buffer to put the entry in.
|
||||
|
||||
BufferSize - The amount of available bytes in the buffer.
|
||||
BufferSize - The amount of available space in the buffer.
|
||||
|
||||
EfiDevicePath - The application's device path.
|
||||
DevicePath - The device path for the application.
|
||||
|
||||
EfiFilePath - The application's file path.
|
||||
FilePath - The file path for the application.
|
||||
|
||||
LoadOptions - Firmware load options string.
|
||||
|
||||
LoadOptionsSize - Size in bytes of the string pointed to by LoadOptions.
|
||||
LoadOptionsSize - Length of the string pointed to by LoadOptions.
|
||||
|
||||
Flags - Unused.
|
||||
BufferUsed - Returns the amount of buffer space used by the routine.
|
||||
|
||||
BufferUsed - Pointer to a ULONG that recieves the buffer space used by this routine.
|
||||
|
||||
BootDevice - Pointer to a PBOOT_DEVICE that recieves the device the application was loaded from.
|
||||
BootDevice - Returns a pointer to the device the application was loaded from.
|
||||
|
||||
Return Value:
|
||||
|
||||
@ -484,33 +69,23 @@ Return Value:
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG BufferRemaining, OptionsSize, Size;
|
||||
PWCHAR BcdOptionString;
|
||||
BOOLEAN BcdIdentifierSet;
|
||||
UNICODE_STRING UnicodeString;
|
||||
PBOOT_ENTRY_OPTION Option, PrevOption;
|
||||
PBCDE_DEVICE BootDeviceElement;
|
||||
|
||||
(VOID)SystemTable;
|
||||
(VOID)Flags;
|
||||
|
||||
*BufferUsed = 0;
|
||||
*BootDevice = NULL;
|
||||
OptionsSize = 0;
|
||||
BcdIdentifierSet = FALSE;
|
||||
|
||||
BufferRemaining = BufferSize;
|
||||
if (BufferRemaining < sizeof(BOOT_INIT_APPLICATION_ENTRY)) {
|
||||
//
|
||||
// Require enough space for the application entry.
|
||||
//
|
||||
if (BufferSize < sizeof(BOOT_APPLICATION_ENTRY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RtlZeroMemory(Entry, sizeof(BOOT_INIT_APPLICATION_ENTRY));
|
||||
Entry->Signature = BOOT_INIT_APPLICATION_ENTRY_SIGNATURE;
|
||||
BufferRemaining -= FIELD_OFFSET(BOOT_INIT_APPLICATION_ENTRY, Options);
|
||||
|
||||
//
|
||||
// Terminate load options.
|
||||
// Terminate load options string.
|
||||
//
|
||||
LoadOptionsSize /= sizeof(WCHAR);
|
||||
if (LoadOptionsSize != 0 && wcsnlen(LoadOptions, LoadOptionsSize) == LoadOptionsSize) {
|
||||
@ -518,7 +93,14 @@ Return Value:
|
||||
}
|
||||
|
||||
//
|
||||
// Parse BCD GUID option if present.
|
||||
// Set up application entry structure.
|
||||
//
|
||||
RtlZeroMemory(Entry, sizeof(BOOT_APPLICATION_ENTRY));
|
||||
Entry->Signature = BOOT_APPLICATION_ENTRY_SIGNATURE;
|
||||
*BufferUsed = sizeof(BOOT_APPLICATION_ENTRY);
|
||||
|
||||
//
|
||||
// Parse BCD GUID if present.
|
||||
//
|
||||
if (LoadOptions != NULL && (BcdOptionString = wcsstr(LoadOptions, L"BCDOBJECT=")) != NULL) {
|
||||
RtlInitUnicodeString(&UnicodeString, (PWCHAR)((PUCHAR)BcdOptionString + sizeof(L"BCDOBJECT=") - sizeof(UNICODE_NULL)));
|
||||
@ -528,197 +110,18 @@ Return Value:
|
||||
}
|
||||
|
||||
if (!BcdIdentifierSet) {
|
||||
Entry->Attributes |= BOOT_APPLICATION_ENTRY_NO_BCD_IDENTIFIER;
|
||||
Entry->Attributes |= BOOT_APPLICATION_ENTRY_BCD_IDENTIFIER_NOT_SET;
|
||||
}
|
||||
|
||||
//
|
||||
// Convert the EFI device path into a boot device option.
|
||||
// TODO: This routine is not fully implemented.
|
||||
//
|
||||
Option = &Entry->Options;
|
||||
Status = EfiInitpConvertEfiDevicePath(EfiDevicePath, BCDE_DATA_TYPE_APPLICATION_DEVICE, Option, BufferRemaining);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
Option->IsInvalid = TRUE;
|
||||
goto exit;
|
||||
}
|
||||
BootDeviceElement = (PBCDE_DEVICE)((PUCHAR)Option + Option->DataOffset);
|
||||
*BootDevice = &BootDeviceElement->Device;
|
||||
Size = BlGetBootOptionSize(Option);
|
||||
OptionsSize += Size;
|
||||
BufferRemaining -= Size;
|
||||
|
||||
//
|
||||
// Convert the EFI file path into a boot file path option.
|
||||
// TODO: Support UDP/PXE boot.
|
||||
//
|
||||
PrevOption = Option;
|
||||
Option = (PBOOT_ENTRY_OPTION)((PUCHAR)&Entry->Options + OptionsSize);
|
||||
Status = EfiInitpConvertEfiFilePath(EfiFilePath, BCDE_DATA_TYPE_APPLICATION_PATH, Option, BufferRemaining);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto exit;
|
||||
}
|
||||
PrevOption->NextOptionOffset = (PUCHAR)Option - (PUCHAR)&Entry->Options;
|
||||
Size = BlGetBootOptionSize(Option);
|
||||
OptionsSize += Size;
|
||||
BufferRemaining -= Size;
|
||||
|
||||
//
|
||||
// TODO: Parse additional options from LoadOptions.
|
||||
//
|
||||
PrevOption = Option;
|
||||
Option = (PBOOT_ENTRY_OPTION)((PUCHAR)&Entry->Options + OptionsSize);
|
||||
// Status = Unknown(LoadOptions, &Entry->Options, RemainingSize, &OptionsSize, &PrevOption, &Size);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
*BufferUsed = BufferSize - BufferRemaining;
|
||||
(VOID)SystemTable;
|
||||
(VOID)DevicePath;
|
||||
(VOID)FilePath;
|
||||
}
|
||||
|
||||
PBOOT_APPLICATION_PARAMETERS
|
||||
EfiInitCreateInputParametersEx (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable,
|
||||
IN ULONG Flags
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
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.
|
||||
|
||||
Flags - Unused.
|
||||
|
||||
Return Value:
|
||||
|
||||
Pointer to parameter structure if successful.
|
||||
NULL on failure.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ULONG ScratchUsed;
|
||||
ULONG ApplicationEntrySize;
|
||||
EFI_PHYSICAL_ADDRESS BadPageAddress;
|
||||
EFI_LOADED_IMAGE *LoadedImage;
|
||||
EFI_DEVICE_PATH *DevicePath;
|
||||
PBOOT_APPLICATION_PARAMETERS InputParameters;
|
||||
PBOOT_MEMORY_INFO MemoryInfo;
|
||||
PMEMORY_DESCRIPTOR MemoryDescriptor;
|
||||
PBOOT_DEVICE BootDevice;
|
||||
PBOOT_FIRMWARE_DATA FirmwareData;
|
||||
PBOOT_RETURN_DATA ReturnData;
|
||||
|
||||
ScratchUsed = 0;
|
||||
|
||||
//
|
||||
// Page 0x102 may be broken on some machines.
|
||||
// It is mapped here so that it does not get used.
|
||||
//
|
||||
BadPageAddress = 0x102 << PAGE_SHIFT;
|
||||
SystemTable->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, 1, &BadPageAddress);
|
||||
|
||||
Status = SystemTable->BootServices->HandleProtocol(
|
||||
ImageHandle,
|
||||
(EFI_GUID*)&EfiLoadedImageProtocol,
|
||||
(VOID**)&LoadedImage
|
||||
);
|
||||
if (Status != EFI_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status = SystemTable->BootServices->HandleProtocol(
|
||||
LoadedImage->DeviceHandle,
|
||||
(EFI_GUID*)&EfiDevicePathProtocol,
|
||||
(VOID**)&DevicePath
|
||||
);
|
||||
if (Status != EFI_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InputParameters = (PBOOT_APPLICATION_PARAMETERS)(&EfiInitScratch[ScratchUsed]);
|
||||
ScratchUsed += sizeof(BOOT_APPLICATION_PARAMETERS);
|
||||
InputParameters->Signature = BOOT_APPLICATION_PARAMETERS_SIGNATURE;
|
||||
InputParameters->Version = BOOT_APPLICATION_PARAMETERS_VERSION;
|
||||
InputParameters->MachineType = BOOT_MACHINE_TYPE;
|
||||
InputParameters->TranslationType = TRANSLATION_TYPE_NONE;
|
||||
InputParameters->ImageBase = LoadedImage->ImageBase;
|
||||
InputParameters->ImageSize = LoadedImage->ImageSize;
|
||||
|
||||
InputParameters->MemoryInfoOffset = ScratchUsed;
|
||||
MemoryInfo = (PBOOT_MEMORY_INFO)(&EfiInitScratch[ScratchUsed]);
|
||||
ScratchUsed += sizeof(BOOT_MEMORY_INFO);
|
||||
MemoryInfo->Version = BOOT_MEMORY_INFO_VERSION;
|
||||
MemoryInfo->MdlOffset = sizeof(BOOT_MEMORY_INFO);
|
||||
MemoryInfo->DescriptorCount = 1;
|
||||
MemoryInfo->DescriptorSize = sizeof(MEMORY_DESCRIPTOR);
|
||||
MemoryInfo->FirstPageOffset = FIELD_OFFSET(MEMORY_DESCRIPTOR, FirstPage);
|
||||
|
||||
MemoryDescriptor = (PMEMORY_DESCRIPTOR)(&EfiInitScratch[ScratchUsed]);
|
||||
ScratchUsed += sizeof(MEMORY_DESCRIPTOR);
|
||||
MemoryDescriptor->FirstPage = (UINTN)InputParameters->ImageBase >> PAGE_SHIFT;
|
||||
MemoryDescriptor->PageCount = ALIGN_UP(InputParameters->ImageSize, PAGE_SIZE) >> PAGE_SHIFT;
|
||||
MemoryDescriptor->Attributes = MEMORY_ATTRIBUTE_WB;
|
||||
MemoryDescriptor->Type = MEMORY_TYPE_BOOT_APPLICATION;
|
||||
|
||||
InputParameters->ApplicationEntryOffset = ScratchUsed;
|
||||
EfiInitpCreateApplicationEntry(
|
||||
SystemTable,
|
||||
(PBOOT_INIT_APPLICATION_ENTRY)(&EfiInitScratch[ScratchUsed]),
|
||||
sizeof(EfiInitScratch) - ScratchUsed,
|
||||
DevicePath,
|
||||
LoadedImage->FilePath,
|
||||
LoadedImage->LoadOptions,
|
||||
LoadedImage->LoadOptionsSize,
|
||||
Flags,
|
||||
&ApplicationEntrySize,
|
||||
&BootDevice
|
||||
);
|
||||
ScratchUsed += ApplicationEntrySize;
|
||||
|
||||
InputParameters->BootDeviceOffset = ScratchUsed;
|
||||
if (BootDevice != NULL) {
|
||||
RtlCopyMemory(&EfiInitScratch[ScratchUsed], BootDevice, BootDevice->Size);
|
||||
ScratchUsed += BootDevice->Size;
|
||||
} else {
|
||||
RtlZeroMemory(&EfiInitScratch[ScratchUsed], sizeof(BOOT_DEVICE));
|
||||
ScratchUsed += sizeof(BOOT_DEVICE);
|
||||
}
|
||||
|
||||
InputParameters->FirmwareDataOffset = ScratchUsed;
|
||||
FirmwareData = (PBOOT_FIRMWARE_DATA)(&EfiInitScratch[ScratchUsed]);
|
||||
ScratchUsed += sizeof(BOOT_FIRMWARE_DATA);
|
||||
RtlZeroMemory(FirmwareData, sizeof(BOOT_FIRMWARE_DATA));
|
||||
FirmwareData->Version = BOOT_FIRMWARE_DATA_VERSION;
|
||||
FirmwareData->ImageHandle = ImageHandle;
|
||||
FirmwareData->SystemTable = SystemTable;
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
asm volatile("mov %%cr3, %0" :"=r"(FirmwareData->Cr3));
|
||||
#endif
|
||||
BlpArchGetDescriptorTableContext(&FirmwareData->DescriptorTableContext);
|
||||
|
||||
InputParameters->ReturnDataOffset = ScratchUsed;
|
||||
ReturnData = (PBOOT_RETURN_DATA)(&EfiInitScratch[ScratchUsed]);
|
||||
ScratchUsed += sizeof(BOOT_RETURN_DATA);
|
||||
ReturnData->Version = BOOT_RETURN_DATA_VERSION;
|
||||
|
||||
InputParameters->Size = ScratchUsed;
|
||||
if (InputParameters->Size > sizeof(EfiInitScratch)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return InputParameters;
|
||||
}
|
||||
|
||||
PBOOT_APPLICATION_PARAMETERS
|
||||
PBOOT_INPUT_PARAMETERS
|
||||
EfiInitCreateInputParameters (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
@ -732,17 +135,150 @@ Routine Description:
|
||||
|
||||
Arguments:
|
||||
|
||||
ImageHandle - EFI handle for the boot application image.
|
||||
ImageHandle - Handle for the boot manager image.
|
||||
|
||||
SystemTable - Pointer to the EFI system table.
|
||||
|
||||
Return Value:
|
||||
|
||||
Pointer to parameter structure if successful.
|
||||
NULL on failure.
|
||||
Pointer to parameter structure on success or NULL on failure.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
return EfiInitCreateInputParametersEx(ImageHandle, SystemTable, 0);
|
||||
ULONG ScratchUsed = 0;
|
||||
ULONG ApplicationEntrySize = 0;
|
||||
EFI_STATUS Status;
|
||||
EFI_PHYSICAL_ADDRESS BadPageAddress;
|
||||
EFI_LOADED_IMAGE *LoadedImage;
|
||||
EFI_DEVICE_PATH *DevicePath;
|
||||
PBOOT_INPUT_PARAMETERS InputParameters;
|
||||
PBOOT_MEMORY_INFO MemoryInfo;
|
||||
PBOOT_MEMORY_DESCRIPTOR MemoryDescriptor;
|
||||
PBOOT_DEVICE BootDevice;
|
||||
PBOOT_FIRMWARE_DATA FirmwareData;
|
||||
PBOOT_RETURN_DATA ReturnData;
|
||||
|
||||
//
|
||||
// Page 0x102 may be broken on some machines.
|
||||
// It is mapped here so that it does not get used.
|
||||
//
|
||||
BadPageAddress = 0x102 << PAGE_SHIFT;
|
||||
SystemTable->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, 1, &BadPageAddress);
|
||||
|
||||
//
|
||||
// Get boot manager image information.
|
||||
//
|
||||
Status = SystemTable->BootServices->HandleProtocol(
|
||||
ImageHandle,
|
||||
(EFI_GUID*)&EfiLoadedImageProtocol,
|
||||
(VOID**)&LoadedImage
|
||||
);
|
||||
if (Status != EFI_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Get boot manager image device path.
|
||||
//
|
||||
Status = SystemTable->BootServices->HandleProtocol(
|
||||
LoadedImage->DeviceHandle,
|
||||
(EFI_GUID*)&EfiDevicePathProtocol,
|
||||
(VOID**)&DevicePath
|
||||
);
|
||||
if (Status != EFI_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Create input parameters structure.
|
||||
//
|
||||
InputParameters = (PBOOT_INPUT_PARAMETERS)(&EfiInitScratch[ScratchUsed]);
|
||||
ScratchUsed += sizeof(BOOT_INPUT_PARAMETERS);
|
||||
InputParameters->Signature = BOOT_INPUT_PARAMETERS_SIGNATURE;
|
||||
InputParameters->Version = BOOT_INPUT_PARAMETERS_VERSION;
|
||||
InputParameters->MachineType = BOOT_MACHINE_TYPE;
|
||||
InputParameters->TranslationType = BOOT_TRANSLATION_TYPE;
|
||||
InputParameters->ImageBase = LoadedImage->ImageBase;
|
||||
InputParameters->ImageSize = LoadedImage->ImageSize;
|
||||
|
||||
//
|
||||
// Create memory info structure.
|
||||
//
|
||||
InputParameters->MemoryInfoOffset = ScratchUsed;
|
||||
MemoryInfo = (PBOOT_MEMORY_INFO)(&EfiInitScratch[ScratchUsed]);
|
||||
ScratchUsed += sizeof(BOOT_MEMORY_INFO);
|
||||
MemoryInfo->Version = BOOT_MEMORY_INFO_VERSION;
|
||||
MemoryInfo->MdlOffset = sizeof(BOOT_MEMORY_INFO);
|
||||
MemoryInfo->DescriptorCount = 1;
|
||||
MemoryInfo->DescriptorSize = sizeof(BOOT_MEMORY_DESCRIPTOR);
|
||||
MemoryInfo->BasePageOffset = FIELD_OFFSET(BOOT_MEMORY_DESCRIPTOR, BasePage);
|
||||
|
||||
//
|
||||
// Create a memory descriptor for the boot manager image.
|
||||
//
|
||||
MemoryDescriptor = (PBOOT_MEMORY_DESCRIPTOR)(&EfiInitScratch[ScratchUsed]);
|
||||
ScratchUsed += sizeof(BOOT_MEMORY_DESCRIPTOR);
|
||||
MemoryDescriptor->BasePage = (UINTN)InputParameters->ImageBase >> PAGE_SHIFT;
|
||||
MemoryDescriptor->Pages = ALIGN_UP(InputParameters->ImageSize, PAGE_SIZE) >> PAGE_SHIFT;
|
||||
MemoryDescriptor->Attributes = MEMORY_ATTRIBUTE_CACHE_WB;
|
||||
MemoryDescriptor->Type = MEMORY_TYPE_BOOT_APPLICATION;
|
||||
|
||||
//
|
||||
// Create an application entry for the boot application.
|
||||
//
|
||||
InputParameters->ApplicationEntryOffset = ScratchUsed;
|
||||
EfiInitpCreateApplicationEntry(
|
||||
SystemTable,
|
||||
(PBOOT_APPLICATION_ENTRY)(&EfiInitScratch[ScratchUsed]),
|
||||
sizeof(EfiInitScratch) - ScratchUsed,
|
||||
DevicePath,
|
||||
LoadedImage->FilePath,
|
||||
LoadedImage->LoadOptions,
|
||||
LoadedImage->LoadOptionsSize,
|
||||
&ApplicationEntrySize,
|
||||
&BootDevice
|
||||
);
|
||||
ScratchUsed += ApplicationEntrySize;
|
||||
|
||||
//
|
||||
// Copy application device to scratch area.
|
||||
//
|
||||
InputParameters->BootDeviceOffset = ScratchUsed;
|
||||
if (BootDevice != NULL) {
|
||||
RtlCopyMemory(&EfiInitScratch[ScratchUsed], BootDevice, BootDevice->Size);
|
||||
ScratchUsed += BootDevice->Size;
|
||||
} else {
|
||||
RtlZeroMemory(&EfiInitScratch[ScratchUsed], sizeof(BOOT_DEVICE));
|
||||
ScratchUsed += sizeof(BOOT_DEVICE);
|
||||
}
|
||||
|
||||
//
|
||||
// Create firmware data structure.
|
||||
//
|
||||
InputParameters->FirmwareDataOffset = ScratchUsed;
|
||||
FirmwareData = (PBOOT_FIRMWARE_DATA)(&EfiInitScratch[ScratchUsed]);
|
||||
ScratchUsed += sizeof(BOOT_FIRMWARE_DATA);
|
||||
FirmwareData->Version = BOOT_FIRMWARE_DATA_VERSION;
|
||||
FirmwareData->Reserved = 0;
|
||||
FirmwareData->ImageHandle = ImageHandle;
|
||||
FirmwareData->SystemTable = SystemTable;
|
||||
|
||||
//
|
||||
// Create return data structure.
|
||||
//
|
||||
InputParameters->ReturnDataOffset = ScratchUsed;
|
||||
ReturnData = (PBOOT_RETURN_DATA)(&EfiInitScratch[ScratchUsed]);
|
||||
ScratchUsed += sizeof(BOOT_RETURN_DATA);
|
||||
ReturnData->Version = BOOT_RETURN_DATA_VERSION;
|
||||
|
||||
//
|
||||
// Set and validate total size.
|
||||
//
|
||||
InputParameters->Size = ScratchUsed;
|
||||
if (InputParameters->Size > sizeof(EfiInitScratch)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return InputParameters;
|
||||
}
|
||||
|
@ -13,10 +13,8 @@ Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#include "efilib.h"
|
||||
#include "mm.h"
|
||||
|
||||
EFI_GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
|
||||
#include "bootmgr.h"
|
||||
#include "efi.h"
|
||||
|
||||
EFI_STATUS
|
||||
EfiGetEfiStatusCode (
|
||||
@ -31,7 +29,7 @@ Routine Description:
|
||||
|
||||
Arguments:
|
||||
|
||||
Status - The NT status code.
|
||||
Status - The NT status code to be converted.
|
||||
|
||||
Return Value:
|
||||
|
||||
@ -58,7 +56,6 @@ Return Value:
|
||||
case STATUS_MEDIA_WRITE_PROTECTED:
|
||||
return EFI_WRITE_PROTECTED;
|
||||
case STATUS_INSUFFICIENT_RESOURCES:
|
||||
case STATUS_INSUFFICIENT_NVRAM_RESOURCES:
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
case STATUS_DISK_CORRUPT_ERROR:
|
||||
return EFI_VOLUME_CORRUPTED;
|
||||
@ -86,451 +83,3 @@ Return Value:
|
||||
return EFI_NO_MAPPING;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
EfiGetNtStatusCode (
|
||||
IN EFI_STATUS Status
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Converts an EFI status code into an NT status code.
|
||||
|
||||
Arguments:
|
||||
|
||||
Status - The EFI status code.
|
||||
|
||||
Return Value:
|
||||
|
||||
The NT status code.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
switch (Status) {
|
||||
case EFI_SUCCESS:
|
||||
return STATUS_SUCCESS;
|
||||
case EFI_LOAD_ERROR:
|
||||
return STATUS_DRIVER_UNABLE_TO_LOAD;
|
||||
case EFI_INVALID_PARAMETER:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
case EFI_UNSUPPORTED:
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
case EFI_BAD_BUFFER_SIZE:
|
||||
return STATUS_INVALID_BUFFER_SIZE;
|
||||
case EFI_BUFFER_TOO_SMALL:
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
case EFI_DEVICE_ERROR:
|
||||
return STATUS_IO_DEVICE_ERROR;
|
||||
case EFI_WRITE_PROTECTED:
|
||||
return STATUS_MEDIA_WRITE_PROTECTED;
|
||||
case EFI_OUT_OF_RESOURCES:
|
||||
return STATUS_INSUFFICIENT_NVRAM_RESOURCES;
|
||||
case EFI_VOLUME_CORRUPTED:
|
||||
return STATUS_DISK_CORRUPT_ERROR;
|
||||
case EFI_VOLUME_FULL:
|
||||
return STATUS_DISK_FULL;
|
||||
case EFI_NO_MEDIA:
|
||||
return STATUS_NO_MEDIA;
|
||||
case EFI_MEDIA_CHANGED:
|
||||
return STATUS_MEDIA_CHANGED;
|
||||
case EFI_NOT_FOUND:
|
||||
case EFI_NOT_READY:
|
||||
return STATUS_NOT_FOUND;
|
||||
case EFI_ACCESS_DENIED:
|
||||
case EFI_SECURITY_VIOLATION:
|
||||
return STATUS_ACCESS_DENIED;
|
||||
case EFI_NO_MAPPING:
|
||||
return STATUS_NO_MATCH;
|
||||
case EFI_TIMEOUT:
|
||||
case EFI_NO_RESPONSE:
|
||||
return STATUS_TIMEOUT;
|
||||
case EFI_NOT_STARTED:
|
||||
return STATUS_DEVICE_NOT_READY;
|
||||
case EFI_ALREADY_STARTED:
|
||||
return STATUS_DEVICE_ALREADY_ATTACHED;
|
||||
case EFI_ABORTED:
|
||||
return STATUS_REQUEST_ABORTED;
|
||||
default:
|
||||
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);
|
||||
}
|
||||
|
@ -1,512 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
|
||||
efimm.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides EFI memory manager routines.
|
||||
|
||||
--*/
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "efi.h"
|
||||
#include "efilib.h"
|
||||
#include "mm.h"
|
||||
|
||||
#define _1MiB 1048576
|
||||
|
||||
#define EFI_PAGE(NtPage) (((NtPage) << PAGE_SHIFT) >> EFI_PAGE_SHIFT)
|
||||
#define NT_PAGE(EfiPage) (((EfiPage) << EFI_PAGE_SHIFT) >> PAGE_SHIFT)
|
||||
|
||||
MEMORY_TYPE
|
||||
BlMmTranslateEfiMemoryType (
|
||||
IN EFI_MEMORY_TYPE EfiMemoryType
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Translates an EFI memory type to an NT memory type.
|
||||
|
||||
Arguments:
|
||||
|
||||
EfiMemoryType - the EFI memory type.
|
||||
|
||||
Return Value:
|
||||
|
||||
The NT memory type.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
switch (EfiMemoryType) {
|
||||
case EfiConventionalMemory:
|
||||
return MEMORY_TYPE_FREE;
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
return MEMORY_TYPE_BOOT_APPLICATION;
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
return MEMORY_TYPE_BOOT_SERVICES;
|
||||
case EfiRuntimeServicesCode:
|
||||
return MEMORY_TYPE_RUNTIME_SERVICES_CODE;
|
||||
case EfiRuntimeServicesData:
|
||||
return MEMORY_TYPE_RUNTIME_SERVICES_DATA;
|
||||
case EfiUnusableMemory:
|
||||
return MEMORY_TYPE_UNUSABLE;
|
||||
case EfiACPIReclaimMemory:
|
||||
return MEMORY_TYPE_ACPI_RECLAIM;
|
||||
case EfiACPIMemoryNVS:
|
||||
return MEMORY_TYPE_ACPI_NVS;
|
||||
case EfiMemoryMappedIO:
|
||||
return MEMORY_TYPE_MMIO;
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
return MEMORY_TYPE_MMIO_PORT_SPACE;
|
||||
case EfiPalCode:
|
||||
return MEMORY_TYPE_PAL_CODE;
|
||||
case EfiPersistentMemory:
|
||||
return MEMORY_TYPE_PERSISTENT;
|
||||
case EfiReservedMemoryType:
|
||||
default:
|
||||
if ((ULONG)EfiMemoryType < MAXLONG) {
|
||||
return MEMORY_TYPE_RESERVED;
|
||||
} else {
|
||||
return (MEMORY_TYPE)EfiMemoryType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ULONG
|
||||
MmFwpGetOsAttributeType (
|
||||
IN UINT64 EfiAttributes
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Translates EFI memory descriptor attributes to NT memory descriptor attributes.
|
||||
|
||||
Arguments:
|
||||
|
||||
EfiAttributes - the EFI attributes.
|
||||
|
||||
Return Value:
|
||||
|
||||
The NT attributes.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
ULONG NtAttributes;
|
||||
|
||||
NtAttributes = 0;
|
||||
|
||||
if (EfiAttributes & EFI_MEMORY_UC) {
|
||||
NtAttributes |= MEMORY_ATTRIBUTE_UC;
|
||||
}
|
||||
|
||||
if (EfiAttributes & EFI_MEMORY_WC) {
|
||||
NtAttributes |= MEMORY_ATTRIBUTE_WC;
|
||||
}
|
||||
|
||||
if (EfiAttributes & EFI_MEMORY_WT) {
|
||||
NtAttributes |= MEMORY_ATTRIBUTE_WT;
|
||||
}
|
||||
|
||||
if (EfiAttributes & EFI_MEMORY_WB) {
|
||||
NtAttributes |= MEMORY_ATTRIBUTE_WB;
|
||||
}
|
||||
|
||||
if (EfiAttributes & EFI_MEMORY_UCE) {
|
||||
NtAttributes |= MEMORY_ATTRIBUTE_UCE;
|
||||
}
|
||||
|
||||
if (EfiAttributes & EFI_MEMORY_WP) {
|
||||
NtAttributes |= MEMORY_ATTRIBUTE_WP;
|
||||
}
|
||||
|
||||
if (EfiAttributes & EFI_MEMORY_RP) {
|
||||
NtAttributes |= MEMORY_ATTRIBUTE_RP;
|
||||
}
|
||||
|
||||
if (EfiAttributes & EFI_MEMORY_XP) {
|
||||
NtAttributes |= MEMORY_ATTRIBUTE_XP;
|
||||
}
|
||||
|
||||
if (EfiAttributes & EFI_MEMORY_RUNTIME) {
|
||||
NtAttributes |= MEMORY_ATTRIBUTE_RUNTIME;
|
||||
}
|
||||
|
||||
return NtAttributes;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmFwGetMemoryMap (
|
||||
IN OUT PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN ULONG Flags
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Gets the memory map from EFI and converts it into an MDL.
|
||||
|
||||
Arguments:
|
||||
|
||||
Mdl - Pointer to the MDL to store new descriptors in.
|
||||
|
||||
Flags - Unused.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful,
|
||||
STATUS_INVALID_PARAMETER if Mdl is invalid.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
EFI_PHYSICAL_ADDRESS EfiBuffer;
|
||||
EFI_MEMORY_DESCRIPTOR *EfiMap;
|
||||
UINTN EfiMapKey;
|
||||
UINTN EfiMapSize, EfiDescriptorSize;
|
||||
UINT32 EfiDescriptorVersion;
|
||||
UINT64 EfiStartPage, EfiEndPage;
|
||||
UINTN EfiPageCount;
|
||||
ULONGLONG NtStartPage;
|
||||
ULONG NtPageCount;
|
||||
BOOLEAN IsRamdisk;
|
||||
UINT64 EfiRamdiskStartPage, EfiRamdiskEndPage;
|
||||
MEMORY_TYPE MemoryType;
|
||||
PMEMORY_DESCRIPTOR NtDescriptor;
|
||||
|
||||
(VOID)Flags;
|
||||
|
||||
EfiBuffer = (EFI_PHYSICAL_ADDRESS)0;
|
||||
|
||||
if (Mdl == NULL) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
MmMdFreeList(Mdl);
|
||||
|
||||
//
|
||||
// Get the memory map from firmware.
|
||||
// This is a "fake" call to actually just get
|
||||
// the required buffer size and other info.
|
||||
//
|
||||
EfiMapSize = 0;
|
||||
Status = EfiGetMemoryMap(&EfiMapSize, NULL, &EfiMapKey, &EfiDescriptorSize, &EfiDescriptorVersion);
|
||||
if (Status != STATUS_BUFFER_TOO_SMALL) {
|
||||
DebugPrint(L"MmFwGetMemoryMap(): EfiGetMemoryMap() failed\r\n");
|
||||
|
||||
//
|
||||
// Make sure status is not successful, just in case
|
||||
// EfiGetMemoryMap() somehow succeeded.
|
||||
//
|
||||
if (NT_SUCCESS(Status)) {
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
EfiMapSize += 4 * EfiDescriptorSize;
|
||||
NtPageCount = (ALIGN_UP(EfiMapSize, PAGE_SIZE) >> PAGE_SHIFT) + 1;
|
||||
EfiPageCount = EFI_PAGE(NtPageCount);
|
||||
Status = EfiAllocatePages(AllocateAnyPages, EfiLoaderData, EfiPageCount, &EfiBuffer);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
DebugPrint(L"MmFwGetMemoryMap(): EfiAllocatePages() failed\r\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
EfiMap = (EFI_MEMORY_DESCRIPTOR *)EfiBuffer;
|
||||
Status = EfiGetMemoryMap(&EfiMapSize, EfiMap, &EfiMapKey, &EfiDescriptorSize, &EfiDescriptorVersion);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
DebugPrint(L"MmFwGetMemoryMap(): EfiGetMemoryMap() failed\r\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (EfiDescriptorSize < sizeof(EFI_MEMORY_DESCRIPTOR) || EfiMapSize % EfiDescriptorSize) {
|
||||
DebugPrint(L"MmFwGetMemoryMap(): Invalid EFI descriptor/map sizes\r\n");
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (BlpBootDevice->Type == BOOT_DEVICE_TYPE_BLOCK && BlpBootDevice->Block.Type == BOOT_BLOCK_DEVICE_TYPE_RAMDISK) {
|
||||
IsRamdisk = TRUE;
|
||||
EfiRamdiskStartPage = BlpBootDevice->Block.Ramdisk.ImageBase.QuadPart >> EFI_PAGE_SHIFT;
|
||||
EfiRamdiskEndPage = EfiRamdiskStartPage + ((BlpBootDevice->Block.Ramdisk.ImageBase.QuadPart + BlpBootDevice->Block.Ramdisk.ImageSize) >> EFI_PAGE_SHIFT);
|
||||
} else {
|
||||
IsRamdisk = FALSE;
|
||||
}
|
||||
|
||||
for (
|
||||
;
|
||||
EfiMapSize > 0;
|
||||
EfiMapSize -= EfiDescriptorSize,
|
||||
EfiMap = (EFI_MEMORY_DESCRIPTOR *)((PUCHAR)EfiMap + EfiDescriptorSize)
|
||||
) {
|
||||
//
|
||||
// Skip desciptors with no pages.
|
||||
//
|
||||
if (EfiMap->NumberOfPages == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MemoryType = BlMmTranslateEfiMemoryType(EfiMap->Type);
|
||||
if (MemoryType == MEMORY_TYPE_FREE) {
|
||||
EfiStartPage = ALIGN_UP(EfiMap->PhysicalStart, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT;
|
||||
|
||||
} else {
|
||||
EfiStartPage = EfiMap->PhysicalStart >> EFI_PAGE_SHIFT;
|
||||
}
|
||||
EfiEndPage = ALIGN_DOWN(EfiStartPage + EfiMap->NumberOfPages, EFI_PAGE(1));
|
||||
|
||||
//
|
||||
// Regions under 1MiB are mapped differently.
|
||||
//
|
||||
if (EfiStartPage < (_1MiB >> EFI_PAGE_SHIFT)) {
|
||||
//
|
||||
// Reserve region at page 0.
|
||||
//
|
||||
if (EfiStartPage == 0) {
|
||||
NtDescriptor = MmMdInitDescriptor(
|
||||
NT_PAGE(EfiStartPage),
|
||||
0,
|
||||
1,
|
||||
MmFwpGetOsAttributeType(EfiMap->Attribute),
|
||||
MEMORY_TYPE_RESERVED
|
||||
);
|
||||
if (NtDescriptor == NULL) {
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NtDescriptor);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Continue if this descriptor was only one page.
|
||||
//
|
||||
if (EfiEndPage == 1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// For regions crossing over the 1MiB boundary,
|
||||
// create two descriptors. One for <1MiB and one
|
||||
// for over >=1MiB.
|
||||
//
|
||||
if (EfiEndPage > (_1MiB >> EFI_PAGE_SHIFT)) {
|
||||
NtDescriptor = MmMdInitDescriptor(
|
||||
NT_PAGE(EfiStartPage),
|
||||
0,
|
||||
(_1MiB >> PAGE_SHIFT) - NT_PAGE(EfiStartPage),
|
||||
MmFwpGetOsAttributeType(EfiMap->Attribute),
|
||||
MemoryType
|
||||
);
|
||||
if (NtDescriptor == NULL) {
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (NtDescriptor->Type == MEMORY_TYPE_FREE) {
|
||||
NtDescriptor->Attributes |= MEMORY_ATTRIBUTE_BELOW_1MIB;
|
||||
}
|
||||
|
||||
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NtDescriptor);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Continue to creating the >=1MiB mapping.
|
||||
//
|
||||
EfiStartPage = _1MiB >> EFI_PAGE_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsRamdisk) {
|
||||
if (
|
||||
EfiStartPage <= EfiRamdiskStartPage
|
||||
&& EfiEndPage >= EfiRamdiskEndPage
|
||||
) {
|
||||
if (NT_PAGE(EfiStartPage) < NT_PAGE(EfiRamdiskStartPage)) {
|
||||
NtDescriptor = MmMdInitDescriptor(
|
||||
NT_PAGE(EfiStartPage),
|
||||
0,
|
||||
NT_PAGE(EfiRamdiskStartPage) - NT_PAGE(EfiStartPage),
|
||||
MmFwpGetOsAttributeType(EfiMap->Attribute),
|
||||
MemoryType
|
||||
);
|
||||
if (NtDescriptor == NULL) {
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NtDescriptor);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a memory descriptor for the ramdisk.
|
||||
//
|
||||
NtDescriptor = MmMdInitDescriptor(
|
||||
NT_PAGE(EfiRamdiskStartPage),
|
||||
0,
|
||||
NT_PAGE(EfiRamdiskEndPage) - NT_PAGE(EfiRamdiskStartPage),
|
||||
MmFwpGetOsAttributeType(EfiMap->Attribute),
|
||||
MemoryType
|
||||
);
|
||||
if (NtDescriptor == NULL) {
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NtDescriptor);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Continue if there is no more memory to map inside the ramdisk.
|
||||
//
|
||||
if (NT_PAGE(EfiEndPage) <= NT_PAGE(EfiRamdiskEndPage)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EfiStartPage = EFI_PAGE(NT_PAGE(EfiRamdiskEndPage - 1) + 1);
|
||||
} else if (
|
||||
NT_PAGE(EfiStartPage) < NT_PAGE(EfiRamdiskStartPage)
|
||||
&& NT_PAGE(EfiEndPage) > NT_PAGE(EfiRamdiskStartPage)
|
||||
) {
|
||||
//
|
||||
// Remove the region inside the start of the ramdisk.
|
||||
//
|
||||
EfiEndPage = EfiRamdiskStartPage;
|
||||
} else if (
|
||||
NT_PAGE(EfiStartPage) < NT_PAGE(EfiRamdiskEndPage)
|
||||
&& NT_PAGE(EfiEndPage) > NT_PAGE(EfiRamdiskEndPage)
|
||||
) {
|
||||
//
|
||||
// Remove the region inside the end of the ramdisk.
|
||||
//
|
||||
EfiStartPage = EfiRamdiskEndPage;
|
||||
}
|
||||
|
||||
//
|
||||
// Continue if the region is now empty.
|
||||
//
|
||||
if (NT_PAGE(EfiStartPage) == NT_PAGE(EfiEndPage)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a memory descriptor for the region.
|
||||
//
|
||||
NtDescriptor = MmMdInitDescriptor(
|
||||
NT_PAGE(EfiStartPage),
|
||||
0,
|
||||
NT_PAGE(EfiEndPage) - NT_PAGE(EfiStartPage),
|
||||
MmFwpGetOsAttributeType(EfiMap->Attribute),
|
||||
MemoryType
|
||||
);
|
||||
if (NtDescriptor == NULL) {
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Set attribute if below 1MiB.
|
||||
//
|
||||
if (NtDescriptor->Type == MEMORY_TYPE_FREE && EfiEndPage <= (_1MiB >> EFI_PAGE_SHIFT)) {
|
||||
NtDescriptor->Attributes |= MEMORY_ATTRIBUTE_BELOW_1MIB;
|
||||
}
|
||||
|
||||
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, MDL_OPERATION_FLAGS_TRUNCATE);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NtDescriptor);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The following code is to free the buffer and
|
||||
// also mark the freed memory as free in the MDL.
|
||||
//
|
||||
|
||||
Status = EfiFreePages(EfiBuffer, EfiPageCount);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
Status = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
EfiBuffer = 0;
|
||||
|
||||
EfiStartPage = EfiBuffer >> EFI_PAGE_SHIFT;
|
||||
EfiEndPage = ALIGN_UP(EfiStartPage + EfiPageCount, EFI_PAGE(1));
|
||||
NtStartPage = NT_PAGE(EfiStartPage);
|
||||
NtPageCount = NT_PAGE(EfiEndPage) - NtStartPage;
|
||||
|
||||
//
|
||||
// Find the current descriptor.
|
||||
//
|
||||
NtDescriptor = MmMdFindDescriptorFromMdl(Mdl, NtStartPage, MDL_OPERATION_FLAGS_PHYSICAL);
|
||||
if (NtDescriptor == NULL) {
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new free descriptor, with the same
|
||||
// attributes as the current one.
|
||||
//
|
||||
NtDescriptor = MmMdInitDescriptor(NtStartPage, 0, NtPageCount, NtDescriptor->Attributes, MEMORY_TYPE_FREE);
|
||||
if (NtDescriptor == NULL) {
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the current descriptor.
|
||||
//
|
||||
Status = MmMdRemoveRegionFromMdl(Mdl, NtStartPage, NtPageCount, MDL_OPERATION_FLAGS_PHYSICAL);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NtDescriptor);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Add the new descriptor to the MDL.
|
||||
//
|
||||
Status = MmMdAddDescriptorToList(Mdl, NtDescriptor, 0x01);
|
||||
|
||||
exit:
|
||||
if (EfiBuffer) {
|
||||
EfiFreePages(EfiBuffer, EfiPageCount);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeList(Mdl);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
|
||||
mm.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides boot library memory manager routines.
|
||||
|
||||
--*/
|
||||
|
||||
#include <ntrtl.h>
|
||||
#include "bootlib.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
|
||||
BlpMmInitializeConstraints (
|
||||
VOID
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initializes physical address constraints.
|
||||
|
||||
Arguments:
|
||||
|
||||
None.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
//
|
||||
// TODO: Implement this routine.
|
||||
//
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlpMmInitialize (
|
||||
IN PBOOT_MEMORY_INFO MemoryInfo,
|
||||
IN ULONG TranslationType,
|
||||
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initializes the boot memory manager.
|
||||
|
||||
Arguments:
|
||||
|
||||
MemoryInfo - Pointer to the memory info.
|
||||
|
||||
TranslationType - The current translation type.
|
||||
|
||||
LibraryParameters - Pointer to the library parameters.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful,
|
||||
STATUS_INVALID_PARAMETER if TranslationType is invalid,
|
||||
Other NTSTATUS value if an error occurs.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
//
|
||||
// Check TranslationType.
|
||||
//
|
||||
if (
|
||||
TranslationType > TRANSLATION_TYPE_MAX
|
||||
|| LibraryParameters->TranslationType > TRANSLATION_TYPE_MAX
|
||||
) {
|
||||
DebugPrint(L"BlpMmInitialize(): TranslationType is invalid\r\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize memory descriptor manager.
|
||||
//
|
||||
MmMdInitialize(0, LibraryParameters);
|
||||
|
||||
//
|
||||
// Initialize page allocator.
|
||||
//
|
||||
Status = MmPaInitialize(MemoryInfo, LibraryParameters->MinimumPageAllocation);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
MmTranslationType = LibraryParameters->TranslationType;
|
||||
|
||||
//
|
||||
// TODO: Finish this routine.
|
||||
//
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
@ -1,959 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
|
||||
mmmd.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides memory descriptor routines.
|
||||
|
||||
--*/
|
||||
|
||||
#include <ntrtl.h>
|
||||
#include "bootlib.h"
|
||||
#include "mm.h"
|
||||
|
||||
#define MAX_STATIC_DESCRIPTOR_COUNT 1024
|
||||
|
||||
MEMORY_DESCRIPTOR MmStaticMemoryDescriptors[MAX_STATIC_DESCRIPTOR_COUNT];
|
||||
|
||||
PMEMORY_DESCRIPTOR MmGlobalMemoryDescriptors;
|
||||
ULONG MmGlobalMemoryDescriptorCount, MmGlobalMemoryDescriptorsUsed;
|
||||
|
||||
PMEMORY_DESCRIPTOR MmDynamicMemoryDescriptors;
|
||||
ULONG MmDynamicMemoryDescriptorCount, MmDynamicMemoryDescriptorsUsed;
|
||||
|
||||
#define MAX_PRECEDENCE_INDEX sizeof(MmPlatformMemoryTypePrecedence) / sizeof(MmPlatformMemoryTypePrecedence[0])
|
||||
|
||||
MEMORY_TYPE MmPlatformMemoryTypePrecedence[] = {
|
||||
MEMORY_TYPE_RESERVED,
|
||||
MEMORY_TYPE_UNUSABLE,
|
||||
MEMORY_TYPE_MMIO,
|
||||
MEMORY_TYPE_MMIO_PORT_SPACE,
|
||||
MEMORY_TYPE_PAL_CODE,
|
||||
MEMORY_TYPE_RUNTIME_SERVICES_CODE,
|
||||
MEMORY_TYPE_RUNTIME_SERVICES_DATA,
|
||||
MEMORY_TYPE_ACPI_NVS,
|
||||
MEMORY_TYPE_ACPI_RECLAIM,
|
||||
MEMORY_TYPE_PERSISTENT,
|
||||
MEMORY_TYPE_BOOT_APPLICATION_2,
|
||||
MEMORY_TYPE_BOOT_SERVICES,
|
||||
MEMORY_TYPE_FREE,
|
||||
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
|
||||
MmMdpHasPrecedence (
|
||||
IN MEMORY_TYPE TypeA,
|
||||
IN MEMORY_TYPE TypeB
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Compares two memory types to determine which has precedence.
|
||||
|
||||
Arguments:
|
||||
|
||||
TypeA - Memory type A.
|
||||
|
||||
TypeB - Memory type B.
|
||||
|
||||
Return Value:
|
||||
|
||||
TRUE if TypeA has precedence over TypeB, or if neither has precedence.
|
||||
FALSE if TypeB has precedence over TypeA.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
ULONG ClassA, ClassB;
|
||||
ULONG PrecedenceIndexA, PrecedenceIndexB;
|
||||
|
||||
if (TypeB == MEMORY_TYPE_FREE_ZEROED) {
|
||||
return TRUE;
|
||||
} else if (TypeA == MEMORY_TYPE_FREE_ZEROED) {
|
||||
return FALSE;
|
||||
} else if (TypeB == MEMORY_TYPE_FREE) {
|
||||
return TRUE;
|
||||
} else if (TypeA == MEMORY_TYPE_FREE) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ClassA = TypeA >> 28;
|
||||
ClassB = TypeB >> 28;
|
||||
if (ClassA != MEMORY_CLASS_APPLICATION
|
||||
&& ClassA != MEMORY_CLASS_LIBRARY
|
||||
&& ClassA != MEMORY_CLASS_SYSTEM) {
|
||||
return TRUE;
|
||||
} else if (ClassB != MEMORY_CLASS_APPLICATION
|
||||
&& ClassB != MEMORY_CLASS_LIBRARY
|
||||
&& ClassB != MEMORY_CLASS_SYSTEM) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ClassA != MEMORY_CLASS_SYSTEM) {
|
||||
return (ClassB != MEMORY_CLASS_SYSTEM
|
||||
&& (ClassA == MEMORY_CLASS_APPLICATION
|
||||
|| ClassB != MEMORY_CLASS_APPLICATION)) ? TRUE:FALSE;
|
||||
} else if (ClassB != MEMORY_CLASS_SYSTEM) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PrecedenceIndexA = GetPrecedenceIndex(TypeA);
|
||||
if (PrecedenceIndexA == MAX_PRECEDENCE_INDEX) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PrecedenceIndexB = GetPrecedenceIndex(TypeB);
|
||||
if (PrecedenceIndexB == MAX_PRECEDENCE_INDEX) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return PrecedenceIndexA <= PrecedenceIndexB ? TRUE:FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
MmMdpTruncateDescriptor (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN PMEMORY_DESCRIPTOR Descriptor,
|
||||
IN ULONG Flags
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Trunactes a memory descriptor that overlaps
|
||||
with adjacent descriptors.
|
||||
|
||||
Arguments:
|
||||
|
||||
Mdl - The MDL containing Descriptor.
|
||||
|
||||
Descriptor - The descriptor to truncate.
|
||||
|
||||
Return Value:
|
||||
|
||||
TRUE if Descriptor was deleted from Mdl.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PMEMORY_DESCRIPTOR PrevDescriptor, NextDescriptor, NewDescriptor;
|
||||
ULONGLONG DescriptorEnd, PrevDescriptorEnd, NextDescriptorEnd;
|
||||
ULONGLONG MappedFirstPage;
|
||||
ULONGLONG Change;
|
||||
|
||||
PrevDescriptor = (PMEMORY_DESCRIPTOR)Descriptor->ListEntry.Blink;
|
||||
NextDescriptor = (PMEMORY_DESCRIPTOR)Descriptor->ListEntry.Flink;
|
||||
|
||||
DescriptorEnd = Descriptor->FirstPage + Descriptor->PageCount;
|
||||
PrevDescriptorEnd = PrevDescriptor->FirstPage + PrevDescriptor->PageCount;
|
||||
NextDescriptorEnd = NextDescriptor->FirstPage + NextDescriptor->PageCount;
|
||||
|
||||
//
|
||||
// Check if overlapping with previous descriptor.
|
||||
//
|
||||
if (Descriptor->ListEntry.Blink != Mdl->Head && Descriptor->FirstPage < PrevDescriptorEnd) {
|
||||
if (MmMdpHasPrecedence(Descriptor->Type, PrevDescriptor->Type)) {
|
||||
PrevDescriptor->PageCount = Descriptor->FirstPage - PrevDescriptor->FirstPage;
|
||||
|
||||
if (DescriptorEnd < PrevDescriptorEnd) {
|
||||
if (PrevDescriptor->MappedFirstPage) {
|
||||
MappedFirstPage = PrevDescriptor->MappedFirstPage + DescriptorEnd - PrevDescriptor->FirstPage;
|
||||
} else {
|
||||
MappedFirstPage = 0;
|
||||
}
|
||||
|
||||
NewDescriptor = MmMdInitDescriptor(
|
||||
DescriptorEnd,
|
||||
MappedFirstPage,
|
||||
PrevDescriptorEnd - DescriptorEnd,
|
||||
PrevDescriptor->Attributes,
|
||||
PrevDescriptor->Type
|
||||
);
|
||||
if (NewDescriptor != NULL) {
|
||||
Status = MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NewDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Delete and free the previous
|
||||
// descriptor if it is now empty.
|
||||
//
|
||||
if (PrevDescriptor->PageCount == 0) {
|
||||
MmMdRemoveDescriptorFromList(Mdl, PrevDescriptor);
|
||||
MmMdFreeDescriptor(PrevDescriptor);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Remove if completely overlapping.
|
||||
//
|
||||
if (DescriptorEnd <= PrevDescriptorEnd) {
|
||||
MmMdRemoveDescriptorFromList(Mdl, Descriptor);
|
||||
MmMdFreeDescriptor(Descriptor);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Otherwise, move the descriptor.
|
||||
//
|
||||
Change = PrevDescriptorEnd - Descriptor->FirstPage;
|
||||
Descriptor->FirstPage += Change;
|
||||
Descriptor->PageCount -= Change;
|
||||
if (Descriptor->MappedFirstPage) {
|
||||
Descriptor->MappedFirstPage += Change;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check if overlapping with next descriptor.
|
||||
//
|
||||
if (Descriptor->ListEntry.Flink != Mdl->Head && NextDescriptor->FirstPage < DescriptorEnd) {
|
||||
if (MmMdpHasPrecedence(NextDescriptor->Type, Descriptor->Type)) {
|
||||
Descriptor->PageCount = NextDescriptor->FirstPage - Descriptor->FirstPage;
|
||||
|
||||
if (NextDescriptorEnd < DescriptorEnd) {
|
||||
if (Descriptor->MappedFirstPage) {
|
||||
MappedFirstPage = Descriptor->MappedFirstPage + NextDescriptorEnd - Descriptor->FirstPage;
|
||||
} else {
|
||||
MappedFirstPage = 0;
|
||||
}
|
||||
|
||||
NewDescriptor = MmMdInitDescriptor(
|
||||
NextDescriptorEnd,
|
||||
MappedFirstPage,
|
||||
DescriptorEnd - NextDescriptorEnd,
|
||||
Descriptor->Attributes,
|
||||
Descriptor->Type
|
||||
);
|
||||
if (NewDescriptor != NULL) {
|
||||
Status = MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NewDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Delete and free the previous
|
||||
// descriptor if it is now empty.
|
||||
//
|
||||
if (Descriptor->PageCount == 0) {
|
||||
MmMdRemoveDescriptorFromList(Mdl, Descriptor);
|
||||
MmMdFreeDescriptor(Descriptor);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Remove if completely overlapping.
|
||||
//
|
||||
if (NextDescriptorEnd <= DescriptorEnd) {
|
||||
MmMdRemoveDescriptorFromList(Mdl, NextDescriptor);
|
||||
MmMdFreeDescriptor(NextDescriptor);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Otherwise, move the next descriptor.
|
||||
//
|
||||
Change = DescriptorEnd - NextDescriptor->FirstPage;
|
||||
NextDescriptor->FirstPage += Change;
|
||||
NextDescriptor->PageCount -= Change;
|
||||
if (NextDescriptor->MappedFirstPage) {
|
||||
NextDescriptor->MappedFirstPage += Change;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmMdAddDescriptorToList (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN PMEMORY_DESCRIPTOR Descriptor,
|
||||
IN ULONG Flags
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Adds a descriptor to a MDL.
|
||||
|
||||
Arguments:
|
||||
|
||||
Mdl - the MDL to add Descriptor to.
|
||||
|
||||
Descriptor - the descriptor to add to Mdl.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful,
|
||||
STATUS_INVALID_PARAMETER if Mdl or Descriptor are invalid.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PLIST_ENTRY Entry;
|
||||
PMEMORY_DESCRIPTOR CurrentDescriptor;
|
||||
|
||||
if (Mdl == NULL || Descriptor == NULL) {
|
||||
DebugPrint(L"MmMdAddDescriptorToList(): Mdl and/or Descriptor are NULL\r\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Mdl->Current) {
|
||||
if (Descriptor->FirstPage < ((PMEMORY_DESCRIPTOR)Mdl->Current)->FirstPage) {
|
||||
Entry = Mdl->Head->Flink;
|
||||
} else {
|
||||
Entry = Mdl->Current;
|
||||
}
|
||||
} else {
|
||||
Entry = Mdl->Head->Flink;
|
||||
}
|
||||
|
||||
//
|
||||
// Search for an existing descriptor for this region.
|
||||
//
|
||||
while (Entry != Mdl->Head) {
|
||||
CurrentDescriptor = (PMEMORY_DESCRIPTOR)Entry;
|
||||
|
||||
if (
|
||||
Descriptor->FirstPage >= CurrentDescriptor->FirstPage && (Descriptor->FirstPage != CurrentDescriptor->FirstPage
|
||||
|| !MmMdpHasPrecedence(Descriptor->Type, CurrentDescriptor->Type))
|
||||
) {
|
||||
Entry = Entry->Flink;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert descriptor into the list
|
||||
// right before the current entry.
|
||||
//
|
||||
Descriptor->ListEntry.Blink = Entry->Blink;
|
||||
Descriptor->ListEntry.Flink = Entry;
|
||||
Entry->Blink->Flink = &Descriptor->ListEntry;
|
||||
Entry->Blink = &Descriptor->ListEntry;
|
||||
|
||||
//
|
||||
// Truncate overlapping descriptors
|
||||
// into one larger descriptor.
|
||||
//
|
||||
if (Flags & MDL_OPERATION_FLAGS_TRUNCATE) {
|
||||
MmMdpTruncateDescriptor(Mdl, Descriptor, Flags);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// If there are no existing descriptors for this region
|
||||
// (or the list is empty), insert and truncate the descriptor.
|
||||
//
|
||||
InsertTailList(Mdl->Head, &Descriptor->ListEntry);
|
||||
if (Flags & MDL_OPERATION_FLAGS_TRUNCATE) {
|
||||
MmMdpTruncateDescriptor(Mdl, Descriptor, Flags);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
MmMdRemoveDescriptorFromList (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN PMEMORY_DESCRIPTOR Descriptor
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Removes a descriptor from a MDL.
|
||||
|
||||
Arguments:
|
||||
|
||||
Mdl - MDL to remove Descriptor from.
|
||||
|
||||
Descriptor - Descriptor to remove from Mdl.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PLIST_ENTRY Blink;
|
||||
|
||||
Blink = Descriptor->ListEntry.Blink;
|
||||
RemoveEntryList(&Descriptor->ListEntry);
|
||||
|
||||
//
|
||||
// Check if the removed descriptor was cached.
|
||||
//
|
||||
if (Mdl->Current != &Descriptor->ListEntry) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Cache the previous descriptor if possible.
|
||||
//
|
||||
if (
|
||||
(
|
||||
(ULONG_PTR)Blink < (ULONG_PTR)MmGlobalMemoryDescriptors
|
||||
|| (ULONG_PTR)Blink >= (ULONG_PTR)&MmGlobalMemoryDescriptors[MmGlobalMemoryDescriptorCount]
|
||||
)
|
||||
&& Blink != Mdl->Head
|
||||
) {
|
||||
Mdl->Current = Blink;
|
||||
} else {
|
||||
Mdl->Current = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PMEMORY_DESCRIPTOR
|
||||
MmMdFindDescriptorFromMdl (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN ULONGLONG Page,
|
||||
IN ULONG Flags
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Searches an MDL for the descriptor containing a page.
|
||||
|
||||
Arguments:
|
||||
|
||||
Mdl - The MDL to search.
|
||||
|
||||
Page - The page to search for.
|
||||
|
||||
Flags - MDL_OPERATION_FLAGS_*
|
||||
MDL_OPERATION_FLAGS_PHYSICAL if Page is physical.
|
||||
MDL_OPERATION_FLAGS_VIRTUAL if Page is virtual.
|
||||
|
||||
Return Value:
|
||||
|
||||
Pointer to the descriptor if successful.
|
||||
NULL if an error occurs.
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
{
|
||||
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 {
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MmMdRemoveRegionFromMdlEx (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||
IN ULONGLONG RemoveStart,
|
||||
IN ULONGLONG PageCount,
|
||||
IN ULONG Flags,
|
||||
OUT PMEMORY_DESCRIPTOR_LIST Unused
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Removes a region from a MDL.
|
||||
|
||||
Arguments:
|
||||
|
||||
Mdl - MDL to remove the region from.
|
||||
|
||||
RemoveStart - The first page in the region.
|
||||
|
||||
PageCount - The number of pages in the region.
|
||||
|
||||
Flags - MDL_OPERATION_FLAGS_*.
|
||||
MDL_OPERATION_FLAGS_PHYSICAL if the region is physical.
|
||||
MDL_OPERATION_FLAGS_VIRTUAL if the region is virtual.
|
||||
|
||||
Unused - Unused.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful,
|
||||
STATUS_INVALID_PARAMETER if Flags value is invalid.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Offset;
|
||||
BOOLEAN Mapped;
|
||||
ULONGLONG RemoveEnd;
|
||||
PLIST_ENTRY ListEntry;
|
||||
ULONGLONG DescriptorStart, DescriptorEnd;
|
||||
PMEMORY_DESCRIPTOR Descriptor, NewDescriptor;
|
||||
|
||||
(VOID)Unused;
|
||||
|
||||
Mapped = FALSE;
|
||||
if (Flags & MDL_OPERATION_FLAGS_VIRTUAL) {
|
||||
if (Mdl->Type == MDL_TYPE_PHYSICAL) {
|
||||
Mapped = TRUE;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
RemoveEnd = RemoveStart + PageCount;
|
||||
ListEntry = Mdl->Head->Flink;
|
||||
while (ListEntry != Mdl->Head) {
|
||||
Descriptor = (PMEMORY_DESCRIPTOR)ListEntry;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//
|
||||
// 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 |
|
||||
//
|
||||
|
||||
//
|
||||
// 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
|
||||
MmMdFreeDescriptor (
|
||||
IN PMEMORY_DESCRIPTOR Descriptor
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Frees a memory descriptor.
|
||||
|
||||
Arguments:
|
||||
|
||||
Descriptor - the descriptor to free.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful,
|
||||
other NTSTATUS value if an error occurs.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
if (
|
||||
(
|
||||
MmDynamicMemoryDescriptors != NULL
|
||||
&& (ULONG_PTR)Descriptor >= (ULONG_PTR)MmDynamicMemoryDescriptors
|
||||
&& (ULONG_PTR)Descriptor <= (ULONG_PTR)&MmDynamicMemoryDescriptors[MmDynamicMemoryDescriptorCount]
|
||||
)
|
||||
|| (
|
||||
(ULONG_PTR)Descriptor >= (ULONG_PTR)MmStaticMemoryDescriptors
|
||||
&& (ULONG_PTR)Descriptor <= (ULONG_PTR)&MmStaticMemoryDescriptors[MAX_STATIC_DESCRIPTOR_COUNT]
|
||||
)
|
||||
) {
|
||||
//
|
||||
// Clear the descriptor from static/dynamic MDL.
|
||||
//
|
||||
RtlZeroMemory(Descriptor, sizeof(MEMORY_DESCRIPTOR));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: Free the descriptor from the heap.
|
||||
// Need BlMmFreeHeap().
|
||||
//
|
||||
DebugPrint(L"MmMdFreeDescriptor(): Heap not available\r\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
// return BlMmFreeHeap(Descriptor);
|
||||
}
|
||||
|
||||
VOID
|
||||
MmMdFreeList (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Frees a memory descriptor list (MDL).
|
||||
|
||||
Arguments:
|
||||
|
||||
Mdl - the MDL.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
Entry = Mdl->Head->Flink;
|
||||
while (Entry != Mdl->Head) {
|
||||
MmMdRemoveDescriptorFromList(Mdl, (PMEMORY_DESCRIPTOR)Entry);
|
||||
MmMdFreeDescriptor((PMEMORY_DESCRIPTOR)Entry);
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
PMEMORY_DESCRIPTOR
|
||||
MmMdInitDescriptor (
|
||||
IN ULONGLONG FirstPage,
|
||||
IN ULONGLONG MappedFirstPage,
|
||||
IN ULONGLONG PageCount,
|
||||
IN ULONG Attributes,
|
||||
IN MEMORY_TYPE Type
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initializes a memory descriptor.
|
||||
|
||||
Arguments:
|
||||
|
||||
FirstPage - The first page in the region.
|
||||
|
||||
MappedFirstPage - The first page in the mapping.
|
||||
|
||||
Attributes - Memory attributes of the region.
|
||||
|
||||
Type - Memory type of the region.
|
||||
|
||||
Return Value:
|
||||
|
||||
Pointer to the memory descriptor,
|
||||
NULL if an error occurs.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PMEMORY_DESCRIPTOR Descriptor;
|
||||
|
||||
if (MmGlobalMemoryDescriptorsUsed >= MmGlobalMemoryDescriptorCount) {
|
||||
DebugPrint(L"MmMdInitDescriptor(): No free descriptors available\r\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Descriptor = &MmGlobalMemoryDescriptors[MmGlobalMemoryDescriptorsUsed++];
|
||||
Descriptor->FirstPage = FirstPage;
|
||||
Descriptor->MappedFirstPage = MappedFirstPage;
|
||||
Descriptor->PageCount = PageCount;
|
||||
Descriptor->Attributes = Attributes;
|
||||
Descriptor->Type = Type;
|
||||
InitializeListHead(&Descriptor->ListEntry);
|
||||
|
||||
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
|
||||
MmMdInitialize (
|
||||
IN ULONG Stage,
|
||||
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initializes the memory descriptor manager.
|
||||
|
||||
Arguments:
|
||||
|
||||
Stage - Which stage of initialization to perform.
|
||||
|
||||
Stage 0: Initializes the static memory descriptor pool.
|
||||
|
||||
LibraryParameters - Pointer to the library parameters structure.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
(VOID)LibraryParameters;
|
||||
|
||||
if (Stage == 0) {
|
||||
//
|
||||
// Initialize static memory descriptor pool.
|
||||
//
|
||||
MmGlobalMemoryDescriptors = &MmStaticMemoryDescriptors[0];
|
||||
MmGlobalMemoryDescriptorCount = MAX_STATIC_DESCRIPTOR_COUNT;
|
||||
MmGlobalMemoryDescriptorsUsed = 0;
|
||||
RtlZeroMemory(MmGlobalMemoryDescriptors, MAX_STATIC_DESCRIPTOR_COUNT * sizeof(MEMORY_DESCRIPTOR));
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: Implement stage 1 initialization.
|
||||
//
|
||||
}
|
@ -1,197 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
|
||||
mmpa.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides memory manager page routines.
|
||||
|
||||
--*/
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "mm.h"
|
||||
|
||||
ULONG PapMinimumAllocationCount;
|
||||
ULONGLONG PapMinimumPhysicalPage;
|
||||
ULONGLONG PapMaximumPhysicalPage;
|
||||
|
||||
MEMORY_DESCRIPTOR_LIST MmMdlFwAllocationTracker;
|
||||
MEMORY_DESCRIPTOR_LIST MmMdlBadMemory;
|
||||
MEMORY_DESCRIPTOR_LIST MmMdlTruncatedMemory;
|
||||
MEMORY_DESCRIPTOR_LIST MmMdlPersistentMemory;
|
||||
MEMORY_DESCRIPTOR_LIST MmMdlReservedAllocated;
|
||||
MEMORY_DESCRIPTOR_LIST MmMdlMappedAllocated;
|
||||
MEMORY_DESCRIPTOR_LIST MmMdlMappedUnallocated;
|
||||
MEMORY_DESCRIPTOR_LIST MmMdlUnmappedAllocated;
|
||||
MEMORY_DESCRIPTOR_LIST MmMdlUnmappedUnallocated;
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
InitializeMdl (
|
||||
IN PMEMORY_DESCRIPTOR_LIST Mdl
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initializes a MDL.
|
||||
|
||||
Arguments:
|
||||
|
||||
Mdl - Pointer to the MDL.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
Mdl->Head = NULL;
|
||||
Mdl->Current = NULL;
|
||||
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
|
||||
MmPaInitialize (
|
||||
IN PBOOT_MEMORY_INFO MemoryInfo,
|
||||
IN ULONG MinimumAllocation
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initializes the page allocator.
|
||||
|
||||
Arguments:
|
||||
|
||||
MemoryInfo - Pointer to the memory info structure.
|
||||
|
||||
MinimumAllocation - Minimum amount of pages to grow the pool by at a time.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful,
|
||||
STATUS_INVALID_PARAMETER if regions in MemoryInfo could not be removed.
|
||||
STATUS_NO_MEMORY if a new descriptor cannot be allocated.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PMEMORY_DESCRIPTOR Descriptor, NewDescriptor;
|
||||
|
||||
PapMinimumAllocationCount = MinimumAllocation;
|
||||
PapMinimumPhysicalPage = 1;
|
||||
PapMaximumPhysicalPage = MAXULONGLONG >> PAGE_SHIFT;
|
||||
|
||||
//
|
||||
// Initialize Memory Descriptor Lists
|
||||
//
|
||||
InitializeMdl(&MmMdlFwAllocationTracker);
|
||||
InitializeMdl(&MmMdlBadMemory);
|
||||
InitializeMdl(&MmMdlTruncatedMemory);
|
||||
InitializeMdl(&MmMdlPersistentMemory);
|
||||
InitializeMdl(&MmMdlReservedAllocated);
|
||||
InitializeMdl(&MmMdlMappedAllocated);
|
||||
InitializeMdl(&MmMdlMappedUnallocated);
|
||||
InitializeMdl(&MmMdlUnmappedAllocated);
|
||||
InitializeMdl(&MmMdlUnmappedUnallocated);
|
||||
|
||||
Status = MmFwGetMemoryMap(&MmMdlUnmappedUnallocated, 0x03);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove regions described in MemoryInfo from the
|
||||
// MDL the memory manager will use for allocation.
|
||||
//
|
||||
Descriptor = (PMEMORY_DESCRIPTOR)((PUCHAR)MemoryInfo + MemoryInfo->MdlOffset);
|
||||
for (ULONG DescriptorCount = MemoryInfo->DescriptorCount;
|
||||
DescriptorCount > 0;
|
||||
DescriptorCount--) {
|
||||
//
|
||||
// Remove from the usable MDL.
|
||||
//
|
||||
Status = MmMdRemoveRegionFromMdl(
|
||||
&MmMdlUnmappedUnallocated,
|
||||
Descriptor->FirstPage,
|
||||
Descriptor->PageCount,
|
||||
MDL_OPERATION_FLAGS_PHYSICAL
|
||||
);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// ... and add to the reserved MDL.
|
||||
//
|
||||
NewDescriptor = MmMdInitDescriptor(
|
||||
Descriptor->FirstPage,
|
||||
Descriptor->MappedFirstPage,
|
||||
Descriptor->PageCount,
|
||||
Descriptor->Attributes,
|
||||
Descriptor->Type
|
||||
);
|
||||
if (NewDescriptor == NULL) {
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
Status = MmMdAddDescriptorToList(&MmMdlReservedAllocated, NewDescriptor, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
MmMdFreeDescriptor(NewDescriptor);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Descriptor = (PMEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryInfo->DescriptorSize);
|
||||
}
|
||||
|
||||
Status = BlpMmInitializeConstraints();
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
@ -1,427 +0,0 @@
|
||||
/*++
|
||||
|
||||
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;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
.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
|
@ -13,26 +13,60 @@ Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#include <ntrtl.h>
|
||||
#include "bootlib.h"
|
||||
|
||||
//
|
||||
// Total size of required structures.
|
||||
//
|
||||
#define MIN_INPUT_PARAMETERS_SIZE ( \
|
||||
sizeof(BOOT_APPLICATION_PARAMETERS) + \
|
||||
sizeof(BOOT_INPUT_PARAMETERS) + \
|
||||
sizeof(BOOT_MEMORY_INFO) + \
|
||||
sizeof(BOOT_INIT_APPLICATION_ENTRY) + \
|
||||
sizeof(BOOT_FIRMWARE_DATA) + \
|
||||
sizeof(BOOT_RETURN_DATA) \
|
||||
)
|
||||
|
||||
ULONG BlPlatformFlags = 0x002a0000 | FIRMWARE_FLAG_EXECUTION_CONTEXT_SUPPORTED;
|
||||
PBOOT_DEVICE BlpBootDevice;
|
||||
PBOOT_APPLICATION_PARAMETERS BlpApplicationParameters;
|
||||
BOOT_LIBRARY_PARAMETERS BlpLibraryParameters;
|
||||
BOOT_APPLICATION_ENTRY BlpApplicationEntry;
|
||||
|
||||
NTSTATUS
|
||||
InitializeLibrary (
|
||||
IN PBOOT_APPLICATION_PARAMETERS ApplicationParameters,
|
||||
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
||||
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Internal routine to initialize the boot library.
|
||||
|
||||
Arguments:
|
||||
|
||||
InputParameters - pointer to the input parameters structure.
|
||||
|
||||
LibraryParameters - pointer to the library parameters structure.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
(VOID)LibraryParameters;
|
||||
|
||||
//
|
||||
// Verify input parameters structure.
|
||||
//
|
||||
if (InputParameters == NULL ||
|
||||
InputParameters->Signature != BOOT_INPUT_PARAMETERS_SIGNATURE ||
|
||||
InputParameters->Size < MIN_INPUT_PARAMETERS_SIZE) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlInitializeLibrary (
|
||||
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
||||
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
|
||||
)
|
||||
|
||||
@ -44,108 +78,9 @@ Routine Description:
|
||||
|
||||
Arguments:
|
||||
|
||||
ApplicationParameters - Pointer to the application's input parameters.
|
||||
InputParameters - pointer to the input parameters structure.
|
||||
|
||||
LibraryParameters - Pointer to the library parameters.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PBOOT_MEMORY_INFO MemoryInfo;
|
||||
PBOOT_INIT_APPLICATION_ENTRY ApplicationEntry;
|
||||
PBOOT_FIRMWARE_DATA FirmwareData;
|
||||
|
||||
if (ApplicationParameters == NULL ||
|
||||
ApplicationParameters->Signature != BOOT_APPLICATION_PARAMETERS_SIGNATURE ||
|
||||
ApplicationParameters->Size < MIN_INPUT_PARAMETERS_SIZE) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
MemoryInfo = (PBOOT_MEMORY_INFO)((PUCHAR)ApplicationParameters + ApplicationParameters->MemoryInfoOffset);
|
||||
ApplicationEntry = (PBOOT_INIT_APPLICATION_ENTRY)((PUCHAR)ApplicationParameters + ApplicationParameters->ApplicationEntryOffset);
|
||||
BlpBootDevice = (PBOOT_DEVICE)((PUCHAR)ApplicationParameters + ApplicationParameters->BootDeviceOffset);
|
||||
FirmwareData = (PBOOT_FIRMWARE_DATA)((PUCHAR)ApplicationParameters + ApplicationParameters->FirmwareDataOffset);
|
||||
|
||||
//
|
||||
// Initialize firmware library.
|
||||
// It is important to do this early so that
|
||||
// ConsolePrint() and DebugPrint() can be used.
|
||||
//
|
||||
Status = BlpFwInitialize(0, FirmwareData);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto Stage0Failed;
|
||||
}
|
||||
|
||||
ConsolePrint(L"> Alcyone EFI Boot Manager\r\n");
|
||||
ConsolePrintf(L"Image base: %x %x\r\nImage size: %x\r\n", HIDWORD((ULONG_PTR)ApplicationParameters->ImageBase), LODWORD((ULONG_PTR)ApplicationParameters->ImageBase), ApplicationParameters->ImageSize);
|
||||
|
||||
if (ApplicationEntry->Signature != BOOT_INIT_APPLICATION_ENTRY_SIGNATURE) {
|
||||
DebugPrint(L"InitializeLibrary(): ApplicationEntry Signature is invalid\r\n");
|
||||
Status = STATUS_INVALID_PARAMETER_9;
|
||||
goto Stage0Failed;
|
||||
}
|
||||
|
||||
//
|
||||
// Save library and application parameters.
|
||||
//
|
||||
BlpApplicationParameters = ApplicationParameters;
|
||||
RtlCopyMemory(&BlpLibraryParameters, LibraryParameters, sizeof(BOOT_LIBRARY_PARAMETERS));
|
||||
|
||||
//
|
||||
// Save application entry.
|
||||
//
|
||||
BlpApplicationEntry.Attributes = ApplicationEntry->Attributes;
|
||||
RtlCopyMemory(&BlpApplicationEntry.BcdIdentifier, &ApplicationEntry->BcdIdentifier, sizeof(GUID));
|
||||
BlpApplicationEntry.Options = &ApplicationEntry->Options;
|
||||
|
||||
Status = BlpArchInitialize(0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto Stage0Failed;
|
||||
}
|
||||
|
||||
Status = BlpMmInitialize(MemoryInfo, ApplicationParameters->TranslationType, LibraryParameters);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto Stage0Failed;
|
||||
}
|
||||
|
||||
Status = BlpFwInitialize(1, FirmwareData);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto Stage1Failed;
|
||||
}
|
||||
|
||||
Status = BlpArchInitialize(1);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
goto Stage1Failed;
|
||||
}
|
||||
|
||||
Stage1Failed:
|
||||
BlpMmDestroy(1);
|
||||
Stage0Failed:
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlInitializeLibrary (
|
||||
IN PBOOT_APPLICATION_PARAMETERS ApplicationParameters,
|
||||
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initializes the boot library. Wrapper for InitializeLibrary().
|
||||
|
||||
Arguments:
|
||||
|
||||
ApplicationParameters - Pointer to the application's input parameters.
|
||||
|
||||
LibraryParameters - Pointer to the library parameters.
|
||||
LibraryParameters - pointer to the library parameters structure.
|
||||
|
||||
Return Value:
|
||||
|
||||
@ -154,7 +89,7 @@ Return Value:
|
||||
--*/
|
||||
|
||||
{
|
||||
return InitializeLibrary(ApplicationParameters, LibraryParameters);
|
||||
return InitializeLibrary(InputParameters, LibraryParameters);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
@ -175,24 +110,10 @@ Arguments:
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful.
|
||||
Error code on failure.
|
||||
Error status if an error is encountered.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
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;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1,89 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
|
||||
bootopt.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides boot option utilities.
|
||||
|
||||
--*/
|
||||
|
||||
#include "bootlib.h"
|
||||
|
||||
ULONG
|
||||
BlGetBootOptionSize (
|
||||
IN PBOOT_ENTRY_OPTION Option
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Gets the size of a boot option.
|
||||
|
||||
Arguments:
|
||||
|
||||
Option - The boot option.
|
||||
|
||||
Return Value:
|
||||
|
||||
The size of the option.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
ULONG TotalSize;
|
||||
|
||||
if (Option->DataOffset != 0) {
|
||||
TotalSize = Option->DataOffset + Option->DataSize;
|
||||
} else {
|
||||
TotalSize = sizeof(BOOT_ENTRY_OPTION);
|
||||
}
|
||||
|
||||
if (Option->OtherOptionsOffset != 0) {
|
||||
TotalSize += BlGetBootOptionListSize((PBOOT_ENTRY_OPTION)((PUCHAR)Option + Option->OtherOptionsOffset));
|
||||
}
|
||||
|
||||
return TotalSize;
|
||||
}
|
||||
|
||||
ULONG
|
||||
BlGetBootOptionListSize (
|
||||
IN PBOOT_ENTRY_OPTION Options
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Gets the total size of a list boot options.
|
||||
|
||||
Arguments:
|
||||
|
||||
Options - The boot option list.
|
||||
|
||||
Return Value:
|
||||
|
||||
The size of the option list.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
ULONG TotalSize, NextOffset;
|
||||
PBOOT_ENTRY_OPTION Option;
|
||||
|
||||
TotalSize = 0;
|
||||
NextOffset = 0;
|
||||
do {
|
||||
Option = (PBOOT_ENTRY_OPTION)((PUCHAR)Options + NextOffset);
|
||||
NextOffset = Option->NextOptionOffset;
|
||||
TotalSize += BlGetBootOptionSize(Option);
|
||||
} while (NextOffset != 0);
|
||||
|
||||
return TotalSize;
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
# Boot Environment Source Files
|
||||
|
||||
> XX = anything
|
||||
|
||||
| File | Public Routines |
|
||||
|-|-|
|
||||
| APP/BOOTMGR/EFI/efientry.c | EfiMain() |
|
||||
| APP/BOOTMGR/bcd.c | BmXXDataStore() |
|
||||
| APP/BOOTMGR/bootmgr.c | BmMain() |
|
||||
| LIB/EFI/eficon.c | ConsoleXX() |
|
||||
| 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/mmmd.c | MmMdXX() |
|
||||
| LIB/MM/mmpa.c | MmPaXX() |
|
||||
| LIB/bootlib.c | BlXXLibrary() |
|
||||
| LIB/bootopt.c | BlXXBootOptionXX() |
|
||||
| LIB/XX/arch.c | BlpArchXX() |
|
@ -1,210 +0,0 @@
|
||||
/*
|
||||
* PROJECT: Alcyone System Kernel
|
||||
* LICENSE: BSD Clause 3
|
||||
* PURPOSE: Cache Controller:: External Cache Compatibility Layer
|
||||
* NT KERNEL: 5.11.9360
|
||||
* COPYRIGHT: 2023-2029 Dibymartanda Samanta <>
|
||||
*/
|
||||
|
||||
NOTE::Alcyone will not notify,in case of Empty External Cache at the moment, feature is planned for threadpool revamp
|
||||
|
||||
/* Move Typedef later cctypes.hpp */
|
||||
typedef struct alignas(24) _DIRTY_PAGE_STATISTICS {
|
||||
ULONGLONG DirtyPages; // 0x0
|
||||
ULONGLONG DirtyPagesLastScan; // 0x8
|
||||
ULONG DirtyPagesScheduledLastScan; // 0x10
|
||||
} DIRTY_PAGE_STATISTICS, *PDIRTY_PAGE_STATISTICS; // 0x18 bytes (sizeof)
|
||||
|
||||
typedef struct alignas(30) _CC_EXTERNAL_CACHE_INFO {
|
||||
VOID (*Callback)(VOID* arg1, ULONGLONG arg2, ULONG arg3); // 0x0
|
||||
struct _DIRTY_PAGE_STATISTICS DirtyPageStatistics; // 0x8
|
||||
struct _LIST_ENTRY Links; // 0x20
|
||||
} CC_EXTERNAL_CACHE_INFO, *PCC_EXTERNAL_CACHE_INFO; // 0x30 bytes (sizeof)
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcDeductDirtyPagesFromExternalCache(
|
||||
IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext,
|
||||
IN ULONG Pages
|
||||
)
|
||||
{
|
||||
KIRQL OldIrql ={0};
|
||||
ULONG PagesToDeduct = {0};
|
||||
|
||||
|
||||
if (Pages > 0)
|
||||
{
|
||||
/* Acquire the master lock */
|
||||
KeAcquireQueuedSpinLock(LockQueueMasterLock, &OldIrql);
|
||||
|
||||
/* Calculate the number of pages to deduct */
|
||||
PagesToDeduct = min(Pages, ExternalCacheContext->DirtyPageStatistics.DirtyPages);
|
||||
|
||||
/* Deduct the pages from the external cache context */
|
||||
ExternalCacheContext->DirtyPageStatistics.DirtyPages -= PagesToDeduct;
|
||||
|
||||
/* Deduct the pages from the global statistics */
|
||||
CcTotalDirtyPages -= PagesToDeduct;
|
||||
|
||||
/* Release the master lock */
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||
}
|
||||
|
||||
/* Check if there are any deferred writes and post them if necessary */
|
||||
if (!IsListEmpty(&CcDeferredWrites))
|
||||
{
|
||||
CcPostDeferredWrites();
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcAddExternalCache(
|
||||
IN PCC_EXTERNAL_CACHE_INFO CacheInfo
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
KLOCK_QUEUE_HANDLE LockHandle ={0};
|
||||
|
||||
/* Acquire the external cache list lock */
|
||||
KeAcquireInStackQueuedSpinLock(&CcExternalCacheListLock,&LockHandle);
|
||||
|
||||
/* Insert the new cache info at the end of the list */
|
||||
InsertTailList(&CcExternalCacheList, &CacheInfo->Links);
|
||||
|
||||
/* Increment the number of external caches */
|
||||
if (_InterlockedIncrement(&CcNumberOfExternalCaches) <= 0)
|
||||
{
|
||||
/* Overflow occurred, bug check */
|
||||
KeBugCheckEx(CACHE_MANAGER,0,STATUS_INTEGER_OVERFLOW,0,0);
|
||||
}
|
||||
|
||||
/* Release the external cache list lock */
|
||||
KeReleaseInStackQueuedSpinLock(&LockHandle);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcRemoveExternalCache(
|
||||
IN PCC_EXTERNAL_CACHE_INFO CacheInfo
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
|
||||
KLOCK_QUEUE_HANDLE LockHandle ={0};
|
||||
|
||||
/* Acquire the external cache list lock */
|
||||
KeAcquireInStackQueuedSpinLock(&CcExternalCacheListLock,&LockHandle);
|
||||
|
||||
/* Remove the entry from the list */
|
||||
RemoveTailList(&CacheInfo->Links.Blink);
|
||||
|
||||
/* Decrement the number of external caches */
|
||||
if (_InterlockedDecrement(&CcNumberOfExternalCaches) < 0)
|
||||
{
|
||||
/* Underflow occurred, bug check */
|
||||
KeBugCheckEx(CACHE_MANAGER,0,STATUS_INTEGER_OVERFLOW,0,0);
|
||||
}
|
||||
|
||||
/* Release the external cache list lock */
|
||||
KeReleaseInStackQueuedSpinLock(&LockHandle);
|
||||
}
|
||||
|
||||
|
||||
/*Exported */
|
||||
VOID
|
||||
NTAPI
|
||||
CcAddDirtyPagesToExternalCache(
|
||||
IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext,
|
||||
IN ULONG Pages
|
||||
)
|
||||
{
|
||||
KIRQL OldIrql ={0};
|
||||
|
||||
|
||||
/* Only proceed if there are pages to add */
|
||||
if (Pages == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Acquire the master lock */
|
||||
KeAcquireQueuedSpinLock(LockQueueMasterLock, &OldIrql);
|
||||
|
||||
/* If this is the first dirty page, schedule a lazy write scan */
|
||||
if (ExternalCacheContext->DirtyPageStatistics.DirtyPages == 0)
|
||||
{
|
||||
CcScheduleLazyWriteScan(FALSE, NULL);
|
||||
}
|
||||
|
||||
/* Increment the dirty page count */
|
||||
ExternalCacheContext->DirtyPageStatistics.DirtyPages += Pages;
|
||||
|
||||
/* Charge the dirty pages */
|
||||
CcChargeDirtyPages(NULL, NULL, NULL, Pages);
|
||||
|
||||
/* Release the master lock */
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcUnregisterExternalCache(
|
||||
IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
/* Remove the external cache from the list */
|
||||
CcRemoveExternalCache(ExternalCacheContext);
|
||||
|
||||
/* Deduct any remaining dirty pages */
|
||||
if (ExternalCacheContext->DirtyPageStatistics.DirtyPages > 0)
|
||||
{
|
||||
CcDeductDirtyPagesFromExternalCache(ExternalCacheContext,ExternalCacheContext->DirtyPageStatistics.DirtyPages);
|
||||
}
|
||||
|
||||
/* Free the external cache context */
|
||||
ExFreePoolWithTag(ExternalCacheContext, CC_EXTERNAL_CACHE_INFO_TAG);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CcRegisterExternalCache(
|
||||
IN PCC_EXTERNAL_CACHE_CALLBACK Callback,
|
||||
OUT PVOID *ExternalCacheContext
|
||||
)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PCC_EXTERNAL_CACHE_INFO CacheInfo;
|
||||
|
||||
|
||||
/* Ensure the Cache Manager is initialized */
|
||||
if (!CcInitializationComplete)
|
||||
{
|
||||
KeBugCheckEx(CACHE_MANAGER,0,STATUS_UNSUCCESSFUL,0,0);
|
||||
}
|
||||
|
||||
/* Allocate memory for the external cache info structure */
|
||||
CacheInfo = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(CC_EXTERNAL_CACHE_INFO),
|
||||
CC_EXTERNAL_CACHE_INFO_TAG);
|
||||
if (CacheInfo == NULL)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Initialize the cache info structure */
|
||||
RtlZeroMemory(CacheInfo, sizeof(CC_EXTERNAL_CACHE_INFO));
|
||||
CacheInfo->Callback = Callback;
|
||||
|
||||
/* Add the external cache to the list */
|
||||
CcAddExternalCache(CacheInfo);
|
||||
|
||||
/* Return the cache info as the context */
|
||||
*ExternalCacheContext = CacheInfo;
|
||||
|
||||
return Status;
|
||||
}
|
@ -105,31 +105,6 @@ private:
|
||||
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>
|
||||
class Array {
|
||||
public:
|
||||
|
@ -13,7 +13,341 @@
|
||||
|
||||
extern "C"
|
||||
|
||||
/*Internal Function*/
|
||||
/* Move Typedef Later to cctypes.hpp */
|
||||
typedef struct _WRITE_BEHIND_THROUGHPUT
|
||||
{
|
||||
ULONG PagesYetToWrite;
|
||||
ULONG Throughput;
|
||||
} WRITE_BEHIND_THROUGHPUT, *PWRITE_BEHIND_THROUGHPUT;
|
||||
|
||||
BOOLEAN
|
||||
CcOkToAddWriteBehindThread(VOID)
|
||||
{
|
||||
ULONG ActiveExtraWriteBehindThreads = {0};
|
||||
PWRITE_BEHIND_THROUGHPUT ThroughputStats = nullptr;
|
||||
ULONG PagesYetToWrite = {0};
|
||||
ULONG Throughput = {0};
|
||||
ULONG PreviousThroughput = {0};
|
||||
LONG ThroughputTrend = {0};
|
||||
BOOLEAN Result = false;
|
||||
|
||||
ActiveExtraWriteBehindThreads = CcActiveExtraWriteBehindThreads;
|
||||
ThroughputStats = CcThroughputStats;
|
||||
PagesYetToWrite = CcPagesYetToWrite;
|
||||
|
||||
Throughput = ThroughputStats[ActiveExtraWriteBehindThreads].PagesYetToWrite;
|
||||
PreviousThroughput = 0;
|
||||
|
||||
if (Throughput >= PagesYetToWrite)
|
||||
{
|
||||
Throughput -= PagesYetToWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
Throughput = 0;
|
||||
}
|
||||
|
||||
ThroughputStats[ActiveExtraWriteBehindThreads].PagesYetToWrite = PagesYetToWrite;
|
||||
Result = true;
|
||||
|
||||
if (ActiveExtraWriteBehindThreads > 0)
|
||||
{
|
||||
PreviousThroughput = ThroughputStats[ActiveExtraWriteBehindThreads - 1].Throughput;
|
||||
}
|
||||
|
||||
ThroughputStats[ActiveExtraWriteBehindThreads].Throughput = Throughput;
|
||||
|
||||
if (Throughput > 0)
|
||||
{
|
||||
ThroughputTrend = CcThroughputTrend;
|
||||
|
||||
if (Throughput < PreviousThroughput)
|
||||
{
|
||||
if (ThroughputTrend > 0)
|
||||
ThroughputTrend = 0;
|
||||
ThroughputTrend--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ThroughputTrend < 0)
|
||||
ThroughputTrend = 0;
|
||||
ThroughputTrend++;
|
||||
}
|
||||
|
||||
CcThroughputTrend = ThroughputTrend;
|
||||
|
||||
if (ThroughputTrend == 3)
|
||||
{
|
||||
CcThroughputTrend = 0;
|
||||
Result = true;
|
||||
|
||||
if (ActiveExtraWriteBehindThreads < CcMaxExtraWriteBehindThreads)
|
||||
{
|
||||
ThroughputStats[ActiveExtraWriteBehindThreads + 1].Throughput = 0;
|
||||
ThroughputStats[ActiveExtraWriteBehindThreads + 1].PagesYetToWrite = PagesYetToWrite;
|
||||
}
|
||||
}
|
||||
else if (ThroughputTrend == -3)
|
||||
{
|
||||
CcThroughputTrend = 0;
|
||||
Result = true;
|
||||
|
||||
if (ActiveExtraWriteBehindThreads > 0)
|
||||
{
|
||||
ThroughputStats[ActiveExtraWriteBehindThreads - 1].Throughput = 0;
|
||||
ThroughputStats[ActiveExtraWriteBehindThreads - 1].PagesYetToWrite = PagesYetToWrite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcSetLazyWriteScanQueued(
|
||||
IN ULONG FlushReason,
|
||||
IN BOOLEAN QueuedState)
|
||||
{
|
||||
switch (FlushReason)
|
||||
{
|
||||
case 1:
|
||||
LazyWriter.PendingLowMemoryScan = QueuedState;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
LazyWriter.PendingPowerScan = QueuedState;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
LazyWriter.PendingPeriodicScan = QueuedState;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
LazyWriter.PendingTeardownScan = QueuedState;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
LazyWriter.PendingCoalescingFlushScan = QueuedState;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
VECTORCALL
|
||||
CcIsLazyWriteScanQueued(
|
||||
_In_ ULONG ReasonForFlush
|
||||
)
|
||||
{
|
||||
switch (ReasonForFlush)
|
||||
{
|
||||
case 0:
|
||||
return false;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
case 16:
|
||||
if (LazyWriter.PendingLowMemoryScan ||
|
||||
LazyWriter.PendingPowerScan ||
|
||||
LazyWriter.PendingCoalescingFlushScan)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case 4:
|
||||
if (LazyWriter.PendingPeriodicScan ||
|
||||
LazyWriter.PendingTeardownScan)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case 8:
|
||||
return (BOOLEAN)LazyWriter.PendingTeardownScan;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcQueueLazyWriteScanThread(
|
||||
_In_ PVOID NULL_PARAM
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(NULL_PARAM);
|
||||
|
||||
ULONG Reason = 0;
|
||||
BOOLEAN NeedAdjustment;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldIrql;
|
||||
PWORK_QUEUE_ENTRY WorkQueueEntry;
|
||||
PVOID WaitObjects[5];
|
||||
|
||||
WaitObjects[0] = &CcLowMemoryEvent;
|
||||
WaitObjects[1] = &CcPowerEvent;
|
||||
WaitObjects[2] = &CcPeriodicEvent;
|
||||
WaitObjects[3] = &CcWaitingForTeardownEvent;
|
||||
WaitObjects[4] = &CcCoalescingFlushEvent;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
NeedAdjustment = false;
|
||||
|
||||
Status = KeWaitForMultipleObjects(
|
||||
5,
|
||||
WaitObjects,
|
||||
WaitAny,
|
||||
WrFreePage,
|
||||
KernelMode,
|
||||
false,
|
||||
NULL,
|
||||
WaitBlockArray);
|
||||
|
||||
switch (Status)
|
||||
{
|
||||
case STATUS_WAIT_0:
|
||||
Reason = 1;
|
||||
NeedAdjustment = true;
|
||||
break;
|
||||
|
||||
case STATUS_WAIT_1:
|
||||
Reason = 2;
|
||||
break;
|
||||
|
||||
case STATUS_WAIT_2:
|
||||
Reason = 4;
|
||||
break;
|
||||
|
||||
case STATUS_WAIT_3:
|
||||
Reason = 8;
|
||||
break;
|
||||
|
||||
case STATUS_WAIT_4:
|
||||
Reason = 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CcNumberOfExternalCaches && !IsListEmpty(&CcExternalCacheList))
|
||||
{
|
||||
CcNotifyExternalCaches(Reason);
|
||||
}
|
||||
|
||||
CcAdjustWriteBehindThreadPoolIfNeeded(NeedAdjustment);
|
||||
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
||||
|
||||
if (CcIsLazyWriteScanQueued(Reason))
|
||||
{
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||
continue;
|
||||
}
|
||||
|
||||
CcSetLazyWriteScanQueued(Reason, true);
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||
|
||||
if (!NT_SUCCESS(CcAllocateWorkQueueEntry(&WorkQueueEntry)))
|
||||
{
|
||||
KSPIN_LOCK_QUEUE_NUMBER queueNumber = LockQueueMasterLock;
|
||||
SpinLockGuard guard(queueNumber);
|
||||
LazyWriter.ScanActive = false;
|
||||
CcSetLazyWriteScanQueued(Reason, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
WorkQueueEntry->Function = 3;
|
||||
WorkQueueEntry->Parameters.Notification.Reason = Reason;
|
||||
|
||||
CcPostWorkQueue(
|
||||
WorkQueueEntry,
|
||||
(Reason != 8) ? &CcRegularWorkQueue : &CcFastTeardownWorkQueue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcRescheduleLazyWriteScan( IN PLARGE_INTEGER NextScanDelay)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(NextScanDelay);
|
||||
LARGE_INTEGER Delay = {0};
|
||||
|
||||
if (LazyWriter.ScanActive)
|
||||
{
|
||||
|
||||
if (NextScanDelay && NextScanDelay->QuadPart != 0x7FFFFFFFFFFFFFFF && NextScanDelay->QuadPart != 0)
|
||||
{
|
||||
Delay.QuadPart = NextScanDelay->QuadPart * KeMaximumIncrement;
|
||||
if (Delay.QuadPart > 160000000)
|
||||
Delay.QuadPart = 160000000;
|
||||
if(Delay.QuadPart < 10000000 )
|
||||
Delay = CcIdleDelay;
|
||||
}
|
||||
KeSetCoalescableTimer(&LazyWriter.ScanTimer,CcIdleDelay,0,1000,&LazyWriter.ScanDpc);
|
||||
}
|
||||
else
|
||||
{
|
||||
CcScheduleLazyWriteScan(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcComputeNextScanTime(PLARGE_INTEGER OldestTICKTIMEForMetadata, PLARGE_INTEGER NextScanDelay)
|
||||
{
|
||||
NextScanDelay- = 0;
|
||||
LARGE_INTEGER CurrentTickCount = {0};
|
||||
LARGE_INTEGER TICKTIME = {0};
|
||||
LARGE_INTEGER WRITE_DELAY = {0};
|
||||
LARGE_INTEGER TICK_ELAPSED = {0};
|
||||
|
||||
if (CcMaxWriteBehindThreads < CcNumberofWorkerThreads)
|
||||
{
|
||||
|
||||
|
||||
KeQueryTickCount(&CurrentTickCount);
|
||||
|
||||
// Calculate Tick Time based on the current tick count and the oldest scan time
|
||||
TICKTIME.QuadPart = 160000000 / KeMaximumIncrement;
|
||||
WRITE_DELAY.QuadPart = (OldestTICKTIMEForMetadata->QuadPart - CurrentTickCount.QuadPart) / KeMaximumIncrement;
|
||||
|
||||
// Increment the consecutive workless lazy scan count
|
||||
++CcConsecutiveWorklessLazyScanCount;
|
||||
|
||||
// Check if the oldest scan time is not the maximum and the calculated delay is greater than the current tick
|
||||
// count
|
||||
if (OldestTICKTIMEForMetadata->QuadPart != -1 && OldestTICKTIMEForMetadata->QuadPart != 0x7FFFFFFFFFFFFFFF &&
|
||||
(TICKTIME.QuadPart + OldestTICKTIMEForMetadata->QuadPart) > CurrentTickCount.QuadPart)
|
||||
{
|
||||
|
||||
TICK_ELAPSED.QuadPart = OldestTICKTIMEForMetadata->QuadPart - CurrentTickCount.QuadPart;
|
||||
|
||||
// Calculate the next scan delay
|
||||
NextScanDelay->QuadPart = TICKTIME.QuadPart + TICK_ELAPSED.QuadPart;
|
||||
|
||||
// Reset the consecutive workless lazy scan count
|
||||
CcConsecutiveWorklessLazyScanCount = 0;
|
||||
}
|
||||
|
||||
// Check if the number of consecutive workless lazy scans has reached the maximum
|
||||
if (CcConsecutiveWorklessLazyScanCount >= CcMaxWorklessLazywriteScans)
|
||||
{
|
||||
// Disable the scan by setting the next scan delay to the maximum values
|
||||
NextScanDelay->QuadPart = -1;
|
||||
CcConsecutiveWorklessLazyScanCount = 0;
|
||||
NextScanDelay->HighPart = 0x7FFFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
VECTORCALL
|
||||
@ -900,10 +1234,10 @@ NTAPI CcLazyWriteScan()
|
||||
|
||||
CcPostWorkQueue(workItem, &CcRegularWorkQueue);
|
||||
}
|
||||
// CcComputeNextScanTime(&OldestLWSTimeStamp, &NextScanDelay); Enable When Threadpool is finished
|
||||
CcComputeNextScanTime(&OldestLWSTimeStamp, &NextScanDelay);
|
||||
|
||||
// if (!IsListEmpty(&PostWorkList) || !IsListEmpty(&CcDeferredWrites) || MmRegistryStatus.ProductStatus ||NextScanDelay.QuadPart != 0x7FFFFFFFFFFFFFFF))
|
||||
if (!IsListEmpty(&PostWorkList) || !IsListEmpty(&CcDeferredWrites) || MmRegistryStatus.ProductStatus))
|
||||
if (!IsListEmpty(&PostWorkList) || !IsListEmpty(&CcDeferredWrites) || MmRegistryStatus.ProductStatus ||
|
||||
NextScanDelay.QuadPart != 0x7FFFFFFFFFFFFFFF))
|
||||
{
|
||||
/* Schedule a lazy write scan */
|
||||
CcRescheduleLazyWriteScan(&NextScanDelay);
|
||||
@ -930,44 +1264,7 @@ NTAPI CcLazyWriteScan()
|
||||
CcScheduleLazyWriteScan(FALSE);
|
||||
}
|
||||
}
|
||||
NTSTATUS CcWaitForCurrentLazyWriterActivity()
|
||||
{
|
||||
NTSTATUS result;
|
||||
PWORK_QUEUE_ENTRY WorkQueueEntry = nullptr;
|
||||
KEVENT Event = {0};
|
||||
KIRQL irql = {0};
|
||||
|
||||
result = CcAllocateWorkQueueEntry(&WorkQueueEntry);
|
||||
if (NT_SUCCESS(result))
|
||||
{
|
||||
WorkQueueEntry->Function = SetDone;
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
WorkQueueEntry->Parameters.Notification.Reason = (ULONG_PTR)&Event;
|
||||
|
||||
if ((PerfGlobalGroupMask.Masks[4] & 0x20000) != 0)
|
||||
CcPerfLogWorkItemEnqueue(&CcPostTickWorkQueue, WorkQueueEntry, 0, 0);
|
||||
|
||||
irql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
||||
|
||||
WorkQueueEntry->WorkQueueLinks.Flink = &CcPostTickWorkQueue;
|
||||
WorkQueueEntry->WorkQueueLinks.Blink = CcPostTickWorkQueue.Blink;
|
||||
CcPostTickWorkQueue.Blink->Flink = &WorkQueueEntry->WorkQueueLinks;
|
||||
CcPostTickWorkQueue.Blink = &WorkQueueEntry->WorkQueueLinks;
|
||||
|
||||
LazyWriter.OtherWork = 1;
|
||||
_InterlockedIncrement(&CcPostTickWorkItemCount);
|
||||
|
||||
CcScheduleLazyWriteScan(1, 1);
|
||||
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, irql);
|
||||
|
||||
result = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
_InterlockedDecrement(&CcPostTickWorkItemCount);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
VOID VECTORCALL CcReEngageWorkerThreads(
|
||||
ULONG NormalThreadsToActivate,
|
||||
ULONG ExtraWriteBehindThreadsToActivate
|
||||
@ -1036,6 +1333,62 @@ VOID VECTORCALL CcReEngageWorkerThreads(
|
||||
ExQueueWorkItem(currentExtraThreadEntry, CriticalWorkQueue);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcAdjustWriteBehindThreadPool(
|
||||
IN BOOLEAN IsThreadPriorityLow)
|
||||
{
|
||||
if (IsThreadPriorityLow)
|
||||
{
|
||||
CcMaxNumberOfWriteBehindThreads = 1;
|
||||
if (CcAddExtraWriteBehindThreads)
|
||||
{
|
||||
CcAddExtraWriteBehindThreads = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CcMaxNumberOfWriteBehindThreads = (ULONG)-1;
|
||||
if (!IsListEmpty(&CcRegularWorkQueue) && !CcQueueThrottle)
|
||||
{
|
||||
CcReEngageWorkerThreads(CcNumberofWorkerThreads, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
VOID
|
||||
NTAPI
|
||||
CcAdjustWriteBehindThreadPoolIfNeeded(
|
||||
IN BOOLEAN NeedAdjustment)
|
||||
{
|
||||
BOOLEAN NeedBoost = false;
|
||||
KSPIN_LOCK_QUEUE_NUMBER queueNumber = LockQueueMasterLock;
|
||||
SpinLockGuard guard(queueNumber);
|
||||
|
||||
if (CcPostTickWorkItemCount != 0)
|
||||
{
|
||||
if (CcIsWriteBehindThreadpoolAtLowPriority())
|
||||
{
|
||||
CcAdjustWriteBehindThreadPool(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ auto DirtyPages = (CcTotalDirtyPages + CcPagesWrittenLastTime);
|
||||
if (DirtyPages > 0x2000 || NeedAdjustment)
|
||||
{
|
||||
if (CcIsWriteBehindThreadpoolAtLowPriority())
|
||||
{
|
||||
CcAdjustWriteBehindThreadPool(false);
|
||||
|
||||
}
|
||||
}
|
||||
else if (!CcExecutingWriteBehindWorkItems && IsListEmpty(&CcRegularWorkQueue))
|
||||
{
|
||||
CcAdjustWriteBehindThreadPool(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
VOID
|
||||
NTAPI
|
||||
CcWorkerThread(PVOID Parameter)
|
||||
@ -1066,7 +1419,7 @@ CcWorkerThread(PVOID Parameter)
|
||||
{
|
||||
CcQueueThrottle = FALSE;
|
||||
DropThrottle = FALSE;
|
||||
// CcReEngageWorkerThreads(CcThreadsActiveBeforeThrottle, CcExtraThreadsActiveBeforeThrottle); Enable When Threadpool is ready
|
||||
CcReEngageWorkerThreads(CcThreadsActiveBeforeThrottle, CcExtraThreadsActiveBeforeThrottle);
|
||||
}
|
||||
|
||||
if (IoStatus.Information == 0x8A5E)
|
||||
|
@ -1,486 +0,0 @@
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,12 +20,6 @@ constexpr ULONG MUTEX_READY_TO_BE_AQUIRED = 0;
|
||||
|
||||
/*Internal Function*/
|
||||
|
||||
/* Fast Mutex definitions */
|
||||
#define FM_LOCK_BIT 0x1
|
||||
#define FM_LOCK_BIT_V 0x0
|
||||
#define FM_LOCK_WAITER_WOKEN 0x2
|
||||
#define FM_LOCK_WAITER_INC 0x4
|
||||
|
||||
typedef struct _FAST_MUTEX
|
||||
{
|
||||
LONG Count; //0x0
|
||||
@ -35,8 +29,6 @@ typedef struct _FAST_MUTEX
|
||||
ULONG OldIrql; //0x1c
|
||||
} FAST_MUTEX, *PFAST_MUTEX; //0x20 bytes (sizeof)
|
||||
|
||||
typedef PFAST_MUTEX PKGUARDED_MUTEX;
|
||||
|
||||
/*Internal Functio*/
|
||||
VOID
|
||||
FASTCALL
|
||||
@ -44,9 +36,9 @@ KiAcquireFastMutex(
|
||||
_Inout_ PFAST_MUTEX Mutex
|
||||
)
|
||||
{
|
||||
LONG AcquireMarker = {0};
|
||||
LONG AcquireBit = {0};
|
||||
LONG OldCount = {0};
|
||||
LONG AcquireMarker;
|
||||
LONG AcquireBit;
|
||||
LONG OldCount;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
@ -57,6 +49,7 @@ KiAcquireFastMutex(
|
||||
AcquireMarker = 4;
|
||||
AcquireBit = 1;
|
||||
|
||||
AcquireLoop:
|
||||
while(true)
|
||||
{
|
||||
/* Read current count */
|
||||
@ -73,7 +66,7 @@ KiAcquireFastMutex(
|
||||
|
||||
AcquireMarker = 2;
|
||||
AcquireBit = 3;
|
||||
continue;
|
||||
goto AcquireLoop;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -88,43 +81,6 @@ KiAcquireFastMutex(
|
||||
}
|
||||
}
|
||||
|
||||
FASTCALL
|
||||
KeReleaseFastMutexContended(
|
||||
IN PFAST_MUTEX FastMutex,
|
||||
IN LONG OldValue)
|
||||
{
|
||||
BOOLEAN WakeWaiter = false;
|
||||
LONG NewValue = {0};
|
||||
PKTHREAD WokenThread = nullptr;
|
||||
KPRIORITY HandoffPriority = {0};
|
||||
|
||||
/* Loop until we successfully update the mutex state */
|
||||
for (;;)
|
||||
{
|
||||
WakeWaiter = false;
|
||||
NewValue = OldValue + FM_LOCK_BIT;
|
||||
|
||||
if (!(OldValue & FM_LOCK_WAITER_WOKEN))
|
||||
{
|
||||
NewValue = OldValue - FM_LOCK_BIT;
|
||||
WakeWaiter = true;
|
||||
}
|
||||
|
||||
LONG PreviousValue = InterlockedCompareExchange(&FastMutex->Lock, NewValue, OldValue);
|
||||
if (PreviousValue == OldValue)
|
||||
break;
|
||||
|
||||
OldValue = PreviousValue;
|
||||
}
|
||||
|
||||
if (WakeWaiter)
|
||||
{
|
||||
/* Wake up a waiter */
|
||||
KeSetEventBoostPriority(&FastMutex->Event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Exported Function */
|
||||
|
||||
VOID
|
||||
@ -133,6 +89,7 @@ KeInitializeFastMutex(
|
||||
_Out_ PFAST_MUTEX Mutex
|
||||
)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
/* Initialize the mutex structure */
|
||||
RtlZeroMemory(Mutex, sizeof(FAST_MUTEX));
|
||||
@ -170,240 +127,7 @@ KeTryToAcquireFastMutex(
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeEnterCriticalRegionAndAcquireFastMutexUnsafe(
|
||||
_In_ PFAST_MUTEX FastMutex)
|
||||
{
|
||||
PKTHREAD OwnerThread = nullptr;
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
/* Get the current thread again (following the pseudocode) */
|
||||
OwnerThread = KeGetCurrentThread();
|
||||
|
||||
/* Try to acquire the FastMutex */
|
||||
if (_InterlockedBitTestAndReset(&FastMutex->Lock, 0))
|
||||
{
|
||||
/* FastMutex was free, we acquired it */
|
||||
FastMutex->Owner = OwnerThread;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FastMutex was locked, we need to wait */
|
||||
KiAcquireFastMutex(FastMutex);
|
||||
FastMutex->Owner = OwnerThread;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
KeReleaseFastMutexUnsafeAndLeaveCriticalRegion(
|
||||
_In_ PFAST_MUTEX FastMutex)
|
||||
{
|
||||
LONG OldValue = {0};
|
||||
PKTHREAD CurrentThread = nullptr ;
|
||||
SHORT NewValue ={0};
|
||||
|
||||
/* Clear the owner */
|
||||
FastMutex->Owner = nullptr;
|
||||
|
||||
/* Try to release the FastMutex */
|
||||
OldValue = InterlockedCompareExchange(&FastMutex->Lock, 1, 0);
|
||||
if (OldValue != 0)
|
||||
{
|
||||
/* Contended case, call the contended release function */
|
||||
KeReleaseFastMutexContended(FastMutex, OldValue);
|
||||
}
|
||||
|
||||
/* leave critical region*/
|
||||
KeLeaveCriticalRegion();
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeAcquireFastMutex(
|
||||
_In_ PFAST_MUTEX FastMutex)
|
||||
{
|
||||
KIRQL OldIrql = {0};
|
||||
|
||||
/* Raise IRQL to APC_LEVEL */
|
||||
OldIrql = KeRaiseIrqlToSynchLevel();
|
||||
|
||||
/* Try to acquire the FastMutex */
|
||||
if (InterlockedBitTestAndReset(&FastMutex->Lock, 0) == 0)
|
||||
{
|
||||
/* We didn't acquire it, we'll have to wait */
|
||||
KiAcquireFastMutex(FastMutex);
|
||||
}
|
||||
|
||||
/* Set the owner thread and save the original IRQL */
|
||||
FastMutex->Owner = KeGetCurrentThread();
|
||||
FastMutex->OldIrql = OldIrql;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeAcquireFastMutexUnsafe(
|
||||
_In_ PFAST_MUTEX FastMutex)
|
||||
{
|
||||
PKTHREAD CurrentThread = nullptr;
|
||||
|
||||
/* Get the current thread */
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
|
||||
/* Try to acquire the FastMutex */
|
||||
if (!InterlockedBitTestAndReset(&FastMutex->Lock, 0))
|
||||
{
|
||||
/* FastMutex was locked, we need to wait */
|
||||
KiAcquireFastMutex(FastMutex);
|
||||
}
|
||||
|
||||
/* Set the owner */
|
||||
FastMutex->Owner = CurrentThread;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeReleaseFastMutex(
|
||||
_Inout_ PFAST_MUTEX FastMutex
|
||||
)
|
||||
{
|
||||
KIRQL OldIrql ={0};
|
||||
LONG OldCount ={0};
|
||||
|
||||
FastMutex->Owner = nullptr;
|
||||
OldIrql = FastMutex->OldIrql;
|
||||
|
||||
OldCount = InterlockedExchangeAdd(&FastMutex->Count, 1);
|
||||
|
||||
if (OldCount != 0 &&
|
||||
(OldCount & 2) == 0 &&
|
||||
InterlockedCompareExchange(&FastMutex->Count, OldCount - 1, OldCount + 1) == OldCount + 1)
|
||||
{
|
||||
KeSetEvent(&FastMutex->Event, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeReleaseFastMutexUnsafe(
|
||||
_In_ PFAST_MUTEX FastMutex)
|
||||
{
|
||||
LONG OldValue = {0};
|
||||
|
||||
/* Clear the owner */
|
||||
FastMutex->Owner = nullptr;
|
||||
|
||||
/* Release the lock and get the old value */
|
||||
OldValue = InterlockedExchangeAdd(&FastMutex->Lock, 1);
|
||||
|
||||
/* Check if there were waiters */
|
||||
if (OldValue != 0)
|
||||
{
|
||||
/* Check if no waiter has been woken up yet */
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Guarded Mutexes in Modern NT behave just like Fast Mutexes with bit of protection */
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeInitializeGuardedMutex(_Out_ PKGUARDED_MUTEX GuardedMutex)
|
||||
{
|
||||
/* Initialize the GuardedMutex*/
|
||||
GuardedMutex->Count = 1;
|
||||
GuardedMutex->Owner = nullptr;
|
||||
GuardedMutex->Contention = 0;
|
||||
/* Initialize the Mutex Gate */
|
||||
KeInitializeEvent(&Mutex->Event, SynchronizationEvent, FALSE);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeAcquireGuardedMutex(_Inout_ PKGUARDED_MUTEX Mutex)
|
||||
{
|
||||
PKTHREAD OwnerThread = KeGetCurrentThread();
|
||||
KeEnterGuardedRegion();
|
||||
if (!_Interlockedbittestandreset(&Mutex->Count, 0) )
|
||||
KiAcquireFastMutex(Mutex);
|
||||
Mutex->Owner = OwnerThread;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeAcquireGuardedMutexUnsafe(
|
||||
_Inout_ PKGUARDED_MUTEX FastMutex
|
||||
)
|
||||
{
|
||||
PKTHREAD CurrentThread = nullptr;
|
||||
KeEnterGuardedRegion();
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
|
||||
if (!_InterlockedBitTestAndReset(&FastMutex->Count, 0))
|
||||
{
|
||||
KiAcquireFastMutex(FastMutex);
|
||||
}
|
||||
|
||||
FastMutex->Owner = CurrentThread;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeReleaseGuardedMutexUnsafe(
|
||||
_Inout_ PKGUARDED_MUTEX FastMutex
|
||||
)
|
||||
{
|
||||
LONG OldCount ={0};
|
||||
|
||||
FastMutex->Owner = nullptr;
|
||||
|
||||
OldCount = _InterlockedExchangeAdd(&FastMutex->Count, 1);
|
||||
|
||||
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);
|
||||
}
|
||||
KeLeaveGuardedRegion();
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeReleaseGuardedMutex(
|
||||
_In_ PKGUARDED_MUTEX FastMutex)
|
||||
{
|
||||
KIRQL OldIrql ={0};
|
||||
LONG OldValue ={0};
|
||||
|
||||
/* Save the old IRQL and clear the owner */
|
||||
OldIrql = FastMutex->OldIrql;
|
||||
FastMutex->Owner = nullptr;
|
||||
|
||||
/* Try to release the FastMutex */
|
||||
OldValue = _InterlockedExchangeAdd(&Mutex->Count, 1);
|
||||
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);
|
||||
}
|
||||
|
||||
/* Lower IRQL */
|
||||
KeLowerIrql(OldIrql);
|
||||
KeLeaveGuardedRegion();
|
||||
}
|
||||
|
@ -34,14 +34,7 @@ Alcyone is written in a subset of C++11 with selected features from modern stand
|
||||
- XDDM: Components related to Display Driver Model
|
||||
|
||||
### SDK Source Directory Structure:
|
||||
- INC: Global header files
|
||||
- CRT: C RunTime source
|
||||
- RTL: Kernel Run-Time Library source
|
||||
|
||||
### Boot Source Directory Structure:
|
||||
- INC: Boot-specific header files
|
||||
- APP/BOOTMGR: Boot Manager source
|
||||
- LIB: Boot library routines and firmware abstractions
|
||||
- CRT: C RunTime
|
||||
|
||||
### Kernel Source Directory Structure:
|
||||
- ALPC: Asynchronous Local Procedure Call
|
||||
|
@ -1,92 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
|
||||
wprintf.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides wide formatted string printing routines.
|
||||
|
||||
--*/
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
static
|
||||
size_t
|
||||
print_hex (
|
||||
wchar_t *wcs,
|
||||
size_t maxlen,
|
||||
unsigned int num
|
||||
)
|
||||
|
||||
{
|
||||
wchar_t *dest;
|
||||
size_t n;
|
||||
int shift;
|
||||
unsigned int x;
|
||||
|
||||
dest = wcs;
|
||||
n = 0;
|
||||
shift = 28;
|
||||
while (n < maxlen && shift >= 0) {
|
||||
x = (num >> shift) & 0xF;
|
||||
if (x >= 0xa) {
|
||||
*dest = 'a' + (x - 0xa);
|
||||
} else {
|
||||
*dest = '0' + x;
|
||||
}
|
||||
|
||||
dest++;
|
||||
n++;
|
||||
shift -= 4;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
vswprintf (
|
||||
wchar_t *wcs,
|
||||
size_t maxlen,
|
||||
const wchar_t *format,
|
||||
va_list args
|
||||
)
|
||||
|
||||
{
|
||||
wchar_t *dest;
|
||||
size_t n, size;
|
||||
|
||||
dest = wcs;
|
||||
n = 0;
|
||||
while (n < maxlen && *format != '\0') {
|
||||
if (*format != '%') {
|
||||
*dest++ = *format++;
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
|
||||
format++;
|
||||
switch (*format) {
|
||||
case 'x':
|
||||
size = print_hex(dest, maxlen - n, va_arg(args, unsigned int));
|
||||
n += size;
|
||||
dest += size;
|
||||
format++;
|
||||
break;
|
||||
case '\0':
|
||||
break;
|
||||
case '%':
|
||||
default:
|
||||
*dest++ = *format++;
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wcs[n] = '\0';
|
||||
return (int)n;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -64,17 +64,21 @@ memmove (
|
||||
|
||||
/* Check for overlap */
|
||||
if (src > dest || ((char *)src + count) < (char *)dest) {
|
||||
/* Low-to-high copy */
|
||||
return memcpy(dest, src, count);
|
||||
}
|
||||
|
||||
/* High-to-low copy */
|
||||
dest = (char *)dest + count - 1;
|
||||
src = (char *)src + count - 1;
|
||||
while (count--) {
|
||||
*(char *)dest = *(char *)src;
|
||||
dest = (char *)dest - 1;
|
||||
src = (char *)src - 1;
|
||||
/* Low-to-high copy, like memcpy() */
|
||||
while (count--) {
|
||||
*(char *)dest = *(char *)src;
|
||||
dest = (char *)dest + 1;
|
||||
src = (char *)src + 1;
|
||||
}
|
||||
} else {
|
||||
/* High-to-low copy */
|
||||
dest = (char *)dest + count - 1;
|
||||
src = (char *)src + count - 1;
|
||||
while (count--) {
|
||||
*(char *)dest = *(char *)src;
|
||||
dest = (char *)dest - 1;
|
||||
src = (char *)src - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -24,11 +24,9 @@ strlen (
|
||||
const char *ptr;
|
||||
|
||||
ptr = str;
|
||||
while (*ptr) {
|
||||
ptr++;
|
||||
}
|
||||
while (*ptr++);
|
||||
|
||||
return ptr - str;
|
||||
return ptr - str - sizeof(char);
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -38,20 +36,18 @@ strnlen (
|
||||
)
|
||||
|
||||
{
|
||||
const char *ptr;
|
||||
size_t len;
|
||||
|
||||
ptr = str;
|
||||
while (maxlen-- && *ptr) {
|
||||
ptr++;
|
||||
}
|
||||
len = 0;
|
||||
while (len < maxlen && str[len++]);
|
||||
|
||||
return ptr - str;
|
||||
return len - sizeof(char);
|
||||
}
|
||||
|
||||
int
|
||||
strcmp (
|
||||
const char *s1,
|
||||
const char *s2
|
||||
const char* s1,
|
||||
const char* s2
|
||||
)
|
||||
|
||||
{
|
||||
@ -69,8 +65,8 @@ strcmp (
|
||||
|
||||
int
|
||||
strncmp (
|
||||
const char *s1,
|
||||
const char *s2,
|
||||
const char* s1,
|
||||
const char* s2,
|
||||
size_t n
|
||||
)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -26,7 +26,8 @@ wmemset (
|
||||
wchar_t *ptr = dest;
|
||||
|
||||
while (count--) {
|
||||
*dest++ = c;
|
||||
*(wchar_t *)dest = c;
|
||||
dest = (wchar_t *)dest + 1;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
@ -43,7 +44,9 @@ wmemcpy (
|
||||
wchar_t *ptr = dest;
|
||||
|
||||
while (count--) {
|
||||
*dest++ = *src++;
|
||||
*(wchar_t *)dest = *(wchar_t *)src;
|
||||
dest = (wchar_t *)dest + 1;
|
||||
src = (wchar_t *)src + 1;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
@ -61,17 +64,21 @@ wmemmove (
|
||||
|
||||
/* Check for overlap */
|
||||
if (src > dest || ((wchar_t *)src + count) < (wchar_t *)dest) {
|
||||
/* Low-to-high copy */
|
||||
return wmemcpy(dest, src, count);
|
||||
}
|
||||
|
||||
/* High-to-low copy */
|
||||
dest = (wchar_t *)dest + count - 1;
|
||||
src = (wchar_t *)src + count - 1;
|
||||
while (count--) {
|
||||
*(wchar_t *)dest = *(wchar_t *)src;
|
||||
dest = (wchar_t *)dest - 1;
|
||||
src = (wchar_t *)src - 1;
|
||||
/* Low-to-high copy, like memcpy() */
|
||||
while (count--) {
|
||||
*(wchar_t *)dest = *(wchar_t *)src;
|
||||
dest = (wchar_t *)dest + 1;
|
||||
src = (wchar_t *)src + 1;
|
||||
}
|
||||
} else {
|
||||
/* High-to-low copy */
|
||||
dest = (wchar_t *)dest + count - 1;
|
||||
src = (wchar_t *)src + count - 1;
|
||||
while (count--) {
|
||||
*(wchar_t *)dest = *(wchar_t *)src;
|
||||
dest = (wchar_t *)dest - 1;
|
||||
src = (wchar_t *)src - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -24,11 +24,9 @@ wcslen (
|
||||
const wchar_t *ptr;
|
||||
|
||||
ptr = str;
|
||||
while (*ptr) {
|
||||
ptr++;
|
||||
}
|
||||
while (*ptr++);
|
||||
|
||||
return ptr - str;
|
||||
return (const char*)ptr - (const char*)str - sizeof(wchar_t);
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -38,20 +36,18 @@ wcsnlen (
|
||||
)
|
||||
|
||||
{
|
||||
const wchar_t *ptr;
|
||||
size_t len;
|
||||
|
||||
ptr = str;
|
||||
while (maxlen-- && *ptr) {
|
||||
ptr++;
|
||||
}
|
||||
len = 0;
|
||||
while (len < maxlen && str[len++]);
|
||||
|
||||
return ptr - str;
|
||||
return len - sizeof(wchar_t);
|
||||
}
|
||||
|
||||
int
|
||||
wcscmp (
|
||||
const wchar_t *s1,
|
||||
const wchar_t *s2
|
||||
const wchar_t* s1,
|
||||
const wchar_t* s2
|
||||
)
|
||||
|
||||
{
|
||||
@ -69,8 +65,8 @@ wcscmp (
|
||||
|
||||
int
|
||||
wcsncmp (
|
||||
const wchar_t *s1,
|
||||
const wchar_t *s2,
|
||||
const wchar_t* s1,
|
||||
const wchar_t* s2,
|
||||
size_t n
|
||||
)
|
||||
|
||||
@ -131,41 +127,3 @@ wcsstr (
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -9,16 +9,16 @@ Module Name:
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides variable argument list definitions.
|
||||
Provides variable arguments definitions.
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _STDARG_H
|
||||
#define _STDARG_H 1
|
||||
#define _STDARG_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@ -29,7 +29,7 @@ typedef __builtin_va_list va_list;
|
||||
#define va_copy(ap, s) __builtin_va_copy(ap, s)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -16,16 +16,14 @@ Abstract:
|
||||
#pragma once
|
||||
|
||||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H 1
|
||||
#define _STDDEF_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#define NULL nullptr
|
||||
#elif defined(__cplusplus)
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void*)0)
|
||||
@ -34,7 +32,7 @@ extern "C" {
|
||||
|
||||
#ifndef _SIZE_T_DEFINED
|
||||
#define _SIZE_T_DEFINED
|
||||
#if defined(_WIN64)
|
||||
#ifdef _WIN64
|
||||
typedef unsigned __int64 size_t;
|
||||
#else
|
||||
typedef unsigned int size_t;
|
||||
@ -43,7 +41,7 @@ typedef unsigned int size_t;
|
||||
|
||||
#ifndef _PTRDIFF_T_DEFINED
|
||||
#define _PTRDIFF_T_DEFINED
|
||||
#if defined(_WIN64)
|
||||
#ifdef _WIN64
|
||||
typedef __int64 ptrdiff_t;
|
||||
#else
|
||||
typedef long int ptrdiff_t;
|
||||
@ -55,9 +53,7 @@ typedef long int ptrdiff_t;
|
||||
typedef unsigned short wchar_t;
|
||||
#endif
|
||||
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -16,26 +16,26 @@ Abstract:
|
||||
#pragma once
|
||||
|
||||
#ifndef _STRING_H
|
||||
#define _STRING_H 1
|
||||
#define _STRING_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
size_t strlen(const char *str);
|
||||
size_t strnlen(const char *str, size_t maxlen);
|
||||
int strcmp(const char* s1, const char* s2);
|
||||
int strncmp(const char* s1, const char* s2, size_t n);
|
||||
char *strchr(const char *s, int c);
|
||||
char *strstr(const char *haystack, const char *needle);
|
||||
|
||||
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 strnlen(const char *str, size_t maxlen);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
int strncmp(const char *s1, const char *s2, size_t n);
|
||||
char *strchr(const char *s, int c);
|
||||
char *strstr(const char *haystack, const char *needle);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -16,31 +16,26 @@ Abstract:
|
||||
#pragma once
|
||||
|
||||
#ifndef _WCHAR_H
|
||||
#define _WCHAR_H 1
|
||||
#define _WCHAR_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
size_t wcslen(const wchar_t *str);
|
||||
size_t wcsnlen(const wchar_t *str, size_t maxlen);
|
||||
int wcscmp(const wchar_t* s1, const wchar_t* s2);
|
||||
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 *wcsstr(const wchar_t *haystack, const wchar_t *needle);
|
||||
|
||||
wchar_t *wmemset(wchar_t *dest, wchar_t c, size_t count);
|
||||
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 wcsnlen(const wchar_t *str, size_t maxlen);
|
||||
int wcscmp(const wchar_t *s1, const wchar_t *s2);
|
||||
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 *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 *wcscat_s(wchar_t *dest, size_t maxlen, const wchar_t *src);
|
||||
|
||||
int vswprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, va_list args);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,78 +0,0 @@
|
||||
/*++
|
||||
|
||||
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 */
|
@ -1,34 +0,0 @@
|
||||
/*++
|
||||
|
||||
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
1006
SDK/INC/EFI/efiapi.h
File diff suppressed because it is too large
Load Diff
@ -1,436 +0,0 @@
|
||||
/*++
|
||||
|
||||
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 */
|
@ -1,377 +0,0 @@
|
||||
/*++
|
||||
|
||||
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 */
|
File diff suppressed because it is too large
Load Diff
@ -1,88 +0,0 @@
|
||||
/*++
|
||||
|
||||
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 */
|
@ -1,72 +0,0 @@
|
||||
/*++
|
||||
|
||||
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 */
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -13,8 +13,6 @@ Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _GUIDDEF_H
|
||||
#define _GUIDDEF_H
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -13,8 +13,6 @@ Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _NT_H
|
||||
#define _NT_H
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -13,8 +13,6 @@ Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _NTDEF_H
|
||||
#define _NTDEF_H
|
||||
|
||||
@ -33,7 +31,7 @@ Abstract:
|
||||
#endif
|
||||
|
||||
#ifndef VOID
|
||||
#define VOID void
|
||||
#define VOID void
|
||||
#endif
|
||||
|
||||
#ifndef CONST
|
||||
@ -46,23 +44,16 @@ Abstract:
|
||||
|
||||
#ifndef NULL
|
||||
#if defined(__cplusplus)
|
||||
#if __cplusplus >= 201103L
|
||||
#define NULL nullptr
|
||||
#else
|
||||
#define NULL 0
|
||||
#endif
|
||||
#else
|
||||
#define NULL ((VOID *) 0)
|
||||
#define NULL ((VOID *)0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef FORCEINLINE
|
||||
#if defined(_MSC_EXTENSIONS)
|
||||
#define FORCEINLINE __forceinline
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
#define FORCEINLINE __attribute__((always_inline))
|
||||
#else
|
||||
#warning Unable to define FORCEINLINE
|
||||
#define FORCEINLINE static inline
|
||||
#endif
|
||||
#endif
|
||||
@ -70,24 +61,14 @@ Abstract:
|
||||
#ifndef FASTCALL
|
||||
#if defined(_M_IX86)
|
||||
#define FASTCALL __fastcall
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
#define FASTCALL __attribute__((fastcall))
|
||||
#else
|
||||
#warning Unable to defined FASTCALL
|
||||
#define FASTCALL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NTAPI
|
||||
#if !defined(_M_AMD64)
|
||||
#if defined(_MSC_EXTENSIONS)
|
||||
#define NTAPI __stdcall
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
#define NTAPI __attribute__((stdcall))
|
||||
#else
|
||||
#warning Unable to define NTAPI
|
||||
#define NTAPI
|
||||
#endif
|
||||
#else
|
||||
#define NTAPI
|
||||
#endif
|
||||
@ -96,86 +77,35 @@ Abstract:
|
||||
//
|
||||
// Basic types.
|
||||
//
|
||||
typedef char CHAR;
|
||||
typedef char CHAR;
|
||||
typedef short SHORT;
|
||||
typedef long LONG;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef long LONG;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned long ULONG;
|
||||
|
||||
//
|
||||
// Minimum/maximum values of basic types.
|
||||
//
|
||||
#define MINCHAR 0x80
|
||||
#define MAXCHAR 0x7F
|
||||
#define MAXCHAR 0x7f
|
||||
#define MINSHORT 0x8000
|
||||
#define MAXSHORT 0x7FFF
|
||||
#define MAXSHORT 0x7fff
|
||||
#define MINLONG 0x80000000
|
||||
#define MAXLONG 0x7FFFFFFF
|
||||
#define MAXUCHAR 0xFF
|
||||
#define MAXUSHORT 0xFFFF
|
||||
#define MAXULONG 0xFFFFFFFF
|
||||
#define MAXLONG 0x7fffffff
|
||||
#define MAXUCHAR 0xff
|
||||
#define MAXUSHORT 0xffff
|
||||
#define MAXULONG 0xffffffff
|
||||
|
||||
//
|
||||
// Long long types.
|
||||
// Basic pointer types.
|
||||
//
|
||||
#if defined(_MSC_EXTENSIONS)
|
||||
typedef __int64 LONGLONG;
|
||||
typedef unsigned __int64 ULONGLONG;
|
||||
#elif defined(UNIX_LP64)
|
||||
typedef long LONGLONG;
|
||||
typedef unsigned long ULONGLONG;
|
||||
#else
|
||||
typedef long long LONGLONG;
|
||||
typedef unsigned long long ULONGLONG;
|
||||
#endif
|
||||
|
||||
#define MAXLONGLONG 0x7FFFFFFFFFFFFFFF
|
||||
#define MAXULONGLONG 0xFFFFFFFFFFFFFFFF
|
||||
|
||||
//
|
||||
// Logical/boolean value types.
|
||||
//
|
||||
typedef ULONG LOGICAL;
|
||||
typedef int BOOL;
|
||||
typedef UCHAR BOOLEAN;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
//
|
||||
// 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 CHAR *PCHAR;
|
||||
typedef SHORT *PSHORT;
|
||||
typedef UCHAR *PUCHAR;
|
||||
typedef VOID *PVOID;
|
||||
typedef CHAR *PCHAR;
|
||||
typedef SHORT *PSHORT;
|
||||
typedef UCHAR *PUCHAR;
|
||||
typedef USHORT *PUSHORT;
|
||||
typedef ULONG *PULONG;
|
||||
|
||||
//
|
||||
// Long long type pointers.
|
||||
//
|
||||
typedef LONGLONG *PLONGLONG;
|
||||
typedef ULONGLONG *PULONGLONG;
|
||||
|
||||
//
|
||||
// Logical/boolean type pointers.
|
||||
//
|
||||
typedef ULONG *PLOGICAL;
|
||||
typedef BOOL *PBOOL;
|
||||
typedef BOOLEAN *PBOOLEAN;
|
||||
typedef ULONG *PULONG;
|
||||
|
||||
//
|
||||
// String types.
|
||||
@ -191,17 +121,39 @@ typedef WCHAR *PWCHAR, *PWSTR, *LPWSTR;
|
||||
typedef CONST WCHAR *PCWSTR, *LPCWSTR;
|
||||
|
||||
//
|
||||
// Handle types.
|
||||
// Long long types.
|
||||
//
|
||||
typedef PVOID HANDLE;
|
||||
typedef HANDLE *PHANDLE;
|
||||
#if defined(_MSC_EXTENSIONS)
|
||||
typedef __int64 LONGLONG;
|
||||
typedef unsigned __int64 ULONGLONG;
|
||||
#elif defined(UNIX_LP64)
|
||||
typedef long LONGLONG;
|
||||
typedef unsigned long ULONGLONG;
|
||||
#else
|
||||
typedef long long LONGLONG;
|
||||
typedef unsigned long long ULONGLONG;
|
||||
#endif
|
||||
|
||||
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR) -1)
|
||||
typedef LONGLONG *PLONGLONG;
|
||||
typedef ULONGLONG *PULONGLONG;
|
||||
|
||||
#define MAXLONGLONG (0x7fffffffffffffff)
|
||||
|
||||
//
|
||||
// Logical/boolean value types.
|
||||
//
|
||||
typedef ULONG LOGICAL;
|
||||
typedef ULONG *PLOGICAL;
|
||||
typedef UCHAR BOOLEAN;
|
||||
typedef BOOLEAN *PBOOLEAN;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
//
|
||||
// Status code types.
|
||||
//
|
||||
typedef LONG NTSTATUS;
|
||||
typedef LONG NTSTATUS;
|
||||
typedef NTSTATUS *PNTSTATUS;
|
||||
|
||||
//
|
||||
@ -227,23 +179,13 @@ typedef NTSTATUS *PNTSTATUS;
|
||||
#define ALIGN_DOWN(x, a) ((x) & ~((a) - 1))
|
||||
#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.
|
||||
//
|
||||
typedef union LARGE_INTEGER {
|
||||
struct {
|
||||
ULONG LowPart;
|
||||
LONG HighPart;
|
||||
LONG HighPart;
|
||||
};
|
||||
|
||||
LONGLONG QuadPart;
|
||||
@ -261,13 +203,21 @@ typedef union ULARGE_INTEGER {
|
||||
ULONGLONG QuadPart;
|
||||
} ULARGE_INTEGER, *PULARGE_INTEGER;
|
||||
|
||||
//
|
||||
// Doubly-linked list entry.
|
||||
//
|
||||
typedef struct _LIST_ENTRY {
|
||||
struct _LIST_ENTRY *ForwardLink;
|
||||
struct _LIST_ENTRY *BackLink;
|
||||
} LIST_ENTRY, *PLIST_ENTRY;
|
||||
|
||||
//
|
||||
// Unicode string.
|
||||
//
|
||||
typedef struct _UNICODE_STRING {
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
PWSTR Buffer;
|
||||
} UNICODE_STRING, *PUNICODE_STRING;
|
||||
typedef CONST UNICODE_STRING *PCUNICODE_STRING;
|
||||
|
||||
@ -275,14 +225,6 @@ typedef CONST UNICODE_STRING *PCUNICODE_STRING;
|
||||
|
||||
#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>
|
||||
|
||||
#endif /* !_NTDEF_H */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -13,36 +13,14 @@ Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _NTIMAGE_H
|
||||
#define _NTIMAGE_H
|
||||
|
||||
//
|
||||
// Machine types.
|
||||
// Machine type values.
|
||||
//
|
||||
#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014C
|
||||
#define IMAGE_FILE_MACHINE_UNKNOWN 0
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||
#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 */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -13,14 +13,11 @@ Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _NTRTL_H
|
||||
#define _NTRTL_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <ntdef.h>
|
||||
|
||||
//
|
||||
// Memory operations.
|
||||
@ -30,184 +27,18 @@ extern "C" {
|
||||
#define RtlFillMemory(Destination, Length, Fill) memset((Destination), (Fill), (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
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
RtlULongSub (
|
||||
IN ULONG ulMinuend,
|
||||
IN ULONG ulSubtrahend,
|
||||
IN OUT PULONG pulResult
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Calculates the difference of two ULONG values.
|
||||
|
||||
Arguments:
|
||||
|
||||
ulMinuend - The value to subtract ulSubtrahend from.
|
||||
|
||||
ulSubtrahend - The value to subtract from ulMinuend.
|
||||
|
||||
pulResult - Pointer to a ULONG to store the difference in.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful.
|
||||
STATUS_INTEGER_OVERFLOW if unsuccessful.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
if (ulMinuend >= ulSubtrahend) {
|
||||
*pulResult = ulMinuend - ulSubtrahend;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
*pulResult = ULONG_ERROR;
|
||||
return STATUS_INTEGER_OVERFLOW;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
RtlInitUnicodeString (
|
||||
OUT PUNICODE_STRING Destination,
|
||||
IN PCWSTR Source
|
||||
IN PCWSTR Source
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlGUIDFromString (
|
||||
IN PUNICODE_STRING String,
|
||||
OUT GUID *Guid
|
||||
IN PUNICODE_STRING String,
|
||||
OUT GUID *Guid
|
||||
);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_NTRTL_H */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -13,47 +13,32 @@ Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _NTSTATUS_H
|
||||
#define _NTSTATUS_H
|
||||
|
||||
#define STATUS_SUCCESS ((NTSTATUS) 0x00000000L)
|
||||
#define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL)
|
||||
#define STATUS_UNSUCCESSFUL ((NTSTATUS) 0xC0000001L)
|
||||
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L)
|
||||
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL)
|
||||
#define STATUS_NO_MEMORY ((NTSTATUS) 0xC0000017L)
|
||||
#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L)
|
||||
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L)
|
||||
#define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L)
|
||||
#define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L)
|
||||
#define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL)
|
||||
#define STATUS_INTEGER_OVERFLOW ((NTSTATUS) 0xC0000095L)
|
||||
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL)
|
||||
#define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L)
|
||||
#define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L)
|
||||
#define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL)
|
||||
#define STATUS_INVALID_PARAMETER_1 ((NTSTATUS) 0xC00000EFL)
|
||||
#define STATUS_INVALID_PARAMETER_2 ((NTSTATUS) 0xC00000F0L)
|
||||
#define STATUS_INVALID_PARAMETER_3 ((NTSTATUS) 0xC00000F1L)
|
||||
#define STATUS_INVALID_PARAMETER_4 ((NTSTATUS) 0xC00000F2L)
|
||||
#define STATUS_INVALID_PARAMETER_5 ((NTSTATUS) 0xC00000F3L)
|
||||
#define STATUS_INVALID_PARAMETER_6 ((NTSTATUS) 0xC00000F4L)
|
||||
#define STATUS_INVALID_PARAMETER_7 ((NTSTATUS) 0xC00000F5L)
|
||||
#define STATUS_INVALID_PARAMETER_8 ((NTSTATUS) 0xC00000F6L)
|
||||
#define STATUS_INVALID_PARAMETER_9 ((NTSTATUS) 0xC00000F7L)
|
||||
#define STATUS_INVALID_PARAMETER_10 ((NTSTATUS) 0xC00000F8L)
|
||||
#define STATUS_INVALID_PARAMETER_11 ((NTSTATUS) 0xC00000F9L)
|
||||
#define STATUS_INVALID_PARAMETER_12 ((NTSTATUS) 0xC00000FAL)
|
||||
#define STATUS_TIMEOUT ((NTSTATUS) 0x00000102L)
|
||||
#define STATUS_NO_MEDIA ((NTSTATUS) 0xC0000178L)
|
||||
#define STATUS_IO_DEVICE_ERROR ((NTSTATUS) 0xC0000185L)
|
||||
#define STATUS_INVALID_BUFFER_SIZE ((NTSTATUS) 0xC0000206L)
|
||||
#define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L)
|
||||
#define STATUS_REQUEST_ABORTED ((NTSTATUS) 0xC0000240L)
|
||||
#define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS) 0xC000026CL)
|
||||
#define STATUS_NO_MATCH ((NTSTATUS) 0xC0000272L)
|
||||
#define STATUS_INSUFFICIENT_NVRAM_RESOURCES ((NTSTATUS) 0xC0000454L)
|
||||
#define STATUS_SUCCESS ((NTSTATUS) 0x00000000L)
|
||||
|
||||
//
|
||||
// TODO: There are an insane amount of status values.
|
||||
//
|
||||
#define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL)
|
||||
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL)
|
||||
#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L)
|
||||
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L)
|
||||
#define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L)
|
||||
#define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L)
|
||||
#define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL)
|
||||
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL)
|
||||
#define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L)
|
||||
#define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L)
|
||||
#define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL)
|
||||
#define STATUS_TIMEOUT ((NTSTATUS) 0x00000102L)
|
||||
#define STATUS_NO_MEDIA ((NTSTATUS) 0xC0000178L)
|
||||
#define STATUS_IO_DEVICE_ERROR ((NTSTATUS) 0xC0000185L)
|
||||
#define STATUS_INVALID_BUFFER_SIZE ((NTSTATUS) 0xC0000206L)
|
||||
#define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L)
|
||||
#define STATUS_REQUEST_ABORTED ((NTSTATUS) 0xC0000240L)
|
||||
#define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS) 0xC000026CL)
|
||||
#define STATUS_NO_MATCH ((NTSTATUS) 0xC0000272L)
|
||||
|
||||
#endif /* !_NTSTATUS_H */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -13,13 +13,14 @@ Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#include <nt.h>
|
||||
#include <ntrtl.h>
|
||||
#include <ntstatus.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int
|
||||
ScanHexFormat (
|
||||
IN PCWSTR Buffer,
|
||||
IN ULONG MaximumLength,
|
||||
IN ULONG MaximumLength,
|
||||
IN PCWSTR Format,
|
||||
...
|
||||
)
|
||||
@ -28,17 +29,13 @@ ScanHexFormat (
|
||||
|
||||
Routine Description:
|
||||
|
||||
Parses a formatted hex string.
|
||||
Turns a text representation of a GUID into the binary format.
|
||||
|
||||
Arguments:
|
||||
|
||||
Buffer - The source string to parse.
|
||||
String - A GUID string in the format {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
|
||||
|
||||
MaximumLength - The length of the source string.
|
||||
|
||||
Format - The format of the source string.
|
||||
|
||||
... - Pointers to data destinations.
|
||||
Guid - The GUID structure which is to recieve the data.
|
||||
|
||||
Return Value:
|
||||
|
||||
@ -97,10 +94,10 @@ Return Value:
|
||||
|
||||
if (*Buffer >= '0' && *Buffer <= '9') {
|
||||
Number += *Buffer - '0';
|
||||
} else if (*Buffer >= 'A' && *Buffer <= 'F') {
|
||||
Number += *Buffer - 'A' + 0xA;
|
||||
} else if (*Buffer >= 'a' && *Buffer <= 'f') {
|
||||
Number += *Buffer - 'a' + 0xa;
|
||||
} else if (*Buffer >= 'A' && *Buffer <= 'F') {
|
||||
Number += *Buffer - 'A' + 0xA;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@ -129,8 +126,8 @@ Return Value:
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlGUIDFromString (
|
||||
IN PUNICODE_STRING String,
|
||||
OUT GUID *Guid
|
||||
IN PUNICODE_STRING String,
|
||||
OUT GUID *Guid
|
||||
)
|
||||
|
||||
/*++
|
||||
@ -159,9 +156,9 @@ Return Value:
|
||||
// Convert string to GUID data.
|
||||
//
|
||||
if (ScanHexFormat(
|
||||
String->Buffer, String->Length / sizeof(WCHAR),
|
||||
L"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
&Guid->Data1, &Guid->Data2, &Guid->Data3, &Data4[0], &Data4[1], &Data4[2], &Data4[3], &Data4[4], &Data4[5], &Data4[6], &Data4[7]
|
||||
String->Buffer, String->Length / sizeof(WCHAR),
|
||||
L"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
&Guid->Data1, &Guid->Data2, &Guid->Data3, &Data4[0], &Data4[1], &Data4[2], &Data4[3], &Data4[4], &Data4[5], &Data4[6], &Data4[7]
|
||||
) == -1) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2024-2025, Quinn Stephens.
|
||||
Copyright (c) 2024, Quinn Stephens.
|
||||
Provided under the BSD 3-Clause license.
|
||||
|
||||
Module Name:
|
||||
@ -13,14 +13,14 @@ Abstract:
|
||||
|
||||
--*/
|
||||
|
||||
#include <nt.h>
|
||||
#include <ntrtl.h>
|
||||
#include <wchar.h>
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
RtlInitUnicodeString (
|
||||
OUT PUNICODE_STRING Destination,
|
||||
IN PCWSTR Source
|
||||
IN PCWSTR Source
|
||||
)
|
||||
|
||||
/*++
|
||||
@ -32,9 +32,9 @@ Routine Description:
|
||||
|
||||
Arguments:
|
||||
|
||||
Destination - Pointer to the unicode string structure.
|
||||
Destination - A 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.
|
||||
|
||||
Return Value:
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
--- Copyright (c) 2024-2025, Quinn Stephens.
|
||||
--- Copyright (c) 2024, Quinn Stephens.
|
||||
--- Provided under the BSD 3-Clause license.
|
||||
---
|
||||
|
||||
@ -44,14 +44,12 @@ project("RTL")
|
||||
project("BOOTMGR")
|
||||
kind("ConsoleApp")
|
||||
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", "SDK/INC/EFI" })
|
||||
includedirs({ "BOOT/ENVIRON/INC", "SDK/INC/CRT", "SDK/INC/NT" })
|
||||
libdirs({ "BUILD/SDK" })
|
||||
objdir("BUILD/BOOT")
|
||||
targetdir("BUILD/BOOT")
|
||||
|
||||
defines({ "_EFI" })
|
||||
files({ "BOOT/ENVIRON/INC/**.h", "BOOT/ENVIRON/**.c" })
|
||||
|
||||
filter("toolset:clang")
|
||||
buildoptions({ "-fshort-wchar", "-fno-strict-aliasing", "-fno-stack-protector", "-fno-stack-check", "-mno-red-zone" })
|
||||
|
Loading…
Reference in New Issue
Block a user