[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 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
|
||||
EfiInitpCreateApplicationEntry (
|
||||
IN EFI_SYSTEM_TABLE *SystemTable,
|
||||
IN OUT PBOOT_APPLICATION_ENTRY Entry,
|
||||
IN ULONG BufferSize,
|
||||
IN EFI_DEVICE_PATH *DevicePath,
|
||||
IN EFI_DEVICE_PATH *FilePath,
|
||||
IN EFI_DEVICE_PATH *EfiDevicePath,
|
||||
IN EFI_DEVICE_PATH *EfiFilePath,
|
||||
IN PWCHAR LoadOptions,
|
||||
IN ULONG LoadOptionsSize,
|
||||
IN ULONG Flags,
|
||||
OUT PULONG BufferUsed,
|
||||
OUT PBOOT_DEVICE *BootDevice
|
||||
)
|
||||
@ -50,14 +282,16 @@ Arguments:
|
||||
|
||||
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.
|
||||
|
||||
LoadOptionsSize - Length of the string pointed to by LoadOptions.
|
||||
|
||||
Flags - Unused.
|
||||
|
||||
BufferUsed - Returns the amount of buffer space used by the routine.
|
||||
|
||||
BootDevice - Returns a pointer to the device the application was loaded from.
|
||||
@ -69,9 +303,18 @@ Return Value:
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG BufferRemaining;
|
||||
PWCHAR BcdOptionString;
|
||||
BOOLEAN BcdIdentifierSet;
|
||||
UNICODE_STRING UnicodeString;
|
||||
PBOOT_APPLICATION_ENTRY_OPTION Option;
|
||||
PBCDE_DEVICE BootDeviceElement;
|
||||
|
||||
(VOID)SystemTable;
|
||||
(VOID)EfiDevicePath;
|
||||
(VOID)EfiFilePath;
|
||||
(VOID)Flags;
|
||||
|
||||
*BufferUsed = 0;
|
||||
*BootDevice = NULL;
|
||||
@ -80,7 +323,8 @@ Return Value:
|
||||
//
|
||||
// Require enough space for the application entry.
|
||||
//
|
||||
if (BufferSize < sizeof(BOOT_APPLICATION_ENTRY)) {
|
||||
BufferRemaining = BufferSize;
|
||||
if (BufferRemaining < sizeof(BOOT_APPLICATION_ENTRY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -110,15 +354,27 @@ Return Value:
|
||||
}
|
||||
|
||||
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.
|
||||
//
|
||||
(VOID)SystemTable;
|
||||
(VOID)DevicePath;
|
||||
(VOID)FilePath;
|
||||
}
|
||||
|
||||
PBOOT_INPUT_PARAMETERS
|
||||
@ -236,6 +492,7 @@ Return Value:
|
||||
LoadedImage->FilePath,
|
||||
LoadedImage->LoadOptions,
|
||||
LoadedImage->LoadOptionsSize,
|
||||
0,
|
||||
&ApplicationEntrySize,
|
||||
&BootDevice
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user