Compare commits

...

3 Commits

Author SHA1 Message Date
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
15 changed files with 1080 additions and 190 deletions

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

@ -28,12 +28,11 @@ Routine Description:
Arguments: Arguments:
DataStore - pointer to memory to put the data store handle in. DataStore - Pointer to a HANDLE that recieves the data store handle.
Return Value: Return Value:
STATUS_SUCCESS if successful, STATUS_SUCCESS.
Other NTSTATUS value on failure.
--*/ --*/

View File

@ -106,25 +106,33 @@ 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;
/* Memory descriptor caching attributes */ //
// Memory descriptor caching attributes.
//
#define MEMORY_ATTRIBUTE_UC 0x0000000000000001 #define MEMORY_ATTRIBUTE_UC 0x0000000000000001
#define MEMORY_ATTRIBUTE_WC 0x0000000000000002 #define MEMORY_ATTRIBUTE_WC 0x0000000000000002
#define MEMORY_ATTRIBUTE_WT 0x0000000000000004 #define MEMORY_ATTRIBUTE_WT 0x0000000000000004
#define MEMORY_ATTRIBUTE_WB 0x0000000000000008 #define MEMORY_ATTRIBUTE_WB 0x0000000000000008
#define MEMORY_ATTRIBUTE_UCE 0x0000000000000010 #define MEMORY_ATTRIBUTE_UCE 0x0000000000000010
/* Memory descriptor protection attributes */ //
// Memory descriptor protection attributes.
//
#define MEMORY_ATTRIBUTE_WP 0x000000000000100 #define MEMORY_ATTRIBUTE_WP 0x000000000000100
#define MEMORY_ATTRIBUTE_RP 0x000000000000200 #define MEMORY_ATTRIBUTE_RP 0x000000000000200
#define MEMORY_ATTRIBUTE_XP 0x000000000000400 #define MEMORY_ATTRIBUTE_XP 0x000000000000400
/* Memory descriptor location attributes */ //
// Memory descriptor location attributes.
//
#define MEMORY_ATTRIBUTE_BELOW_1MIB 0x80000 #define MEMORY_ATTRIBUTE_BELOW_1MIB 0x80000
/* Memory descriptor runtime mapping attributes */ //
// Memory descriptor runtime mapping attributes.
//
#define MEMORY_ATTRIBUTE_RUNTIME 0x1000000 #define MEMORY_ATTRIBUTE_RUNTIME 0x1000000
typedef enum { typedef enum {
@ -146,11 +154,12 @@ typedef enum {
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;
} MEMORY_DESCRIPTOR, *PMEMORY_DESCRIPTOR; } MEMORY_DESCRIPTOR, *PMEMORY_DESCRIPTOR;
typedef enum { typedef enum {

View File

@ -18,12 +18,27 @@ Abstract:
#include "bootlib.h" #include "bootlib.h"
#define MDL_OPERATION_FLAGS_TRUNCATE 0x02
NTSTATUS NTSTATUS
MmFwGetMemoryMap ( MmFwGetMemoryMap (
IN OUT PMEMORY_DESCRIPTOR_LIST Mdl, IN OUT PMEMORY_DESCRIPTOR_LIST Mdl,
IN ULONG Flags 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 NTSTATUS
MmMdAddDescriptorToList ( MmMdAddDescriptorToList (
IN PMEMORY_DESCRIPTOR_LIST Mdl, IN PMEMORY_DESCRIPTOR_LIST Mdl,
@ -49,8 +64,8 @@ MmMdFreeList (
PMEMORY_DESCRIPTOR PMEMORY_DESCRIPTOR
MmMdInitDescriptor ( MmMdInitDescriptor (
IN ULONGLONG BasePage, IN ULONGLONG FirstPage,
IN ULONGLONG MappedBasePage, IN ULONGLONG MappedFirstPage,
IN ULONGLONG PageCount, IN ULONGLONG PageCount,
IN ULONG Attributes, IN ULONG Attributes,
IN MEMORY_TYPE Type IN MEMORY_TYPE Type

View File

@ -32,7 +32,7 @@ Routine Description:
Arguments: Arguments:
String - string to print. String.
Return Value: Return Value:
@ -58,9 +58,9 @@ Routine Description:
Arguments: Arguments:
Format - format string handled by vswprintf(). Format - Format string handled by vswprintf().
... - arguments. ... - Arguments.
Return Value: Return Value:

View File

@ -38,7 +38,7 @@ Arguments:
Stage - 0 or 1. Stage - 0 or 1.
FirmwareData - firmware data structure to use for initialization. FirmwareData - Pointer to BOOT_FIRMWARE_DATA.
Return Value: Return Value:

View File

@ -41,15 +41,15 @@ Routine Description:
Arguments: Arguments:
Destination - the path to append to. Destination - Path to append Source to.
BufferSize - the maximum number of bytes to append. BufferSize - Maximum number of bytes to append to Destination.
Source - the source path to append to Destination. Source - Source path to append to Destination.
SourceSize - the size of Source, in bytes. SourceSize - Size of Source, in bytes.
BufferUsed - pointer to a ULONG to store the number of bytes appended in. BufferUsed - Pointer to a ULONG recieving the number of bytes appended in.
Return Value: Return Value:
@ -138,27 +138,21 @@ Routine Description:
Arguments: Arguments:
DevicePath - EFI device path to search. DevicePath - EFI_DEVICE_PATH *.
Return Value: Return Value:
Pointer to the last device path node. EFI_DEVICE_PATH *.
--*/ --*/
{ {
EFI_DEVICE_PATH *Node; EFI_DEVICE_PATH *Node;
//
// Check if the current node is the end of the path.
//
if (IsDevicePathEndType(DevicePath)) { if (IsDevicePathEndType(DevicePath)) {
return DevicePath; return DevicePath;
} }
//
// Find the last non-filepath node.
//
Node = NextDevicePathNode(DevicePath); Node = NextDevicePathNode(DevicePath);
while (!IsDevicePathEndType(Node)) { while (!IsDevicePathEndType(Node)) {
if (DevicePathType(Node) == MEDIA_DEVICE_PATH && DevicePathSubType(Node) == MEDIA_FILEPATH_DP) { if (DevicePathType(Node) == MEDIA_DEVICE_PATH && DevicePathSubType(Node) == MEDIA_FILEPATH_DP) {
@ -183,19 +177,19 @@ EfiInitTranslateDevicePath (
Routine Description: Routine Description:
Translates an EFI device path into boot device format. Translates an EFI_DEVICE_PATH into a BOOT_DEVICE.
Arguments: Arguments:
EfiDevicePath - The EFI device path to be translated. EfiDevicePath - Path to be translated.
BootDevice - Pointer to the destination device structure. BootDevice - Pointer to a buffer that recieves the device.
BufferSize - The amount of available space in the buffer. BufferSize - Amount of available bytes in the buffer.
Return Value: Return Value:
STATUS_SUCCESS if successful, STATUS_SUCCESS if successful.
STATUS_INVALID_PARAMETER if the buffer is too small. STATUS_INVALID_PARAMETER if the buffer is too small.
STATUS_UNSUCCESSFUL if the path could not be translated. STATUS_UNSUCCESSFUL if the path could not be translated.
@ -207,17 +201,11 @@ Return Value:
HARDDRIVE_DEVICE_PATH *HarddriveNode; HARDDRIVE_DEVICE_PATH *HarddriveNode;
PBOOT_BLOCK_IDENTIFIER BlockDevice; PBOOT_BLOCK_IDENTIFIER BlockDevice;
//
// Check for available buffer space.
//
if (BufferSize < sizeof(BOOT_DEVICE)) { if (BufferSize < sizeof(BOOT_DEVICE)) {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
BootDevice->Size = sizeof(BOOT_DEVICE); BootDevice->Size = sizeof(BOOT_DEVICE);
//
// Memory mapped device paths are treated as ramdisks.
//
if (DevicePathType(EfiDevicePath) == HARDWARE_DEVICE_PATH && DevicePathSubType(EfiDevicePath) == HW_MEMMAP_DP) { if (DevicePathType(EfiDevicePath) == HARDWARE_DEVICE_PATH && DevicePathSubType(EfiDevicePath) == HW_MEMMAP_DP) {
MemmapNode = (MEMMAP_DEVICE_PATH *)EfiDevicePath; MemmapNode = (MEMMAP_DEVICE_PATH *)EfiDevicePath;
BlockDevice = &BootDevice->Block; BlockDevice = &BootDevice->Block;
@ -230,7 +218,6 @@ Return Value:
} }
// //
// Get the device node, the device the application was loaded from.
// TODO: Only media devices and ramdisks are currently supported. // TODO: Only media devices and ramdisks are currently supported.
// //
DeviceNode = EfiInitpGetDeviceNode(EfiDevicePath); DeviceNode = EfiInitpGetDeviceNode(EfiDevicePath);
@ -238,15 +225,12 @@ Return Value:
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
//
// Check device node subtype.
//
switch (DevicePathSubType(DeviceNode)) { switch (DevicePathSubType(DeviceNode)) {
case MEDIA_HARDDRIVE_DP: case MEDIA_HARDDRIVE_DP:
HarddriveNode = (HARDDRIVE_DEVICE_PATH *)DeviceNode; HarddriveNode = (HARDDRIVE_DEVICE_PATH *)DeviceNode;
// //
// Use correct block device and partition format. // MBR disks still use the old partition struct.
// //
if (HarddriveNode->SignatureType != SIGNATURE_TYPE_MBR) { if (HarddriveNode->SignatureType != SIGNATURE_TYPE_MBR) {
BlockDevice = &BootDevice->PartitionEx.Parent; BlockDevice = &BootDevice->PartitionEx.Parent;
@ -257,9 +241,6 @@ Return Value:
} }
BlockDevice->Type = BOOT_BLOCK_DEVICE_TYPE_HARDDRIVE; BlockDevice->Type = BOOT_BLOCK_DEVICE_TYPE_HARDDRIVE;
//
// Initialize partition based on the drive's partitioning system.
//
switch (HarddriveNode->SignatureType) { switch (HarddriveNode->SignatureType) {
case SIGNATURE_TYPE_MBR: case SIGNATURE_TYPE_MBR:
BlockDevice->Harddrive.PartitionType = BOOT_HARDDRIVE_PARTITION_TYPE_MBR; BlockDevice->Harddrive.PartitionType = BOOT_HARDDRIVE_PARTITION_TYPE_MBR;
@ -301,22 +282,23 @@ EfiInitpConvertEfiDevicePath (
Routine Description: Routine Description:
Converts an EFI device path into BCD format. Converts an EFI device path into option format.
Arguments: Arguments:
EfiDevicePath - The EFI device path to be converted. EfiDevicePath - Path to be converted.
OptionType - The data type to be assigned to option. OptionType - The data type to be assigned to Option->Type.
Option - Pointer to the destination option structure. Option - Pointer to a buffer that recieves the option.
BufferSize - The amount of available space in the buffer. BufferSize - The amount of available bytes in the buffer.
Return Value: Return Value:
STATUS_SUCCESS if successful. STATUS_SUCCESS if successful.
other NTSTATUS value if failure occurs. STATUS_INVALID_PARAMETER if the buffer is too small.
Any status code returned by EfiInitTranslateDevicePath().
--*/ --*/
@ -324,16 +306,10 @@ Return Value:
NTSTATUS Status; NTSTATUS Status;
PBCDE_DEVICE DeviceElement; PBCDE_DEVICE DeviceElement;
//
// Check for available buffer space.
//
if (BufferSize < sizeof(BOOT_APPLICATION_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device)) { if (BufferSize < sizeof(BOOT_APPLICATION_OPTION) + FIELD_OFFSET(BCDE_DEVICE, Device)) {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
//
// Translate device path.
//
RtlZeroMemory(Option, sizeof(BOOT_APPLICATION_OPTION)); RtlZeroMemory(Option, sizeof(BOOT_APPLICATION_OPTION));
DeviceElement = (PBCDE_DEVICE)((PUCHAR)Option + sizeof(BOOT_APPLICATION_OPTION)); DeviceElement = (PBCDE_DEVICE)((PUCHAR)Option + sizeof(BOOT_APPLICATION_OPTION));
Status = EfiInitTranslateDevicePath( Status = EfiInitTranslateDevicePath(
@ -345,9 +321,6 @@ Return Value:
return Status; return Status;
} }
//
// Set up option structure.
//
Option->Type = OptionType; Option->Type = OptionType;
Option->DataOffset = sizeof(BOOT_APPLICATION_OPTION); Option->DataOffset = sizeof(BOOT_APPLICATION_OPTION);
Option->DataSize = FIELD_OFFSET(BCDE_DEVICE, Device) + DeviceElement->Device.Size; Option->DataSize = FIELD_OFFSET(BCDE_DEVICE, Device) + DeviceElement->Device.Size;
@ -367,22 +340,22 @@ EfiInitpConvertEfiFilePath (
Routine Description: Routine Description:
Converts an EFI file path into BCD format. Converts an EFI file path into option format.
Arguments: Arguments:
EfiFilePath - The EFI file path to be converted. EfiFilePath - Path to be converted.
OptionType - The data type to be assigned to option. OptionType - The data type to be assigned to Option->Type.
Option - Pointer to the destination option structure. Option - Pointer to a buffer that recieves the option.
BufferSize - The amount of available space in the buffer. BufferSize - The amount of available bytes in the buffer.
Return Value: Return Value:
STATUS_SUCCESS if successful. STATUS_SUCCESS if successful.
other NTSTATUS value if failure occurs. STATUS_INVALID_PARAMETER if the buffer is too small.
--*/ --*/
@ -392,22 +365,16 @@ Return Value:
PWCHAR PathStart, Position; PWCHAR PathStart, Position;
ULONG BufferRemaining, Length, Appended; ULONG BufferRemaining, Length, Appended;
//
// Check for available buffer space.
//
if (BufferSize < sizeof(BOOT_APPLICATION_OPTION)) { if (BufferSize < sizeof(BOOT_APPLICATION_OPTION)) {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
//
// Set up option structure.
//
RtlZeroMemory(Option, sizeof(BOOT_APPLICATION_OPTION)); RtlZeroMemory(Option, sizeof(BOOT_APPLICATION_OPTION));
Option->Type = OptionType; Option->Type = OptionType;
Option->DataOffset = sizeof(BOOT_APPLICATION_OPTION); Option->DataOffset = sizeof(BOOT_APPLICATION_OPTION);
// //
// Add to the path one file path node at a time. // Loop through nodes and add one at a time.
// //
Option->DataSize = 0; Option->DataSize = 0;
BufferRemaining = BufferSize - sizeof(BOOT_APPLICATION_OPTION); BufferRemaining = BufferSize - sizeof(BOOT_APPLICATION_OPTION);
@ -415,21 +382,33 @@ Return Value:
PathStart = (PWCHAR)((PUCHAR)Option + Option->DataOffset); PathStart = (PWCHAR)((PUCHAR)Option + Option->DataOffset);
Position = PathStart; Position = PathStart;
while (!IsDevicePathEndType(Node)) { while (!IsDevicePathEndType(Node)) {
//
// Ignore non-filepath nodes.
//
if (DevicePathType(Node) != MEDIA_DEVICE_PATH || DevicePathSubType(Node) != MEDIA_FILEPATH_DP) { if (DevicePathType(Node) != MEDIA_DEVICE_PATH || DevicePathSubType(Node) != MEDIA_FILEPATH_DP) {
Node = NextDevicePathNode(Node); Node = NextDevicePathNode(Node);
continue; continue;
} }
//
// Find the length of this path.
//
Status = RtlULongSub(DevicePathNodeLength(Node), FIELD_OFFSET(FILEPATH_DEVICE_PATH, PathName), &Length); Status = RtlULongSub(DevicePathNodeLength(Node), FIELD_OFFSET(FILEPATH_DEVICE_PATH, PathName), &Length);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
return Status; return Status;
} }
//
// Append this path to the path string.
//
Status = EfiInitpAppendPathString(Position, BufferRemaining, &((FILEPATH_DEVICE_PATH *)Node)->PathName[0], Length, &Appended); Status = EfiInitpAppendPathString(Position, BufferRemaining, &((FILEPATH_DEVICE_PATH *)Node)->PathName[0], Length, &Appended);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
return Status; return Status;
} }
//
// Update counters & position.
//
Option->DataSize += Appended; Option->DataSize += Appended;
BufferRemaining -= Appended; BufferRemaining -= Appended;
Position = (PWCHAR)((PUCHAR)Position + Appended); Position = (PWCHAR)((PUCHAR)Position + Appended);
@ -437,7 +416,7 @@ Return Value:
} }
// //
// Terminate path string. // NULL-terminate path string.
// //
if (BufferRemaining < sizeof(UNICODE_NULL)) { if (BufferRemaining < sizeof(UNICODE_NULL)) {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
@ -446,7 +425,7 @@ Return Value:
Option->DataSize += sizeof(UNICODE_NULL); Option->DataSize += sizeof(UNICODE_NULL);
// //
// The path option is invalid if the path is NULL. // The option is invalid if the path is empty.
// //
if (Position == PathStart) { if (Position == PathStart) {
Option->IsInvalid = TRUE; Option->IsInvalid = TRUE;
@ -473,29 +452,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.
EfiDevicePath - The device path for the application. EfiDevicePath - The application's device path.
EfiFilePath - 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.
Flags - Unused. Flags - Unused.
BufferUsed - Returns the amount of buffer space used by the routine. BufferUsed - Pointer to a ULONG that recieves the buffer space used by this routine.
BootDevice - Returns a pointer to the device the application was loaded from. BootDevice - Pointer to a PBOOT_DEVICE that recieves the device the application was loaded from.
Return Value: Return Value:
@ -513,8 +492,6 @@ Return Value:
PBCDE_DEVICE BootDeviceElement; PBCDE_DEVICE BootDeviceElement;
(VOID)SystemTable; (VOID)SystemTable;
(VOID)EfiDevicePath;
(VOID)EfiFilePath;
(VOID)Flags; (VOID)Flags;
*BufferUsed = 0; *BufferUsed = 0;
@ -522,23 +499,17 @@ Return Value:
OptionsSize = 0; OptionsSize = 0;
BcdIdentifierSet = FALSE; BcdIdentifierSet = FALSE;
//
// Require enough space for the application entry.
//
BufferRemaining = BufferSize; BufferRemaining = BufferSize;
if (BufferRemaining < sizeof(BOOT_INPUT_APPLICATION_ENTRY)) { if (BufferRemaining < sizeof(BOOT_INPUT_APPLICATION_ENTRY)) {
return; return;
} }
//
// Set up application entry structure.
//
RtlZeroMemory(Entry, sizeof(BOOT_INPUT_APPLICATION_ENTRY)); RtlZeroMemory(Entry, sizeof(BOOT_INPUT_APPLICATION_ENTRY));
Entry->Signature = BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE; Entry->Signature = BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE;
BufferRemaining -= FIELD_OFFSET(BOOT_INPUT_APPLICATION_ENTRY, Options); 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) {
@ -546,7 +517,7 @@ Return Value:
} }
// //
// Parse BCD GUID if present. // Parse BCD GUID option 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)));
@ -576,7 +547,7 @@ Return Value:
// //
// Convert the EFI file path into a boot file path option. // Convert the EFI file path into a boot file path option.
// TODO: UDP/PXE boot is not supported. // TODO: UDP/PXE are not supported.
// //
PrevOption = Option; PrevOption = Option;
Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)&Entry->Options + OptionsSize); Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)&Entry->Options + OptionsSize);
@ -590,7 +561,7 @@ Return Value:
BufferRemaining -= Size; BufferRemaining -= Size;
// //
// TODO: This section is incomplete. // TODO: Additional options in LoadOptions are not parsed.
// //
PrevOption = Option; PrevOption = Option;
Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)&Entry->Options + OptionsSize); Option = (PBOOT_APPLICATION_OPTION)((PUCHAR)&Entry->Options + OptionsSize);
@ -617,13 +588,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.
--*/ --*/
@ -648,9 +620,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,
@ -660,9 +629,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,
@ -672,9 +638,6 @@ 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;
@ -684,9 +647,6 @@ Return Value:
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);
@ -694,21 +654,15 @@ Return Value:
MemoryInfo->MdlOffset = sizeof(BOOT_MEMORY_INFO); MemoryInfo->MdlOffset = sizeof(BOOT_MEMORY_INFO);
MemoryInfo->DescriptorCount = 1; MemoryInfo->DescriptorCount = 1;
MemoryInfo->DescriptorSize = sizeof(MEMORY_DESCRIPTOR); MemoryInfo->DescriptorSize = sizeof(MEMORY_DESCRIPTOR);
MemoryInfo->BasePageOffset = FIELD_OFFSET(MEMORY_DESCRIPTOR, BasePage); MemoryInfo->FirstPageOffset = FIELD_OFFSET(MEMORY_DESCRIPTOR, FirstPage);
//
// Create a memory descriptor for the boot manager image.
//
MemoryDescriptor = (PMEMORY_DESCRIPTOR)(&EfiInitScratch[ScratchUsed]); MemoryDescriptor = (PMEMORY_DESCRIPTOR)(&EfiInitScratch[ScratchUsed]);
ScratchUsed += sizeof(MEMORY_DESCRIPTOR); ScratchUsed += sizeof(MEMORY_DESCRIPTOR);
MemoryDescriptor->BasePage = (UINTN)InputParameters->ImageBase >> PAGE_SHIFT; MemoryDescriptor->FirstPage = (UINTN)InputParameters->ImageBase >> PAGE_SHIFT;
MemoryDescriptor->Pages = ALIGN_UP(InputParameters->ImageSize, PAGE_SIZE) >> PAGE_SHIFT; MemoryDescriptor->PageCount = ALIGN_UP(InputParameters->ImageSize, PAGE_SIZE) >> PAGE_SHIFT;
MemoryDescriptor->Attributes = MEMORY_ATTRIBUTE_WB; MemoryDescriptor->Attributes = MEMORY_ATTRIBUTE_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,
@ -724,9 +678,6 @@ Return Value:
); );
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);
@ -736,9 +687,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);
@ -747,17 +695,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:
@ -99,7 +99,7 @@ Routine Description:
Arguments: Arguments:
Status - The EFI status code to be converted. Status - The EFI status code.
Return Value: Return Value:

View File

@ -15,8 +15,266 @@ Abstract:
#include "bootmgr.h" #include "bootmgr.h"
#include "efi.h" #include "efi.h"
#include "efilib.h"
#include "mm.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 NTSTATUS
MmFwGetMemoryMap ( MmFwGetMemoryMap (
IN OUT PMEMORY_DESCRIPTOR_LIST Mdl, IN OUT PMEMORY_DESCRIPTOR_LIST Mdl,
@ -27,11 +285,13 @@ MmFwGetMemoryMap (
Routine Description: Routine Description:
Converts an NT status code into an EFI status code. Gets the memory map from EFI and converts it into an MDL.
Arguments: Arguments:
Status - The NT status code to be converted. Mdl - Pointer to the MDL to store new descriptors in.
Flags - Unused.
Return Value: Return Value:
@ -41,16 +301,288 @@ Return Value:
--*/ --*/
{ {
NTSTATUS Status;
UINTN EfiMapSize;
UINTN EfiMapKey;
UINTN EfiDescriptorSize;
UINT32 EfiDescriptorVersion;
UINTN PageCount, EfiPageCount;
EFI_PHYSICAL_ADDRESS EfiBuffer;
EFI_MEMORY_DESCRIPTOR *EfiMap;
BOOLEAN IsRamdisk;
MEMORY_TYPE MemoryType;
UINT64 EfiStartPage, EfiEndPage;
UINT64 EfiRamdiskStartPage, EfiRamdiskEndPage;
PMEMORY_DESCRIPTOR NtDescriptor;
(VOID)Flags; (VOID)Flags;
// EfiBuffer = (EFI_PHYSICAL_ADDRESS)0;
// Make sure Mdl is valid.
//
if (Mdl == NULL) { if (Mdl == NULL) {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
MmMdFreeList(Mdl); MmMdFreeList(Mdl);
return STATUS_SUCCESS; //
// 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;
PageCount = (ALIGN_UP(EfiMapSize, PAGE_SIZE) >> PAGE_SHIFT) + 1;
EfiPageCount = EFI_PAGE(PageCount);
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;
}
}
//
// TODO: Account for possible MDL changes due to EfiFreePages(EfiBuffer).
//
exit:
if (EfiBuffer) {
EfiFreePages(EfiBuffer, EfiPageCount);
}
if (!NT_SUCCESS(Status)) {
MmMdFreeList(Mdl);
}
return Status;
} }

View File

@ -32,11 +32,11 @@ Routine Description:
Arguments: Arguments:
MemoryInfo - pointer to the memory info structure. MemoryInfo - Pointer to the memory info.
TranslationType - the current translation type being used. TranslationType - The current translation type.
LibraryParameters - pointer to the library parameters structure. LibraryParameters - Pointer to the library parameters.
Return Value: Return Value:

View File

@ -22,10 +22,316 @@ Abstract:
MEMORY_DESCRIPTOR MmStaticMemoryDescriptors[MAX_STATIC_DESCRIPTOR_COUNT]; MEMORY_DESCRIPTOR MmStaticMemoryDescriptors[MAX_STATIC_DESCRIPTOR_COUNT];
PMEMORY_DESCRIPTOR MmGlobalMemoryDescriptors; PMEMORY_DESCRIPTOR MmGlobalMemoryDescriptors;
ULONG MmGlobalMemoryDescriptorCount; ULONG MmGlobalMemoryDescriptorCount, MmGlobalMemoryDescriptorsUsed;
PMEMORY_DESCRIPTOR MmDynamicMemoryDescriptors; PMEMORY_DESCRIPTOR MmDynamicMemoryDescriptors;
ULONG MmDynamicMemoryDescriptorCount; 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: Incomplete.
//
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 VOID
MmMdRemoveDescriptorFromList ( MmMdRemoveDescriptorFromList (
@ -55,10 +361,6 @@ Return Value:
PLIST_ENTRY Blink; PLIST_ENTRY Blink;
Blink = Descriptor->ListEntry.Blink; Blink = Descriptor->ListEntry.Blink;
//
// Remove the descriptor from the MDL.
//
RemoveEntryList(&Descriptor->ListEntry); RemoveEntryList(&Descriptor->ListEntry);
// //
@ -129,7 +431,7 @@ Return Value:
// Free the descriptor from the heap. // Free the descriptor from the heap.
// TODO: Use BlMmFreeHeap() // TODO: Use BlMmFreeHeap()
// //
ConsolePrint(L"Cannot free memory descriptor: BlMmFreeHeap() is not implemented\r\n"); ConsolePrint(L"MmMdFreeDescriptor(): need BlMmFreeHeap() to free descriptor\r\n");
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
// return BlMmFreeHeap(Descriptor); // return BlMmFreeHeap(Descriptor);
} }
@ -147,7 +449,7 @@ Routine Description:
Arguments: Arguments:
Mdl - the MDL to free. Mdl - the MDL.
Return Value: Return Value:
@ -166,6 +468,56 @@ Return Value:
} }
} }
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) {
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 VOID
MmMdInitialize ( MmMdInitialize (
IN ULONG Unused, IN ULONG Unused,
@ -201,6 +553,7 @@ Return Value:
// //
MmGlobalMemoryDescriptors = &MmStaticMemoryDescriptors[0]; MmGlobalMemoryDescriptors = &MmStaticMemoryDescriptors[0];
MmGlobalMemoryDescriptorCount = MAX_STATIC_DESCRIPTOR_COUNT; MmGlobalMemoryDescriptorCount = MAX_STATIC_DESCRIPTOR_COUNT;
MmGlobalMemoryDescriptorsUsed = 0;
RtlZeroMemory(MmGlobalMemoryDescriptors, MAX_STATIC_DESCRIPTOR_COUNT * sizeof(MEMORY_DESCRIPTOR)); RtlZeroMemory(MmGlobalMemoryDescriptors, MAX_STATIC_DESCRIPTOR_COUNT * sizeof(MEMORY_DESCRIPTOR));
DebugPrintf(L"Global memory descriptor count: %x\r\n", MmGlobalMemoryDescriptorCount); DebugPrintf(L"Global memory descriptor count: %x\r\n", MmGlobalMemoryDescriptorCount);
} }

View File

@ -44,7 +44,7 @@ Routine Description:
Arguments: Arguments:
Mdl - the MDL to initialize. Mdl - Pointer to the MDL.
Return Value: Return Value:
@ -72,9 +72,9 @@ Routine Description:
Arguments: Arguments:
MemoryInfo - pointer to the memory info structure. MemoryInfo - Pointer to the memory info structure.
MinimumAllocation - minimum amount of pages to grow the pool by at a time. MinimumAllocation - Minimum amount of pages to grow the pool by at a time.
Return Value: Return Value:

View File

@ -16,9 +16,6 @@ Abstract:
#include <ntrtl.h> #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) + \
@ -40,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:
@ -64,18 +61,12 @@ Return Value:
(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;
} }
//
// Calculate structure addresses from offsets.
//
MemoryInfo = (PBOOT_MEMORY_INFO)((PUCHAR)InputParameters + InputParameters->MemoryInfoOffset); MemoryInfo = (PBOOT_MEMORY_INFO)((PUCHAR)InputParameters + InputParameters->MemoryInfoOffset);
ApplicationEntry = (PBOOT_INPUT_APPLICATION_ENTRY)((PUCHAR)InputParameters + InputParameters->ApplicationEntryOffset); ApplicationEntry = (PBOOT_INPUT_APPLICATION_ENTRY)((PUCHAR)InputParameters + InputParameters->ApplicationEntryOffset);
BlpBootDevice = (PBOOT_DEVICE)((PUCHAR)InputParameters + InputParameters->BootDeviceOffset); BlpBootDevice = (PBOOT_DEVICE)((PUCHAR)InputParameters + InputParameters->BootDeviceOffset);
@ -91,31 +82,22 @@ Return Value:
return Status; return Status;
} }
//
// Print image information.
//
ConsolePrintf(L"Image base: %x %x\r\n", (ULONG)((ULONG_PTR)InputParameters->ImageBase >> 32), (ULONG)((ULONG_PTR)InputParameters->ImageBase)); ConsolePrintf(L"Image base: %x %x\r\n", (ULONG)((ULONG_PTR)InputParameters->ImageBase >> 32), (ULONG)((ULONG_PTR)InputParameters->ImageBase));
ConsolePrintf(L"Image size: %x\r\n", InputParameters->ImageSize); ConsolePrintf(L"Image size: %x\r\n", InputParameters->ImageSize);
//
// Check application entry signature.
//
if (ApplicationEntry->Signature != BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE) { if (ApplicationEntry->Signature != BOOT_INPUT_APPLICATION_ENTRY_SIGNATURE) {
DebugPrint(L"InitializeLibrary(): ApplicationEntry Signature is invalid\r\n"); DebugPrint(L"InitializeLibrary(): ApplicationEntry Signature is invalid\r\n");
return STATUS_INVALID_PARAMETER_9; return STATUS_INVALID_PARAMETER_9;
} }
// //
// Save input parameters and application entry data. // Save input parameters and application entry.
// //
BlpApplicationParameters = InputParameters; BlpApplicationParameters = InputParameters;
BlpApplicationEntry.Attributes = ApplicationEntry->Attributes; BlpApplicationEntry.Attributes = ApplicationEntry->Attributes;
RtlCopyMemory(&BlpApplicationEntry.BcdIdentifier, &ApplicationEntry->BcdIdentifier, sizeof(GUID)); RtlCopyMemory(&BlpApplicationEntry.BcdIdentifier, &ApplicationEntry->BcdIdentifier, sizeof(GUID));
BlpApplicationEntry.Options = &ApplicationEntry->Options; BlpApplicationEntry.Options = &ApplicationEntry->Options;
//
// Initialize memory manager.
//
Status = BlpMmInitialize(MemoryInfo, InputParameters->TranslationType, LibraryParameters); Status = BlpMmInitialize(MemoryInfo, InputParameters->TranslationType, LibraryParameters);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
return Status; return Status;
@ -191,13 +173,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:
@ -226,8 +208,7 @@ Arguments:
Return Value: Return Value:
STATUS_SUCCESS if successful. STATUS_SUCCESS.
Error status if an error is encountered.
--*/ --*/

View File

@ -28,7 +28,7 @@ Routine Description:
Arguments: Arguments:
Option - the boot option to get the size of. Option - The boot option.
Return Value: Return Value:
@ -65,11 +65,11 @@ Routine Description:
Arguments: Arguments:
Options - the boot option list to get the size of. Options - The boot option list.
Return Value: Return Value:
The size of the options. The size of the option list.
--*/ --*/

View File

@ -260,6 +260,66 @@ Return Value:
Head->Flink = 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 FORCEINLINE
BOOLEAN BOOLEAN
RemoveEntryList ( RemoveEntryList (