| /** @file | |
| Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> | |
| 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; | |
| } |