1 /** @file 2 3 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 13 **/ 14 15 #include "Edb.h" 16 17 /** 18 Read a file. 19 20 @param Vol - File System Volume 21 @param FileName - The file to be read. 22 @param BufferSize - The file buffer size 23 @param Buffer - The file buffer 24 25 @retval EFI_SUCCESS - read file successfully 26 @retval EFI_NOT_FOUND - file not found 27 28 **/ 29 EFI_STATUS 30 EFIAPI 31 ReadFileFromVol ( 32 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol, 33 IN CHAR16 *FileName, 34 OUT UINTN *BufferSize, 35 OUT VOID **Buffer 36 ) 37 { 38 EFI_STATUS Status; 39 EFI_FILE_HANDLE RootDir; 40 EFI_FILE_HANDLE Handle; 41 UINTN FileInfoSize; 42 EFI_FILE_INFO *FileInfo; 43 UINTN TempBufferSize; 44 VOID *TempBuffer; 45 46 // 47 // Open the root directory 48 // 49 Status = Vol->OpenVolume (Vol, &RootDir); 50 if (EFI_ERROR (Status)) { 51 return Status; 52 } 53 54 // 55 // Open the file 56 // 57 Status = RootDir->Open ( 58 RootDir, 59 &Handle, 60 FileName, 61 EFI_FILE_MODE_READ, 62 0 63 ); 64 if (EFI_ERROR (Status)) { 65 RootDir->Close (RootDir); 66 return Status; 67 } 68 69 RootDir->Close (RootDir); 70 71 // 72 // Get the file information 73 // 74 FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; 75 76 FileInfo = AllocateZeroPool (FileInfoSize); 77 if (FileInfo == NULL) { 78 Handle->Close (Handle); 79 return Status; 80 } 81 82 Status = Handle->GetInfo ( 83 Handle, 84 &gEfiFileInfoGuid, 85 &FileInfoSize, 86 FileInfo 87 ); 88 if (EFI_ERROR (Status)) { 89 Handle->Close (Handle); 90 gBS->FreePool (FileInfo); 91 return Status; 92 } 93 94 // 95 // Allocate buffer for the file data. The last CHAR16 is for L'\0' 96 // 97 TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16); 98 TempBuffer = AllocateZeroPool (TempBufferSize); 99 if (TempBuffer == NULL) { 100 Handle->Close (Handle); 101 gBS->FreePool (FileInfo); 102 return Status; 103 } 104 105 gBS->FreePool (FileInfo); 106 107 // 108 // Read the file data to the buffer 109 // 110 Status = Handle->Read ( 111 Handle, 112 &TempBufferSize, 113 TempBuffer 114 ); 115 if (EFI_ERROR (Status)) { 116 Handle->Close (Handle); 117 gBS->FreePool (TempBuffer); 118 return Status; 119 } 120 121 Handle->Close (Handle); 122 123 *BufferSize = TempBufferSize; 124 *Buffer = TempBuffer; 125 return EFI_SUCCESS; 126 } 127 128 /** 129 130 Read a file. 131 If ScanFs is FLASE, it will use DebuggerPrivate->Vol as default Fs. 132 If ScanFs is TRUE, it will scan all FS and check the file. 133 If there is only one file match the name, it will be read. 134 If there is more than one file match the name, it will return Error. 135 136 @param DebuggerPrivate - EBC Debugger private data structure 137 @param FileName - The file to be read. 138 @param BufferSize - The file buffer size 139 @param Buffer - The file buffer 140 @param ScanFs - Need Scan all FS 141 142 @retval EFI_SUCCESS - read file successfully 143 @retval EFI_NOT_FOUND - file not found 144 @retval EFI_NO_MAPPING - there is duplicated files found 145 146 **/ 147 EFI_STATUS 148 EFIAPI 149 ReadFileToBuffer ( 150 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, 151 IN CHAR16 *FileName, 152 OUT UINTN *BufferSize, 153 OUT VOID **Buffer, 154 IN BOOLEAN ScanFs 155 ) 156 { 157 EFI_STATUS Status; 158 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; 159 UINTN TempBufferSize; 160 VOID *TempBuffer; 161 UINTN NoHandles; 162 EFI_HANDLE *HandleBuffer; 163 UINTN Index; 164 165 // 166 // Check parameters 167 // 168 if ((FileName == NULL) || (Buffer == NULL)) { 169 return EFI_INVALID_PARAMETER; 170 } 171 172 // 173 // not scan fs 174 // 175 if (!ScanFs) { 176 if (DebuggerPrivate->Vol == NULL) { 177 return EFI_INVALID_PARAMETER; 178 } 179 // 180 // Read file directly from Vol 181 // 182 return ReadFileFromVol (DebuggerPrivate->Vol, FileName, BufferSize, Buffer); 183 } 184 185 // 186 // need scan fs 187 // 188 189 // 190 // Get all Vol handle 191 // 192 Status = gBS->LocateHandleBuffer ( 193 ByProtocol, 194 &gEfiSimpleFileSystemProtocolGuid, 195 NULL, 196 &NoHandles, 197 &HandleBuffer 198 ); 199 if (EFI_ERROR (Status) && (NoHandles == 0)) { 200 return EFI_NOT_FOUND; 201 } 202 203 // 204 // Walk through each Vol 205 // 206 DebuggerPrivate->Vol = NULL; 207 *BufferSize = 0; 208 *Buffer = NULL; 209 for (Index = 0; Index < NoHandles; Index++) { 210 Status = gBS->HandleProtocol ( 211 HandleBuffer[Index], 212 &gEfiSimpleFileSystemProtocolGuid, 213 (VOID**) &Vol 214 ); 215 if (EFI_ERROR(Status)) { 216 continue; 217 } 218 219 Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer); 220 if (!EFI_ERROR (Status)) { 221 // 222 // Read file OK, check duplication 223 // 224 if (DebuggerPrivate->Vol != NULL) { 225 // 226 // Find the duplicated file 227 // 228 gBS->FreePool (TempBuffer); 229 gBS->FreePool (*Buffer); 230 EDBPrint (L"Duplicated FileName found!\n"); 231 return EFI_NO_MAPPING; 232 } else { 233 // 234 // Record value 235 // 236 DebuggerPrivate->Vol = Vol; 237 *BufferSize = TempBufferSize; 238 *Buffer = TempBuffer; 239 } 240 } 241 } 242 243 // 244 // Scan Fs done 245 // 246 if (DebuggerPrivate->Vol == NULL) { 247 return EFI_NOT_FOUND; 248 } 249 250 // 251 // Done 252 // 253 return EFI_SUCCESS; 254 } 255 256 /** 257 258 Get file name under this dir with index 259 260 @param DebuggerPrivate - EBC Debugger private data structure 261 @param DirName - The dir to be read. 262 @param FileName - The file name pattern under this dir 263 @param Index - The file index under this dir 264 265 @return File Name which match the pattern and index. 266 267 **/ 268 CHAR16 * 269 EFIAPI 270 GetFileNameUnderDir ( 271 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, 272 IN CHAR16 *DirName, 273 IN CHAR16 *FileName, 274 IN OUT UINTN *Index 275 ) 276 { 277 EFI_STATUS Status; 278 EFI_FILE_HANDLE RootDir; 279 EFI_FILE_HANDLE Handle; 280 UINTN FileInfoSize; 281 EFI_FILE_INFO *FileInfo; 282 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; 283 VOID *TempName; 284 UINTN FileIndex; 285 286 if (DebuggerPrivate->Vol == NULL) { 287 Status = gBS->LocateProtocol ( 288 &gEfiSimpleFileSystemProtocolGuid, 289 NULL, 290 (VOID**) &DebuggerPrivate->Vol 291 ); 292 if (EFI_ERROR(Status)) { 293 return NULL; 294 } 295 } 296 Vol = DebuggerPrivate->Vol; 297 298 // 299 // Open the root directory 300 // 301 Status = Vol->OpenVolume (Vol, &RootDir); 302 if (EFI_ERROR (Status)) { 303 return NULL; 304 } 305 306 // 307 // Open the file 308 // 309 Status = RootDir->Open ( 310 RootDir, 311 &Handle, 312 DirName, 313 EFI_FILE_MODE_READ, 314 EFI_FILE_DIRECTORY 315 ); 316 if (EFI_ERROR (Status)) { 317 RootDir->Close (RootDir); 318 return NULL; 319 } 320 RootDir->Close (RootDir); 321 322 // 323 // Set Dir Position 324 // 325 Status = Handle->SetPosition (Handle, 0); 326 if (EFI_ERROR (Status)) { 327 Handle->Close (Handle); 328 return NULL; 329 } 330 331 // 332 // Get the file information 333 // 334 FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; 335 336 FileInfo = AllocateZeroPool (FileInfoSize); 337 if (FileInfo == NULL) { 338 Handle->Close (Handle); 339 return NULL; 340 } 341 342 // 343 // Walk through each file in the directory 344 // 345 FileIndex = 0; 346 TempName = NULL; 347 while (TRUE) { 348 // 349 // Read a file entry 350 // 351 FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; 352 353 Status = Handle->Read ( 354 Handle, 355 &FileInfoSize, 356 FileInfo 357 ); 358 if (EFI_ERROR (Status) || (FileInfoSize == 0)) { 359 break; 360 } 361 362 if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { 363 // 364 // This is a file 365 // 366 367 // 368 // Only deal with the EFI key file 369 // 370 if (!StrEndWith (FileInfo->FileName, FileName)) { 371 continue; 372 } 373 374 if (FileIndex == *Index) { 375 TempName = StrDuplicate (FileInfo->FileName); 376 *Index = *Index + 1; 377 break; 378 } 379 FileIndex ++; 380 } 381 } 382 383 // 384 // Free resources 385 // 386 gBS->FreePool (FileInfo); 387 Handle->Close (Handle); 388 389 return TempName; 390 } 391