/** @file Copyright (c) 2007, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Edb.h" /** Read a file. @param Vol - File System Volume @param FileName - The file to be read. @param BufferSize - The file buffer size @param Buffer - The file buffer @retval EFI_SUCCESS - read file successfully @retval EFI_NOT_FOUND - file not found **/ EFI_STATUS EFIAPI ReadFileFromVol ( IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol, IN CHAR16 *FileName, OUT UINTN *BufferSize, OUT VOID **Buffer ) { EFI_STATUS Status; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; UINTN FileInfoSize; EFI_FILE_INFO *FileInfo; UINTN TempBufferSize; VOID *TempBuffer; // // Open the root directory // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return Status; } // // Open the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } RootDir->Close (RootDir); // // Get the file information // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; FileInfo = AllocateZeroPool (FileInfoSize); if (FileInfo == NULL) { Handle->Close (Handle); return Status; } Status = Handle->GetInfo ( Handle, &gEfiFileInfoGuid, &FileInfoSize, FileInfo ); if (EFI_ERROR (Status)) { Handle->Close (Handle); gBS->FreePool (FileInfo); return Status; } // // Allocate buffer for the file data. The last CHAR16 is for L'\0' // TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16); TempBuffer = AllocateZeroPool (TempBufferSize); if (TempBuffer == NULL) { Handle->Close (Handle); gBS->FreePool (FileInfo); return Status; } gBS->FreePool (FileInfo); // // Read the file data to the buffer // Status = Handle->Read ( Handle, &TempBufferSize, TempBuffer ); if (EFI_ERROR (Status)) { Handle->Close (Handle); gBS->FreePool (TempBuffer); return Status; } Handle->Close (Handle); *BufferSize = TempBufferSize; *Buffer = TempBuffer; return EFI_SUCCESS; } /** Read a file. If ScanFs is FLASE, it will use DebuggerPrivate->Vol as default Fs. If ScanFs is TRUE, it will scan all FS and check the file. If there is only one file match the name, it will be read. If there is more than one file match the name, it will return Error. @param DebuggerPrivate - EBC Debugger private data structure @param FileName - The file to be read. @param BufferSize - The file buffer size @param Buffer - The file buffer @param ScanFs - Need Scan all FS @retval EFI_SUCCESS - read file successfully @retval EFI_NOT_FOUND - file not found @retval EFI_NO_MAPPING - there is duplicated files found **/ EFI_STATUS EFIAPI ReadFileToBuffer ( IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, IN CHAR16 *FileName, OUT UINTN *BufferSize, OUT VOID **Buffer, IN BOOLEAN ScanFs ) { EFI_STATUS Status; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; UINTN TempBufferSize; VOID *TempBuffer; UINTN NoHandles; EFI_HANDLE *HandleBuffer; UINTN Index; // // Check parameters // if ((FileName == NULL) || (Buffer == NULL)) { return EFI_INVALID_PARAMETER; } // // not scan fs // if (!ScanFs) { if (DebuggerPrivate->Vol == NULL) { return EFI_INVALID_PARAMETER; } // // Read file directly from Vol // return ReadFileFromVol (DebuggerPrivate->Vol, FileName, BufferSize, Buffer); } // // need scan fs // // // Get all Vol handle // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &NoHandles, &HandleBuffer ); if (EFI_ERROR (Status) && (NoHandles == 0)) { return EFI_NOT_FOUND; } // // Walk through each Vol // DebuggerPrivate->Vol = NULL; *BufferSize = 0; *Buffer = NULL; for (Index = 0; Index < NoHandles; Index++) { Status = gBS->HandleProtocol ( HandleBuffer[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID**) &Vol ); if (EFI_ERROR(Status)) { continue; } Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer); if (!EFI_ERROR (Status)) { // // Read file OK, check duplication // if (DebuggerPrivate->Vol != NULL) { // // Find the duplicated file // gBS->FreePool (TempBuffer); gBS->FreePool (*Buffer); EDBPrint (L"Duplicated FileName found!\n"); return EFI_NO_MAPPING; } else { // // Record value // DebuggerPrivate->Vol = Vol; *BufferSize = TempBufferSize; *Buffer = TempBuffer; } } } // // Scan Fs done // if (DebuggerPrivate->Vol == NULL) { return EFI_NOT_FOUND; } // // Done // return EFI_SUCCESS; } /** Get file name under this dir with index @param DebuggerPrivate - EBC Debugger private data structure @param DirName - The dir to be read. @param FileName - The file name pattern under this dir @param Index - The file index under this dir @return File Name which match the pattern and index. **/ CHAR16 * EFIAPI GetFileNameUnderDir ( IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, IN CHAR16 *DirName, IN CHAR16 *FileName, IN OUT UINTN *Index ) { EFI_STATUS Status; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; UINTN FileInfoSize; EFI_FILE_INFO *FileInfo; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; VOID *TempName; UINTN FileIndex; if (DebuggerPrivate->Vol == NULL) { Status = gBS->LocateProtocol ( &gEfiSimpleFileSystemProtocolGuid, NULL, (VOID**) &DebuggerPrivate->Vol ); if (EFI_ERROR(Status)) { return NULL; } } Vol = DebuggerPrivate->Vol; // // Open the root directory // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return NULL; } // // Open the file // Status = RootDir->Open ( RootDir, &Handle, DirName, EFI_FILE_MODE_READ, EFI_FILE_DIRECTORY ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return NULL; } RootDir->Close (RootDir); // // Set Dir Position // Status = Handle->SetPosition (Handle, 0); if (EFI_ERROR (Status)) { Handle->Close (Handle); return NULL; } // // Get the file information // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; FileInfo = AllocateZeroPool (FileInfoSize); if (FileInfo == NULL) { Handle->Close (Handle); return NULL; } // // Walk through each file in the directory // FileIndex = 0; TempName = NULL; while (TRUE) { // // Read a file entry // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; Status = Handle->Read ( Handle, &FileInfoSize, FileInfo ); if (EFI_ERROR (Status) || (FileInfoSize == 0)) { break; } if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { // // This is a file // // // Only deal with the EFI key file // if (!StrEndWith (FileInfo->FileName, FileName)) { continue; } if (FileIndex == *Index) { TempName = StrDuplicate (FileInfo->FileName); *Index = *Index + 1; break; } FileIndex ++; } } // // Free resources // gBS->FreePool (FileInfo); Handle->Close (Handle); return TempName; }