From 212091811fabf0ae18c22c29f491da537af713ba Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Fri, 8 Dec 2023 15:57:44 +0100 Subject: [PATCH] Implement BlReadFile() routine --- xtldr2/includes/bootman.h | 7 +++ xtldr2/protocol.c | 5 +- xtldr2/volume.c | 119 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) diff --git a/xtldr2/includes/bootman.h b/xtldr2/includes/bootman.h index 2a1647a..cedf062 100644 --- a/xtldr2/includes/bootman.h +++ b/xtldr2/includes/bootman.h @@ -57,6 +57,13 @@ BlOpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle); +XTCDECL +EFI_STATUS +BlReadFile(IN PEFI_FILE_HANDLE DirHandle, + IN CONST PWCHAR FileName, + OUT PVOID *FileData, + OUT PSIZE_T FileSize); + XTCDECL VOID BlConsoleClearScreen(); diff --git a/xtldr2/protocol.c b/xtldr2/protocol.c index 2a3d20c..53feebe 100644 --- a/xtldr2/protocol.c +++ b/xtldr2/protocol.c @@ -95,6 +95,9 @@ BlpRegisterXtLoaderProtocol() LdrProtocol.Console.EnableCursor = BlConsoleEnableCursor; LdrProtocol.Console.Print = BlConsolePrint; LdrProtocol.Debug.Print = BlDebugPrint; + LdrProtocol.Disk.CloseVolume = BlCloseVolume; + LdrProtocol.Disk.OpenVolume = BlOpenVolume; + LdrProtocol.Disk.ReadFile = BlReadFile; LdrProtocol.Memory.AllocatePages = BlMemoryAllocatePages; LdrProtocol.Memory.AllocatePool = BlMemoryAllocatePool; LdrProtocol.Memory.FreePages = BlMemoryFreePages; @@ -102,8 +105,6 @@ BlpRegisterXtLoaderProtocol() LdrProtocol.Protocol.Open = BlOpenXtProtocol; LdrProtocol.Util.ExitBootServices = BlExitBootServices; LdrProtocol.Util.SleepExecution = BlSleepExecution; - LdrProtocol.Volume.Close = BlCloseVolume; - LdrProtocol.Volume.Open = BlOpenVolume; /* Register XTLDR loader protocol */ BlDebugPrint(L"Registering XT loader protocol\n"); diff --git a/xtldr2/volume.c b/xtldr2/volume.c index 8176190..8b11882 100644 --- a/xtldr2/volume.c +++ b/xtldr2/volume.c @@ -470,6 +470,125 @@ BlOpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, return STATUS_EFI_SUCCESS; } +/** + * Reads data from the file. + * + * @param DirHandle + * Supplies a handle of the opened filesystem directory. + * + * @param FileName + * Supplies the name of the file to read. + * + * @param FileData + * Provides a buffer to store the data read from the file. + * + * @param FileSize + * Provides a pointer to the variable to store a size of the buffer. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlReadFile(IN PEFI_FILE_HANDLE DirHandle, + IN CONST PWCHAR FileName, + OUT PVOID *FileData, + OUT PSIZE_T FileSize) +{ + EFI_GUID FileInfoGuid = EFI_FILE_INFO_PROTOCOL_GUID; + EFI_PHYSICAL_ADDRESS Address; + PEFI_FILE_HANDLE FileHandle; + PEFI_FILE_INFO FileInfo; + EFI_STATUS Status; + UINT_PTR ReadSize; + SIZE_T Pages; + + Status = DirHandle->Open(DirHandle, &FileHandle, FileName, EFI_FILE_MODE_READ, + EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open file */ + return Status; + } + + /* Set required size for getting file information */ + ReadSize = sizeof(EFI_FILE_INFO) + 32; + + /* Allocate necessary amount of memory */ + Status = BlMemoryAllocatePool(ReadSize, (PVOID *)&FileInfo); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + FileHandle->Close(FileHandle); + return Status; + } + + /* First attempt to get file information */ + FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); + if(Status == STATUS_EFI_BUFFER_TOO_SMALL) + { + /* Buffer is too small, but EFI tells the required size, so reallocate */ + BlMemoryFreePool(&FileInfo); + Status = BlMemoryAllocatePool(ReadSize, (PVOID *)&FileInfo); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + FileHandle->Close(FileHandle); + return Status; + } + + /* Second attempt to get file information */ + Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); + } + + /* Check if file information got successfully */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to get file information */ + FileHandle->Close(FileHandle); + BlMemoryFreePool(&FileInfo); + return Status; + } + + /* Store file size and calculate number of pages */ + *FileSize = FileInfo->FileSize; + Pages = EFI_SIZE_TO_PAGES(FileInfo->FileSize); + + /* Allocate pages */ + Status = BlMemoryAllocatePages(Pages, &Address); + if(Status != STATUS_EFI_SUCCESS) + { + /* Pages allocation failure */ + FileHandle->Close(FileHandle); + BlMemoryFreePool(&FileInfo); + return Status; + } + + /* Calculate number of bytes to read and zero memory*/ + ReadSize = Pages * EFI_PAGE_SIZE; + *FileData = (PCHAR)(UINT_PTR)Address; + RtlZeroMemory(*FileData, ReadSize); + + /* Read data from the file */ + Status = FileHandle->Read(FileHandle, &ReadSize, *FileData); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to read data */ + FileHandle->Close(FileHandle); + BlMemoryFreePool(&FileInfo); + BlMemoryFreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)*FileData); + return Status; + } + + /* Close handle and free memory */ + FileHandle->Close(FileHandle); + BlMemoryFreePool(&FileInfo); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + /** * Gets a list of block devices from an EFI enabled BIOS. *