Home | History | Annotate | Download | only in BootMaint
      1 /** @file
      2   Utility routines used by boot maintenance modules.
      3 
      4 Copyright (c) 2004 - 2014, 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 "BootMaint.h"
     16 
     17 /**
     18 
     19   Function opens and returns a file handle to the root directory of a volume.
     20 
     21   @param DeviceHandle    A handle for a device
     22 
     23   @return A valid file handle or NULL is returned
     24 
     25 **/
     26 EFI_FILE_HANDLE
     27 EfiLibOpenRoot (
     28   IN EFI_HANDLE                   DeviceHandle
     29   )
     30 {
     31   EFI_STATUS                      Status;
     32   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
     33   EFI_FILE_HANDLE                 File;
     34 
     35   File = NULL;
     36 
     37   //
     38   // File the file system interface to the device
     39   //
     40   Status = gBS->HandleProtocol (
     41                   DeviceHandle,
     42                   &gEfiSimpleFileSystemProtocolGuid,
     43                   (VOID *) &Volume
     44                   );
     45 
     46   //
     47   // Open the root directory of the volume
     48   //
     49   if (!EFI_ERROR (Status)) {
     50     Status = Volume->OpenVolume (
     51                       Volume,
     52                       &File
     53                       );
     54   }
     55   //
     56   // Done
     57   //
     58   return EFI_ERROR (Status) ? NULL : File;
     59 }
     60 
     61 /**
     62 
     63   Helper function called as part of the code needed
     64   to allocate the proper sized buffer for various
     65   EFI interfaces.
     66 
     67 
     68   @param Status          Current status
     69   @param Buffer          Current allocated buffer, or NULL
     70   @param BufferSize      Current buffer size needed
     71 
     72   @retval  TRUE  if the buffer was reallocated and the caller
     73                  should try the API again.
     74   @retval  FALSE The caller should not call this function again.
     75 
     76 **/
     77 BOOLEAN
     78 EfiGrowBuffer (
     79   IN OUT EFI_STATUS   *Status,
     80   IN OUT VOID         **Buffer,
     81   IN UINTN            BufferSize
     82   )
     83 {
     84   BOOLEAN TryAgain;
     85 
     86   //
     87   // If this is an initial request, buffer will be null with a new buffer size
     88   //
     89   if ((*Buffer == NULL) && (BufferSize != 0)) {
     90     *Status = EFI_BUFFER_TOO_SMALL;
     91   }
     92   //
     93   // If the status code is "buffer too small", resize the buffer
     94   //
     95   TryAgain = FALSE;
     96   if (*Status == EFI_BUFFER_TOO_SMALL) {
     97 
     98     if (*Buffer != NULL) {
     99       FreePool (*Buffer);
    100     }
    101 
    102     *Buffer = AllocateZeroPool (BufferSize);
    103 
    104     if (*Buffer != NULL) {
    105       TryAgain = TRUE;
    106     } else {
    107       *Status = EFI_OUT_OF_RESOURCES;
    108     }
    109   }
    110   //
    111   // If there's an error, free the buffer
    112   //
    113   if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {
    114     FreePool (*Buffer);
    115     *Buffer = NULL;
    116   }
    117 
    118   return TryAgain;
    119 }
    120 
    121 /**
    122   Function returns the value of the specified variable.
    123 
    124 
    125   @param Name            A Null-terminated Unicode string that is
    126                          the name of the vendor's variable.
    127   @param VendorGuid      A unique identifier for the vendor.
    128 
    129   @return               The payload of the variable.
    130   @retval NULL          If the variable can't be read.
    131 
    132 **/
    133 VOID *
    134 EfiLibGetVariable (
    135   IN CHAR16               *Name,
    136   IN EFI_GUID             *VendorGuid
    137   )
    138 {
    139   UINTN VarSize;
    140 
    141   return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);
    142 }
    143 
    144 /**
    145   Function deletes the variable specified by VarName and VarGuid.
    146 
    147   @param VarName           A Null-terminated Unicode string that is
    148                            the name of the vendor's variable.
    149 
    150   @param VarGuid           A unique identifier for the vendor.
    151 
    152   @retval  EFI_SUCCESS           The variable was found and removed
    153   @retval  EFI_UNSUPPORTED       The variable store was inaccessible
    154   @retval  EFI_OUT_OF_RESOURCES  The temporary buffer was not available
    155   @retval  EFI_NOT_FOUND         The variable was not found
    156 
    157 **/
    158 EFI_STATUS
    159 EfiLibDeleteVariable (
    160   IN CHAR16   *VarName,
    161   IN EFI_GUID *VarGuid
    162   )
    163 {
    164   VOID        *VarBuf;
    165   EFI_STATUS  Status;
    166 
    167   VarBuf  = EfiLibGetVariable (VarName, VarGuid);
    168   Status  = EFI_NOT_FOUND;
    169 
    170   if (VarBuf != NULL) {
    171     //
    172     // Delete variable from Storage
    173     //
    174     Status = gRT->SetVariable (
    175                     VarName,
    176                     VarGuid,
    177                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    178                     0,
    179                     NULL
    180                     );
    181     //
    182     // Deleting variable with current variable implementation shouldn't fail.
    183     //
    184     ASSERT_EFI_ERROR (Status);
    185     FreePool (VarBuf);
    186   }
    187 
    188   return Status;
    189 }
    190 
    191 /**
    192 
    193   Function gets the file system information from an open file descriptor,
    194   and stores it in a buffer allocated from pool.
    195 
    196 
    197   @param FHand           The file handle.
    198 
    199   @return                A pointer to a buffer with file information.
    200   @retval                NULL is returned if failed to get Vaolume Label Info.
    201 
    202 **/
    203 EFI_FILE_SYSTEM_VOLUME_LABEL *
    204 EfiLibFileSystemVolumeLabelInfo (
    205   IN EFI_FILE_HANDLE      FHand
    206   )
    207 {
    208   EFI_STATUS                        Status;
    209   EFI_FILE_SYSTEM_VOLUME_LABEL      *Buffer;
    210   UINTN                             BufferSize;
    211   //
    212   // Initialize for GrowBuffer loop
    213   //
    214   Buffer      = NULL;
    215   BufferSize  = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200;
    216 
    217   //
    218   // Call the real function
    219   //
    220   while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
    221     Status = FHand->GetInfo (
    222                       FHand,
    223                       &gEfiFileSystemVolumeLabelInfoIdGuid,
    224                       &BufferSize,
    225                       Buffer
    226                       );
    227   }
    228 
    229   return Buffer;
    230 }
    231 
    232 /**
    233   Duplicate a string.
    234 
    235   @param Src             The source.
    236 
    237   @return A new string which is duplicated copy of the source.
    238   @retval NULL If there is not enough memory.
    239 
    240 **/
    241 CHAR16 *
    242 EfiStrDuplicate (
    243   IN CHAR16   *Src
    244   )
    245 {
    246   CHAR16  *Dest;
    247   UINTN   Size;
    248 
    249   Size  = StrSize (Src);
    250   Dest  = AllocateZeroPool (Size);
    251   ASSERT (Dest != NULL);
    252   if (Dest != NULL) {
    253     CopyMem (Dest, Src, Size);
    254   }
    255 
    256   return Dest;
    257 }
    258 
    259 /**
    260 
    261   Function gets the file information from an open file descriptor, and stores it
    262   in a buffer allocated from pool.
    263 
    264   @param FHand           File Handle.
    265 
    266   @return                A pointer to a buffer with file information or NULL is returned
    267 
    268 **/
    269 EFI_FILE_INFO *
    270 EfiLibFileInfo (
    271   IN EFI_FILE_HANDLE      FHand
    272   )
    273 {
    274   EFI_STATUS    Status;
    275   EFI_FILE_INFO *Buffer;
    276   UINTN         BufferSize;
    277 
    278   //
    279   // Initialize for GrowBuffer loop
    280   //
    281   Buffer      = NULL;
    282   BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;
    283 
    284   //
    285   // Call the real function
    286   //
    287   while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
    288     Status = FHand->GetInfo (
    289                       FHand,
    290                       &gEfiFileInfoGuid,
    291                       &BufferSize,
    292                       Buffer
    293                       );
    294   }
    295 
    296   return Buffer;
    297 }
    298 
    299 /**
    300   Function is used to determine the number of device path instances
    301   that exist in a device path.
    302 
    303 
    304   @param DevicePath      A pointer to a device path data structure.
    305 
    306   @return This function counts and returns the number of device path instances
    307           in DevicePath.
    308 
    309 **/
    310 UINTN
    311 EfiDevicePathInstanceCount (
    312   IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath
    313   )
    314 {
    315   UINTN Count;
    316   UINTN Size;
    317 
    318   Count = 0;
    319   while (GetNextDevicePathInstance (&DevicePath, &Size) != NULL) {
    320     Count += 1;
    321   }
    322 
    323   return Count;
    324 }
    325 
    326 /**
    327   Adjusts the size of a previously allocated buffer.
    328 
    329 
    330   @param OldPool         - A pointer to the buffer whose size is being adjusted.
    331   @param OldSize         - The size of the current buffer.
    332   @param NewSize         - The size of the new buffer.
    333 
    334   @return   The newly allocated buffer.
    335   @retval   NULL  Allocation failed.
    336 
    337 **/
    338 VOID *
    339 EfiReallocatePool (
    340   IN VOID                 *OldPool,
    341   IN UINTN                OldSize,
    342   IN UINTN                NewSize
    343   )
    344 {
    345   VOID  *NewPool;
    346 
    347   NewPool = NULL;
    348   if (NewSize != 0) {
    349     NewPool = AllocateZeroPool (NewSize);
    350   }
    351 
    352   if (OldPool != NULL) {
    353     if (NewPool != NULL) {
    354       CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
    355     }
    356 
    357     FreePool (OldPool);
    358   }
    359 
    360   return NewPool;
    361 }
    362 
    363 /**
    364   Get a string from the Data Hub record based on
    365   a device path.
    366 
    367   @param DevPath         The device Path.
    368 
    369   @return A string located from the Data Hub records based on
    370           the device path.
    371   @retval NULL  If failed to get the String from Data Hub.
    372 
    373 **/
    374 UINT16 *
    375 EfiLibStrFromDatahub (
    376   IN EFI_DEVICE_PATH_PROTOCOL                 *DevPath
    377   )
    378 {
    379   return NULL;
    380 }
    381 
    382 /**
    383 
    384   Find the first instance of this Protocol
    385   in the system and return it's interface.
    386 
    387 
    388   @param ProtocolGuid    Provides the protocol to search for
    389   @param Interface       On return, a pointer to the first interface
    390                          that matches ProtocolGuid
    391 
    392   @retval  EFI_SUCCESS      A protocol instance matching ProtocolGuid was found
    393   @retval  EFI_NOT_FOUND    No protocol instances were found that match ProtocolGuid
    394 
    395 **/
    396 EFI_STATUS
    397 EfiLibLocateProtocol (
    398   IN  EFI_GUID    *ProtocolGuid,
    399   OUT VOID        **Interface
    400   )
    401 {
    402   EFI_STATUS  Status;
    403 
    404   Status = gBS->LocateProtocol (
    405                   ProtocolGuid,
    406                   NULL,
    407                   (VOID **) Interface
    408                   );
    409   return Status;
    410 }
    411 
    412