Compare commits
43 Commits
LazyWriter
...
4c32340803
Author | SHA1 | Date | |
---|---|---|---|
4c32340803 | |||
a32d72be1e | |||
75197cc8b5 | |||
6fc91eb58c | |||
437b19a0f5 | |||
860874640e | |||
2751b0f7bb | |||
6a868b45ba | |||
831a676af8 | |||
d759302400 | |||
c7298452ff | |||
72f7e5057c | |||
b63d80d5c9 | |||
ef1ac515dd | |||
bbd8f475bb | |||
caec9bc42e | |||
1581638c26 | |||
664bf6d713 | |||
76b01cfb00 | |||
4dbb5235e3
|
|||
dd7ae11851 | |||
7125a17aca | |||
de9501aee9 | |||
e61d0f5155 | |||
b8afb1aad4 | |||
fb0e36f5cf | |||
c091f7ef59 | |||
3759f7dbfe | |||
b96b3d769c | |||
7aac701cc1 | |||
77d2f84e97 | |||
b870d5a015 | |||
5235ebdfa4 | |||
874d95ae4c | |||
8f56881d02 | |||
0743fa0106 | |||
fd670ace0d | |||
9b66f166d6 | |||
a6aa028e5c | |||
ccb62c05f5 | |||
1c2c797365 | |||
08d017171d
|
|||
d0d6097d57
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -9,6 +9,7 @@
|
|||||||
Makefile
|
Makefile
|
||||||
/BUILD/
|
/BUILD/
|
||||||
/UNUSED/
|
/UNUSED/
|
||||||
|
/DISK/
|
||||||
|
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
*.d
|
*.d
|
||||||
@@ -43,3 +44,7 @@ Makefile
|
|||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
|
|
||||||
|
# Disk image files
|
||||||
|
*.img
|
||||||
|
*.iso
|
||||||
|
*.fd
|
||||||
|
@@ -31,15 +31,14 @@ Routine Description:
|
|||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
ImageHandle - Handle for the boot manager image.
|
ImageHandle - EFI handle for the boot manager image.
|
||||||
|
|
||||||
SystemTable - Pointer to the EFI system table.
|
SystemTable - Pointer to the EFI system table.
|
||||||
|
|
||||||
Return Value:
|
Return Value:
|
||||||
|
|
||||||
EFI_SUCCESS if successful.
|
EFI_INVALID_PARAMETER if EfiInitCreateInputParameters() fails.
|
||||||
EFI_INVALID_PARAMEER if input parameter structure creation fails.
|
Any status code returned by EfiGetEfiStatusCode(BmMain()).
|
||||||
Any other value defined in efierr.h.
|
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
55
BOOT/ENVIRON/APP/BOOTMGR/bcd.c
Normal file
55
BOOT/ENVIRON/APP/BOOTMGR/bcd.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
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 "bootlib.h"
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BmOpenDataStore (
|
||||||
|
IN OUT PHANDLE DataStore
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Opens the boot configuration data store.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DataStore - Pointer to a HANDLE that recieves the data store handle.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
STATUS_SUCCESS.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
*DataStore = 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;
|
||||||
|
}
|
@@ -41,17 +41,27 @@ Return Value:
|
|||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
BOOT_LIBRARY_PARAMETERS LibraryParameters;
|
BOOT_LIBRARY_PARAMETERS LibraryParameters;
|
||||||
|
HANDLE DataStore;
|
||||||
|
|
||||||
LibraryParameters.Flags = 0;
|
LibraryParameters.Flags = 0;
|
||||||
|
LibraryParameters.MinimumPageAllocation = 16;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize the boot library.
|
// Initialize the boot library.
|
||||||
//
|
//
|
||||||
Status = BlInitializeLibrary(InputParameters, &LibraryParameters);
|
Status = BlInitializeLibrary(InputParameters, &LibraryParameters);
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
ConsolePrintf(L"BlInitializeLibrary() failed: 0x%x\r\n", Status);
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Open the boot data store.
|
||||||
|
//
|
||||||
|
(VOID)BmOpenDataStore(&DataStore);
|
||||||
|
|
||||||
|
while (TRUE);
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
BlDestroyLibrary();
|
BlDestroyLibrary();
|
||||||
return Status;
|
return Status;
|
||||||
|
@@ -21,8 +21,60 @@ Abstract:
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
|
ULONG TranslationType;
|
||||||
|
ULONG MinimumPageAllocation;
|
||||||
} BOOT_LIBRARY_PARAMETERS, *PBOOT_LIBRARY_PARAMETERS;
|
} BOOT_LIBRARY_PARAMETERS, *PBOOT_LIBRARY_PARAMETERS;
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ConsolePrint (
|
||||||
|
IN PWSTR String
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ConsolePrintf (
|
||||||
|
IN PWSTR Format,
|
||||||
|
...
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Enable/disable debug printing.
|
||||||
|
//
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define DebugPrint(String) ConsolePrint(String)
|
||||||
|
#define DebugPrintf(Format, ...) ConsolePrintf(Format, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DebugPrint(String)
|
||||||
|
#define DebugPrintf(Format, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
BlGetBootOptionSize (
|
||||||
|
IN PBOOT_APPLICATION_OPTION Option
|
||||||
|
);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
BlGetBootOptionListSize (
|
||||||
|
IN PBOOT_APPLICATION_OPTION Options
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlpFwInitialize (
|
||||||
|
IN ULONG Stage,
|
||||||
|
IN PBOOT_FIRMWARE_DATA FirmwareData
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlpMmInitializeConstraints (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlpMmInitialize (
|
||||||
|
IN PBOOT_MEMORY_INFO MemoryInfo,
|
||||||
|
IN ULONG TranslationType,
|
||||||
|
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BlInitializeLibrary (
|
BlInitializeLibrary (
|
||||||
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
||||||
|
@@ -28,17 +28,18 @@ Abstract:
|
|||||||
#define BOOT_MACHINE_TYPE IMAGE_FILE_MACHINE_I386
|
#define BOOT_MACHINE_TYPE IMAGE_FILE_MACHINE_I386
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
|
||||||
// No address translation.
|
|
||||||
//
|
|
||||||
#define BOOT_TRANSLATION_TYPE 0
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Use EFI page size.
|
// Use EFI page size.
|
||||||
//
|
//
|
||||||
#define PAGE_SIZE EFI_PAGE_SIZE
|
#define PAGE_SIZE EFI_PAGE_SIZE
|
||||||
#define PAGE_SHIFT EFI_PAGE_SHIFT
|
#define PAGE_SHIFT EFI_PAGE_SHIFT
|
||||||
|
|
||||||
|
//
|
||||||
|
// Address translation types.
|
||||||
|
//
|
||||||
|
#define BOOT_TRANSLATION_TYPE_NONE 0
|
||||||
|
#define BOOT_TRANSLATION_TYPE_MAX 1
|
||||||
|
|
||||||
#define BOOT_INPUT_PARAMETERS_SIGNATURE 0x50504120544f4f42 /* "BOOT APP" */
|
#define BOOT_INPUT_PARAMETERS_SIGNATURE 0x50504120544f4f42 /* "BOOT APP" */
|
||||||
#define BOOT_INPUT_PARAMETERS_VERSION 2
|
#define BOOT_INPUT_PARAMETERS_VERSION 2
|
||||||
|
|
||||||
@@ -67,18 +68,35 @@ typedef struct {
|
|||||||
ULONG BootDeviceOffset;
|
ULONG BootDeviceOffset;
|
||||||
ULONG FirmwareDataOffset;
|
ULONG FirmwareDataOffset;
|
||||||
ULONG ReturnDataOffset;
|
ULONG ReturnDataOffset;
|
||||||
|
|
||||||
ULONG PlatformDataOffset;
|
ULONG PlatformDataOffset;
|
||||||
} BOOT_INPUT_PARAMETERS, *PBOOT_INPUT_PARAMETERS;
|
} BOOT_INPUT_PARAMETERS, *PBOOT_INPUT_PARAMETERS;
|
||||||
|
|
||||||
#define BOOT_APPLICATION_ENTRY_SIGNATURE 0x544e4550415442 /* "BTAPENT" */
|
typedef struct {
|
||||||
|
ULONG Type;
|
||||||
|
ULONG DataOffset;
|
||||||
|
ULONG DataSize;
|
||||||
|
ULONG OtherOptionsOffset;
|
||||||
|
ULONG NextOptionOffset;
|
||||||
|
BOOLEAN IsInvalid;
|
||||||
|
UCHAR Unknown[3];
|
||||||
|
} BOOT_APPLICATION_OPTION, *PBOOT_APPLICATION_OPTION;
|
||||||
|
|
||||||
#define BOOT_APPLICATION_ENTRY_BCD_IDENTIFIER_NOT_SET 0x01
|
#define BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE 0x544e4550415442 /* "BTAPENT" */
|
||||||
|
|
||||||
|
#define BOOT_INPUT_APPLICATION_ENTRY_NO_BCD_IDENTIFIER 0x01
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ULONGLONG Signature;
|
ULONGLONG Signature;
|
||||||
ULONG Attributes;
|
ULONG Attributes;
|
||||||
GUID BcdIdentifier;
|
GUID BcdIdentifier;
|
||||||
|
UCHAR Unknown[16];
|
||||||
|
BOOT_APPLICATION_OPTION Options;
|
||||||
|
} BOOT_INPUT_APPLICATION_ENTRY, *PBOOT_INPUT_APPLICATION_ENTRY;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ULONG Attributes;
|
||||||
|
GUID BcdIdentifier;
|
||||||
|
PBOOT_APPLICATION_OPTION Options;
|
||||||
} BOOT_APPLICATION_ENTRY, *PBOOT_APPLICATION_ENTRY;
|
} BOOT_APPLICATION_ENTRY, *PBOOT_APPLICATION_ENTRY;
|
||||||
|
|
||||||
#define BOOT_MEMORY_INFO_VERSION 1
|
#define BOOT_MEMORY_INFO_VERSION 1
|
||||||
@@ -88,22 +106,74 @@ typedef struct {
|
|||||||
ULONG MdlOffset;
|
ULONG MdlOffset;
|
||||||
ULONG DescriptorCount;
|
ULONG DescriptorCount;
|
||||||
ULONG DescriptorSize;
|
ULONG DescriptorSize;
|
||||||
ULONG BasePageOffset;
|
ULONG FirstPageOffset;
|
||||||
} BOOT_MEMORY_INFO, *PBOOT_MEMORY_INFO;
|
} BOOT_MEMORY_INFO, *PBOOT_MEMORY_INFO;
|
||||||
|
|
||||||
#define MEMORY_ATTRIBUTE_CACHE_WB 0x08
|
//
|
||||||
|
// Memory descriptor caching attributes.
|
||||||
|
//
|
||||||
|
#define MEMORY_ATTRIBUTE_UC 0x0000000000000001
|
||||||
|
#define MEMORY_ATTRIBUTE_WC 0x0000000000000002
|
||||||
|
#define MEMORY_ATTRIBUTE_WT 0x0000000000000004
|
||||||
|
#define MEMORY_ATTRIBUTE_WB 0x0000000000000008
|
||||||
|
#define MEMORY_ATTRIBUTE_UCE 0x0000000000000010
|
||||||
|
|
||||||
#define MEMORY_TYPE_BOOT_APPLICATION 0xd0000002
|
//
|
||||||
|
// Memory descriptor protection attributes.
|
||||||
|
//
|
||||||
|
#define MEMORY_ATTRIBUTE_WP 0x000000000000100
|
||||||
|
#define MEMORY_ATTRIBUTE_RP 0x000000000000200
|
||||||
|
#define MEMORY_ATTRIBUTE_XP 0x000000000000400
|
||||||
|
|
||||||
|
//
|
||||||
|
// Memory descriptor location attributes.
|
||||||
|
//
|
||||||
|
#define MEMORY_ATTRIBUTE_BELOW_1MIB 0x80000
|
||||||
|
|
||||||
|
//
|
||||||
|
// Memory descriptor runtime mapping attributes.
|
||||||
|
//
|
||||||
|
#define MEMORY_ATTRIBUTE_RUNTIME 0x1000000
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MEMORY_TYPE_BOOT_APPLICATION = 0xD0000002,
|
||||||
|
MEMORY_TYPE_FREE = 0xF0000001,
|
||||||
|
MEMORY_TYPE_UNUSABLE = 0xF0000002,
|
||||||
|
MEMORY_TYPE_RESERVED = 0xF0000003,
|
||||||
|
MEMORY_TYPE_BOOT_SERVICES = 0xF0000004,
|
||||||
|
MEMORY_TYPE_RUNTIME_SERVICES_CODE = 0xF0000006,
|
||||||
|
MEMORY_TYPE_PERSISTENT = 0xF0000007,
|
||||||
|
MEMORY_TYPE_ACPI_RECLAIM = 0xF0000008,
|
||||||
|
MEMORY_TYPE_ACPI_NVS = 0xF0000009,
|
||||||
|
MEMORY_TYPE_MMIO = 0xF000000A,
|
||||||
|
MEMORY_TYPE_MMIO_PORT_SPACE = 0xF000000B,
|
||||||
|
MEMORY_TYPE_PAL_CODE = 0xF000000C,
|
||||||
|
MEMORY_TYPE_RUNTIME_SERVICES_DATA = 0xF000000E
|
||||||
|
} MEMORY_TYPE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
LIST_ENTRY ListEntry;
|
LIST_ENTRY ListEntry;
|
||||||
|
|
||||||
ULONGLONG BasePage;
|
ULONGLONG FirstPage;
|
||||||
ULONG Pages;
|
ULONGLONG MappedFirstPage;
|
||||||
|
ULONG PageCount;
|
||||||
|
|
||||||
ULONG Attributes;
|
ULONG Attributes;
|
||||||
ULONG Type;
|
MEMORY_TYPE Type;
|
||||||
} BOOT_MEMORY_DESCRIPTOR, *PBOOT_MEMORY_DESCRIPTOR;
|
} MEMORY_DESCRIPTOR, *PMEMORY_DESCRIPTOR;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MDL_TYPE_PHYSICAL,
|
||||||
|
MDL_TYPE_VIRTUAL
|
||||||
|
} MEMORY_DESCRIPTOR_LIST_TYPE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
|
||||||
|
PLIST_ENTRY Head;
|
||||||
|
PLIST_ENTRY Current;
|
||||||
|
MEMORY_DESCRIPTOR_LIST_TYPE Type;
|
||||||
|
} MEMORY_DESCRIPTOR_LIST, *PMEMORY_DESCRIPTOR_LIST;
|
||||||
|
|
||||||
#define BOOT_FIRMWARE_DATA_VERSION 2
|
#define BOOT_FIRMWARE_DATA_VERSION 2
|
||||||
|
|
||||||
@@ -123,9 +193,125 @@ typedef struct {
|
|||||||
} BOOT_RETURN_DATA, *PBOOT_RETURN_DATA;
|
} BOOT_RETURN_DATA, *PBOOT_RETURN_DATA;
|
||||||
|
|
||||||
typedef struct {
|
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 Size;
|
||||||
|
ULONG Pad;
|
||||||
|
|
||||||
|
union {
|
||||||
|
BOOT_BLOCK_IDENTIFIER Block;
|
||||||
|
BOOT_PARTITION_IDENTIFIER Partition;
|
||||||
|
BOOT_PARTITION_IDENTIFIER_EX PartitionEx;
|
||||||
|
};
|
||||||
} BOOT_DEVICE, *PBOOT_DEVICE;
|
} BOOT_DEVICE, *PBOOT_DEVICE;
|
||||||
|
|
||||||
|
#define BCDE_DATA_FORMAT_MASK 0x0F000000
|
||||||
|
|
||||||
|
#define BCDE_DATA_FORMAT_DEVICE 1
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BCDE_DATA_TYPE_APPLICATION_DEVICE = 0x11000001,
|
||||||
|
BCDE_DATA_TYPE_APPLICATION_PATH = 0x22000002
|
||||||
|
} BCDE_DATA_TYPE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GUID OtherOptions;
|
||||||
|
BOOT_DEVICE Device;
|
||||||
|
} BCDE_DEVICE, *PBCDE_DEVICE;
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BmOpenDataStore (
|
||||||
|
IN OUT PHANDLE DataStore
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BmMain (
|
BmMain (
|
||||||
IN PBOOT_INPUT_PARAMETERS InputParameters
|
IN PBOOT_INPUT_PARAMETERS InputParameters
|
||||||
|
@@ -123,6 +123,16 @@ EFI_STATUS
|
|||||||
IN UINTN Pages
|
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
|
typedef
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
(EFIAPI *EFI_HANDLE_PROTOCOL) (
|
(EFIAPI *EFI_HANDLE_PROTOCOL) (
|
||||||
@@ -139,7 +149,7 @@ typedef struct _EFI_BOOT_SERVICES {
|
|||||||
|
|
||||||
EFI_ALLOCATE_PAGES AllocatePages;
|
EFI_ALLOCATE_PAGES AllocatePages;
|
||||||
EFI_FREE_PAGES FreePages;
|
EFI_FREE_PAGES FreePages;
|
||||||
EFI_HANDLE GetMemoryMap;
|
EFI_GET_MEMORY_MAP GetMemoryMap;
|
||||||
EFI_HANDLE AllocatePool;
|
EFI_HANDLE AllocatePool;
|
||||||
EFI_HANDLE FreePool;
|
EFI_HANDLE FreePool;
|
||||||
|
|
||||||
|
@@ -24,8 +24,40 @@ typedef struct _EFI_DEVICE_PATH_PROTOCOL {
|
|||||||
typedef struct _EFI_DEVICE_PATH_PROTOCOL _EFI_DEVICE_PATH;
|
typedef struct _EFI_DEVICE_PATH_PROTOCOL _EFI_DEVICE_PATH;
|
||||||
typedef 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_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
|
#define MEDIA_CDROM_DP 0x02
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -35,6 +67,13 @@ typedef struct {
|
|||||||
UINT64 PartitionSize;
|
UINT64 PartitionSize;
|
||||||
} CDROM_DEVICE_PATH;
|
} CDROM_DEVICE_PATH;
|
||||||
|
|
||||||
|
#define MEDIA_FILEPATH_DP 0x04
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EFI_DEVICE_PATH Header;
|
||||||
|
CHAR16 PathName[1];
|
||||||
|
} FILEPATH_DEVICE_PATH;
|
||||||
|
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
UINT8
|
UINT8
|
||||||
DevicePathType (
|
DevicePathType (
|
||||||
|
@@ -16,7 +16,6 @@ Abstract:
|
|||||||
#ifndef _EFILIB_H
|
#ifndef _EFILIB_H
|
||||||
#define _EFILIB_H
|
#define _EFILIB_H
|
||||||
|
|
||||||
#include <nt.h>
|
|
||||||
#include "bootmgr.h"
|
#include "bootmgr.h"
|
||||||
#include "efi.h"
|
#include "efi.h"
|
||||||
|
|
||||||
@@ -31,4 +30,9 @@ EfiGetEfiStatusCode (
|
|||||||
IN NTSTATUS Status
|
IN NTSTATUS Status
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
EfiGetNtStatusCode (
|
||||||
|
IN EFI_STATUS Status
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
103
BOOT/ENVIRON/INC/mm.h
Normal file
103
BOOT/ENVIRON/INC/mm.h
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmMdInitialize (
|
||||||
|
IN ULONG Unused,
|
||||||
|
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
MmPaInitialize (
|
||||||
|
IN PBOOT_MEMORY_INFO MemoryInfo,
|
||||||
|
IN ULONG MinimumAllocation
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
82
BOOT/ENVIRON/LIB/EFI/eficon.c
Normal file
82
BOOT/ENVIRON/LIB/EFI/eficon.c
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
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 "bootmgr.h"
|
||||||
|
|
||||||
|
extern SIMPLE_TEXT_OUTPUT_INTERFACE *EfiConOut;
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ConsolePrint (
|
||||||
|
IN PWSTR String
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Prints a string to the console.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
String.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
EfiConOut->OutputString(EfiConOut, String);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
64
BOOT/ENVIRON/LIB/EFI/efifw.c
Normal file
64
BOOT/ENVIRON/LIB/EFI/efifw.c
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2024, Quinn Stephens.
|
||||||
|
Provided under the BSD 3-Clause license.
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
efifw.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Provides EFI firmware utilities.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "bootlib.h"
|
||||||
|
#include "bootmgr.h"
|
||||||
|
|
||||||
|
EFI_SYSTEM_TABLE *EfiST;
|
||||||
|
EFI_BOOT_SERVICES *EfiBS;
|
||||||
|
EFI_RUNTIME_SERVICES *EfiRT;
|
||||||
|
SIMPLE_TEXT_OUTPUT_INTERFACE *EfiConOut;
|
||||||
|
SIMPLE_INPUT_INTERFACE *EfiConIn;
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BlpFwInitialize (
|
||||||
|
IN ULONG Stage,
|
||||||
|
IN PBOOT_FIRMWARE_DATA FirmwareData
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Internal routine to initialize the boot library.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Stage - 0 or 1.
|
||||||
|
|
||||||
|
FirmwareData - Pointer to BOOT_FIRMWARE_DATA.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
STATUS_SUCCESS if successful,
|
||||||
|
STATUS_INVALID_PARAMETER if FirmwareData is invalid.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
if (FirmwareData == NULL || FirmwareData->Version == 0) {
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Stage == 0) {
|
||||||
|
EfiST = FirmwareData->SystemTable;
|
||||||
|
EfiBS = EfiST->BootServices;
|
||||||
|
EfiRT = EfiST->RuntimeServices;
|
||||||
|
EfiConOut = EfiST->ConOut;
|
||||||
|
EfiConIn = EfiST->ConIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
@@ -16,6 +16,7 @@ Abstract:
|
|||||||
#include <ntrtl.h>
|
#include <ntrtl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#include "bootlib.h"
|
||||||
#include "bootmgr.h"
|
#include "bootmgr.h"
|
||||||
#include "efi.h"
|
#include "efi.h"
|
||||||
|
|
||||||
@@ -23,15 +24,429 @@ UCHAR EfiInitScratch[2048];
|
|||||||
const EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
|
const EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
|
||||||
const EFI_GUID EfiDevicePathProtocol = DEVICE_PATH_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_APPLICATION_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_APPLICATION_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device)) {
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(Option, sizeof(BOOT_APPLICATION_OPTION));
|
||||||
|
DeviceElement = (PBCDE_DEVICE)((PUCHAR)Option + sizeof(BOOT_APPLICATION_OPTION));
|
||||||
|
Status = EfiInitTranslateDevicePath(
|
||||||
|
EfiDevicePath,
|
||||||
|
&DeviceElement->Device,
|
||||||
|
BufferSize - (sizeof(BOOT_APPLICATION_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device))
|
||||||
|
);
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Option->Type = OptionType;
|
||||||
|
Option->DataOffset = sizeof(BOOT_APPLICATION_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_APPLICATION_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_APPLICATION_OPTION)) {
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(Option, sizeof(BOOT_APPLICATION_OPTION));
|
||||||
|
Option->Type = OptionType;
|
||||||
|
Option->DataOffset = sizeof(BOOT_APPLICATION_OPTION);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Loop through nodes and add one at a time.
|
||||||
|
//
|
||||||
|
Option->DataSize = 0;
|
||||||
|
BufferRemaining = BufferSize - sizeof(BOOT_APPLICATION_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
|
VOID
|
||||||
EfiInitpCreateApplicationEntry (
|
EfiInitpCreateApplicationEntry (
|
||||||
IN EFI_SYSTEM_TABLE *SystemTable,
|
IN EFI_SYSTEM_TABLE *SystemTable,
|
||||||
IN OUT PBOOT_APPLICATION_ENTRY Entry,
|
IN OUT PBOOT_INPUT_APPLICATION_ENTRY Entry,
|
||||||
IN ULONG BufferSize,
|
IN ULONG BufferSize,
|
||||||
IN EFI_DEVICE_PATH *DevicePath,
|
IN EFI_DEVICE_PATH *EfiDevicePath,
|
||||||
IN EFI_DEVICE_PATH *FilePath,
|
IN EFI_DEVICE_PATH *EfiFilePath,
|
||||||
IN PWCHAR LoadOptions,
|
IN PWCHAR LoadOptions,
|
||||||
IN ULONG LoadOptionsSize,
|
IN ULONG LoadOptionsSize,
|
||||||
|
IN ULONG Flags,
|
||||||
OUT PULONG BufferUsed,
|
OUT PULONG BufferUsed,
|
||||||
OUT PBOOT_DEVICE *BootDevice
|
OUT PBOOT_DEVICE *BootDevice
|
||||||
)
|
)
|
||||||
@@ -40,27 +455,29 @@ EfiInitpCreateApplicationEntry (
|
|||||||
|
|
||||||
Routine Description:
|
Routine Description:
|
||||||
|
|
||||||
Creates an application entry structure for the boot application.
|
Creates an application entry for the boot application.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
SystemTable - Pointer to the EFI system table.
|
SystemTable - Pointer to the EFI system table.
|
||||||
|
|
||||||
Entry - A buffer to put the entry in.
|
Entry - Pointer to a buffer that recieves the entry.
|
||||||
|
|
||||||
BufferSize - The amount of available space in the buffer.
|
BufferSize - The amount of available bytes in the buffer.
|
||||||
|
|
||||||
DevicePath - The device path for the application.
|
EfiDevicePath - The application's device path.
|
||||||
|
|
||||||
FilePath - The file path for the application.
|
EfiFilePath - The application's file path.
|
||||||
|
|
||||||
LoadOptions - Firmware load options string.
|
LoadOptions - Firmware load options string.
|
||||||
|
|
||||||
LoadOptionsSize - Length of the string pointed to by LoadOptions.
|
LoadOptionsSize - Size in bytes of the string pointed to by LoadOptions.
|
||||||
|
|
||||||
BufferUsed - Returns the amount of buffer space used by the routine.
|
Flags - Unused.
|
||||||
|
|
||||||
BootDevice - Returns a pointer to the device the application was loaded from.
|
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.
|
||||||
|
|
||||||
Return Value:
|
Return Value:
|
||||||
|
|
||||||
@@ -69,23 +486,33 @@ Return Value:
|
|||||||
--*/
|
--*/
|
||||||
|
|
||||||
{
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG BufferRemaining, OptionsSize, Size;
|
||||||
PWCHAR BcdOptionString;
|
PWCHAR BcdOptionString;
|
||||||
BOOLEAN BcdIdentifierSet;
|
BOOLEAN BcdIdentifierSet;
|
||||||
UNICODE_STRING UnicodeString;
|
UNICODE_STRING UnicodeString;
|
||||||
|
PBOOT_APPLICATION_OPTION Option, PrevOption;
|
||||||
|
PBCDE_DEVICE BootDeviceElement;
|
||||||
|
|
||||||
|
(VOID)SystemTable;
|
||||||
|
(VOID)Flags;
|
||||||
|
|
||||||
*BufferUsed = 0;
|
*BufferUsed = 0;
|
||||||
*BootDevice = NULL;
|
*BootDevice = NULL;
|
||||||
|
OptionsSize = 0;
|
||||||
BcdIdentifierSet = FALSE;
|
BcdIdentifierSet = FALSE;
|
||||||
|
|
||||||
//
|
BufferRemaining = BufferSize;
|
||||||
// Require enough space for the application entry.
|
if (BufferRemaining < sizeof(BOOT_INPUT_APPLICATION_ENTRY)) {
|
||||||
//
|
|
||||||
if (BufferSize < sizeof(BOOT_APPLICATION_ENTRY)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(Entry, sizeof(BOOT_INPUT_APPLICATION_ENTRY));
|
||||||
|
Entry->Signature = BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE;
|
||||||
|
BufferRemaining -= FIELD_OFFSET(BOOT_INPUT_APPLICATION_ENTRY, Options);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Terminate load options string.
|
// Terminate load options.
|
||||||
//
|
//
|
||||||
LoadOptionsSize /= sizeof(WCHAR);
|
LoadOptionsSize /= sizeof(WCHAR);
|
||||||
if (LoadOptionsSize != 0 && wcsnlen(LoadOptions, LoadOptionsSize) == LoadOptionsSize) {
|
if (LoadOptionsSize != 0 && wcsnlen(LoadOptions, LoadOptionsSize) == LoadOptionsSize) {
|
||||||
@@ -93,14 +520,7 @@ Return Value:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set up application entry structure.
|
// Parse BCD GUID option if present.
|
||||||
//
|
|
||||||
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) {
|
if (LoadOptions != NULL && (BcdOptionString = wcsstr(LoadOptions, L"BCDOBJECT=")) != NULL) {
|
||||||
RtlInitUnicodeString(&UnicodeString, (PWCHAR)((PUCHAR)BcdOptionString + sizeof(L"BCDOBJECT=") - sizeof(UNICODE_NULL)));
|
RtlInitUnicodeString(&UnicodeString, (PWCHAR)((PUCHAR)BcdOptionString + sizeof(L"BCDOBJECT=") - sizeof(UNICODE_NULL)));
|
||||||
@@ -110,15 +530,51 @@ Return Value:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!BcdIdentifierSet) {
|
if (!BcdIdentifierSet) {
|
||||||
Entry->Attributes |= BOOT_APPLICATION_ENTRY_BCD_IDENTIFIER_NOT_SET;
|
Entry->Attributes |= BOOT_INPUT_APPLICATION_ENTRY_NO_BCD_IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// TODO: This routine is not fully implemented.
|
// Convert the EFI device path into a boot device option.
|
||||||
//
|
//
|
||||||
(VOID)SystemTable;
|
Option = &Entry->Options;
|
||||||
(VOID)DevicePath;
|
Status = EfiInitpConvertEfiDevicePath(EfiDevicePath, BCDE_DATA_TYPE_APPLICATION_DEVICE, Option, BufferRemaining);
|
||||||
(VOID)FilePath;
|
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_APPLICATION_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_APPLICATION_OPTION)((PUCHAR)&Entry->Options + OptionsSize);
|
||||||
|
// Status = Unknown(LoadOptions, &Entry->Options, RemainingSize, &OptionsSize, &PrevOption, &Size);
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
*BufferUsed = BufferSize - BufferRemaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
PBOOT_INPUT_PARAMETERS
|
PBOOT_INPUT_PARAMETERS
|
||||||
@@ -135,13 +591,14 @@ Routine Description:
|
|||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
ImageHandle - Handle for the boot manager image.
|
ImageHandle - EFI handle for the boot application image.
|
||||||
|
|
||||||
SystemTable - Pointer to the EFI system table.
|
SystemTable - Pointer to the EFI system table.
|
||||||
|
|
||||||
Return Value:
|
Return Value:
|
||||||
|
|
||||||
Pointer to parameter structure on success or NULL on failure.
|
Pointer to parameter structure if successful.
|
||||||
|
NULL on failure.
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
@@ -154,7 +611,7 @@ Return Value:
|
|||||||
EFI_DEVICE_PATH *DevicePath;
|
EFI_DEVICE_PATH *DevicePath;
|
||||||
PBOOT_INPUT_PARAMETERS InputParameters;
|
PBOOT_INPUT_PARAMETERS InputParameters;
|
||||||
PBOOT_MEMORY_INFO MemoryInfo;
|
PBOOT_MEMORY_INFO MemoryInfo;
|
||||||
PBOOT_MEMORY_DESCRIPTOR MemoryDescriptor;
|
PMEMORY_DESCRIPTOR MemoryDescriptor;
|
||||||
PBOOT_DEVICE BootDevice;
|
PBOOT_DEVICE BootDevice;
|
||||||
PBOOT_FIRMWARE_DATA FirmwareData;
|
PBOOT_FIRMWARE_DATA FirmwareData;
|
||||||
PBOOT_RETURN_DATA ReturnData;
|
PBOOT_RETURN_DATA ReturnData;
|
||||||
@@ -166,9 +623,6 @@ Return Value:
|
|||||||
BadPageAddress = 0x102 << PAGE_SHIFT;
|
BadPageAddress = 0x102 << PAGE_SHIFT;
|
||||||
SystemTable->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, 1, &BadPageAddress);
|
SystemTable->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, 1, &BadPageAddress);
|
||||||
|
|
||||||
//
|
|
||||||
// Get boot manager image information.
|
|
||||||
//
|
|
||||||
Status = SystemTable->BootServices->HandleProtocol(
|
Status = SystemTable->BootServices->HandleProtocol(
|
||||||
ImageHandle,
|
ImageHandle,
|
||||||
(EFI_GUID*)&EfiLoadedImageProtocol,
|
(EFI_GUID*)&EfiLoadedImageProtocol,
|
||||||
@@ -178,9 +632,6 @@ Return Value:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Get boot manager image device path.
|
|
||||||
//
|
|
||||||
Status = SystemTable->BootServices->HandleProtocol(
|
Status = SystemTable->BootServices->HandleProtocol(
|
||||||
LoadedImage->DeviceHandle,
|
LoadedImage->DeviceHandle,
|
||||||
(EFI_GUID*)&EfiDevicePathProtocol,
|
(EFI_GUID*)&EfiDevicePathProtocol,
|
||||||
@@ -190,60 +641,46 @@ Return Value:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Create input parameters structure.
|
|
||||||
//
|
|
||||||
InputParameters = (PBOOT_INPUT_PARAMETERS)(&EfiInitScratch[ScratchUsed]);
|
InputParameters = (PBOOT_INPUT_PARAMETERS)(&EfiInitScratch[ScratchUsed]);
|
||||||
ScratchUsed += sizeof(BOOT_INPUT_PARAMETERS);
|
ScratchUsed += sizeof(BOOT_INPUT_PARAMETERS);
|
||||||
InputParameters->Signature = BOOT_INPUT_PARAMETERS_SIGNATURE;
|
InputParameters->Signature = BOOT_INPUT_PARAMETERS_SIGNATURE;
|
||||||
InputParameters->Version = BOOT_INPUT_PARAMETERS_VERSION;
|
InputParameters->Version = BOOT_INPUT_PARAMETERS_VERSION;
|
||||||
InputParameters->MachineType = BOOT_MACHINE_TYPE;
|
InputParameters->MachineType = BOOT_MACHINE_TYPE;
|
||||||
InputParameters->TranslationType = BOOT_TRANSLATION_TYPE;
|
InputParameters->TranslationType = BOOT_TRANSLATION_TYPE_NONE;
|
||||||
InputParameters->ImageBase = LoadedImage->ImageBase;
|
InputParameters->ImageBase = LoadedImage->ImageBase;
|
||||||
InputParameters->ImageSize = LoadedImage->ImageSize;
|
InputParameters->ImageSize = LoadedImage->ImageSize;
|
||||||
|
|
||||||
//
|
|
||||||
// Create memory info structure.
|
|
||||||
//
|
|
||||||
InputParameters->MemoryInfoOffset = ScratchUsed;
|
InputParameters->MemoryInfoOffset = ScratchUsed;
|
||||||
MemoryInfo = (PBOOT_MEMORY_INFO)(&EfiInitScratch[ScratchUsed]);
|
MemoryInfo = (PBOOT_MEMORY_INFO)(&EfiInitScratch[ScratchUsed]);
|
||||||
ScratchUsed += sizeof(BOOT_MEMORY_INFO);
|
ScratchUsed += sizeof(BOOT_MEMORY_INFO);
|
||||||
MemoryInfo->Version = BOOT_MEMORY_INFO_VERSION;
|
MemoryInfo->Version = BOOT_MEMORY_INFO_VERSION;
|
||||||
MemoryInfo->MdlOffset = sizeof(BOOT_MEMORY_INFO);
|
MemoryInfo->MdlOffset = sizeof(BOOT_MEMORY_INFO);
|
||||||
MemoryInfo->DescriptorCount = 1;
|
MemoryInfo->DescriptorCount = 1;
|
||||||
MemoryInfo->DescriptorSize = sizeof(BOOT_MEMORY_DESCRIPTOR);
|
MemoryInfo->DescriptorSize = sizeof(MEMORY_DESCRIPTOR);
|
||||||
MemoryInfo->BasePageOffset = FIELD_OFFSET(BOOT_MEMORY_DESCRIPTOR, BasePage);
|
MemoryInfo->FirstPageOffset = FIELD_OFFSET(MEMORY_DESCRIPTOR, FirstPage);
|
||||||
|
|
||||||
//
|
MemoryDescriptor = (PMEMORY_DESCRIPTOR)(&EfiInitScratch[ScratchUsed]);
|
||||||
// Create a memory descriptor for the boot manager image.
|
ScratchUsed += sizeof(MEMORY_DESCRIPTOR);
|
||||||
//
|
MemoryDescriptor->FirstPage = (UINTN)InputParameters->ImageBase >> PAGE_SHIFT;
|
||||||
MemoryDescriptor = (PBOOT_MEMORY_DESCRIPTOR)(&EfiInitScratch[ScratchUsed]);
|
MemoryDescriptor->PageCount = ALIGN_UP(InputParameters->ImageSize, PAGE_SIZE) >> PAGE_SHIFT;
|
||||||
ScratchUsed += sizeof(BOOT_MEMORY_DESCRIPTOR);
|
MemoryDescriptor->Attributes = MEMORY_ATTRIBUTE_WB;
|
||||||
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;
|
MemoryDescriptor->Type = MEMORY_TYPE_BOOT_APPLICATION;
|
||||||
|
|
||||||
//
|
|
||||||
// Create an application entry for the boot application.
|
|
||||||
//
|
|
||||||
InputParameters->ApplicationEntryOffset = ScratchUsed;
|
InputParameters->ApplicationEntryOffset = ScratchUsed;
|
||||||
EfiInitpCreateApplicationEntry(
|
EfiInitpCreateApplicationEntry(
|
||||||
SystemTable,
|
SystemTable,
|
||||||
(PBOOT_APPLICATION_ENTRY)(&EfiInitScratch[ScratchUsed]),
|
(PBOOT_INPUT_APPLICATION_ENTRY)(&EfiInitScratch[ScratchUsed]),
|
||||||
sizeof(EfiInitScratch) - ScratchUsed,
|
sizeof(EfiInitScratch) - ScratchUsed,
|
||||||
DevicePath,
|
DevicePath,
|
||||||
LoadedImage->FilePath,
|
LoadedImage->FilePath,
|
||||||
LoadedImage->LoadOptions,
|
LoadedImage->LoadOptions,
|
||||||
LoadedImage->LoadOptionsSize,
|
LoadedImage->LoadOptionsSize,
|
||||||
|
0,
|
||||||
&ApplicationEntrySize,
|
&ApplicationEntrySize,
|
||||||
&BootDevice
|
&BootDevice
|
||||||
);
|
);
|
||||||
ScratchUsed += ApplicationEntrySize;
|
ScratchUsed += ApplicationEntrySize;
|
||||||
|
|
||||||
//
|
|
||||||
// Copy application device to scratch area.
|
|
||||||
//
|
|
||||||
InputParameters->BootDeviceOffset = ScratchUsed;
|
InputParameters->BootDeviceOffset = ScratchUsed;
|
||||||
if (BootDevice != NULL) {
|
if (BootDevice != NULL) {
|
||||||
RtlCopyMemory(&EfiInitScratch[ScratchUsed], BootDevice, BootDevice->Size);
|
RtlCopyMemory(&EfiInitScratch[ScratchUsed], BootDevice, BootDevice->Size);
|
||||||
@@ -253,9 +690,6 @@ Return Value:
|
|||||||
ScratchUsed += sizeof(BOOT_DEVICE);
|
ScratchUsed += sizeof(BOOT_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Create firmware data structure.
|
|
||||||
//
|
|
||||||
InputParameters->FirmwareDataOffset = ScratchUsed;
|
InputParameters->FirmwareDataOffset = ScratchUsed;
|
||||||
FirmwareData = (PBOOT_FIRMWARE_DATA)(&EfiInitScratch[ScratchUsed]);
|
FirmwareData = (PBOOT_FIRMWARE_DATA)(&EfiInitScratch[ScratchUsed]);
|
||||||
ScratchUsed += sizeof(BOOT_FIRMWARE_DATA);
|
ScratchUsed += sizeof(BOOT_FIRMWARE_DATA);
|
||||||
@@ -264,17 +698,11 @@ Return Value:
|
|||||||
FirmwareData->ImageHandle = ImageHandle;
|
FirmwareData->ImageHandle = ImageHandle;
|
||||||
FirmwareData->SystemTable = SystemTable;
|
FirmwareData->SystemTable = SystemTable;
|
||||||
|
|
||||||
//
|
|
||||||
// Create return data structure.
|
|
||||||
//
|
|
||||||
InputParameters->ReturnDataOffset = ScratchUsed;
|
InputParameters->ReturnDataOffset = ScratchUsed;
|
||||||
ReturnData = (PBOOT_RETURN_DATA)(&EfiInitScratch[ScratchUsed]);
|
ReturnData = (PBOOT_RETURN_DATA)(&EfiInitScratch[ScratchUsed]);
|
||||||
ScratchUsed += sizeof(BOOT_RETURN_DATA);
|
ScratchUsed += sizeof(BOOT_RETURN_DATA);
|
||||||
ReturnData->Version = BOOT_RETURN_DATA_VERSION;
|
ReturnData->Version = BOOT_RETURN_DATA_VERSION;
|
||||||
|
|
||||||
//
|
|
||||||
// Set and validate total size.
|
|
||||||
//
|
|
||||||
InputParameters->Size = ScratchUsed;
|
InputParameters->Size = ScratchUsed;
|
||||||
if (InputParameters->Size > sizeof(EfiInitScratch)) {
|
if (InputParameters->Size > sizeof(EfiInitScratch)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@@ -29,7 +29,7 @@ Routine Description:
|
|||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
Status - The NT status code to be converted.
|
Status - The NT status code.
|
||||||
|
|
||||||
Return Value:
|
Return Value:
|
||||||
|
|
||||||
@@ -56,6 +56,7 @@ Return Value:
|
|||||||
case STATUS_MEDIA_WRITE_PROTECTED:
|
case STATUS_MEDIA_WRITE_PROTECTED:
|
||||||
return EFI_WRITE_PROTECTED;
|
return EFI_WRITE_PROTECTED;
|
||||||
case STATUS_INSUFFICIENT_RESOURCES:
|
case STATUS_INSUFFICIENT_RESOURCES:
|
||||||
|
case STATUS_INSUFFICIENT_NVRAM_RESOURCES:
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
case STATUS_DISK_CORRUPT_ERROR:
|
case STATUS_DISK_CORRUPT_ERROR:
|
||||||
return EFI_VOLUME_CORRUPTED;
|
return EFI_VOLUME_CORRUPTED;
|
||||||
@@ -83,3 +84,75 @@ Return Value:
|
|||||||
return EFI_NO_MAPPING;
|
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;
|
||||||
|
}
|
||||||
|
}
|
635
BOOT/ENVIRON/LIB/EFI/efimm.c
Normal file
635
BOOT/ENVIRON/LIB/EFI/efimm.c
Normal file
@@ -0,0 +1,635 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2024, Quinn Stephens.
|
||||||
|
Provided under the BSD 3-Clause license.
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
efimm.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Provides EFI memory manager routines.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "bootmgr.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)
|
||||||
|
|
||||||
|
extern EFI_BOOT_SERVICES *EfiBS;
|
||||||
|
extern PBOOT_DEVICE BlpBootDevice;
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
EfiGetMemoryMap (
|
||||||
|
IN OUT UINTN *MemoryMapSize,
|
||||||
|
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
|
||||||
|
IN OUT UINTN *MapKey,
|
||||||
|
IN OUT UINTN *DescriptorSize,
|
||||||
|
IN OUT UINT32 *DescriptorVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Wrapper for EFI_BOOT_SERVICES.GetMemoryMap(). Gets the firmware memory map
|
||||||
|
and places it into a buffer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
MemoryMapSize - pointer to the size of the buffer.
|
||||||
|
|
||||||
|
MemoryMap - pointer to the buffer to store the memory map in.
|
||||||
|
|
||||||
|
MapKey - ponter to the memory map key.
|
||||||
|
|
||||||
|
DescriptorSize - pointer to the size of each memory map descriptor.
|
||||||
|
|
||||||
|
DescriptorVersion - pointer to the version of memory map descriptors.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
STATUS_SUCCESS if successful,
|
||||||
|
Other NTSTATUS value if an error occurs.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
return EfiGetNtStatusCode(
|
||||||
|
EfiBS->GetMemoryMap(
|
||||||
|
MemoryMapSize,
|
||||||
|
MemoryMap,
|
||||||
|
MapKey,
|
||||||
|
DescriptorSize,
|
||||||
|
DescriptorVersion
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
EfiAllocatePages (
|
||||||
|
IN EFI_ALLOCATE_TYPE Type,
|
||||||
|
IN EFI_MEMORY_TYPE MemoryType,
|
||||||
|
IN UINTN Pages,
|
||||||
|
IN OUT EFI_PHYSICAL_ADDRESS *Memory
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Wrapper for EFI_BOOT_SERVICES.AllocatePages(). Allocates contiguous pages
|
||||||
|
of physical memory.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Type - the type of allocation.
|
||||||
|
|
||||||
|
MemoryType - the type of memory to allocate.
|
||||||
|
|
||||||
|
Pages - the number of pages to allocate.
|
||||||
|
|
||||||
|
Memory - pointer to a physical address of the allocation.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
STATUS_SUCCESS if successful,
|
||||||
|
Other NTSTATUS value if an error occurs.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
return EfiGetNtStatusCode(
|
||||||
|
EfiBS->AllocatePages(
|
||||||
|
Type,
|
||||||
|
MemoryType,
|
||||||
|
Pages,
|
||||||
|
Memory
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
EfiFreePages (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS Memory,
|
||||||
|
IN UINTN Pages
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Wrapper for EFI_BOOT_SERVICES.FreePages(). Frees contiguous pages
|
||||||
|
of physical memory.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Memory - physical address of the pages to be freed.
|
||||||
|
|
||||||
|
Pages - the number of pages to free.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
STATUS_SUCCESS if successful,
|
||||||
|
Other NTSTATUS value if an error occurs.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
return EfiGetNtStatusCode(
|
||||||
|
EfiBS->FreePages(
|
||||||
|
Memory,
|
||||||
|
Pages
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMORY_TYPE
|
||||||
|
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)) {
|
||||||
|
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)) {
|
||||||
|
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)) {
|
||||||
|
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)) {
|
||||||
|
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)) {
|
||||||
|
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 = MmMdRemoveRegionFromMdlEx(Mdl, NtStartPage, NtPageCount, MDL_OPERATION_FLAGS_PHYSICAL, 0);
|
||||||
|
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;
|
||||||
|
}
|
109
BOOT/ENVIRON/LIB/MM/mm.c
Normal file
109
BOOT/ENVIRON/LIB/MM/mm.c
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
DebugPrint(L"Initializing memory manager...\r\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check TranslationType.
|
||||||
|
//
|
||||||
|
if (
|
||||||
|
TranslationType > BOOT_TRANSLATION_TYPE_MAX ||
|
||||||
|
LibraryParameters->TranslationType > BOOT_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
660
BOOT/ENVIRON/LIB/MM/mmmd.c
Normal file
660
BOOT/ENVIRON/LIB/MM/mmmd.c
Normal file
@@ -0,0 +1,660 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
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 "bootmgr.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;
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
MmMdpHasPrecedence (
|
||||||
|
IN MEMORY_TYPE A,
|
||||||
|
IN MEMORY_TYPE B
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Compares two memory types to determine which has precedence.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
A - memory type A.
|
||||||
|
|
||||||
|
B - memory type B.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
TRUE if A has precedence over B, or if neither has precedence.
|
||||||
|
FALSE if B has precedence over A.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
ULONG ClassA, ClassB;
|
||||||
|
|
||||||
|
ClassA = A >> 28;
|
||||||
|
ClassB = B >> 28;
|
||||||
|
|
||||||
|
if (B == MEMORY_TYPE_FREE) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (A == MEMORY_TYPE_FREE) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClassA > 0x0F) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClassB > 0x0F) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClassA != 0x0F) {
|
||||||
|
return (ClassB != 0x0F && (ClassA == 0x0D || ClassB != 0x0D)) ? TRUE:FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClassB != 0x0F) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: Implement the rest of this routine.
|
||||||
|
//
|
||||||
|
ConsolePrint(L"MmMdpHasPrecedence() is incomplete\r\n");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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) {
|
||||||
|
MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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) {
|
||||||
|
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.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// TODO: Implement this routine.
|
||||||
|
//
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
MmMdRemoveRegionFromMdlEx (
|
||||||
|
IN PMEMORY_DESCRIPTOR_LIST Mdl,
|
||||||
|
IN ULONGLONG FirstPage,
|
||||||
|
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.
|
||||||
|
|
||||||
|
FirstPage - The first page in the region.
|
||||||
|
|
||||||
|
PageCount - The number of pages in the region.
|
||||||
|
|
||||||
|
Flags - MDL_OPERATION_FLAGS_*.
|
||||||
|
|
||||||
|
Unused - Unused.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
ULONGLONG RemoveEnd, DescriptorEnd;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PMEMORY_DESCRIPTOR Descriptor;
|
||||||
|
MEMORY_DESCRIPTOR RemovedDescriptor;
|
||||||
|
|
||||||
|
(VOID)Flags;
|
||||||
|
(VOID)Unused;
|
||||||
|
|
||||||
|
RemoveEnd = FirstPage + PageCount;
|
||||||
|
Entry = Mdl->Head->Flink;
|
||||||
|
while (Entry != Mdl->Head) {
|
||||||
|
Descriptor = (PMEMORY_DESCRIPTOR)Entry;
|
||||||
|
DescriptorEnd = Descriptor->FirstPage + Descriptor->PageCount;
|
||||||
|
|
||||||
|
RtlCopyMemory(&RemovedDescriptor, Descriptor, sizeof(MEMORY_DESCRIPTOR));
|
||||||
|
|
||||||
|
// if (FirstPage <= Descriptor->FirstPage && Descriptor->FirstPage < RemoveEnd) {
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: Implement the rest of this routine.
|
||||||
|
//
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free the descriptor from the heap.
|
||||||
|
// TODO: Use BlMmFreeHeap().
|
||||||
|
//
|
||||||
|
ConsolePrint(L"MmMdFreeDescriptor(): need BlMmFreeHeap() to free descriptor\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;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmMdInitialize (
|
||||||
|
IN ULONG Unused,
|
||||||
|
IN PBOOT_LIBRARY_PARAMETERS LibraryParameters
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Initializes the memory descriptor manager.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Unused - Ignored.
|
||||||
|
|
||||||
|
LibraryParameters - pointer to the library parameters structure.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
(VOID)Unused;
|
||||||
|
(VOID)LibraryParameters;
|
||||||
|
|
||||||
|
DebugPrint(L"Initializing memory descriptor manager...\r\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize global memory descriptor list.
|
||||||
|
//
|
||||||
|
MmGlobalMemoryDescriptors = &MmStaticMemoryDescriptors[0];
|
||||||
|
MmGlobalMemoryDescriptorCount = MAX_STATIC_DESCRIPTOR_COUNT;
|
||||||
|
MmGlobalMemoryDescriptorsUsed = 0;
|
||||||
|
RtlZeroMemory(MmGlobalMemoryDescriptors, MAX_STATIC_DESCRIPTOR_COUNT * sizeof(MEMORY_DESCRIPTOR));
|
||||||
|
DebugPrintf(L"Global memory descriptor count: %x\r\n", MmGlobalMemoryDescriptorCount);
|
||||||
|
}
|
156
BOOT/ENVIRON/LIB/MM/mmpa.c
Normal file
156
BOOT/ENVIRON/LIB/MM/mmpa.c
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
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
|
||||||
|
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;
|
||||||
|
|
||||||
|
(VOID)MemoryInfo;
|
||||||
|
|
||||||
|
DebugPrint(L"Initializing page allocator...\r\n");
|
||||||
|
|
||||||
|
PapMinimumAllocationCount = MinimumAllocation;
|
||||||
|
PapMinimumPhysicalPage = 1;
|
||||||
|
PapMaximumPhysicalPage = MAXULONGLONG >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
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 = MmMdRemoveRegionFromMdlEx(&MmMdlUnmappedUnallocated, Descriptor->FirstPage, Descriptor->PageCount, MDL_OPERATION_FLAGS_PHYSICAL, NULL);
|
||||||
|
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, 0x00);
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Descriptor = (PMEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryInfo->DescriptorSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = BlpMmInitializeConstraints();
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
@@ -13,11 +13,9 @@ Abstract:
|
|||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
#include <ntrtl.h>
|
||||||
#include "bootlib.h"
|
#include "bootlib.h"
|
||||||
|
|
||||||
//
|
|
||||||
// Total size of required structures.
|
|
||||||
//
|
|
||||||
#define MIN_INPUT_PARAMETERS_SIZE ( \
|
#define MIN_INPUT_PARAMETERS_SIZE ( \
|
||||||
sizeof(BOOT_INPUT_PARAMETERS) + \
|
sizeof(BOOT_INPUT_PARAMETERS) + \
|
||||||
sizeof(BOOT_MEMORY_INFO) + \
|
sizeof(BOOT_MEMORY_INFO) + \
|
||||||
@@ -25,6 +23,10 @@ Abstract:
|
|||||||
sizeof(BOOT_RETURN_DATA) \
|
sizeof(BOOT_RETURN_DATA) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
PBOOT_INPUT_PARAMETERS BlpApplicationParameters;
|
||||||
|
BOOT_APPLICATION_ENTRY BlpApplicationEntry;
|
||||||
|
PBOOT_DEVICE BlpBootDevice;
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
InitializeLibrary (
|
InitializeLibrary (
|
||||||
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
||||||
@@ -35,13 +37,13 @@ InitializeLibrary (
|
|||||||
|
|
||||||
Routine Description:
|
Routine Description:
|
||||||
|
|
||||||
Internal routine to initialize the boot library.
|
Initializes the boot library.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
InputParameters - pointer to the input parameters structure.
|
InputParameters - Pointer to the application's input parameters.
|
||||||
|
|
||||||
LibraryParameters - pointer to the library parameters structure.
|
LibraryParameters - Pointer to the library parameters.
|
||||||
|
|
||||||
Return Value:
|
Return Value:
|
||||||
|
|
||||||
@@ -50,17 +52,116 @@ Return Value:
|
|||||||
--*/
|
--*/
|
||||||
|
|
||||||
{
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PBOOT_MEMORY_INFO MemoryInfo;
|
||||||
|
PBOOT_INPUT_APPLICATION_ENTRY ApplicationEntry;
|
||||||
|
PBOOT_FIRMWARE_DATA FirmwareData;
|
||||||
|
PBOOT_BLOCK_IDENTIFIER BlockDevice;
|
||||||
|
PBOOT_APPLICATION_OPTION Option;
|
||||||
|
|
||||||
(VOID)LibraryParameters;
|
(VOID)LibraryParameters;
|
||||||
|
|
||||||
//
|
|
||||||
// Verify input parameters structure.
|
|
||||||
//
|
|
||||||
if (InputParameters == NULL ||
|
if (InputParameters == NULL ||
|
||||||
InputParameters->Signature != BOOT_INPUT_PARAMETERS_SIGNATURE ||
|
InputParameters->Signature != BOOT_INPUT_PARAMETERS_SIGNATURE ||
|
||||||
InputParameters->Size < MIN_INPUT_PARAMETERS_SIZE) {
|
InputParameters->Size < MIN_INPUT_PARAMETERS_SIZE) {
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryInfo = (PBOOT_MEMORY_INFO)((PUCHAR)InputParameters + InputParameters->MemoryInfoOffset);
|
||||||
|
ApplicationEntry = (PBOOT_INPUT_APPLICATION_ENTRY)((PUCHAR)InputParameters + InputParameters->ApplicationEntryOffset);
|
||||||
|
BlpBootDevice = (PBOOT_DEVICE)((PUCHAR)InputParameters + InputParameters->BootDeviceOffset);
|
||||||
|
FirmwareData = (PBOOT_FIRMWARE_DATA)((PUCHAR)InputParameters + InputParameters->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)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsolePrint(L"> Alcyone EFI Boot Manager\r\n");
|
||||||
|
ConsolePrintf(L"Image base: %x %x\r\nImage size: %x\r\n", HIDWORD((ULONG_PTR)InputParameters->ImageBase), LODWORD((ULONG_PTR)InputParameters->ImageBase), InputParameters->ImageSize);
|
||||||
|
|
||||||
|
DebugPrint(L"Initializing boot library...\r\n");
|
||||||
|
|
||||||
|
if (ApplicationEntry->Signature != BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE) {
|
||||||
|
DebugPrint(L"InitializeLibrary(): ApplicationEntry Signature is invalid\r\n");
|
||||||
|
return STATUS_INVALID_PARAMETER_9;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save input parameters and application entry.
|
||||||
|
//
|
||||||
|
BlpApplicationParameters = InputParameters;
|
||||||
|
BlpApplicationEntry.Attributes = ApplicationEntry->Attributes;
|
||||||
|
RtlCopyMemory(&BlpApplicationEntry.BcdIdentifier, &ApplicationEntry->BcdIdentifier, sizeof(GUID));
|
||||||
|
BlpApplicationEntry.Options = &ApplicationEntry->Options;
|
||||||
|
|
||||||
|
Status = BlpMmInitialize(MemoryInfo, InputParameters->TranslationType, LibraryParameters);
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Print debug information.
|
||||||
|
// TODO: Remove this once the project is more stable?
|
||||||
|
//
|
||||||
|
#ifdef _DEBUG
|
||||||
|
DebugPrint(L"Boot device type: ");
|
||||||
|
switch (BlpBootDevice->Type) {
|
||||||
|
case BOOT_DEVICE_TYPE_PARTITION:
|
||||||
|
DebugPrint(L"partition\r\n");
|
||||||
|
BlockDevice = &BlpBootDevice->Partition.Parent;
|
||||||
|
break;
|
||||||
|
case BOOT_DEVICE_TYPE_PARTITION_EX:
|
||||||
|
DebugPrint(L"partition\r\n");
|
||||||
|
BlockDevice = &BlpBootDevice->PartitionEx.Parent;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DebugPrint(L"generic block device\r\n");
|
||||||
|
BlockDevice = &BlpBootDevice->Block;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugPrint(L"Boot device parent type: ");
|
||||||
|
switch (BlockDevice->Type) {
|
||||||
|
case BOOT_BLOCK_DEVICE_TYPE_HARDDRIVE:
|
||||||
|
DebugPrint(L"hard drive\r\n");
|
||||||
|
break;
|
||||||
|
case BOOT_BLOCK_DEVICE_TYPE_CDROM:
|
||||||
|
DebugPrint(L"CD-ROM\r\n");
|
||||||
|
break;
|
||||||
|
case BOOT_BLOCK_DEVICE_TYPE_RAMDISK:
|
||||||
|
DebugPrint(L"RAM disk\r\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DebugPrint(L"generic block device\r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Option = &ApplicationEntry->Options;
|
||||||
|
for (ULONG Index = 0; !Option->IsInvalid; Index++) {
|
||||||
|
DebugPrintf(L"Boot entry option %x: ", Index);
|
||||||
|
|
||||||
|
if (Option->Type == BCDE_DATA_TYPE_APPLICATION_PATH) {
|
||||||
|
DebugPrint(L"application path \"");
|
||||||
|
DebugPrint((PWSTR)((PUCHAR)Option + Option->DataOffset));
|
||||||
|
DebugPrint(L"\"\r\n");
|
||||||
|
} else {
|
||||||
|
DebugPrintf(L"type %x, data size %x\r\n", Option->Type, Option->DataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Option->NextOptionOffset == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)Option + Option->NextOptionOffset);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,13 +175,13 @@ BlInitializeLibrary (
|
|||||||
|
|
||||||
Routine Description:
|
Routine Description:
|
||||||
|
|
||||||
Initializes the boot library.
|
Initializes the boot library. Wrapper for InitializeLibrary().
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
InputParameters - pointer to the input parameters structure.
|
InputParameters - Pointer to the application's input parameters.
|
||||||
|
|
||||||
LibraryParameters - pointer to the library parameters structure.
|
LibraryParameters - Pointer to the library parameters.
|
||||||
|
|
||||||
Return Value:
|
Return Value:
|
||||||
|
|
||||||
@@ -109,8 +210,7 @@ Arguments:
|
|||||||
|
|
||||||
Return Value:
|
Return Value:
|
||||||
|
|
||||||
STATUS_SUCCESS if successful.
|
STATUS_SUCCESS.
|
||||||
Error status if an error is encountered.
|
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
89
BOOT/ENVIRON/LIB/bootopt.c
Normal file
89
BOOT/ENVIRON/LIB/bootopt.c
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
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_APPLICATION_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_APPLICATION_OPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Option->OtherOptionsOffset != 0) {
|
||||||
|
TotalSize += BlGetBootOptionListSize((PBOOT_APPLICATION_OPTION)((PUCHAR)Option + Option->OtherOptionsOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
return TotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
BlGetBootOptionListSize (
|
||||||
|
IN PBOOT_APPLICATION_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_APPLICATION_OPTION Option;
|
||||||
|
|
||||||
|
TotalSize = 0;
|
||||||
|
NextOffset = 0;
|
||||||
|
do {
|
||||||
|
Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)Options + NextOffset);
|
||||||
|
NextOffset = Option->NextOptionOffset;
|
||||||
|
TotalSize += BlGetBootOptionSize(Option);
|
||||||
|
} while (NextOffset != 0);
|
||||||
|
|
||||||
|
return TotalSize;
|
||||||
|
}
|
18
BOOT/ENVIRON/README.md
Normal file
18
BOOT/ENVIRON/README.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Boot Environment Source Files
|
||||||
|
|
||||||
|
> XX = anything
|
||||||
|
|
||||||
|
| File | Public Routines |
|
||||||
|
|-|-|
|
||||||
|
| APP/BOOTMGR/EFI/efientry.c | EfiMain() |
|
||||||
|
| APP/BOOTMGR/bootmgr.c | BmMain() |
|
||||||
|
| APP/BOOTMGR/bcd.c | BmXXDataStore() |
|
||||||
|
| LIB/EFI/efifw.c | BlpFwXX() |
|
||||||
|
| LIB/EFI/efimm.c | MmFwXX() |
|
||||||
|
| LIB/EFI/efiinit.c | EfiInitXX() |
|
||||||
|
| LIB/EFI/eficon.c | ConsoleXX() |
|
||||||
|
| LIB/EFI/efilib.c | EfiGetEfiStatusCode() |
|
||||||
|
| LIB/MM/mm.c | BlpMmXX() |
|
||||||
|
| LIB/MM/mmpa.c | MmPaXX() |
|
||||||
|
| LIB/bootlib.c | BlXXLibrary() |
|
||||||
|
| LIB/bootopt.c | BlXXBootOptionXX() |
|
210
NTOSKRNL/CC/ccexternalcache.cpp
Normal file
210
NTOSKRNL/CC/ccexternalcache.cpp
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
@@ -15,57 +15,6 @@ extern "C"
|
|||||||
|
|
||||||
/*Internal Function*/
|
/*Internal Function*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
VOID
|
||||||
VECTORCALL
|
VECTORCALL
|
||||||
CcPostWorkQueue(IN PWORK_QUEUE_ENTRY WorkItem,
|
CcPostWorkQueue(IN PWORK_QUEUE_ENTRY WorkItem,
|
||||||
@@ -951,10 +900,10 @@ NTAPI CcLazyWriteScan()
|
|||||||
|
|
||||||
CcPostWorkQueue(workItem, &CcRegularWorkQueue);
|
CcPostWorkQueue(workItem, &CcRegularWorkQueue);
|
||||||
}
|
}
|
||||||
CcComputeNextScanTime(&OldestLWSTimeStamp, &NextScanDelay);
|
// CcComputeNextScanTime(&OldestLWSTimeStamp, &NextScanDelay); Enable When Threadpool is finished
|
||||||
|
|
||||||
if (!IsListEmpty(&PostWorkList) || !IsListEmpty(&CcDeferredWrites) || MmRegistryStatus.ProductStatus ||
|
// if (!IsListEmpty(&PostWorkList) || !IsListEmpty(&CcDeferredWrites) || MmRegistryStatus.ProductStatus ||NextScanDelay.QuadPart != 0x7FFFFFFFFFFFFFFF))
|
||||||
NextScanDelay.QuadPart != 0x7FFFFFFFFFFFFFFF))
|
if (!IsListEmpty(&PostWorkList) || !IsListEmpty(&CcDeferredWrites) || MmRegistryStatus.ProductStatus))
|
||||||
{
|
{
|
||||||
/* Schedule a lazy write scan */
|
/* Schedule a lazy write scan */
|
||||||
CcRescheduleLazyWriteScan(&NextScanDelay);
|
CcRescheduleLazyWriteScan(&NextScanDelay);
|
||||||
@@ -1117,7 +1066,7 @@ CcWorkerThread(PVOID Parameter)
|
|||||||
{
|
{
|
||||||
CcQueueThrottle = FALSE;
|
CcQueueThrottle = FALSE;
|
||||||
DropThrottle = FALSE;
|
DropThrottle = FALSE;
|
||||||
CcReEngageWorkerThreads(CcThreadsActiveBeforeThrottle, CcExtraThreadsActiveBeforeThrottle);
|
// CcReEngageWorkerThreads(CcThreadsActiveBeforeThrottle, CcExtraThreadsActiveBeforeThrottle); Enable When Threadpool is ready
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IoStatus.Information == 0x8A5E)
|
if (IoStatus.Information == 0x8A5E)
|
||||||
|
@@ -20,6 +20,12 @@ constexpr ULONG MUTEX_READY_TO_BE_AQUIRED = 0;
|
|||||||
|
|
||||||
/*Internal Function*/
|
/*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
|
typedef struct _FAST_MUTEX
|
||||||
{
|
{
|
||||||
LONG Count; //0x0
|
LONG Count; //0x0
|
||||||
@@ -29,6 +35,8 @@ typedef struct _FAST_MUTEX
|
|||||||
ULONG OldIrql; //0x1c
|
ULONG OldIrql; //0x1c
|
||||||
} FAST_MUTEX, *PFAST_MUTEX; //0x20 bytes (sizeof)
|
} FAST_MUTEX, *PFAST_MUTEX; //0x20 bytes (sizeof)
|
||||||
|
|
||||||
|
typedef PFAST_MUTEX PKGUARDED_MUTEX;
|
||||||
|
|
||||||
/*Internal Functio*/
|
/*Internal Functio*/
|
||||||
VOID
|
VOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
@@ -36,9 +44,9 @@ KiAcquireFastMutex(
|
|||||||
_Inout_ PFAST_MUTEX Mutex
|
_Inout_ PFAST_MUTEX Mutex
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
LONG AcquireMarker;
|
LONG AcquireMarker = {0};
|
||||||
LONG AcquireBit;
|
LONG AcquireBit = {0};
|
||||||
LONG OldCount;
|
LONG OldCount = {0};
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
@@ -49,7 +57,6 @@ KiAcquireFastMutex(
|
|||||||
AcquireMarker = 4;
|
AcquireMarker = 4;
|
||||||
AcquireBit = 1;
|
AcquireBit = 1;
|
||||||
|
|
||||||
AcquireLoop:
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
/* Read current count */
|
/* Read current count */
|
||||||
@@ -66,7 +73,7 @@ AcquireLoop:
|
|||||||
|
|
||||||
AcquireMarker = 2;
|
AcquireMarker = 2;
|
||||||
AcquireBit = 3;
|
AcquireBit = 3;
|
||||||
goto AcquireLoop;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -81,6 +88,43 @@ AcquireLoop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 */
|
/* Exported Function */
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
@@ -89,7 +133,6 @@ KeInitializeFastMutex(
|
|||||||
_Out_ PFAST_MUTEX Mutex
|
_Out_ PFAST_MUTEX Mutex
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
/* Initialize the mutex structure */
|
/* Initialize the mutex structure */
|
||||||
RtlZeroMemory(Mutex, sizeof(FAST_MUTEX));
|
RtlZeroMemory(Mutex, sizeof(FAST_MUTEX));
|
||||||
@@ -127,7 +170,240 @@ KeTryToAcquireFastMutex(
|
|||||||
return Result;
|
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,7 +34,14 @@ Alcyone is written in a subset of C++11 with selected features from modern stand
|
|||||||
- XDDM: Components related to Display Driver Model
|
- XDDM: Components related to Display Driver Model
|
||||||
|
|
||||||
### SDK Source Directory Structure:
|
### SDK Source Directory Structure:
|
||||||
- CRT: C RunTime
|
- 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
|
||||||
|
|
||||||
### Kernel Source Directory Structure:
|
### Kernel Source Directory Structure:
|
||||||
- ALPC: Asynchronous Local Procedure Call
|
- ALPC: Asynchronous Local Procedure Call
|
||||||
|
92
SDK/CRT/STDIO/wprintf.c
Normal file
92
SDK/CRT/STDIO/wprintf.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2024, Quinn Stephens.
|
||||||
|
Provided under the BSD 3-Clause license.
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
printf.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;
|
||||||
|
}
|
@@ -22,6 +22,7 @@ Abstract:
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
size_t wcslen(const wchar_t *str);
|
size_t wcslen(const wchar_t *str);
|
||||||
@@ -35,6 +36,8 @@ 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 *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count);
|
||||||
wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t count);
|
wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t count);
|
||||||
|
|
||||||
|
int vswprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, va_list args);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -97,29 +97,6 @@ typedef unsigned long ULONG;
|
|||||||
#define MAXUSHORT 0xffff
|
#define MAXUSHORT 0xffff
|
||||||
#define MAXULONG 0xffffffff
|
#define MAXULONG 0xffffffff
|
||||||
|
|
||||||
//
|
|
||||||
// Basic pointer types.
|
|
||||||
//
|
|
||||||
typedef VOID *PVOID;
|
|
||||||
typedef CHAR *PCHAR;
|
|
||||||
typedef SHORT *PSHORT;
|
|
||||||
typedef UCHAR *PUCHAR;
|
|
||||||
typedef USHORT *PUSHORT;
|
|
||||||
typedef ULONG *PULONG;
|
|
||||||
|
|
||||||
//
|
|
||||||
// String types.
|
|
||||||
//
|
|
||||||
typedef CHAR *PSTR, *LPSTR;
|
|
||||||
typedef CONST CHAR *PCSTR, *LPCSTR;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Wide character/string types.
|
|
||||||
//
|
|
||||||
typedef USHORT WCHAR;
|
|
||||||
typedef WCHAR *PWCHAR, *PWSTR, *LPWSTR;
|
|
||||||
typedef CONST WCHAR *PCWSTR, *LPCWSTR;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Long long types.
|
// Long long types.
|
||||||
//
|
//
|
||||||
@@ -137,19 +114,73 @@ typedef unsigned long long ULONGLONG;
|
|||||||
typedef LONGLONG *PLONGLONG;
|
typedef LONGLONG *PLONGLONG;
|
||||||
typedef ULONGLONG *PULONGLONG;
|
typedef ULONGLONG *PULONGLONG;
|
||||||
|
|
||||||
#define MAXLONGLONG (0x7fffffffffffffff)
|
#define MAXLONGLONG 0x7fffffffffffffff
|
||||||
|
#define MAXULONGLONG 0xffffffffffffffff
|
||||||
|
|
||||||
|
#define LODWORD(x) ((ULONG)(x))
|
||||||
|
#define HIDWORD(x) ((ULONG)((x) >> 32))
|
||||||
|
|
||||||
|
#define LOWORD(x) ((USHORT)(x))
|
||||||
|
#define HIWORD(x) ((USHORT)((x) >> 16))
|
||||||
|
|
||||||
|
#define LOBYTE(x) ((UCHAR)(x))
|
||||||
|
#define HIBYTE(x) ((UCHAR)((x) >> 8))
|
||||||
|
|
||||||
//
|
//
|
||||||
// Logical/boolean value types.
|
// Logical/boolean value types.
|
||||||
//
|
//
|
||||||
typedef ULONG LOGICAL;
|
typedef ULONG LOGICAL;
|
||||||
typedef ULONG *PLOGICAL;
|
typedef ULONG *PLOGICAL;
|
||||||
|
typedef int BOOL;
|
||||||
|
typedef BOOL *PBOOL;
|
||||||
typedef UCHAR BOOLEAN;
|
typedef UCHAR BOOLEAN;
|
||||||
typedef BOOLEAN *PBOOLEAN;
|
typedef BOOLEAN *PBOOLEAN;
|
||||||
|
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
|
|
||||||
|
//
|
||||||
|
// Basic pointer types.
|
||||||
|
//
|
||||||
|
typedef VOID *PVOID;
|
||||||
|
typedef CHAR *PCHAR;
|
||||||
|
typedef SHORT *PSHORT;
|
||||||
|
typedef UCHAR *PUCHAR;
|
||||||
|
typedef USHORT *PUSHORT;
|
||||||
|
typedef ULONG *PULONG;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Numeric pointer types.
|
||||||
|
//
|
||||||
|
#ifdef _WIN64
|
||||||
|
typedef LONGLONG LONG_PTR;
|
||||||
|
typedef ULONGLONG ULONG_PTR;
|
||||||
|
#else
|
||||||
|
typedef LONG LONG_PTR;
|
||||||
|
typedef ULONG ULONG_PTR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// String types.
|
||||||
|
//
|
||||||
|
typedef CHAR *PSTR, *LPSTR;
|
||||||
|
typedef CONST CHAR *PCSTR, *LPCSTR;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wide character/string types.
|
||||||
|
//
|
||||||
|
typedef USHORT WCHAR;
|
||||||
|
typedef WCHAR *PWCHAR, *PWSTR, *LPWSTR;
|
||||||
|
typedef CONST WCHAR *PCWSTR, *LPCWSTR;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle types.
|
||||||
|
//
|
||||||
|
typedef PVOID HANDLE;
|
||||||
|
typedef HANDLE *PHANDLE;
|
||||||
|
|
||||||
|
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Status code types.
|
// Status code types.
|
||||||
//
|
//
|
||||||
@@ -207,10 +238,131 @@ typedef union ULARGE_INTEGER {
|
|||||||
// Doubly-linked list entry.
|
// Doubly-linked list entry.
|
||||||
//
|
//
|
||||||
typedef struct _LIST_ENTRY {
|
typedef struct _LIST_ENTRY {
|
||||||
struct _LIST_ENTRY *ForwardLink;
|
struct _LIST_ENTRY *Flink;
|
||||||
struct _LIST_ENTRY *BackLink;
|
struct _LIST_ENTRY *Blink;
|
||||||
} LIST_ENTRY, *PLIST_ENTRY;
|
} LIST_ENTRY, *PLIST_ENTRY;
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
InitializeListHead (
|
||||||
|
IN PLIST_ENTRY Head
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Initializes a list head.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Head - the list head.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
Head->Blink = Head;
|
||||||
|
Head->Flink = Head;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
InsertHeadList (
|
||||||
|
IN PLIST_ENTRY Head,
|
||||||
|
IN PLIST_ENTRY Entry
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Inserts a list entry at the head of a list.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Entry - The list entry.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
Entry->Flink = Head->Flink;
|
||||||
|
Entry->Blink = Head;
|
||||||
|
Head->Flink->Blink = Entry;
|
||||||
|
Head->Flink = Entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
VOID
|
||||||
|
InsertTailList (
|
||||||
|
IN PLIST_ENTRY Head,
|
||||||
|
IN PLIST_ENTRY Entry
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Inserts a list entry at the tail of a list.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Entry - The list entry.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
Entry->Blink = Head->Blink;
|
||||||
|
Entry->Flink = Head;
|
||||||
|
Head->Blink->Flink = Entry;
|
||||||
|
Head->Blink = Entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
BOOLEAN
|
||||||
|
RemoveEntryList (
|
||||||
|
IN PLIST_ENTRY Entry
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Removes a list entry from a list.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Entry - the entry to remove.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
True if the list is now empty,
|
||||||
|
False if the list still has at least one entry.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Blink, Flink;
|
||||||
|
|
||||||
|
Blink = Entry->Blink;
|
||||||
|
Flink = Entry->Flink;
|
||||||
|
Blink->Flink = Flink;
|
||||||
|
Flink->Blink = Blink;
|
||||||
|
|
||||||
|
return (BOOLEAN)(Flink == Blink);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Unicode string.
|
// Unicode string.
|
||||||
//
|
//
|
||||||
|
@@ -18,6 +18,7 @@ Abstract:
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ntdef.h>
|
#include <ntdef.h>
|
||||||
|
#include <ntstatus.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// Memory operations.
|
// Memory operations.
|
||||||
@@ -27,6 +28,47 @@ Abstract:
|
|||||||
#define RtlFillMemory(Destination, Length, Fill) memset((Destination), (Fill), (Length))
|
#define RtlFillMemory(Destination, Length, Fill) memset((Destination), (Fill), (Length))
|
||||||
#define RtlZeroMemory(Destination, Length) memset((Destination), 0, (Length))
|
#define RtlZeroMemory(Destination, Length) memset((Destination), 0, (Length))
|
||||||
|
|
||||||
|
#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
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
RtlInitUnicodeString (
|
RtlInitUnicodeString (
|
||||||
|
@@ -21,24 +21,41 @@ Abstract:
|
|||||||
//
|
//
|
||||||
// TODO: There are an insane amount of status values.
|
// TODO: There are an insane amount of status values.
|
||||||
//
|
//
|
||||||
#define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL)
|
#define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL)
|
||||||
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL)
|
#define STATUS_UNSUCCESSFUL ((NTSTATUS) 0xC0000001L)
|
||||||
#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L)
|
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L)
|
||||||
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L)
|
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL)
|
||||||
#define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L)
|
#define STATUS_NO_MEMORY ((NTSTATUS) 0xC0000017L)
|
||||||
#define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L)
|
#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L)
|
||||||
#define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL)
|
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L)
|
||||||
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL)
|
#define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L)
|
||||||
#define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L)
|
#define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L)
|
||||||
#define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L)
|
#define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL)
|
||||||
#define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL)
|
#define STATUS_INTEGER_OVERFLOW ((NTSTATUS) 0xC0000095L)
|
||||||
#define STATUS_TIMEOUT ((NTSTATUS) 0x00000102L)
|
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL)
|
||||||
#define STATUS_NO_MEDIA ((NTSTATUS) 0xC0000178L)
|
#define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L)
|
||||||
#define STATUS_IO_DEVICE_ERROR ((NTSTATUS) 0xC0000185L)
|
#define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L)
|
||||||
#define STATUS_INVALID_BUFFER_SIZE ((NTSTATUS) 0xC0000206L)
|
#define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL)
|
||||||
#define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L)
|
#define STATUS_INVALID_PARAMETER_1 ((NTSTATUS) 0xC00000EFL)
|
||||||
#define STATUS_REQUEST_ABORTED ((NTSTATUS) 0xC0000240L)
|
#define STATUS_INVALID_PARAMETER_2 ((NTSTATUS) 0xC00000F0L)
|
||||||
#define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS) 0xC000026CL)
|
#define STATUS_INVALID_PARAMETER_3 ((NTSTATUS) 0xC00000F1L)
|
||||||
#define STATUS_NO_MATCH ((NTSTATUS) 0xC0000272L)
|
#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)
|
||||||
|
|
||||||
#endif /* !_NTSTATUS_H */
|
#endif /* !_NTSTATUS_H */
|
||||||
|
@@ -49,7 +49,7 @@ project("BOOTMGR")
|
|||||||
libdirs({ "BUILD/SDK" })
|
libdirs({ "BUILD/SDK" })
|
||||||
objdir("BUILD/BOOT")
|
objdir("BUILD/BOOT")
|
||||||
targetdir("BUILD/BOOT")
|
targetdir("BUILD/BOOT")
|
||||||
files({ "BOOT/ENVIRON/INC/**.h", "BOOT/ENVIRON/**.c" })
|
files({ "BOOT/ENVIRON/INC/**.h", "BOOT/ENVIRON/LIB/**.c", "BOOT/ENVIRON/APP/BOOTMGR/**.c" })
|
||||||
|
|
||||||
filter("toolset:clang")
|
filter("toolset:clang")
|
||||||
buildoptions({ "-fshort-wchar", "-fno-strict-aliasing", "-fno-stack-protector", "-fno-stack-check", "-mno-red-zone" })
|
buildoptions({ "-fshort-wchar", "-fno-strict-aliasing", "-fno-stack-protector", "-fno-stack-check", "-mno-red-zone" })
|
||||||
|
Reference in New Issue
Block a user