[BOOT:LIB] Implement EfiInitpConvertEfiFilePath()

Also implemented RtlULongSub() and EfiInitpAppendPathString()
This commit is contained in:
Quinn Stephens 2024-08-24 12:39:16 -04:00
parent 8f56881d02
commit 874d95ae4c
3 changed files with 207 additions and 4 deletions

View File

@ -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;
}

View File

@ -18,6 +18,7 @@ Abstract:
#include <string.h>
#include <ntdef.h>
#include <ntstatus.h>
//
// Memory operations.
@ -27,6 +28,47 @@ Abstract:
#define RtlFillMemory(Destination, Length, Fill) memset((Destination), (Fill), (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
NTAPI
RtlInitUnicodeString (

View File

@ -29,6 +29,7 @@ Abstract:
#define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L)
#define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L)
#define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL)
#define STATUS_INTEGER_OVERFLOW ((NTSTATUS) 0xC0000095L)
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL)
#define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L)
#define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L)