Home | History | Annotate | Download | only in BdsLib
      1 /** @file
      2 *
      3 *  Copyright (c) 2011-2015, ARM Limited. All rights reserved.
      4 *
      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 "BdsInternal.h"
     16 
     17 /**
     18   Locate an EFI application in a the Firmware Volumes by its Name
     19 
     20   @param  EfiAppGuid            Guid of the EFI Application into the Firmware Volume
     21   @param  DevicePath            EFI Device Path of the EFI application
     22 
     23   @return EFI_SUCCESS           The function completed successfully.
     24   @return EFI_NOT_FOUND         The protocol could not be located.
     25   @return EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.
     26 
     27 **/
     28 EFI_STATUS
     29 LocateEfiApplicationInFvByName (
     30   IN  CONST CHAR16*             EfiAppName,
     31   OUT EFI_DEVICE_PATH           **DevicePath
     32   )
     33 {
     34   VOID                          *Key;
     35   EFI_STATUS                    Status, FileStatus;
     36   EFI_GUID                      NameGuid;
     37   EFI_FV_FILETYPE               FileType;
     38   EFI_FV_FILE_ATTRIBUTES        Attributes;
     39   UINTN                         Size;
     40   UINTN                         UiStringLen;
     41   CHAR16                        *UiSection;
     42   UINT32                        Authentication;
     43   EFI_DEVICE_PATH               *FvDevicePath;
     44   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH    FileDevicePath;
     45   EFI_HANDLE                    *HandleBuffer;
     46   UINTN                         NumberOfHandles;
     47   UINTN                         Index;
     48   EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
     49 
     50   ASSERT (DevicePath != NULL);
     51 
     52   // Length of FilePath
     53   UiStringLen = StrLen (EfiAppName);
     54 
     55   // Locate all the Firmware Volume protocols.
     56   Status = gBS->LocateHandleBuffer (
     57                    ByProtocol,
     58                    &gEfiFirmwareVolume2ProtocolGuid,
     59                    NULL,
     60                    &NumberOfHandles,
     61                    &HandleBuffer
     62                    );
     63   if (EFI_ERROR (Status)) {
     64     return Status;
     65   }
     66 
     67   *DevicePath = NULL;
     68 
     69   // Looking for FV with ACPI storage file
     70   for (Index = 0; Index < NumberOfHandles; Index++) {
     71     //
     72     // Get the protocol on this handle
     73     // This should not fail because of LocateHandleBuffer
     74     //
     75     Status = gBS->HandleProtocol (
     76                      HandleBuffer[Index],
     77                      &gEfiFirmwareVolume2ProtocolGuid,
     78                      (VOID**) &FvInstance
     79                      );
     80     if (EFI_ERROR (Status)) {
     81       goto FREE_HANDLE_BUFFER;
     82     }
     83 
     84     // Allocate Key
     85     Key = AllocatePool (FvInstance->KeySize);
     86     ASSERT (Key != NULL);
     87     ZeroMem (Key, FvInstance->KeySize);
     88 
     89     do {
     90       // Search in all files
     91       FileType = EFI_FV_FILETYPE_ALL;
     92 
     93       Status = FvInstance->GetNextFile (FvInstance, Key, &FileType, &NameGuid, &Attributes, &Size);
     94       if (!EFI_ERROR (Status)) {
     95         UiSection = NULL;
     96         FileStatus = FvInstance->ReadSection (
     97                       FvInstance,
     98                       &NameGuid,
     99                       EFI_SECTION_USER_INTERFACE,
    100                       0,
    101                       (VOID **)&UiSection,
    102                       &Size,
    103                       &Authentication
    104                       );
    105         if (!EFI_ERROR (FileStatus)) {
    106           if (StrnCmp (EfiAppName, UiSection, UiStringLen) == 0) {
    107             //
    108             // We found a UiString match.
    109             //
    110             Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
    111 
    112             // Generate the Device Path for the file
    113             EfiInitializeFwVolDevicepathNode (&FileDevicePath, &NameGuid);
    114             *DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath);
    115             ASSERT (*DevicePath != NULL);
    116 
    117             FreePool (Key);
    118             FreePool (UiSection);
    119             FreePool (HandleBuffer);
    120             return FileStatus;
    121           }
    122           FreePool (UiSection);
    123         }
    124       }
    125     } while (!EFI_ERROR (Status));
    126 
    127     FreePool (Key);
    128   }
    129 
    130 FREE_HANDLE_BUFFER:
    131   FreePool (HandleBuffer);
    132   return EFI_NOT_FOUND;
    133 }
    134 
    135 /**
    136   Locate an EFI application in a the Firmware Volumes by its GUID
    137 
    138   @param  EfiAppGuid            Guid of the EFI Application into the Firmware Volume
    139   @param  DevicePath            EFI Device Path of the EFI application
    140 
    141   @return EFI_SUCCESS           The function completed successfully.
    142   @return EFI_NOT_FOUND         The protocol could not be located.
    143   @return EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.
    144 
    145 **/
    146 EFI_STATUS
    147 LocateEfiApplicationInFvByGuid (
    148   IN  CONST EFI_GUID            *EfiAppGuid,
    149   OUT EFI_DEVICE_PATH           **DevicePath
    150   )
    151 {
    152   EFI_STATUS                    Status;
    153   EFI_DEVICE_PATH               *FvDevicePath;
    154   EFI_HANDLE                    *HandleBuffer;
    155   UINTN                         NumberOfHandles;
    156   UINTN                         Index;
    157   EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
    158   EFI_FV_FILE_ATTRIBUTES        Attributes;
    159   UINT32                        AuthenticationStatus;
    160   EFI_FV_FILETYPE               Type;
    161   UINTN                         Size;
    162   CHAR16                        *UiSection;
    163   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileDevicePath;
    164 
    165   ASSERT (DevicePath != NULL);
    166 
    167   // Locate all the Firmware Volume protocols.
    168   Status = gBS->LocateHandleBuffer (
    169                    ByProtocol,
    170                    &gEfiFirmwareVolume2ProtocolGuid,
    171                    NULL,
    172                    &NumberOfHandles,
    173                    &HandleBuffer
    174                    );
    175   if (EFI_ERROR (Status)) {
    176     return Status;
    177   }
    178 
    179   *DevicePath = NULL;
    180 
    181   // Looking for FV with ACPI storage file
    182   for (Index = 0; Index < NumberOfHandles; Index++) {
    183     //
    184     // Get the protocol on this handle
    185     // This should not fail because of LocateHandleBuffer
    186     //
    187     Status = gBS->HandleProtocol (
    188                      HandleBuffer[Index],
    189                      &gEfiFirmwareVolume2ProtocolGuid,
    190                      (VOID**) &FvInstance
    191                      );
    192     if (EFI_ERROR (Status)) {
    193       goto FREE_HANDLE_BUFFER;
    194     }
    195 
    196     Status = FvInstance->ReadFile (
    197                   FvInstance,
    198                   EfiAppGuid,
    199                   NULL,
    200                   &Size,
    201                   &Type,
    202                   &Attributes,
    203                   &AuthenticationStatus
    204                   );
    205     if (EFI_ERROR (Status)) {
    206       //
    207       // Skip if no EFI application file in the FV
    208       //
    209       continue;
    210     } else {
    211       UiSection = NULL;
    212       Status = FvInstance->ReadSection (
    213                     FvInstance,
    214                     EfiAppGuid,
    215                     EFI_SECTION_USER_INTERFACE,
    216                     0,
    217                     (VOID **)&UiSection,
    218                     &Size,
    219                     &AuthenticationStatus
    220                     );
    221       if (!EFI_ERROR (Status)) {
    222         //
    223         // Create the EFI Device Path for the application using the Filename of the application
    224         //
    225         *DevicePath = FileDevicePath (HandleBuffer[Index], UiSection);
    226       } else {
    227         Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID**)&FvDevicePath);
    228         ASSERT_EFI_ERROR (Status);
    229 
    230         //
    231         // Create the EFI Device Path for the application using the EFI GUID of the application
    232         //
    233         EfiInitializeFwVolDevicepathNode (&FvFileDevicePath, EfiAppGuid);
    234 
    235         *DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FvFileDevicePath);
    236         ASSERT (*DevicePath != NULL);
    237       }
    238       break;
    239     }
    240   }
    241 
    242 FREE_HANDLE_BUFFER:
    243   //
    244   // Free any allocated buffers
    245   //
    246   FreePool (HandleBuffer);
    247 
    248   if (*DevicePath == NULL) {
    249     return EFI_NOT_FOUND;
    250   } else {
    251     return EFI_SUCCESS;
    252   }
    253 }
    254