Compare commits
6 Commits
5235ebdfa4
...
LazyWriter
Author | SHA1 | Date | |
---|---|---|---|
11683762c3
|
|||
3ae19eaf01
|
|||
e75a2adeec
|
|||
1c173364a1
|
|||
104a0212e0
|
|||
1dec536c4d
|
@@ -23,33 +23,6 @@ typedef struct {
|
|||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
} BOOT_LIBRARY_PARAMETERS, *PBOOT_LIBRARY_PARAMETERS;
|
} BOOT_LIBRARY_PARAMETERS, *PBOOT_LIBRARY_PARAMETERS;
|
||||||
|
|
||||||
VOID
|
|
||||||
ConsolePrint (
|
|
||||||
IN PWSTR String
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ConsolePrintf (
|
|
||||||
IN PWSTR Format,
|
|
||||||
...
|
|
||||||
);
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
BlGetBootOptionSize (
|
|
||||||
IN PBOOT_APPLICATION_ENTRY_OPTION Option
|
|
||||||
);
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
BlGetBootOptionListSize (
|
|
||||||
IN PBOOT_APPLICATION_ENTRY_OPTION Options
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
BlpFwInitialize (
|
|
||||||
IN ULONG Stage,
|
|
||||||
IN PBOOT_FIRMWARE_DATA FirmwareData
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BlInitializeLibrary (
|
BlInitializeLibrary (
|
||||||
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
||||||
|
@@ -67,29 +67,18 @@ 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;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ULONG Type;
|
|
||||||
ULONG DataOffset;
|
|
||||||
ULONG DataSize;
|
|
||||||
ULONG OtherOptionsOffset;
|
|
||||||
ULONG NextOptionOffset;
|
|
||||||
BOOLEAN IsInvalid;
|
|
||||||
UCHAR Unknown[3];
|
|
||||||
} BOOT_APPLICATION_ENTRY_OPTION, *PBOOT_APPLICATION_ENTRY_OPTION;
|
|
||||||
|
|
||||||
#define BOOT_APPLICATION_ENTRY_SIGNATURE 0x544e4550415442 /* "BTAPENT" */
|
#define BOOT_APPLICATION_ENTRY_SIGNATURE 0x544e4550415442 /* "BTAPENT" */
|
||||||
|
|
||||||
#define BOOT_APPLICATION_ENTRY_NO_BCD_IDENTIFIER 0x01
|
#define BOOT_APPLICATION_ENTRY_BCD_IDENTIFIER_NOT_SET 0x01
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ULONGLONG Signature;
|
ULONGLONG Signature;
|
||||||
ULONG Attributes;
|
ULONG Attributes;
|
||||||
GUID BcdIdentifier;
|
GUID BcdIdentifier;
|
||||||
UCHAR Unknown[16];
|
|
||||||
BOOT_APPLICATION_ENTRY_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
|
||||||
@@ -134,116 +123,9 @@ 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;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
BCDE_DATA_TYPE_APPLICATION_DEVICE = 0x11000001,
|
|
||||||
BCDE_DATA_TYPE_APPLICATION_PATH = 0x22000002
|
|
||||||
} BCDE_DATA_TYPE;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GUID OtherOptions;
|
|
||||||
BOOT_DEVICE Device;
|
|
||||||
} BCDE_DEVICE, *PBCDE_DEVICE;
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
BmMain (
|
BmMain (
|
||||||
IN PBOOT_INPUT_PARAMETERS InputParameters
|
IN PBOOT_INPUT_PARAMETERS InputParameters
|
||||||
|
@@ -24,40 +24,8 @@ 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 {
|
||||||
@@ -67,13 +35,6 @@ 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 (
|
||||||
|
@@ -1,64 +0,0 @@
|
|||||||
/*++
|
|
||||||
|
|
||||||
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 - firmware data structure to use for initialization.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
STATUS_SUCCESS if successful,
|
|
||||||
STATUS_INVALID_PARAMETER if FirmwareData is invalid.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
|
|
||||||
{
|
|
||||||
if (FirmwareData == NULL || FirmwareData->Version == 0) {
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Stage == 0) {
|
|
||||||
EfiST = FirmwareData->SystemTable;
|
|
||||||
EfiBS = EfiST->BootServices;
|
|
||||||
EfiRT = EfiST->RuntimeServices;
|
|
||||||
EfiConOut = EfiST->ConOut;
|
|
||||||
EfiConIn = EfiST->ConIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
@@ -16,7 +16,6 @@ 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"
|
||||||
|
|
||||||
@@ -24,447 +23,15 @@ 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 - the path to append to.
|
|
||||||
|
|
||||||
BufferSize - the maximum number of bytes to append.
|
|
||||||
|
|
||||||
Source - the source path to append to Destination.
|
|
||||||
|
|
||||||
SourceSize - the size of Source, in bytes.
|
|
||||||
|
|
||||||
BufferUsed - pointer to a ULONG to store 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 to search.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
Pointer to the last device path node.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
|
|
||||||
{
|
|
||||||
EFI_DEVICE_PATH *Node;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check if the current node is the end of the path.
|
|
||||||
//
|
|
||||||
if (IsDevicePathEndType(DevicePath)) {
|
|
||||||
return DevicePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Find the last non-filepath node.
|
|
||||||
//
|
|
||||||
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 boot device format.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
EfiDevicePath - The EFI device path to be translated.
|
|
||||||
|
|
||||||
BootDevice - Pointer to the destination device structure.
|
|
||||||
|
|
||||||
BufferSize - The amount of available space 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;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check for available buffer space.
|
|
||||||
//
|
|
||||||
if (BufferSize < sizeof(BOOT_DEVICE)) {
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
BootDevice->Size = sizeof(BOOT_DEVICE);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Memory mapped device paths 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get the device node, the device the application was loaded from.
|
|
||||||
// TODO: Only media devices and ramdisks are currently supported.
|
|
||||||
//
|
|
||||||
DeviceNode = EfiInitpGetDeviceNode(EfiDevicePath);
|
|
||||||
if (DevicePathType(DeviceNode) != MEDIA_DEVICE_PATH) {
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check device node subtype.
|
|
||||||
//
|
|
||||||
switch (DevicePathSubType(DeviceNode)) {
|
|
||||||
case MEDIA_HARDDRIVE_DP:
|
|
||||||
HarddriveNode = (HARDDRIVE_DEVICE_PATH *)DeviceNode;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Use correct block device and partition format.
|
|
||||||
//
|
|
||||||
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;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize partition based on the drive's partitioning system.
|
|
||||||
//
|
|
||||||
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_ENTRY_OPTION Option,
|
|
||||||
IN ULONG BufferSize
|
|
||||||
)
|
|
||||||
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Converts an EFI device path into BCD format.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
EfiDevicePath - The EFI device path to be converted.
|
|
||||||
|
|
||||||
OptionType - The data type to be assigned to option.
|
|
||||||
|
|
||||||
Option - Pointer to the destination option structure.
|
|
||||||
|
|
||||||
BufferSize - The amount of available space in the buffer.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
STATUS_SUCCESS if successful.
|
|
||||||
other NTSTATUS value if failure occurs.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
PBCDE_DEVICE DeviceElement;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check for available buffer space.
|
|
||||||
//
|
|
||||||
if (BufferSize < sizeof(BOOT_APPLICATION_ENTRY_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device)) {
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Translate device path.
|
|
||||||
//
|
|
||||||
RtlZeroMemory(Option, sizeof(BOOT_APPLICATION_ENTRY_OPTION));
|
|
||||||
DeviceElement = (PBCDE_DEVICE)((PUCHAR)Option + sizeof(BOOT_APPLICATION_ENTRY_OPTION));
|
|
||||||
Status = EfiInitTranslateDevicePath(
|
|
||||||
EfiDevicePath,
|
|
||||||
&DeviceElement->Device,
|
|
||||||
BufferSize - (sizeof(BOOT_APPLICATION_ENTRY_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device))
|
|
||||||
);
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set up option structure.
|
|
||||||
//
|
|
||||||
Option->Type = OptionType;
|
|
||||||
Option->DataOffset = sizeof(BOOT_APPLICATION_ENTRY_OPTION);
|
|
||||||
Option->DataSize = FIELD_OFFSET(BCDE_DEVICE, Device) + DeviceElement->Device.Size;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
EfiInitpConvertEfiFilePath (
|
|
||||||
IN EFI_DEVICE_PATH *EfiFilePath,
|
|
||||||
IN BCDE_DATA_TYPE OptionType,
|
|
||||||
IN OUT PBOOT_APPLICATION_ENTRY_OPTION Option,
|
|
||||||
IN ULONG BufferSize
|
|
||||||
)
|
|
||||||
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Converts an EFI file path into BCD format.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
EfiFilePath - The EFI file path to be converted.
|
|
||||||
|
|
||||||
OptionType - The data type to be assigned to option.
|
|
||||||
|
|
||||||
Option - Pointer to the destination option structure.
|
|
||||||
|
|
||||||
BufferSize - The amount of available space in the buffer.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
STATUS_SUCCESS if successful.
|
|
||||||
other NTSTATUS value if failure occurs.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
EFI_DEVICE_PATH *Node;
|
|
||||||
PWCHAR PathStart, Position;
|
|
||||||
ULONG BufferRemaining, Length, Appended;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check for available buffer space.
|
|
||||||
//
|
|
||||||
if (BufferSize < sizeof(BOOT_APPLICATION_ENTRY_OPTION)) {
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set up option structure.
|
|
||||||
//
|
|
||||||
RtlZeroMemory(Option, sizeof(BOOT_APPLICATION_ENTRY_OPTION));
|
|
||||||
Option->Type = OptionType;
|
|
||||||
Option->DataOffset = sizeof(BOOT_APPLICATION_ENTRY_OPTION);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Add to the path one file path node at a time.
|
|
||||||
//
|
|
||||||
Option->DataSize = 0;
|
|
||||||
BufferRemaining = BufferSize - sizeof(BOOT_APPLICATION_ENTRY_OPTION);
|
|
||||||
Node = EfiFilePath;
|
|
||||||
PathStart = (PWCHAR)((PUCHAR)Option + Option->DataOffset);
|
|
||||||
Position = PathStart;
|
|
||||||
while (!IsDevicePathEndType(Node)) {
|
|
||||||
if (DevicePathType(Node) != MEDIA_DEVICE_PATH || DevicePathSubType(Node) != MEDIA_FILEPATH_DP) {
|
|
||||||
Node = NextDevicePathNode(Node);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = RtlULongSub(DevicePathNodeLength(Node), FIELD_OFFSET(FILEPATH_DEVICE_PATH, PathName), &Length);
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = EfiInitpAppendPathString(Position, BufferRemaining, &((FILEPATH_DEVICE_PATH *)Node)->PathName[0], Length, &Appended);
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Option->DataSize += Appended;
|
|
||||||
BufferRemaining -= Appended;
|
|
||||||
Position = (PWCHAR)((PUCHAR)Position + Appended);
|
|
||||||
Node = NextDevicePathNode(Node);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Terminate path string.
|
|
||||||
//
|
|
||||||
if (BufferRemaining < sizeof(UNICODE_NULL)) {
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
*Position = L'\0';
|
|
||||||
Option->DataSize += sizeof(UNICODE_NULL);
|
|
||||||
|
|
||||||
//
|
|
||||||
// The path option is invalid if the path is NULL.
|
|
||||||
//
|
|
||||||
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_APPLICATION_ENTRY Entry,
|
||||||
IN ULONG BufferSize,
|
IN ULONG BufferSize,
|
||||||
IN EFI_DEVICE_PATH *EfiDevicePath,
|
IN EFI_DEVICE_PATH *DevicePath,
|
||||||
IN EFI_DEVICE_PATH *EfiFilePath,
|
IN EFI_DEVICE_PATH *FilePath,
|
||||||
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
|
||||||
)
|
)
|
||||||
@@ -483,16 +50,14 @@ Arguments:
|
|||||||
|
|
||||||
BufferSize - The amount of available space in the buffer.
|
BufferSize - The amount of available space in the buffer.
|
||||||
|
|
||||||
EfiDevicePath - The device path for the application.
|
DevicePath - The device path for the application.
|
||||||
|
|
||||||
EfiFilePath - The file path for the application.
|
FilePath - The file path for the application.
|
||||||
|
|
||||||
LoadOptions - Firmware load options string.
|
LoadOptions - Firmware load options string.
|
||||||
|
|
||||||
LoadOptionsSize - Length of the string pointed to by LoadOptions.
|
LoadOptionsSize - Length of the string pointed to by LoadOptions.
|
||||||
|
|
||||||
Flags - Unused.
|
|
||||||
|
|
||||||
BufferUsed - Returns the amount of buffer space used by the routine.
|
BufferUsed - Returns the amount of buffer space used by the routine.
|
||||||
|
|
||||||
BootDevice - Returns a pointer to the device the application was loaded from.
|
BootDevice - Returns a pointer to the device the application was loaded from.
|
||||||
@@ -504,39 +69,21 @@ Return Value:
|
|||||||
--*/
|
--*/
|
||||||
|
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
|
||||||
ULONG BufferRemaining, OptionsSize, Size;
|
|
||||||
PWCHAR BcdOptionString;
|
PWCHAR BcdOptionString;
|
||||||
BOOLEAN BcdIdentifierSet;
|
BOOLEAN BcdIdentifierSet;
|
||||||
UNICODE_STRING UnicodeString;
|
UNICODE_STRING UnicodeString;
|
||||||
PBOOT_APPLICATION_ENTRY_OPTION Option, PrevOption;
|
|
||||||
PBCDE_DEVICE BootDeviceElement;
|
|
||||||
|
|
||||||
(VOID)SystemTable;
|
|
||||||
(VOID)EfiDevicePath;
|
|
||||||
(VOID)EfiFilePath;
|
|
||||||
(VOID)Flags;
|
|
||||||
|
|
||||||
*BufferUsed = 0;
|
*BufferUsed = 0;
|
||||||
*BootDevice = NULL;
|
*BootDevice = NULL;
|
||||||
OptionsSize = 0;
|
|
||||||
BcdIdentifierSet = FALSE;
|
BcdIdentifierSet = FALSE;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Require enough space for the application entry.
|
// Require enough space for the application entry.
|
||||||
//
|
//
|
||||||
BufferRemaining = BufferSize;
|
if (BufferSize < sizeof(BOOT_APPLICATION_ENTRY)) {
|
||||||
if (BufferRemaining < sizeof(BOOT_APPLICATION_ENTRY)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Set up application entry structure.
|
|
||||||
//
|
|
||||||
RtlZeroMemory(Entry, sizeof(BOOT_APPLICATION_ENTRY));
|
|
||||||
Entry->Signature = BOOT_APPLICATION_ENTRY_SIGNATURE;
|
|
||||||
BufferRemaining -= FIELD_OFFSET(BOOT_APPLICATION_ENTRY, Options);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Terminate load options string.
|
// Terminate load options string.
|
||||||
//
|
//
|
||||||
@@ -545,6 +92,13 @@ Return Value:
|
|||||||
LoadOptions[LoadOptionsSize - 1] = L'\0';
|
LoadOptions[LoadOptionsSize - 1] = L'\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set up application entry structure.
|
||||||
|
//
|
||||||
|
RtlZeroMemory(Entry, sizeof(BOOT_APPLICATION_ENTRY));
|
||||||
|
Entry->Signature = BOOT_APPLICATION_ENTRY_SIGNATURE;
|
||||||
|
*BufferUsed = sizeof(BOOT_APPLICATION_ENTRY);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse BCD GUID if present.
|
// Parse BCD GUID if present.
|
||||||
//
|
//
|
||||||
@@ -556,51 +110,15 @@ Return Value:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!BcdIdentifierSet) {
|
if (!BcdIdentifierSet) {
|
||||||
Entry->Attributes |= BOOT_APPLICATION_ENTRY_NO_BCD_IDENTIFIER;
|
Entry->Attributes |= BOOT_APPLICATION_ENTRY_BCD_IDENTIFIER_NOT_SET;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Convert the EFI device path into a boot device option.
|
// TODO: This routine is not fully implemented.
|
||||||
//
|
//
|
||||||
Option = &Entry->Options;
|
(VOID)SystemTable;
|
||||||
Status = EfiInitpConvertEfiDevicePath(EfiDevicePath, BCDE_DATA_TYPE_APPLICATION_DEVICE, Option, BufferRemaining);
|
(VOID)DevicePath;
|
||||||
if (!NT_SUCCESS(Status)) {
|
(VOID)FilePath;
|
||||||
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: UDP/PXE boot is not supported.
|
|
||||||
//
|
|
||||||
PrevOption = Option;
|
|
||||||
Option = (PBOOT_APPLICATION_ENTRY_OPTION)((PUCHAR)&Entry->Options + OptionsSize);
|
|
||||||
Status = EfiInitpConvertEfiFilePath(EfiFilePath, BCDE_DATA_TYPE_APPLICATION_PATH, Option, BufferRemaining);
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
PrevOption->NextOptionOffset = (PUCHAR)Option - (PUCHAR)&Entry->Options;
|
|
||||||
Size = BlGetBootOptionSize(Option);
|
|
||||||
OptionsSize += Size;
|
|
||||||
BufferRemaining -= Size;
|
|
||||||
|
|
||||||
//
|
|
||||||
// TODO: This section is incomplete.
|
|
||||||
//
|
|
||||||
PrevOption = Option;
|
|
||||||
Option = (PBOOT_APPLICATION_ENTRY_OPTION)((PUCHAR)&Entry->Options + OptionsSize);
|
|
||||||
// Status = Unknown(LoadOptions, &Entry->Options, RemainingSize, &OptionsSize, &PrevOption, &Size);
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
*BufferUsed = BufferSize - BufferRemaining;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PBOOT_INPUT_PARAMETERS
|
PBOOT_INPUT_PARAMETERS
|
||||||
@@ -718,7 +236,6 @@ Return Value:
|
|||||||
LoadedImage->FilePath,
|
LoadedImage->FilePath,
|
||||||
LoadedImage->LoadOptions,
|
LoadedImage->LoadOptions,
|
||||||
LoadedImage->LoadOptionsSize,
|
LoadedImage->LoadOptionsSize,
|
||||||
0,
|
|
||||||
&ApplicationEntrySize,
|
&ApplicationEntrySize,
|
||||||
&BootDevice
|
&BootDevice
|
||||||
);
|
);
|
||||||
|
@@ -25,84 +25,6 @@ Abstract:
|
|||||||
sizeof(BOOT_RETURN_DATA) \
|
sizeof(BOOT_RETURN_DATA) \
|
||||||
)
|
)
|
||||||
|
|
||||||
ULONG
|
|
||||||
BlGetBootOptionListSize (
|
|
||||||
IN PBOOT_APPLICATION_ENTRY_OPTION Options
|
|
||||||
);
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
BlGetBootOptionSize (
|
|
||||||
IN PBOOT_APPLICATION_ENTRY_OPTION Option
|
|
||||||
)
|
|
||||||
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Gets the size of a boot option.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
Option - the boot option to get the size of.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
The size of the option.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
|
|
||||||
{
|
|
||||||
ULONG TotalSize;
|
|
||||||
|
|
||||||
if (Option->DataOffset != 0) {
|
|
||||||
TotalSize = Option->DataOffset + Option->DataSize;
|
|
||||||
} else {
|
|
||||||
TotalSize = sizeof(BOOT_APPLICATION_ENTRY_OPTION);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Option->OtherOptionsOffset != 0) {
|
|
||||||
TotalSize += BlGetBootOptionListSize((PBOOT_APPLICATION_ENTRY_OPTION)((PUCHAR)Option + Option->OtherOptionsOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
return TotalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
BlGetBootOptionListSize (
|
|
||||||
IN PBOOT_APPLICATION_ENTRY_OPTION Options
|
|
||||||
)
|
|
||||||
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Gets the total size of a list boot options.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
Options - the boot option list to get the size of.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
The size of the options.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
|
|
||||||
{
|
|
||||||
ULONG TotalSize, NextOffset;
|
|
||||||
PBOOT_APPLICATION_ENTRY_OPTION Option;
|
|
||||||
|
|
||||||
TotalSize = 0;
|
|
||||||
NextOffset = 0;
|
|
||||||
do {
|
|
||||||
Option = (PBOOT_APPLICATION_ENTRY_OPTION)((PUCHAR)Options + NextOffset);
|
|
||||||
NextOffset = Option->NextOptionOffset;
|
|
||||||
TotalSize += BlGetBootOptionSize(Option);
|
|
||||||
} while (NextOffset != 0);
|
|
||||||
|
|
||||||
return TotalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
InitializeLibrary (
|
InitializeLibrary (
|
||||||
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
IN PBOOT_INPUT_PARAMETERS InputParameters,
|
||||||
@@ -128,9 +50,6 @@ Return Value:
|
|||||||
--*/
|
--*/
|
||||||
|
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
|
||||||
PBOOT_FIRMWARE_DATA FirmwareData;
|
|
||||||
|
|
||||||
(VOID)LibraryParameters;
|
(VOID)LibraryParameters;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -142,15 +61,6 @@ Return Value:
|
|||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize firmware library.
|
|
||||||
//
|
|
||||||
FirmwareData = (PBOOT_FIRMWARE_DATA)((PUCHAR)InputParameters + InputParameters->FirmwareDataOffset);
|
|
||||||
Status = BlpFwInitialize(0, FirmwareData);
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,210 +0,0 @@
|
|||||||
/*
|
|
||||||
* PROJECT: Alcyone System Kernel
|
|
||||||
* LICENSE: BSD Clause 3
|
|
||||||
* PURPOSE: Cache Controller:: External Cache Compatibility Layer
|
|
||||||
* NT KERNEL: 5.11.9360
|
|
||||||
* COPYRIGHT: 2023-2029 Dibymartanda Samanta <>
|
|
||||||
*/
|
|
||||||
|
|
||||||
NOTE::Alcyone will not notify,in case of Empty External Cache at the moment, feature is planned for threadpool revamp
|
|
||||||
|
|
||||||
/* Move Typedef later cctypes.hpp */
|
|
||||||
typedef struct alignas(24) _DIRTY_PAGE_STATISTICS {
|
|
||||||
ULONGLONG DirtyPages; // 0x0
|
|
||||||
ULONGLONG DirtyPagesLastScan; // 0x8
|
|
||||||
ULONG DirtyPagesScheduledLastScan; // 0x10
|
|
||||||
} DIRTY_PAGE_STATISTICS, *PDIRTY_PAGE_STATISTICS; // 0x18 bytes (sizeof)
|
|
||||||
|
|
||||||
typedef struct alignas(30) _CC_EXTERNAL_CACHE_INFO {
|
|
||||||
VOID (*Callback)(VOID* arg1, ULONGLONG arg2, ULONG arg3); // 0x0
|
|
||||||
struct _DIRTY_PAGE_STATISTICS DirtyPageStatistics; // 0x8
|
|
||||||
struct _LIST_ENTRY Links; // 0x20
|
|
||||||
} CC_EXTERNAL_CACHE_INFO, *PCC_EXTERNAL_CACHE_INFO; // 0x30 bytes (sizeof)
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
CcDeductDirtyPagesFromExternalCache(
|
|
||||||
IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext,
|
|
||||||
IN ULONG Pages
|
|
||||||
)
|
|
||||||
{
|
|
||||||
KIRQL OldIrql ={0};
|
|
||||||
ULONG PagesToDeduct = {0};
|
|
||||||
|
|
||||||
|
|
||||||
if (Pages > 0)
|
|
||||||
{
|
|
||||||
/* Acquire the master lock */
|
|
||||||
KeAcquireQueuedSpinLock(LockQueueMasterLock, &OldIrql);
|
|
||||||
|
|
||||||
/* Calculate the number of pages to deduct */
|
|
||||||
PagesToDeduct = min(Pages, ExternalCacheContext->DirtyPageStatistics.DirtyPages);
|
|
||||||
|
|
||||||
/* Deduct the pages from the external cache context */
|
|
||||||
ExternalCacheContext->DirtyPageStatistics.DirtyPages -= PagesToDeduct;
|
|
||||||
|
|
||||||
/* Deduct the pages from the global statistics */
|
|
||||||
CcTotalDirtyPages -= PagesToDeduct;
|
|
||||||
|
|
||||||
/* Release the master lock */
|
|
||||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if there are any deferred writes and post them if necessary */
|
|
||||||
if (!IsListEmpty(&CcDeferredWrites))
|
|
||||||
{
|
|
||||||
CcPostDeferredWrites();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
CcAddExternalCache(
|
|
||||||
IN PCC_EXTERNAL_CACHE_INFO CacheInfo
|
|
||||||
)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
KLOCK_QUEUE_HANDLE LockHandle ={0};
|
|
||||||
|
|
||||||
/* Acquire the external cache list lock */
|
|
||||||
KeAcquireInStackQueuedSpinLock(&CcExternalCacheListLock,&LockHandle);
|
|
||||||
|
|
||||||
/* Insert the new cache info at the end of the list */
|
|
||||||
InsertTailList(&CcExternalCacheList, &CacheInfo->Links);
|
|
||||||
|
|
||||||
/* Increment the number of external caches */
|
|
||||||
if (_InterlockedIncrement(&CcNumberOfExternalCaches) <= 0)
|
|
||||||
{
|
|
||||||
/* Overflow occurred, bug check */
|
|
||||||
KeBugCheckEx(CACHE_MANAGER,0,STATUS_INTEGER_OVERFLOW,0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release the external cache list lock */
|
|
||||||
KeReleaseInStackQueuedSpinLock(&LockHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
CcRemoveExternalCache(
|
|
||||||
IN PCC_EXTERNAL_CACHE_INFO CacheInfo
|
|
||||||
)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KLOCK_QUEUE_HANDLE LockHandle ={0};
|
|
||||||
|
|
||||||
/* Acquire the external cache list lock */
|
|
||||||
KeAcquireInStackQueuedSpinLock(&CcExternalCacheListLock,&LockHandle);
|
|
||||||
|
|
||||||
/* Remove the entry from the list */
|
|
||||||
RemoveTailList(&CacheInfo->Links.Blink);
|
|
||||||
|
|
||||||
/* Decrement the number of external caches */
|
|
||||||
if (_InterlockedDecrement(&CcNumberOfExternalCaches) < 0)
|
|
||||||
{
|
|
||||||
/* Underflow occurred, bug check */
|
|
||||||
KeBugCheckEx(CACHE_MANAGER,0,STATUS_INTEGER_OVERFLOW,0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release the external cache list lock */
|
|
||||||
KeReleaseInStackQueuedSpinLock(&LockHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*Exported */
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
CcAddDirtyPagesToExternalCache(
|
|
||||||
IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext,
|
|
||||||
IN ULONG Pages
|
|
||||||
)
|
|
||||||
{
|
|
||||||
KIRQL OldIrql ={0};
|
|
||||||
|
|
||||||
|
|
||||||
/* Only proceed if there are pages to add */
|
|
||||||
if (Pages == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Acquire the master lock */
|
|
||||||
KeAcquireQueuedSpinLock(LockQueueMasterLock, &OldIrql);
|
|
||||||
|
|
||||||
/* If this is the first dirty page, schedule a lazy write scan */
|
|
||||||
if (ExternalCacheContext->DirtyPageStatistics.DirtyPages == 0)
|
|
||||||
{
|
|
||||||
CcScheduleLazyWriteScan(FALSE, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Increment the dirty page count */
|
|
||||||
ExternalCacheContext->DirtyPageStatistics.DirtyPages += Pages;
|
|
||||||
|
|
||||||
/* Charge the dirty pages */
|
|
||||||
CcChargeDirtyPages(NULL, NULL, NULL, Pages);
|
|
||||||
|
|
||||||
/* Release the master lock */
|
|
||||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
CcUnregisterExternalCache(
|
|
||||||
IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
/* Remove the external cache from the list */
|
|
||||||
CcRemoveExternalCache(ExternalCacheContext);
|
|
||||||
|
|
||||||
/* Deduct any remaining dirty pages */
|
|
||||||
if (ExternalCacheContext->DirtyPageStatistics.DirtyPages > 0)
|
|
||||||
{
|
|
||||||
CcDeductDirtyPagesFromExternalCache(ExternalCacheContext,ExternalCacheContext->DirtyPageStatistics.DirtyPages);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free the external cache context */
|
|
||||||
ExFreePoolWithTag(ExternalCacheContext, CC_EXTERNAL_CACHE_INFO_TAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
CcRegisterExternalCache(
|
|
||||||
IN PCC_EXTERNAL_CACHE_CALLBACK Callback,
|
|
||||||
OUT PVOID *ExternalCacheContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
PCC_EXTERNAL_CACHE_INFO CacheInfo;
|
|
||||||
|
|
||||||
|
|
||||||
/* Ensure the Cache Manager is initialized */
|
|
||||||
if (!CcInitializationComplete)
|
|
||||||
{
|
|
||||||
KeBugCheckEx(CACHE_MANAGER,0,STATUS_UNSUCCESSFUL,0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate memory for the external cache info structure */
|
|
||||||
CacheInfo = ExAllocatePoolWithTag(NonPagedPool,
|
|
||||||
sizeof(CC_EXTERNAL_CACHE_INFO),
|
|
||||||
CC_EXTERNAL_CACHE_INFO_TAG);
|
|
||||||
if (CacheInfo == NULL)
|
|
||||||
{
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the cache info structure */
|
|
||||||
RtlZeroMemory(CacheInfo, sizeof(CC_EXTERNAL_CACHE_INFO));
|
|
||||||
CacheInfo->Callback = Callback;
|
|
||||||
|
|
||||||
/* Add the external cache to the list */
|
|
||||||
CcAddExternalCache(CacheInfo);
|
|
||||||
|
|
||||||
/* Return the cache info as the context */
|
|
||||||
*ExternalCacheContext = CacheInfo;
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
@@ -13,7 +13,341 @@
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
|
||||||
/*Internal Function*/
|
/* Move Typedef Later to cctypes.hpp */
|
||||||
|
typedef struct _WRITE_BEHIND_THROUGHPUT
|
||||||
|
{
|
||||||
|
ULONG PagesYetToWrite;
|
||||||
|
ULONG Throughput;
|
||||||
|
} WRITE_BEHIND_THROUGHPUT, *PWRITE_BEHIND_THROUGHPUT;
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
CcOkToAddWriteBehindThread(VOID)
|
||||||
|
{
|
||||||
|
ULONG ActiveExtraWriteBehindThreads = {0};
|
||||||
|
PWRITE_BEHIND_THROUGHPUT ThroughputStats = nullptr;
|
||||||
|
ULONG PagesYetToWrite = {0};
|
||||||
|
ULONG Throughput = {0};
|
||||||
|
ULONG PreviousThroughput = {0};
|
||||||
|
LONG ThroughputTrend = {0};
|
||||||
|
BOOLEAN Result = false;
|
||||||
|
|
||||||
|
ActiveExtraWriteBehindThreads = CcActiveExtraWriteBehindThreads;
|
||||||
|
ThroughputStats = CcThroughputStats;
|
||||||
|
PagesYetToWrite = CcPagesYetToWrite;
|
||||||
|
|
||||||
|
Throughput = ThroughputStats[ActiveExtraWriteBehindThreads].PagesYetToWrite;
|
||||||
|
PreviousThroughput = 0;
|
||||||
|
|
||||||
|
if (Throughput >= PagesYetToWrite)
|
||||||
|
{
|
||||||
|
Throughput -= PagesYetToWrite;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Throughput = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThroughputStats[ActiveExtraWriteBehindThreads].PagesYetToWrite = PagesYetToWrite;
|
||||||
|
Result = true;
|
||||||
|
|
||||||
|
if (ActiveExtraWriteBehindThreads > 0)
|
||||||
|
{
|
||||||
|
PreviousThroughput = ThroughputStats[ActiveExtraWriteBehindThreads - 1].Throughput;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThroughputStats[ActiveExtraWriteBehindThreads].Throughput = Throughput;
|
||||||
|
|
||||||
|
if (Throughput > 0)
|
||||||
|
{
|
||||||
|
ThroughputTrend = CcThroughputTrend;
|
||||||
|
|
||||||
|
if (Throughput < PreviousThroughput)
|
||||||
|
{
|
||||||
|
if (ThroughputTrend > 0)
|
||||||
|
ThroughputTrend = 0;
|
||||||
|
ThroughputTrend--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ThroughputTrend < 0)
|
||||||
|
ThroughputTrend = 0;
|
||||||
|
ThroughputTrend++;
|
||||||
|
}
|
||||||
|
|
||||||
|
CcThroughputTrend = ThroughputTrend;
|
||||||
|
|
||||||
|
if (ThroughputTrend == 3)
|
||||||
|
{
|
||||||
|
CcThroughputTrend = 0;
|
||||||
|
Result = true;
|
||||||
|
|
||||||
|
if (ActiveExtraWriteBehindThreads < CcMaxExtraWriteBehindThreads)
|
||||||
|
{
|
||||||
|
ThroughputStats[ActiveExtraWriteBehindThreads + 1].Throughput = 0;
|
||||||
|
ThroughputStats[ActiveExtraWriteBehindThreads + 1].PagesYetToWrite = PagesYetToWrite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ThroughputTrend == -3)
|
||||||
|
{
|
||||||
|
CcThroughputTrend = 0;
|
||||||
|
Result = true;
|
||||||
|
|
||||||
|
if (ActiveExtraWriteBehindThreads > 0)
|
||||||
|
{
|
||||||
|
ThroughputStats[ActiveExtraWriteBehindThreads - 1].Throughput = 0;
|
||||||
|
ThroughputStats[ActiveExtraWriteBehindThreads - 1].PagesYetToWrite = PagesYetToWrite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcSetLazyWriteScanQueued(
|
||||||
|
IN ULONG FlushReason,
|
||||||
|
IN BOOLEAN QueuedState)
|
||||||
|
{
|
||||||
|
switch (FlushReason)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
LazyWriter.PendingLowMemoryScan = QueuedState;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
LazyWriter.PendingPowerScan = QueuedState;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
LazyWriter.PendingPeriodicScan = QueuedState;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
LazyWriter.PendingTeardownScan = QueuedState;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
LazyWriter.PendingCoalescingFlushScan = QueuedState;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
VECTORCALL
|
||||||
|
CcIsLazyWriteScanQueued(
|
||||||
|
_In_ ULONG ReasonForFlush
|
||||||
|
)
|
||||||
|
{
|
||||||
|
switch (ReasonForFlush)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 16:
|
||||||
|
if (LazyWriter.PendingLowMemoryScan ||
|
||||||
|
LazyWriter.PendingPowerScan ||
|
||||||
|
LazyWriter.PendingCoalescingFlushScan)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (LazyWriter.PendingPeriodicScan ||
|
||||||
|
LazyWriter.PendingTeardownScan)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
return (BOOLEAN)LazyWriter.PendingTeardownScan;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcQueueLazyWriteScanThread(
|
||||||
|
_In_ PVOID NULL_PARAM
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UNREFERENCED_PARAMETER(NULL_PARAM);
|
||||||
|
|
||||||
|
ULONG Reason = 0;
|
||||||
|
BOOLEAN NeedAdjustment;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
PWORK_QUEUE_ENTRY WorkQueueEntry;
|
||||||
|
PVOID WaitObjects[5];
|
||||||
|
|
||||||
|
WaitObjects[0] = &CcLowMemoryEvent;
|
||||||
|
WaitObjects[1] = &CcPowerEvent;
|
||||||
|
WaitObjects[2] = &CcPeriodicEvent;
|
||||||
|
WaitObjects[3] = &CcWaitingForTeardownEvent;
|
||||||
|
WaitObjects[4] = &CcCoalescingFlushEvent;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
NeedAdjustment = false;
|
||||||
|
|
||||||
|
Status = KeWaitForMultipleObjects(
|
||||||
|
5,
|
||||||
|
WaitObjects,
|
||||||
|
WaitAny,
|
||||||
|
WrFreePage,
|
||||||
|
KernelMode,
|
||||||
|
false,
|
||||||
|
NULL,
|
||||||
|
WaitBlockArray);
|
||||||
|
|
||||||
|
switch (Status)
|
||||||
|
{
|
||||||
|
case STATUS_WAIT_0:
|
||||||
|
Reason = 1;
|
||||||
|
NeedAdjustment = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATUS_WAIT_1:
|
||||||
|
Reason = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATUS_WAIT_2:
|
||||||
|
Reason = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATUS_WAIT_3:
|
||||||
|
Reason = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATUS_WAIT_4:
|
||||||
|
Reason = 16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CcNumberOfExternalCaches && !IsListEmpty(&CcExternalCacheList))
|
||||||
|
{
|
||||||
|
CcNotifyExternalCaches(Reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
CcAdjustWriteBehindThreadPoolIfNeeded(NeedAdjustment);
|
||||||
|
|
||||||
|
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
||||||
|
|
||||||
|
if (CcIsLazyWriteScanQueued(Reason))
|
||||||
|
{
|
||||||
|
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CcSetLazyWriteScanQueued(Reason, true);
|
||||||
|
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(CcAllocateWorkQueueEntry(&WorkQueueEntry)))
|
||||||
|
{
|
||||||
|
KSPIN_LOCK_QUEUE_NUMBER queueNumber = LockQueueMasterLock;
|
||||||
|
SpinLockGuard guard(queueNumber);
|
||||||
|
LazyWriter.ScanActive = false;
|
||||||
|
CcSetLazyWriteScanQueued(Reason, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WorkQueueEntry->Function = 3;
|
||||||
|
WorkQueueEntry->Parameters.Notification.Reason = Reason;
|
||||||
|
|
||||||
|
CcPostWorkQueue(
|
||||||
|
WorkQueueEntry,
|
||||||
|
(Reason != 8) ? &CcRegularWorkQueue : &CcFastTeardownWorkQueue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcRescheduleLazyWriteScan( IN PLARGE_INTEGER NextScanDelay)
|
||||||
|
{
|
||||||
|
UNREFERENCED_PARAMETER(NextScanDelay);
|
||||||
|
LARGE_INTEGER Delay = {0};
|
||||||
|
|
||||||
|
if (LazyWriter.ScanActive)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (NextScanDelay && NextScanDelay->QuadPart != 0x7FFFFFFFFFFFFFFF && NextScanDelay->QuadPart != 0)
|
||||||
|
{
|
||||||
|
Delay.QuadPart = NextScanDelay->QuadPart * KeMaximumIncrement;
|
||||||
|
if (Delay.QuadPart > 160000000)
|
||||||
|
Delay.QuadPart = 160000000;
|
||||||
|
if(Delay.QuadPart < 10000000 )
|
||||||
|
Delay = CcIdleDelay;
|
||||||
|
}
|
||||||
|
KeSetCoalescableTimer(&LazyWriter.ScanTimer,CcIdleDelay,0,1000,&LazyWriter.ScanDpc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CcScheduleLazyWriteScan(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcComputeNextScanTime(PLARGE_INTEGER OldestTICKTIMEForMetadata, PLARGE_INTEGER NextScanDelay)
|
||||||
|
{
|
||||||
|
NextScanDelay- = 0;
|
||||||
|
LARGE_INTEGER CurrentTickCount = {0};
|
||||||
|
LARGE_INTEGER TICKTIME = {0};
|
||||||
|
LARGE_INTEGER WRITE_DELAY = {0};
|
||||||
|
LARGE_INTEGER TICK_ELAPSED = {0};
|
||||||
|
|
||||||
|
if (CcMaxWriteBehindThreads < CcNumberofWorkerThreads)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
KeQueryTickCount(&CurrentTickCount);
|
||||||
|
|
||||||
|
// Calculate Tick Time based on the current tick count and the oldest scan time
|
||||||
|
TICKTIME.QuadPart = 160000000 / KeMaximumIncrement;
|
||||||
|
WRITE_DELAY.QuadPart = (OldestTICKTIMEForMetadata->QuadPart - CurrentTickCount.QuadPart) / KeMaximumIncrement;
|
||||||
|
|
||||||
|
// Increment the consecutive workless lazy scan count
|
||||||
|
++CcConsecutiveWorklessLazyScanCount;
|
||||||
|
|
||||||
|
// Check if the oldest scan time is not the maximum and the calculated delay is greater than the current tick
|
||||||
|
// count
|
||||||
|
if (OldestTICKTIMEForMetadata->QuadPart != -1 && OldestTICKTIMEForMetadata->QuadPart != 0x7FFFFFFFFFFFFFFF &&
|
||||||
|
(TICKTIME.QuadPart + OldestTICKTIMEForMetadata->QuadPart) > CurrentTickCount.QuadPart)
|
||||||
|
{
|
||||||
|
|
||||||
|
TICK_ELAPSED.QuadPart = OldestTICKTIMEForMetadata->QuadPart - CurrentTickCount.QuadPart;
|
||||||
|
|
||||||
|
// Calculate the next scan delay
|
||||||
|
NextScanDelay->QuadPart = TICKTIME.QuadPart + TICK_ELAPSED.QuadPart;
|
||||||
|
|
||||||
|
// Reset the consecutive workless lazy scan count
|
||||||
|
CcConsecutiveWorklessLazyScanCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the number of consecutive workless lazy scans has reached the maximum
|
||||||
|
if (CcConsecutiveWorklessLazyScanCount >= CcMaxWorklessLazywriteScans)
|
||||||
|
{
|
||||||
|
// Disable the scan by setting the next scan delay to the maximum values
|
||||||
|
NextScanDelay->QuadPart = -1;
|
||||||
|
CcConsecutiveWorklessLazyScanCount = 0;
|
||||||
|
NextScanDelay->HighPart = 0x7FFFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
VECTORCALL
|
VECTORCALL
|
||||||
@@ -900,10 +1234,10 @@ NTAPI CcLazyWriteScan()
|
|||||||
|
|
||||||
CcPostWorkQueue(workItem, &CcRegularWorkQueue);
|
CcPostWorkQueue(workItem, &CcRegularWorkQueue);
|
||||||
}
|
}
|
||||||
// CcComputeNextScanTime(&OldestLWSTimeStamp, &NextScanDelay); Enable When Threadpool is finished
|
CcComputeNextScanTime(&OldestLWSTimeStamp, &NextScanDelay);
|
||||||
|
|
||||||
// if (!IsListEmpty(&PostWorkList) || !IsListEmpty(&CcDeferredWrites) || MmRegistryStatus.ProductStatus ||NextScanDelay.QuadPart != 0x7FFFFFFFFFFFFFFF))
|
if (!IsListEmpty(&PostWorkList) || !IsListEmpty(&CcDeferredWrites) || MmRegistryStatus.ProductStatus ||
|
||||||
if (!IsListEmpty(&PostWorkList) || !IsListEmpty(&CcDeferredWrites) || MmRegistryStatus.ProductStatus))
|
NextScanDelay.QuadPart != 0x7FFFFFFFFFFFFFFF))
|
||||||
{
|
{
|
||||||
/* Schedule a lazy write scan */
|
/* Schedule a lazy write scan */
|
||||||
CcRescheduleLazyWriteScan(&NextScanDelay);
|
CcRescheduleLazyWriteScan(&NextScanDelay);
|
||||||
@@ -930,44 +1264,7 @@ NTAPI CcLazyWriteScan()
|
|||||||
CcScheduleLazyWriteScan(FALSE);
|
CcScheduleLazyWriteScan(FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NTSTATUS CcWaitForCurrentLazyWriterActivity()
|
|
||||||
{
|
|
||||||
NTSTATUS result;
|
|
||||||
PWORK_QUEUE_ENTRY WorkQueueEntry = nullptr;
|
|
||||||
KEVENT Event = {0};
|
|
||||||
KIRQL irql = {0};
|
|
||||||
|
|
||||||
result = CcAllocateWorkQueueEntry(&WorkQueueEntry);
|
|
||||||
if (NT_SUCCESS(result))
|
|
||||||
{
|
|
||||||
WorkQueueEntry->Function = SetDone;
|
|
||||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
||||||
WorkQueueEntry->Parameters.Notification.Reason = (ULONG_PTR)&Event;
|
|
||||||
|
|
||||||
if ((PerfGlobalGroupMask.Masks[4] & 0x20000) != 0)
|
|
||||||
CcPerfLogWorkItemEnqueue(&CcPostTickWorkQueue, WorkQueueEntry, 0, 0);
|
|
||||||
|
|
||||||
irql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
|
||||||
|
|
||||||
WorkQueueEntry->WorkQueueLinks.Flink = &CcPostTickWorkQueue;
|
|
||||||
WorkQueueEntry->WorkQueueLinks.Blink = CcPostTickWorkQueue.Blink;
|
|
||||||
CcPostTickWorkQueue.Blink->Flink = &WorkQueueEntry->WorkQueueLinks;
|
|
||||||
CcPostTickWorkQueue.Blink = &WorkQueueEntry->WorkQueueLinks;
|
|
||||||
|
|
||||||
LazyWriter.OtherWork = 1;
|
|
||||||
_InterlockedIncrement(&CcPostTickWorkItemCount);
|
|
||||||
|
|
||||||
CcScheduleLazyWriteScan(1, 1);
|
|
||||||
|
|
||||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, irql);
|
|
||||||
|
|
||||||
result = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
||||||
|
|
||||||
_InterlockedDecrement(&CcPostTickWorkItemCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
VOID VECTORCALL CcReEngageWorkerThreads(
|
VOID VECTORCALL CcReEngageWorkerThreads(
|
||||||
ULONG NormalThreadsToActivate,
|
ULONG NormalThreadsToActivate,
|
||||||
ULONG ExtraWriteBehindThreadsToActivate
|
ULONG ExtraWriteBehindThreadsToActivate
|
||||||
@@ -1036,6 +1333,62 @@ VOID VECTORCALL CcReEngageWorkerThreads(
|
|||||||
ExQueueWorkItem(currentExtraThreadEntry, CriticalWorkQueue);
|
ExQueueWorkItem(currentExtraThreadEntry, CriticalWorkQueue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcAdjustWriteBehindThreadPool(
|
||||||
|
IN BOOLEAN IsThreadPriorityLow)
|
||||||
|
{
|
||||||
|
if (IsThreadPriorityLow)
|
||||||
|
{
|
||||||
|
CcMaxNumberOfWriteBehindThreads = 1;
|
||||||
|
if (CcAddExtraWriteBehindThreads)
|
||||||
|
{
|
||||||
|
CcAddExtraWriteBehindThreads = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CcMaxNumberOfWriteBehindThreads = (ULONG)-1;
|
||||||
|
if (!IsListEmpty(&CcRegularWorkQueue) && !CcQueueThrottle)
|
||||||
|
{
|
||||||
|
CcReEngageWorkerThreads(CcNumberofWorkerThreads, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcAdjustWriteBehindThreadPoolIfNeeded(
|
||||||
|
IN BOOLEAN NeedAdjustment)
|
||||||
|
{
|
||||||
|
BOOLEAN NeedBoost = false;
|
||||||
|
KSPIN_LOCK_QUEUE_NUMBER queueNumber = LockQueueMasterLock;
|
||||||
|
SpinLockGuard guard(queueNumber);
|
||||||
|
|
||||||
|
if (CcPostTickWorkItemCount != 0)
|
||||||
|
{
|
||||||
|
if (CcIsWriteBehindThreadpoolAtLowPriority())
|
||||||
|
{
|
||||||
|
CcAdjustWriteBehindThreadPool(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ auto DirtyPages = (CcTotalDirtyPages + CcPagesWrittenLastTime);
|
||||||
|
if (DirtyPages > 0x2000 || NeedAdjustment)
|
||||||
|
{
|
||||||
|
if (CcIsWriteBehindThreadpoolAtLowPriority())
|
||||||
|
{
|
||||||
|
CcAdjustWriteBehindThreadPool(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!CcExecutingWriteBehindWorkItems && IsListEmpty(&CcRegularWorkQueue))
|
||||||
|
{
|
||||||
|
CcAdjustWriteBehindThreadPool(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
CcWorkerThread(PVOID Parameter)
|
CcWorkerThread(PVOID Parameter)
|
||||||
@@ -1066,7 +1419,7 @@ CcWorkerThread(PVOID Parameter)
|
|||||||
{
|
{
|
||||||
CcQueueThrottle = FALSE;
|
CcQueueThrottle = FALSE;
|
||||||
DropThrottle = FALSE;
|
DropThrottle = FALSE;
|
||||||
// CcReEngageWorkerThreads(CcThreadsActiveBeforeThrottle, CcExtraThreadsActiveBeforeThrottle); Enable When Threadpool is ready
|
CcReEngageWorkerThreads(CcThreadsActiveBeforeThrottle, CcExtraThreadsActiveBeforeThrottle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IoStatus.Information == 0x8A5E)
|
if (IoStatus.Information == 0x8A5E)
|
||||||
|
@@ -144,8 +144,6 @@ typedef ULONGLONG *PULONGLONG;
|
|||||||
//
|
//
|
||||||
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;
|
||||||
|
|
||||||
|
@@ -18,7 +18,6 @@ Abstract:
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ntdef.h>
|
#include <ntdef.h>
|
||||||
#include <ntstatus.h>
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Memory operations.
|
// Memory operations.
|
||||||
@@ -28,47 +27,6 @@ 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 (
|
||||||
|
@@ -22,14 +22,12 @@ 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_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL)
|
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL)
|
||||||
#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)
|
||||||
|
@@ -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/LIB/**.c", "BOOT/ENVIRON/APP/BOOTMGR/**.c" })
|
files({ "BOOT/ENVIRON/INC/**.h", "BOOT/ENVIRON/**.c" })
|
||||||
|
|
||||||
filter("toolset:clang")
|
filter("toolset:clang")
|
||||||
buildoptions({ "-fshort-wchar", "-fno-strict-aliasing", "-fno-stack-protector", "-fno-stack-check", "-mno-red-zone" })
|
buildoptions({ "-fshort-wchar", "-fno-strict-aliasing", "-fno-stack-protector", "-fno-stack-check", "-mno-red-zone" })
|
||||||
|
Reference in New Issue
Block a user