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
LocateEfiApplicationInFvByName(IN CONST CHAR16 * EfiAppName,OUT EFI_DEVICE_PATH ** DevicePath)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
LocateEfiApplicationInFvByGuid(IN CONST EFI_GUID * EfiAppGuid,OUT EFI_DEVICE_PATH ** DevicePath)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