From f03b79ee2fa5954d2df7a5c782b0e843bf62d63f Mon Sep 17 00:00:00 2001 From: belliash Date: Mon, 22 Aug 2022 20:09:50 +0200 Subject: [PATCH] Implement BlGetVolumeDevicePath() and BlpDissectVolumeArcPath() --- sdk/xtdk/rtltypes.h | 19 ++++ sdk/xtdk/xtkmapi.h | 1 + xtldr/includes/xtbl.h | 16 +++ xtldr/string.c | 42 ++++++++ xtldr/volume.c | 234 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 sdk/xtdk/rtltypes.h diff --git a/sdk/xtdk/rtltypes.h b/sdk/xtdk/rtltypes.h new file mode 100644 index 0000000..de6471e --- /dev/null +++ b/sdk/xtdk/rtltypes.h @@ -0,0 +1,19 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: sdk/xtdk/rtltypes.h + * DESCRIPTION: Runtime library structures definitions + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTDK_RTLTYPES_H +#define __XTDK_RTLTYPES_H + +#include "xttypes.h" + + +/* UUID string lengths */ +#define GUID_STRING_LENGTH 38 +#define PARTUUID_STRING_LENGTH 13 + +#endif /* __XTDK_RTLTYPES_H */ diff --git a/sdk/xtdk/xtkmapi.h b/sdk/xtdk/xtkmapi.h index dc5e8ae..be40f7f 100644 --- a/sdk/xtdk/xtkmapi.h +++ b/sdk/xtdk/xtkmapi.h @@ -23,4 +23,5 @@ #include "xtuefi.h" /* Low level data types headers */ +#include "rtltypes.h" #include "hltypes.h" diff --git a/xtldr/includes/xtbl.h b/xtldr/includes/xtbl.h index 8e6c789..3fee04c 100644 --- a/xtldr/includes/xtbl.h +++ b/xtldr/includes/xtbl.h @@ -61,10 +61,19 @@ BlEfiPrint(IN PUINT16 Format, EFI_STATUS BlEnumerateEfiBlockDevices(); +EFI_STATUS +BlGetVolumeDevicePath(IN PUCHAR SystemPath, + OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT PUCHAR *Path); + EFI_STATUS BlStartXtLoader(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); +INT +BlStringCompareInsensitive(IN PUCHAR String1, + IN PUCHAR String2); + VOID BlStringPrint(IN VOID PutChar(IN USHORT Character), IN PUINT16 Format, @@ -73,6 +82,13 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character), EFI_STATUS BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices); +EFI_STATUS +BlpDissectVolumeArcPath(IN PUCHAR SystemPath, + OUT PUCHAR *Path, + OUT PUSHORT DriveType, + OUT PULONG DriveNumber, + OUT PULONG PartNumber); + PEFI_DEVICE_PATH_PROTOCOL BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath); diff --git a/xtldr/string.c b/xtldr/string.c index add8de3..b3a7b81 100644 --- a/xtldr/string.c +++ b/xtldr/string.c @@ -11,6 +11,48 @@ STATIC PUINT16 HexTable = L"0123456789abcdef"; +INT +BlStringCompareInsensitive(IN PUCHAR String1, + IN PUCHAR String2) +{ + UCHAR Character1; + UCHAR Character2; + ULONG Index = 0; + + /* Iterate through the strings */ + while(String1[Index] != '\0' && String2[Index] != '\0') + { + /* Get the characters */ + Character1 = String1[Index]; + Character2 = String2[Index]; + + /* Lowercase string1 character if needed */ + if(String1[Index] >= 'A' && String1[Index] <= 'Z') + { + Character1 = String1[Index] - 'A' + 'a'; + } + + /* Lowercase string2 character if needed */ + if(String2[Index] >= 'A' && String2[Index] <= 'Z') + { + Character2 = String2[Index] - 'A' + 'a'; + } + + /* Compare the characters */ + if(Character1 != Character2) + { + /* Strings are not equal */ + return Character1 > Character2 ? 1 : -1; + } + + /* Get next character */ + Index++; + } + + /* Strings are equal */ + return 0; +} + /** * This routine formats the input string and prints it using specified routine. * diff --git a/xtldr/volume.c b/xtldr/volume.c index 276672a..010b323 100644 --- a/xtldr/volume.c +++ b/xtldr/volume.c @@ -105,7 +105,7 @@ BlEnumerateEfiBlockDevices() PartitionGuid = (PEFI_GUID)HDPath->Signature; /* Print debug message */ - BlDbgPrint(L"Found Hard Disk partition (DiskNumber: %lu, PartNumber: %u, " + BlDbgPrint(L"Found Hard Disk partition (DiskNumber: %lu, PartNumber: %lu, " L"MBRType: %u, GUID: {%g}, PartSize: %luB)\n", DriveNumber, PartitionNumber, HDPath->MBRType, PartitionGuid, HDPath->PartitionSize * Media->BlockSize); @@ -160,6 +160,103 @@ BlEnumerateEfiBlockDevices() return STATUS_EFI_SUCCESS; } +EFI_STATUS +BlGetVolumeDevicePath(IN PUCHAR SystemPath, + OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT PUCHAR *Path) +{ + PEFI_BLOCK_DEVICE Device; + USHORT DriveType; + ULONG DriveNumber; + ULONG PartNumber; + PUCHAR Volume; + ULONG PathLength; + PLIST_ENTRY ListEntry; + EFI_STATUS Status; + + /* Make sure this is not set */ + *DevicePath = NULL; + + /* Find volume path and its length */ + Volume = SystemPath; + while(*Volume != '/' && *Volume != '\\' && *Volume != '\0') + { + Volume++; + } + PathLength = Volume - SystemPath; + + /* Check if valume path specified */ + if(PathLength == 0) + { + /* No volume path available */ + *Path = SystemPath; + return STATUS_EFI_NOT_FOUND; + } + + /* Check system path format */ + if(SystemPath[0] == '{') + { + if(PathLength == GUID_STRING_LENGTH) + { + /* This is EFI GUID */ + BlDbgPrint(L"EFI/GPT GUID in system path is not supported yet\n"); + return STATUS_EFI_UNSUPPORTED; + } + else if(PathLength == PARTUUID_STRING_LENGTH) + { + /* This is MBR UUID */ + BlDbgPrint(L"MBR partition UUID in system path is not supported yet\n"); + return STATUS_EFI_UNSUPPORTED; + } + else + { + /* Invalid UUID format */ + return STATUS_EFI_INVALID_PARAMETER; + } + } + else + { + /* Defaults to ARC path, dissect it */ + Status = BlpDissectVolumeArcPath(SystemPath, Path, &DriveType, &DriveNumber, &PartNumber); + } + + /* Check if volume path parsed successfully */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to parse system path */ + BlDbgPrint(L"Failed to parse system path: '%s' with status code: %lx\n", SystemPath, Status); + return Status; + } + + /* Look for block device corresponding to dissected ARC path */ + ListEntry = BlBlockDevices.Flink; + while(ListEntry != &BlBlockDevices) + { + /* Check if this is the volume we are looking for */ + Device = CONTAIN_RECORD(ListEntry, EFI_BLOCK_DEVICE, ListEntry); + if((Device->DriveType == DriveType && Device->DriveNumber == DriveNumber && + Device->PartitionNumber == PartNumber)) + { + /* Found volume */ + *DevicePath = Device->DevicePath; + break; + } + ListEntry = ListEntry->Flink; + } + + /* Check if volume was found */ + if(*DevicePath == NULL) + { + /* Failed to find volume */ + BlDbgPrint(L"Volume (DriveType: %u, DriveNumber: %lu, PartNumber: %lu) not found\n", + DriveType, DriveNumber, PartNumber); + return STATUS_EFI_NOT_FOUND; + } + + /* return success */ + return STATUS_EFI_SUCCESS; +} + EFI_STATUS BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices) { @@ -241,6 +338,141 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices) return STATUS_EFI_SUCCESS; } +EFI_STATUS +BlpDissectVolumeArcPath(IN PUCHAR SystemPath, + OUT PUCHAR *Path, + OUT PUSHORT DriveType, + OUT PULONG DriveNumber, + OUT PULONG PartNumber) +{ + PUCHAR ArcPath; + ULONG ArcLength = 0; + + /* Set default values */ + *DriveType = XT_BOOT_DEVICE_UNKNOWN; + *DriveNumber = 0; + *PartNumber = 0; + + /* Look for the ARC path */ + if(BlStringCompareInsensitive(SystemPath, (PUCHAR)"ramdisk(0)") == 0) + { + /* This is RAM disk */ + ArcLength = 10; + *DriveType = XT_BOOT_DEVICE_RAMDISK; + } + else if(BlStringCompareInsensitive(SystemPath, (PUCHAR)"multi(0)disk(0)") == 0) + { + /* This is a multi-disk port */ + ArcLength = 15; + ArcPath = SystemPath + ArcLength; + + /* Check for disk type */ + if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"cdrom(") == 0) + { + /* This is an optical drive */ + ArcLength += 6; + + /* Find drive number */ + while(SystemPath[ArcLength] != ')' && SystemPath[ArcLength] != '\0') + { + if(SystemPath[ArcLength] >= '0' && SystemPath[ArcLength] <= '9') + { + /* Calculate drive number */ + *DriveNumber *= 10; + *DriveNumber += SystemPath[ArcLength] - '0'; + } + ArcLength++; + } + + /* Set proper drive type */ + *DriveType = XT_BOOT_DEVICE_CDROM; + ArcLength++; + } + else if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"fdisk(") == 0) + { + /* This is a floppy drive */ + ArcLength += 6; + + /* Find drive number */ + while(SystemPath[ArcLength] != ')' && SystemPath[ArcLength] != '\0') + { + if(SystemPath[ArcLength] >= '0' && SystemPath[ArcLength] <= '9') + { + /* Calculate drive number */ + *DriveNumber *= 10; + *DriveNumber += SystemPath[ArcLength] - '0'; + } + ArcLength++; + } + + /* Set proper drive type */ + *DriveType = XT_BOOT_DEVICE_FLOPPY; + ArcLength++; + } + else if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"rdisk(") == 0) + { + /* This is a hard disk */ + ArcLength += 6; + + /* Find drive number */ + while(SystemPath[ArcLength] != ')' && SystemPath[ArcLength] != '\0') + { + if(SystemPath[ArcLength] >= '0' && SystemPath[ArcLength] <= '9') + { + /* Calculate drive number */ + *DriveNumber *= 10; + *DriveNumber += SystemPath[ArcLength] - '0'; + } + ArcLength++; + } + + /* Set proper drive type */ + *DriveType = XT_BOOT_DEVICE_HARDDISK; + ArcLength++; + ArcPath = SystemPath + ArcLength; + + /* Look for a partition */ + if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"partition(") == 0) + { + /* Partition information found */ + ArcLength += 10; + + /* Find partition number */ + while(SystemPath[ArcLength] != ')' && SystemPath[ArcLength] != '\0') + { + if(SystemPath[ArcLength] >= '0' && SystemPath[ArcLength] <= '9') + { + /* Calculate partition number */ + *PartNumber *= 10; + *PartNumber += SystemPath[ArcLength] - '0'; + } + ArcLength++; + } + ArcLength++; + } + } + else + { + /* Unsupported disk type */ + return STATUS_EFI_UNSUPPORTED; + } + } + else + { + /* Unsupported ARC path */ + return STATUS_EFI_UNSUPPORTED; + } + + /* Store the path if possible */ + if(Path) + { + *Path = SystemPath + ArcLength; + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + PEFI_DEVICE_PATH_PROTOCOL BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath) {