Home | History | Annotate | Download | only in RamDiskDxe
      1 /** @file
      2   Internal file explorer helper functions for RamDiskDxe driver.
      3 
      4   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "RamDiskImpl.h"
     16 
     17 
     18 /**
     19   Helper function called as part of the code needed to allocate the proper
     20   sized buffer for various EFI interfaces.
     21 
     22   @param[in, out] Status     Current status.
     23   @param[in, out] Buffer     Current allocated buffer, or NULL.
     24   @param[in]      BufferSize Current buffer size needed.
     25 
     26   @retval  TRUE         If the buffer was reallocated and the caller should
     27                         try the API again.
     28   @retval  FALSE        The caller should not call this function again.
     29 
     30 **/
     31 BOOLEAN
     32 GrowBuffer (
     33   IN OUT EFI_STATUS   *Status,
     34   IN OUT VOID         **Buffer,
     35   IN UINTN            BufferSize
     36   )
     37 {
     38   BOOLEAN TryAgain;
     39 
     40   //
     41   // If this is an initial request, buffer will be null with a new buffer size
     42   //
     43   if ((*Buffer == NULL) && (BufferSize != 0)) {
     44     *Status = EFI_BUFFER_TOO_SMALL;
     45   }
     46   //
     47   // If the status code is "buffer too small", resize the buffer
     48   //
     49   TryAgain = FALSE;
     50   if (*Status == EFI_BUFFER_TOO_SMALL) {
     51 
     52     if (*Buffer != NULL) {
     53       FreePool (*Buffer);
     54     }
     55 
     56     *Buffer = AllocateZeroPool (BufferSize);
     57 
     58     if (*Buffer != NULL) {
     59       TryAgain = TRUE;
     60     } else {
     61       *Status = EFI_OUT_OF_RESOURCES;
     62     }
     63   }
     64   //
     65   // If there's an error, free the buffer
     66   //
     67   if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {
     68     FreePool (*Buffer);
     69     *Buffer = NULL;
     70   }
     71 
     72   return TryAgain;
     73 }
     74 
     75 
     76 /**
     77   This function gets the file information from an open file descriptor,
     78   and stores it in a buffer allocated from pool.
     79 
     80   @param[in] FHand           File Handle.
     81 
     82   @return    A pointer to a buffer with file information or NULL is returned.
     83 
     84 **/
     85 EFI_FILE_INFO *
     86 FileInfo (
     87   IN EFI_FILE_HANDLE                        FHand
     88   )
     89 {
     90   EFI_STATUS                           Status;
     91   EFI_FILE_INFO                        *Buffer;
     92   UINTN                                BufferSize;
     93 
     94   //
     95   // Initialize for GrowBuffer loop
     96   //
     97   Buffer      = NULL;
     98   BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;
     99 
    100   //
    101   // Call the real function
    102   //
    103   while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
    104     Status = FHand->GetInfo (
    105                       FHand,
    106                       &gEfiFileInfoGuid,
    107                       &BufferSize,
    108                       Buffer
    109                       );
    110   }
    111 
    112   return Buffer;
    113 }
    114 
    115 
    116 /**
    117   This function will open a file or directory referenced by DevicePath.
    118 
    119   This function opens a file with the open mode according to the file path. The
    120   Attributes is valid only for EFI_FILE_MODE_CREATE.
    121 
    122   @param[in, out] FilePath   On input, the device path to the file.
    123                              On output, the remaining device path.
    124   @param[out]     FileHandle Pointer to the file handle.
    125   @param[in]      OpenMode   The mode to open the file with.
    126   @param[in]      Attributes The file's file attributes.
    127 
    128   @retval EFI_SUCCESS             The information was set.
    129   @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.
    130   @retval EFI_UNSUPPORTED         Could not open the file path.
    131   @retval EFI_NOT_FOUND           The specified file could not be found on the
    132                                   device or the file system could not be found
    133                                   on the device.
    134   @retval EFI_NO_MEDIA            The device has no medium.
    135   @retval EFI_MEDIA_CHANGED       The device has a different medium in it or
    136                                   the medium is no longer supported.
    137   @retval EFI_DEVICE_ERROR        The device reported an error.
    138   @retval EFI_VOLUME_CORRUPTED    The file system structures are corrupted.
    139   @retval EFI_WRITE_PROTECTED     The file or medium is write protected.
    140   @retval EFI_ACCESS_DENIED       The file was opened read only.
    141   @retval EFI_OUT_OF_RESOURCES    Not enough resources were available to open
    142                                   the file.
    143   @retval EFI_VOLUME_FULL         The volume is full.
    144 **/
    145 EFI_STATUS
    146 EFIAPI
    147 OpenFileByDevicePath(
    148   IN OUT EFI_DEVICE_PATH_PROTOCOL           **FilePath,
    149   OUT EFI_FILE_HANDLE                       *FileHandle,
    150   IN UINT64                                 OpenMode,
    151   IN UINT64                                 Attributes
    152   )
    153 {
    154   EFI_STATUS                           Status;
    155   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL      *EfiSimpleFileSystemProtocol;
    156   EFI_FILE_PROTOCOL                    *Handle1;
    157   EFI_FILE_PROTOCOL                    *Handle2;
    158   EFI_HANDLE                           DeviceHandle;
    159 
    160   if ((FilePath == NULL || FileHandle == NULL)) {
    161     return EFI_INVALID_PARAMETER;
    162   }
    163 
    164   Status = gBS->LocateDevicePath (
    165                   &gEfiSimpleFileSystemProtocolGuid,
    166                   FilePath,
    167                   &DeviceHandle
    168                   );
    169   if (EFI_ERROR (Status)) {
    170     return Status;
    171   }
    172 
    173   Status = gBS->OpenProtocol(
    174                   DeviceHandle,
    175                   &gEfiSimpleFileSystemProtocolGuid,
    176                   (VOID**)&EfiSimpleFileSystemProtocol,
    177                   gImageHandle,
    178                   NULL,
    179                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    180                   );
    181   if (EFI_ERROR (Status)) {
    182     return Status;
    183   }
    184 
    185   Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
    186   if (EFI_ERROR (Status)) {
    187     FileHandle = NULL;
    188     return Status;
    189   }
    190 
    191   //
    192   // go down directories one node at a time.
    193   //
    194   while (!IsDevicePathEnd (*FilePath)) {
    195     //
    196     // For file system access each node should be a file path component
    197     //
    198     if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
    199         DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
    200        ) {
    201       FileHandle = NULL;
    202       return (EFI_INVALID_PARAMETER);
    203     }
    204     //
    205     // Open this file path node
    206     //
    207     Handle2  = Handle1;
    208     Handle1 = NULL;
    209 
    210     //
    211     // Try to test opening an existing file
    212     //
    213     Status = Handle2->Open (
    214                           Handle2,
    215                           &Handle1,
    216                           ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
    217                           OpenMode &~EFI_FILE_MODE_CREATE,
    218                           0
    219                          );
    220 
    221     //
    222     // see if the error was that it needs to be created
    223     //
    224     if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
    225       Status = Handle2->Open (
    226                             Handle2,
    227                             &Handle1,
    228                             ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
    229                             OpenMode,
    230                             Attributes
    231                            );
    232     }
    233     //
    234     // Close the last node
    235     //
    236     Handle2->Close (Handle2);
    237 
    238     if (EFI_ERROR(Status)) {
    239       return (Status);
    240     }
    241 
    242     //
    243     // Get the next node
    244     //
    245     *FilePath = NextDevicePathNode (*FilePath);
    246   }
    247 
    248   //
    249   // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
    250   //
    251   *FileHandle = (VOID*)Handle1;
    252   return EFI_SUCCESS;
    253 }
    254