Compare commits

...

43 Commits

Author SHA1 Message Date
4c32340803 [BOOT:MM] Finish MmFwGetMemoryMap()
Added stub for MmMdFindDescriptorFromMdl().
2024-09-01 10:38:28 -04:00
a32d72be1e [BOOT] Improve TODO comments 2024-09-01 09:36:09 -04:00
75197cc8b5 [SDK:NT] Add STATUS_NO_MEMORY 2024-08-27 13:58:50 -04:00
6fc91eb58c [BOOT] Add stubs to complete MmPaInitialize()
MmPaInitialize() is now complete
Added BlpMmInitializeConstraints() and MmMdRemoveRegionFromMdlEx()
2024-08-27 13:57:21 -04:00
437b19a0f5 [BOOT] Better debug logging 2024-08-27 13:21:45 -04:00
860874640e [SDK:NT] Add bit extraction helpers
Added LO/HIDWORD(), LO/HIWORD(), and LO/HIBYTE() macros
2024-08-27 13:20:09 -04:00
2751b0f7bb [BOOT:MM] Big work on MM :) 2024-08-27 09:32:16 -04:00
6a868b45ba [SDK:NT] Even more list helpers
Added InsertHeadList() and InsertTailList()
2024-08-27 09:20:10 -04:00
831a676af8 [BOOT] Get rid of useless comments 2024-08-27 08:13:49 -04:00
d759302400 [BOOT:LIB] Implement EfiGetNtStatusCode() 2024-08-26 19:56:20 -04:00
c7298452ff [BOOT] Small refactoring 2024-08-26 19:55:32 -04:00
72f7e5057c [BOOT] More header stuff 2024-08-26 19:54:21 -04:00
b63d80d5c9 [SDK:NT] Another list helper & more status values
Added STATUS_INSUFFICIENT_NVRAM_RESOURCES
Added InitializeListHead()
2024-08-26 19:51:36 -04:00
ef1ac515dd [BOOT:MM] More work on memory manager 2024-08-26 12:30:31 -04:00
bbd8f475bb [BOOT] Add additional README.md 2024-08-26 12:29:04 -04:00
caec9bc42e [SDK:NT] More status values and list helpers.
Added STATUS_NOT_IMPLEMENTED.
Added RemoveEntryList().
2024-08-26 12:27:59 -04:00
1581638c26 [BOOT:MM] Begin work on memory manager 2024-08-26 11:20:25 -04:00
664bf6d713 [SDK:NT] Add MAXULONGLONG to ntdef.h 2024-08-26 11:18:00 -04:00
76b01cfb00 [BOOT:LIB] Add conditional debug printing
Added DebugPrint() and DebugPrintf() macros, which are aliases of
ConsolePrint() and ConsolePrintf() if _DEBUG is defined. Otherwise, they
do not generate any code.
2024-08-26 10:44:31 -04:00
4dbb5235e3 [NTOSKRNL::KE] Implement all Mutex Directives
Implemented:: KeReleaseFastMutexContended
                      KeEnterCriticalRegionAndAcquireFastMutexUnsafe
                      KeReleaseFastMutexUnsafeAndLeaveCriticalRegion
                      KeAcquireFastMutex
                      KeAcquireFastMutexUnsafe
                      KeReleaseFastMutex
                      KeReleaseFastMutexUnsafe
                      KeInitializeGuardedMutex
                      KeAcquireGuardedMutex
                      KeAcquireGuardedMutexUnsafe
                      KeReleaseGuardedMutexUnsafe
2024-08-26 15:38:37 +02:00
dd7ae11851 Add more directory structure info to README.md 2024-08-25 11:02:08 -04:00
7125a17aca [BOOT:LIB] Refactor bootlib.c
InitializeLibary() now saves parameters data in
BlpApplicationParameters, BlpApplicationEntry, and BlpBootDevice.
Moved BlGetBootOptionSize() and BlGetBootOptionListSize() to bootopt.c
2024-08-25 10:55:20 -04:00
de9501aee9 [BOOT:LIB] Do some renaming
BOOT_APPLICATION_ENTRY_OPTION -> BOOT_APPLICATION_OPTION
BOOT_APPLICATION_ENTRY -> BOOT_INPUT_APPLICATION_ENTRY
2024-08-25 10:49:44 -04:00
e61d0f5155 [BOOT:BOOTMGR] Begin work on BCD support
Added stub for BmOpenDataStore()
2024-08-25 10:43:48 -04:00
b8afb1aad4 [SDK:NT] Reorganize and extend ntdef.h
Added LONG_PTR
Added INVALID_HANDLE_VALUE
2024-08-25 10:42:37 -04:00
fb0e36f5cf [SDK:NT] Add more status values and handles
Added STATUS_INVALID_PARAMETER_[1-12]
Added HANDLE and PHANDLE
2024-08-25 10:31:04 -04:00
c091f7ef59 [BOOT:LIB] Print boot info in InitializeLibrary() 2024-08-24 18:55:13 -04:00
3759f7dbfe [SDK:NT] Add ULONG_PTR type 2024-08-24 18:54:33 -04:00
b96b3d769c Update .gitignore 2024-08-24 16:44:43 -04:00
7aac701cc1 [BOOT:BOOTMGR] Print error message on failure 2024-08-24 16:35:36 -04:00
77d2f84e97 [BOOT:LIB] Implement ConsolePrintf() 2024-08-24 16:34:59 -04:00
b870d5a015 [SDK:CRT] Implement vswprintf() 2024-08-24 16:33:16 -04:00
5235ebdfa4 [BOOT:LIB] Implement BlpFwInitialize() 2024-08-24 16:32:22 -04:00
874d95ae4c [BOOT:LIB] Implement EfiInitpConvertEfiFilePath()
Also implemented RtlULongSub() and EfiInitpAppendPathString()
2024-08-24 12:39:16 -04:00
8f56881d02 [BOOT:LIB] More work on efiinit.c
EfiInitpCreateApplicationEntry() is almost complete.
2024-08-24 10:36:32 -04:00
0743fa0106 [BOOT:LIB] Add boot option size helpers 2024-08-24 10:35:48 -04:00
fd670ace0d [BOOT:LIB] Major work on efiinit.c
Improved EfiInitpCreateApplicationEntry()
Implemented EfiInitpGetDeviceNode(), EfiInitTranslateDevicePath(),
and EfiInitpConvertDevicePath()
2024-08-24 09:30:52 -04:00
9b66f166d6 [BOOT:BOOTMGR] Add device definitions to bootmgr.h 2024-08-24 09:16:34 -04:00
a6aa028e5c [BUILD] Fix source file paths 2024-08-24 09:12:52 -04:00
ccb62c05f5 [SDK:NT] Add BOOL and STATUS_UNSUCCESSFUL 2024-08-24 09:12:16 -04:00
1c2c797365 [BOOT] Add more definitions to efidevp.h 2024-08-24 09:11:21 -04:00
08d017171d [NTOSKRNL:CC] Implement Extarnal Cache Directives
Implemented::
CcDeductDirtyPagesFromExternalCache
CcAddDirtyPagesToExternalCache:: Exported 
CcAddExternalCache
CcRegisterExternalCache:: Exported 
CcRemoveExternalCache
CcUnregisterExternalCache :: Exported
2024-08-18 11:11:36 +02:00
d0d6097d57 [NTOSKRNL:CC] Disable ExtraWriteBehind Threadpool ,
Threadpool facility will be developed first in  LazyWriter-Threadpool branch before merging, to ensure stability. 

Removed : CcComputeNextScanTime
2024-08-18 08:22:58 +02:00
31 changed files with 3840 additions and 215 deletions

5
.gitignore vendored
View File

@@ -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

View File

@@ -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.
--*/ --*/

View 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;
}

View File

@@ -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;

View File

@@ -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,

View File

@@ -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

View File

@@ -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;

View File

@@ -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 (

View File

@@ -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
View 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

View 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);
}
}

View 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;
}

View File

@@ -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;

View File

@@ -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;
}
}

View 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
View 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
View 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
View 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;
}

View File

@@ -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.
--*/ --*/

View 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
View 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() |

View 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;
}

View File

@@ -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)

View File

@@ -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();
}

View File

@@ -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
View 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;
}

View File

@@ -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

View File

@@ -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.
// //

View File

@@ -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 (

View File

@@ -22,16 +22,32 @@ 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_UNSUCCESSFUL ((NTSTATUS) 0xC0000001L)
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L)
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL) #define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL)
#define STATUS_NO_MEMORY ((NTSTATUS) 0xC0000017L)
#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L) #define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L) #define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L)
#define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L) #define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L)
#define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L) #define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L)
#define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL) #define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL)
#define STATUS_INTEGER_OVERFLOW ((NTSTATUS) 0xC0000095L)
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL) #define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL)
#define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L) #define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L)
#define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L) #define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L)
#define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL) #define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL)
#define STATUS_INVALID_PARAMETER_1 ((NTSTATUS) 0xC00000EFL)
#define STATUS_INVALID_PARAMETER_2 ((NTSTATUS) 0xC00000F0L)
#define STATUS_INVALID_PARAMETER_3 ((NTSTATUS) 0xC00000F1L)
#define STATUS_INVALID_PARAMETER_4 ((NTSTATUS) 0xC00000F2L)
#define STATUS_INVALID_PARAMETER_5 ((NTSTATUS) 0xC00000F3L)
#define STATUS_INVALID_PARAMETER_6 ((NTSTATUS) 0xC00000F4L)
#define STATUS_INVALID_PARAMETER_7 ((NTSTATUS) 0xC00000F5L)
#define STATUS_INVALID_PARAMETER_8 ((NTSTATUS) 0xC00000F6L)
#define STATUS_INVALID_PARAMETER_9 ((NTSTATUS) 0xC00000F7L)
#define STATUS_INVALID_PARAMETER_10 ((NTSTATUS) 0xC00000F8L)
#define STATUS_INVALID_PARAMETER_11 ((NTSTATUS) 0xC00000F9L)
#define STATUS_INVALID_PARAMETER_12 ((NTSTATUS) 0xC00000FAL)
#define STATUS_TIMEOUT ((NTSTATUS) 0x00000102L) #define STATUS_TIMEOUT ((NTSTATUS) 0x00000102L)
#define STATUS_NO_MEDIA ((NTSTATUS) 0xC0000178L) #define STATUS_NO_MEDIA ((NTSTATUS) 0xC0000178L)
#define STATUS_IO_DEVICE_ERROR ((NTSTATUS) 0xC0000185L) #define STATUS_IO_DEVICE_ERROR ((NTSTATUS) 0xC0000185L)
@@ -40,5 +56,6 @@ Abstract:
#define STATUS_REQUEST_ABORTED ((NTSTATUS) 0xC0000240L) #define STATUS_REQUEST_ABORTED ((NTSTATUS) 0xC0000240L)
#define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS) 0xC000026CL) #define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS) 0xC000026CL)
#define STATUS_NO_MATCH ((NTSTATUS) 0xC0000272L) #define STATUS_NO_MATCH ((NTSTATUS) 0xC0000272L)
#define STATUS_INSUFFICIENT_NVRAM_RESOURCES ((NTSTATUS) 0xC0000454L)
#endif /* !_NTSTATUS_H */ #endif /* !_NTSTATUS_H */

View File

@@ -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" })