[BOOT:LIB] Major work on efiinit.c
Improved EfiInitpCreateApplicationEntry() Implemented EfiInitpGetDeviceNode(), EfiInitTranslateDevicePath(), and EfiInitpConvertDevicePath()
This commit is contained in:
parent
9b66f166d6
commit
fd670ace0d
@ -23,15 +23,247 @@ 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
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 *DevicePath,
|
IN EFI_DEVICE_PATH *EfiDevicePath,
|
||||||
IN EFI_DEVICE_PATH *FilePath,
|
IN EFI_DEVICE_PATH *EfiFilePath,
|
||||||
IN PWCHAR LoadOptions,
|
IN PWCHAR LoadOptions,
|
||||||
IN ULONG LoadOptionsSize,
|
IN ULONG LoadOptionsSize,
|
||||||
|
IN ULONG Flags,
|
||||||
OUT PULONG BufferUsed,
|
OUT PULONG BufferUsed,
|
||||||
OUT PBOOT_DEVICE *BootDevice
|
OUT PBOOT_DEVICE *BootDevice
|
||||||
)
|
)
|
||||||
@ -50,14 +282,16 @@ Arguments:
|
|||||||
|
|
||||||
BufferSize - The amount of available space in the buffer.
|
BufferSize - The amount of available space in the buffer.
|
||||||
|
|
||||||
DevicePath - The device path for the application.
|
EfiDevicePath - The device path for the application.
|
||||||
|
|
||||||
FilePath - The file path for the application.
|
EfiFilePath - 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.
|
||||||
@ -69,9 +303,18 @@ Return Value:
|
|||||||
--*/
|
--*/
|
||||||
|
|
||||||
{
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG BufferRemaining;
|
||||||
PWCHAR BcdOptionString;
|
PWCHAR BcdOptionString;
|
||||||
BOOLEAN BcdIdentifierSet;
|
BOOLEAN BcdIdentifierSet;
|
||||||
UNICODE_STRING UnicodeString;
|
UNICODE_STRING UnicodeString;
|
||||||
|
PBOOT_APPLICATION_ENTRY_OPTION Option;
|
||||||
|
PBCDE_DEVICE BootDeviceElement;
|
||||||
|
|
||||||
|
(VOID)SystemTable;
|
||||||
|
(VOID)EfiDevicePath;
|
||||||
|
(VOID)EfiFilePath;
|
||||||
|
(VOID)Flags;
|
||||||
|
|
||||||
*BufferUsed = 0;
|
*BufferUsed = 0;
|
||||||
*BootDevice = NULL;
|
*BootDevice = NULL;
|
||||||
@ -80,7 +323,8 @@ Return Value:
|
|||||||
//
|
//
|
||||||
// Require enough space for the application entry.
|
// Require enough space for the application entry.
|
||||||
//
|
//
|
||||||
if (BufferSize < sizeof(BOOT_APPLICATION_ENTRY)) {
|
BufferRemaining = BufferSize;
|
||||||
|
if (BufferRemaining < sizeof(BOOT_APPLICATION_ENTRY)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,15 +354,27 @@ Return Value:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!BcdIdentifierSet) {
|
if (!BcdIdentifierSet) {
|
||||||
Entry->Attributes |= BOOT_APPLICATION_ENTRY_BCD_IDENTIFIER_NOT_SET;
|
Entry->Attributes |= BOOT_APPLICATION_ENTRY_NO_BCD_IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convert the EFI device path into a boot device option.
|
||||||
|
//
|
||||||
|
Option = &Entry->Options;
|
||||||
|
BufferRemaining -= FIELD_OFFSET(BOOT_APPLICATION_ENTRY, Options);
|
||||||
|
Status = EfiInitpConvertEfiDevicePath(EfiDevicePath, BCDE_DATA_TYPE_APPLICATION_DEVICE, Option, BufferRemaining);
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
Option->IsInvalid = TRUE;
|
||||||
|
*BufferUsed = sizeof(BOOT_APPLICATION_ENTRY_OPTION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BootDeviceElement = (PBCDE_DEVICE)((PUCHAR)Option + Option->DataOffset);
|
||||||
|
*BootDevice = &BootDeviceElement->Device;
|
||||||
|
|
||||||
//
|
//
|
||||||
// TODO: This routine is not fully implemented.
|
// TODO: This routine is not fully implemented.
|
||||||
//
|
//
|
||||||
(VOID)SystemTable;
|
|
||||||
(VOID)DevicePath;
|
|
||||||
(VOID)FilePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PBOOT_INPUT_PARAMETERS
|
PBOOT_INPUT_PARAMETERS
|
||||||
@ -236,6 +492,7 @@ Return Value:
|
|||||||
LoadedImage->FilePath,
|
LoadedImage->FilePath,
|
||||||
LoadedImage->LoadOptions,
|
LoadedImage->LoadOptions,
|
||||||
LoadedImage->LoadOptionsSize,
|
LoadedImage->LoadOptionsSize,
|
||||||
|
0,
|
||||||
&ApplicationEntrySize,
|
&ApplicationEntrySize,
|
||||||
&BootDevice
|
&BootDevice
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user