Home | History | Annotate | Download | only in EbcDebugger
      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