[BOOT:LIB] Implement EfiInitpConvertEfiFilePath()
Also implemented RtlULongSub() and EfiInitpAppendPathString()
This commit is contained in:
@@ -24,6 +24,106 @@ UCHAR EfiInitScratch[2048];
|
||||
const EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_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
|
||||
@@ -287,10 +387,70 @@ Return Value:
|
||||
--*/
|
||||
|
||||
{
|
||||
(VOID)EfiFilePath;
|
||||
(VOID)OptionType;
|
||||
(VOID)Option;
|
||||
(VOID)BufferSize;
|
||||
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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user