]>
Commit | Line | Data |
---|---|---|
1c280088 | 1 | /** @file\r |
9095d37b | 2 | MDE DXE Services Library provides functions that simplify the development of DXE Drivers.\r |
84716614 | 3 | These functions help access data from sections of FFS files or from file path.\r |
1c280088 | 4 | \r |
9095d37b | 5 | Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r |
711ef3f6 | 6 | (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r |
9344f092 | 7 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
1c280088 | 8 | \r |
9 | **/\r | |
10 | \r | |
11 | #include <PiDxe.h>\r | |
12 | #include <Library/DebugLib.h>\r | |
13 | #include <Library/MemoryAllocationLib.h>\r | |
14 | #include <Library/UefiBootServicesTableLib.h>\r | |
84716614 LG |
15 | #include <Library/DevicePathLib.h>\r |
16 | #include <Library/UefiLib.h>\r | |
eb9dd4d0 | 17 | #include <Library/DxeServicesLib.h>\r |
1c280088 | 18 | #include <Protocol/FirmwareVolume2.h>\r |
19 | #include <Protocol/LoadedImage.h>\r | |
84716614 LG |
20 | #include <Protocol/LoadFile2.h>\r |
21 | #include <Protocol/LoadFile.h>\r | |
22 | #include <Protocol/SimpleFileSystem.h>\r | |
23 | #include <Guid/FileInfo.h>\r | |
1c280088 | 24 | \r |
25 | /**\r | |
166152e8 | 26 | Identify the device handle from which the Image is loaded from. As this device handle is passed to\r |
9095d37b | 27 | GetSectionFromFv as the identifier for a Firmware Volume, an EFI_FIRMWARE_VOLUME2_PROTOCOL\r |
c1d8b697 | 28 | protocol instance should be located successfully by calling gBS->HandleProtocol ().\r |
1c280088 | 29 | \r |
166152e8 | 30 | This function locates the EFI_LOADED_IMAGE_PROTOCOL instance installed\r |
31 | on ImageHandle. It then returns EFI_LOADED_IMAGE_PROTOCOL.DeviceHandle.\r | |
9095d37b | 32 | \r |
166152e8 | 33 | If ImageHandle is NULL, then ASSERT ();\r |
34 | If failed to locate a EFI_LOADED_IMAGE_PROTOCOL on ImageHandle, then ASSERT ();\r | |
9095d37b | 35 | \r |
166152e8 | 36 | @param ImageHandle The firmware allocated handle for UEFI image.\r |
1c280088 | 37 | \r |
58380e9c | 38 | @retval EFI_HANDLE The device handle from which the Image is loaded from.\r |
1c280088 | 39 | \r |
40 | **/\r | |
166152e8 | 41 | EFI_HANDLE\r |
42 | InternalImageHandleToFvHandle (\r | |
2f88bd3a | 43 | EFI_HANDLE ImageHandle\r |
166152e8 | 44 | )\r |
45 | {\r | |
2f88bd3a MK |
46 | EFI_STATUS Status;\r |
47 | EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r | |
9095d37b | 48 | \r |
166152e8 | 49 | ASSERT (ImageHandle != NULL);\r |
50 | \r | |
51 | Status = gBS->HandleProtocol (\r | |
2f88bd3a MK |
52 | ImageHandle,\r |
53 | &gEfiLoadedImageProtocolGuid,\r | |
54 | (VOID **)&LoadedImage\r | |
55 | );\r | |
166152e8 | 56 | \r |
57 | ASSERT_EFI_ERROR (Status);\r | |
58 | \r | |
d7b96017 SZ |
59 | //\r |
60 | // The LoadedImage->DeviceHandle may be NULL.\r | |
61 | // For example for DxeCore, there is LoadedImage protocol installed for it, but the\r | |
62 | // LoadedImage->DeviceHandle could not be initialized before the FV2 (contain DxeCore)\r | |
63 | // protocol is installed.\r | |
64 | //\r | |
166152e8 | 65 | return LoadedImage->DeviceHandle;\r |
166152e8 | 66 | }\r |
67 | \r | |
68 | /**\r | |
9095d37b | 69 | Allocate and fill a buffer from a Firmware Section identified by a Firmware File GUID name, a Firmware\r |
b75a165d LG |
70 | Section type and instance number from the specified Firmware Volume.\r |
71 | \r | |
9095d37b | 72 | This functions first locate the EFI_FIRMWARE_VOLUME2_PROTOCOL protocol instance on FvHandle in order to\r |
c1d8b697 | 73 | carry out the Firmware Volume read operation. The function then reads the Firmware Section found specified\r |
9095d37b LG |
74 | by NameGuid, SectionType and SectionInstance.\r |
75 | \r | |
76 | The details of this search order is defined in description of EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection ()\r | |
b75a165d | 77 | found in PI Specification.\r |
9095d37b LG |
78 | \r |
79 | If SectionType is EFI_SECTION_TE, EFI_SECTION_TE is used as section type to start the search. If EFI_SECTION_TE section\r | |
80 | is not found, EFI_SECTION_PE32 will be used to try the search again. If no EFI_SECTION_PE32 section is found, EFI_NOT_FOUND\r | |
b75a165d | 81 | is returned.\r |
9095d37b LG |
82 | \r |
83 | The data and size is returned by Buffer and Size. The caller is responsible to free the Buffer allocated\r | |
b75a165d | 84 | by this function. This function can be only called at TPL_NOTIFY and below.\r |
9095d37b | 85 | \r |
b75a165d LG |
86 | If NameGuid is NULL, then ASSERT();\r |
87 | If Buffer is NULL, then ASSERT();\r | |
88 | If Size is NULL, then ASSERT().\r | |
89 | \r | |
9095d37b | 90 | @param FvHandle The device handle that contains a instance of\r |
58380e9c | 91 | EFI_FIRMWARE_VOLUME2_PROTOCOL instance.\r |
b75a165d LG |
92 | @param NameGuid The GUID name of a Firmware File.\r |
93 | @param SectionType The Firmware Section type.\r | |
9095d37b | 94 | @param SectionInstance The instance number of Firmware Section to\r |
58380e9c | 95 | read from starting from 0.\r |
c1d8b697 | 96 | @param Buffer On output, Buffer contains the data read\r |
58380e9c | 97 | from the section in the Firmware File found.\r |
b75a165d LG |
98 | @param Size On output, the size of Buffer.\r |
99 | \r | |
100 | @retval EFI_SUCCESS The image is found and data and size is returned.\r | |
9095d37b | 101 | @retval EFI_NOT_FOUND The image specified by NameGuid and SectionType\r |
58380e9c | 102 | can't be found.\r |
9095d37b | 103 | @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the\r |
58380e9c | 104 | output data buffer or complete the operations.\r |
9095d37b | 105 | @retval EFI_DEVICE_ERROR A hardware error occurs during reading from the\r |
58380e9c | 106 | Firmware Volume.\r |
9095d37b | 107 | @retval EFI_ACCESS_DENIED The firmware volume containing the searched\r |
58380e9c | 108 | Firmware File is configured to disallow reads.\r |
9095d37b | 109 | \r |
f80b0830 | 110 | **/\r |
1c280088 | 111 | EFI_STATUS\r |
eb9dd4d0 | 112 | InternalGetSectionFromFv (\r |
2f88bd3a MK |
113 | IN EFI_HANDLE FvHandle,\r |
114 | IN CONST EFI_GUID *NameGuid,\r | |
115 | IN EFI_SECTION_TYPE SectionType,\r | |
116 | IN UINTN SectionInstance,\r | |
117 | OUT VOID **Buffer,\r | |
118 | OUT UINTN *Size\r | |
1c280088 | 119 | )\r |
120 | {\r | |
2f88bd3a MK |
121 | EFI_STATUS Status;\r |
122 | EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r | |
123 | UINT32 AuthenticationStatus;\r | |
166152e8 | 124 | \r |
8cf43dd7 | 125 | ASSERT (NameGuid != NULL);\r |
126 | ASSERT (Buffer != NULL);\r | |
127 | ASSERT (Size != NULL);\r | |
9095d37b | 128 | \r |
d7b96017 SZ |
129 | if (FvHandle == NULL) {\r |
130 | //\r | |
131 | // Return EFI_NOT_FOUND directly for NULL FvHandle.\r | |
132 | //\r | |
133 | return EFI_NOT_FOUND;\r | |
134 | }\r | |
166152e8 | 135 | \r |
136 | Status = gBS->HandleProtocol (\r | |
137 | FvHandle,\r | |
138 | &gEfiFirmwareVolume2ProtocolGuid,\r | |
2f88bd3a | 139 | (VOID **)&Fv\r |
166152e8 | 140 | );\r |
141 | if (EFI_ERROR (Status)) {\r | |
7ca066f9 | 142 | return EFI_NOT_FOUND;\r |
166152e8 | 143 | }\r |
1c280088 | 144 | \r |
145 | //\r | |
146 | // Read desired section content in NameGuid file\r | |
147 | //\r | |
2f88bd3a MK |
148 | *Buffer = NULL;\r |
149 | *Size = 0;\r | |
150 | Status = Fv->ReadSection (\r | |
151 | Fv,\r | |
152 | NameGuid,\r | |
153 | SectionType,\r | |
154 | SectionInstance,\r | |
155 | Buffer,\r | |
156 | Size,\r | |
157 | &AuthenticationStatus\r | |
158 | );\r | |
1c280088 | 159 | \r |
160 | if (EFI_ERROR (Status) && (SectionType == EFI_SECTION_TE)) {\r | |
161 | //\r | |
9095d37b | 162 | // Try reading PE32 section, if the required section is TE type\r |
1c280088 | 163 | //\r |
164 | *Buffer = NULL;\r | |
165 | *Size = 0;\r | |
166 | Status = Fv->ReadSection (\r | |
167 | Fv,\r | |
168 | NameGuid,\r | |
169 | EFI_SECTION_PE32,\r | |
ff197efb | 170 | SectionInstance,\r |
1c280088 | 171 | Buffer,\r |
172 | Size,\r | |
173 | &AuthenticationStatus\r | |
174 | );\r | |
175 | }\r | |
176 | \r | |
1c280088 | 177 | return Status;\r |
178 | }\r | |
179 | \r | |
682cee4c | 180 | /**\r |
9095d37b | 181 | Searches all the available firmware volumes and returns the first matching FFS section.\r |
682cee4c LG |
182 | \r |
183 | This function searches all the firmware volumes for FFS files with FV file type specified by FileType\r | |
9095d37b LG |
184 | The order that the firmware volumes is searched is not deterministic. For each available FV a search\r |
185 | is made for FFS file of type FileType. If the FV contains more than one FFS file with the same FileType,\r | |
186 | the FileInstance instance will be the matched FFS file. For each FFS file found a search\r | |
187 | is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance instances\r | |
188 | of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer.\r | |
189 | Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size.\r | |
190 | It is the caller's responsibility to use FreePool() to free the allocated buffer.\r | |
191 | See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections\r | |
682cee4c LG |
192 | are retrieved from an FFS file based on SectionType and SectionInstance.\r |
193 | \r | |
9095d37b | 194 | If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,\r |
682cee4c LG |
195 | the search will be retried with a section type of EFI_SECTION_PE32.\r |
196 | This function must be called with a TPL <= TPL_NOTIFY.\r | |
197 | \r | |
198 | If Buffer is NULL, then ASSERT().\r | |
199 | If Size is NULL, then ASSERT().\r | |
200 | \r | |
9095d37b | 201 | @param FileType Indicates the FV file type to search for within all\r |
58380e9c | 202 | available FVs.\r |
9095d37b | 203 | @param FileInstance Indicates which file instance within all available\r |
58380e9c | 204 | FVs specified by FileType.\r |
682cee4c | 205 | FileInstance starts from zero.\r |
9095d37b LG |
206 | @param SectionType Indicates the FFS section type to search for\r |
207 | within the FFS file\r | |
682cee4c | 208 | specified by FileType with FileInstance.\r |
9095d37b LG |
209 | @param SectionInstance Indicates which section instance within the FFS file\r |
210 | specified by FileType with FileInstance to retrieve.\r | |
58380e9c | 211 | SectionInstance starts from zero.\r |
9095d37b | 212 | @param Buffer On output, a pointer to a callee allocated buffer\r |
58380e9c | 213 | containing the FFS file section that was found.\r |
9095d37b | 214 | Is it the caller's responsibility to free this\r |
58380e9c | 215 | buffer using FreePool().\r |
682cee4c LG |
216 | @param Size On output, a pointer to the size, in bytes, of Buffer.\r |
217 | \r | |
218 | @retval EFI_SUCCESS The specified FFS section was returned.\r | |
219 | @retval EFI_NOT_FOUND The specified FFS section could not be found.\r | |
9095d37b | 220 | @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve\r |
58380e9c | 221 | the matching FFS section.\r |
9095d37b | 222 | @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a\r |
58380e9c | 223 | device error.\r |
9095d37b LG |
224 | @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because\r |
225 | the firmware volume that\r | |
682cee4c LG |
226 | contains the matching FFS section does not allow reads.\r |
227 | **/\r | |
228 | EFI_STATUS\r | |
229 | EFIAPI\r | |
230 | GetSectionFromAnyFvByFileType (\r | |
2f88bd3a MK |
231 | IN EFI_FV_FILETYPE FileType,\r |
232 | IN UINTN FileInstance,\r | |
233 | IN EFI_SECTION_TYPE SectionType,\r | |
234 | IN UINTN SectionInstance,\r | |
235 | OUT VOID **Buffer,\r | |
236 | OUT UINTN *Size\r | |
682cee4c LG |
237 | )\r |
238 | {\r | |
2f88bd3a MK |
239 | EFI_STATUS Status;\r |
240 | EFI_HANDLE *HandleBuffer;\r | |
241 | UINTN HandleCount;\r | |
242 | UINTN IndexFv;\r | |
243 | UINTN IndexFile;\r | |
244 | UINTN Key;\r | |
245 | EFI_GUID NameGuid;\r | |
246 | EFI_FV_FILE_ATTRIBUTES Attributes;\r | |
247 | EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r | |
682cee4c | 248 | \r |
59222fe9 DB |
249 | ASSERT (Buffer != NULL);\r |
250 | ASSERT (Size != NULL);\r | |
251 | \r | |
682cee4c LG |
252 | //\r |
253 | // Locate all available FVs.\r | |
254 | //\r | |
255 | HandleBuffer = NULL;\r | |
2f88bd3a MK |
256 | Status = gBS->LocateHandleBuffer (\r |
257 | ByProtocol,\r | |
258 | &gEfiFirmwareVolume2ProtocolGuid,\r | |
259 | NULL,\r | |
260 | &HandleCount,\r | |
261 | &HandleBuffer\r | |
262 | );\r | |
682cee4c LG |
263 | if (EFI_ERROR (Status)) {\r |
264 | return Status;\r | |
265 | }\r | |
266 | \r | |
267 | //\r | |
268 | // Go through FVs one by one to find the required section data.\r | |
269 | //\r | |
270 | for (IndexFv = 0; IndexFv < HandleCount; IndexFv++) {\r | |
271 | Status = gBS->HandleProtocol (\r | |
272 | HandleBuffer[IndexFv],\r | |
273 | &gEfiFirmwareVolume2ProtocolGuid,\r | |
274 | (VOID **)&Fv\r | |
275 | );\r | |
276 | if (EFI_ERROR (Status)) {\r | |
277 | continue;\r | |
278 | }\r | |
279 | \r | |
280 | //\r | |
281 | // Use Firmware Volume 2 Protocol to search for a file of type FileType in all FVs.\r | |
282 | //\r | |
283 | IndexFile = FileInstance + 1;\r | |
2f88bd3a | 284 | Key = 0;\r |
682cee4c LG |
285 | do {\r |
286 | Status = Fv->GetNextFile (Fv, &Key, &FileType, &NameGuid, &Attributes, Size);\r | |
287 | if (EFI_ERROR (Status)) {\r | |
288 | break;\r | |
289 | }\r | |
2f88bd3a MK |
290 | \r |
291 | IndexFile--;\r | |
682cee4c | 292 | } while (IndexFile > 0);\r |
b0d803fe | 293 | \r |
682cee4c LG |
294 | //\r |
295 | // Fv File with the required FV file type is found.\r | |
296 | // Search the section file in the found FV file.\r | |
297 | //\r | |
298 | if (IndexFile == 0) {\r | |
299 | Status = InternalGetSectionFromFv (\r | |
9095d37b | 300 | HandleBuffer[IndexFv],\r |
682cee4c LG |
301 | &NameGuid,\r |
302 | SectionType,\r | |
303 | SectionInstance,\r | |
304 | Buffer,\r | |
305 | Size\r | |
306 | );\r | |
307 | \r | |
308 | if (!EFI_ERROR (Status)) {\r | |
309 | goto Done;\r | |
310 | }\r | |
311 | }\r | |
312 | }\r | |
313 | \r | |
314 | //\r | |
9095d37b | 315 | // The required FFS section file is not found.\r |
682cee4c LG |
316 | //\r |
317 | if (IndexFv == HandleCount) {\r | |
318 | Status = EFI_NOT_FOUND;\r | |
319 | }\r | |
320 | \r | |
321 | Done:\r | |
9095d37b | 322 | if (HandleBuffer != NULL) {\r |
2f88bd3a | 323 | FreePool (HandleBuffer);\r |
682cee4c LG |
324 | }\r |
325 | \r | |
326 | return Status;\r | |
327 | }\r | |
b0d803fe | 328 | \r |
f80b0830 | 329 | /**\r |
9095d37b LG |
330 | Searches all the availables firmware volumes and returns the first matching FFS section.\r |
331 | \r | |
332 | This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid.\r | |
333 | The order that the firmware volumes is searched is not deterministic. For each FFS file found a search\r | |
334 | is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance instances\r | |
335 | of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer.\r | |
336 | Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size.\r | |
337 | It is the caller's responsibility to use FreePool() to free the allocated buffer.\r | |
338 | See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections\r | |
b75a165d LG |
339 | are retrieved from an FFS file based on SectionType and SectionInstance.\r |
340 | \r | |
9095d37b | 341 | If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,\r |
b75a165d LG |
342 | the search will be retried with a section type of EFI_SECTION_PE32.\r |
343 | This function must be called with a TPL <= TPL_NOTIFY.\r | |
344 | \r | |
345 | If NameGuid is NULL, then ASSERT().\r | |
346 | If Buffer is NULL, then ASSERT().\r | |
ff197efb | 347 | If Size is NULL, then ASSERT().\r |
348 | \r | |
f80b0830 | 349 | \r |
9095d37b LG |
350 | @param NameGuid A pointer to to the FFS filename GUID to search for\r |
351 | within any of the firmware volumes in the platform.\r | |
352 | @param SectionType Indicates the FFS section type to search for within\r | |
58380e9c | 353 | the FFS file specified by NameGuid.\r |
9095d37b | 354 | @param SectionInstance Indicates which section instance within the FFS file\r |
58380e9c | 355 | specified by NameGuid to retrieve.\r |
9095d37b LG |
356 | @param Buffer On output, a pointer to a callee allocated buffer\r |
357 | containing the FFS file section that was found.\r | |
358 | Is it the caller's responsibility to free this buffer\r | |
58380e9c | 359 | using FreePool().\r |
b75a165d LG |
360 | @param Size On output, a pointer to the size, in bytes, of Buffer.\r |
361 | \r | |
362 | @retval EFI_SUCCESS The specified FFS section was returned.\r | |
363 | @retval EFI_NOT_FOUND The specified FFS section could not be found.\r | |
9095d37b | 364 | @retval EFI_OUT_OF_RESOURCES There are not enough resources available to\r |
58380e9c | 365 | retrieve the matching FFS section.\r |
9095d37b | 366 | @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a\r |
58380e9c | 367 | device error.\r |
9095d37b LG |
368 | @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the\r |
369 | firmware volume that\r | |
b75a165d | 370 | contains the matching FFS section does not allow reads.\r |
f80b0830 | 371 | **/\r |
b0d803fe | 372 | EFI_STATUS\r |
373 | EFIAPI\r | |
eb9dd4d0 | 374 | GetSectionFromAnyFv (\r |
2f88bd3a MK |
375 | IN CONST EFI_GUID *NameGuid,\r |
376 | IN EFI_SECTION_TYPE SectionType,\r | |
377 | IN UINTN SectionInstance,\r | |
378 | OUT VOID **Buffer,\r | |
379 | OUT UINTN *Size\r | |
b0d803fe | 380 | )\r |
381 | {\r | |
2f88bd3a MK |
382 | EFI_STATUS Status;\r |
383 | EFI_HANDLE *HandleBuffer;\r | |
384 | UINTN HandleCount;\r | |
385 | UINTN Index;\r | |
386 | EFI_HANDLE FvHandle;\r | |
b0d803fe | 387 | \r |
388 | //\r | |
389 | // Search the FV that contain the caller's FFS first.\r | |
390 | // FV builder can choose to build FFS into the this FV\r | |
391 | // so that this implementation of GetSectionFromAnyFv\r | |
392 | // will locate the FFS faster.\r | |
393 | //\r | |
166152e8 | 394 | FvHandle = InternalImageHandleToFvHandle (gImageHandle);\r |
2f88bd3a MK |
395 | Status = InternalGetSectionFromFv (\r |
396 | FvHandle,\r | |
397 | NameGuid,\r | |
398 | SectionType,\r | |
399 | SectionInstance,\r | |
400 | Buffer,\r | |
401 | Size\r | |
402 | );\r | |
b0d803fe | 403 | if (!EFI_ERROR (Status)) {\r |
404 | return EFI_SUCCESS;\r | |
405 | }\r | |
406 | \r | |
b0d803fe | 407 | HandleBuffer = NULL;\r |
2f88bd3a MK |
408 | Status = gBS->LocateHandleBuffer (\r |
409 | ByProtocol,\r | |
410 | &gEfiFirmwareVolume2ProtocolGuid,\r | |
411 | NULL,\r | |
412 | &HandleCount,\r | |
413 | &HandleBuffer\r | |
414 | );\r | |
b0d803fe | 415 | if (EFI_ERROR (Status)) {\r |
416 | goto Done;\r | |
417 | }\r | |
418 | \r | |
ff197efb | 419 | for (Index = 0; Index < HandleCount; Index++) {\r |
b0d803fe | 420 | //\r |
421 | // Skip the FV that contain the caller's FFS\r | |
422 | //\r | |
ff197efb | 423 | if (HandleBuffer[Index] != FvHandle) {\r |
eb9dd4d0 | 424 | Status = InternalGetSectionFromFv (\r |
9095d37b LG |
425 | HandleBuffer[Index],\r |
426 | NameGuid,\r | |
427 | SectionType,\r | |
ff197efb | 428 | SectionInstance,\r |
9095d37b | 429 | Buffer,\r |
ff197efb | 430 | Size\r |
431 | );\r | |
432 | \r | |
433 | if (!EFI_ERROR (Status)) {\r | |
434 | goto Done;\r | |
435 | }\r | |
b0d803fe | 436 | }\r |
b0d803fe | 437 | }\r |
438 | \r | |
439 | if (Index == HandleCount) {\r | |
440 | Status = EFI_NOT_FOUND;\r | |
441 | }\r | |
442 | \r | |
443 | Done:\r | |
9095d37b LG |
444 | \r |
445 | if (HandleBuffer != NULL) {\r | |
2f88bd3a | 446 | FreePool (HandleBuffer);\r |
b0d803fe | 447 | }\r |
9095d37b | 448 | \r |
2f88bd3a | 449 | return Status;\r |
b0d803fe | 450 | }\r |
451 | \r | |
f80b0830 | 452 | /**\r |
9095d37b | 453 | Searches the firmware volume that the currently executing module was loaded from and returns the first matching FFS section.\r |
b75a165d | 454 | \r |
9095d37b LG |
455 | This function searches the firmware volume that the currently executing module was loaded\r |
456 | from for an FFS file with an FFS filename specified by NameGuid. If the FFS file is found a search\r | |
457 | is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance\r | |
b75a165d | 458 | instances of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer.\r |
9095d37b LG |
459 | Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size.\r |
460 | It is the caller's responsibility to use FreePool() to free the allocated buffer.\r | |
461 | See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections are retrieved from\r | |
b75a165d LG |
462 | an FFS file based on SectionType and SectionInstance.\r |
463 | \r | |
464 | If the currently executing module was not loaded from a firmware volume, then EFI_NOT_FOUND is returned.\r | |
9095d37b | 465 | If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,\r |
b75a165d | 466 | the search will be retried with a section type of EFI_SECTION_PE32.\r |
9095d37b | 467 | \r |
b75a165d LG |
468 | This function must be called with a TPL <= TPL_NOTIFY.\r |
469 | If NameGuid is NULL, then ASSERT().\r | |
470 | If Buffer is NULL, then ASSERT().\r | |
ff197efb | 471 | If Size is NULL, then ASSERT().\r |
472 | \r | |
9095d37b LG |
473 | @param NameGuid A pointer to to the FFS filename GUID to search for\r |
474 | within the firmware volumes that the currently\r | |
58380e9c | 475 | executing module was loaded from.\r |
9095d37b | 476 | @param SectionType Indicates the FFS section type to search for within\r |
58380e9c | 477 | the FFS file specified by NameGuid.\r |
9095d37b | 478 | @param SectionInstance Indicates which section instance within the FFS file\r |
58380e9c | 479 | specified by NameGuid to retrieve.\r |
9095d37b LG |
480 | @param Buffer On output, a pointer to a callee allocated buffer\r |
481 | containing the FFS file section that was found.\r | |
482 | Is it the caller's responsibility to free this buffer\r | |
58380e9c | 483 | using FreePool().\r |
b75a165d LG |
484 | @param Size On output, a pointer to the size, in bytes, of Buffer.\r |
485 | \r | |
486 | \r | |
487 | @retval EFI_SUCCESS The specified FFS section was returned.\r | |
488 | @retval EFI_NOT_FOUND The specified FFS section could not be found.\r | |
9095d37b | 489 | @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve\r |
58380e9c | 490 | the matching FFS section.\r |
9095d37b | 491 | @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a\r |
58380e9c | 492 | device error.\r |
9095d37b LG |
493 | @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the\r |
494 | firmware volume that contains the matching FFS\r | |
495 | section does not allow reads.\r | |
f80b0830 | 496 | **/\r |
b0d803fe | 497 | EFI_STATUS\r |
498 | EFIAPI\r | |
eb9dd4d0 | 499 | GetSectionFromFv (\r |
2f88bd3a MK |
500 | IN CONST EFI_GUID *NameGuid,\r |
501 | IN EFI_SECTION_TYPE SectionType,\r | |
502 | IN UINTN SectionInstance,\r | |
503 | OUT VOID **Buffer,\r | |
504 | OUT UINTN *Size\r | |
505 | )\r | |
b0d803fe | 506 | {\r |
eb9dd4d0 | 507 | return InternalGetSectionFromFv (\r |
2f88bd3a | 508 | InternalImageHandleToFvHandle (gImageHandle),\r |
eb9dd4d0 | 509 | NameGuid,\r |
510 | SectionType,\r | |
511 | SectionInstance,\r | |
512 | Buffer,\r | |
513 | Size\r | |
514 | );\r | |
b0d803fe | 515 | }\r |
516 | \r | |
f80b0830 | 517 | /**\r |
c1d8b697 | 518 | Searches the FFS file the currently executing module was loaded from and returns the first matching FFS section.\r |
b75a165d LG |
519 | \r |
520 | This function searches the FFS file that the currently executing module was loaded from for a FFS sections of type SectionType.\r | |
9095d37b LG |
521 | If the FFS file contains at least SectionInstance instances of the FFS section specified by SectionType,\r |
522 | then the SectionInstance instance is returned in Buffer. Buffer is allocated using AllocatePool(),\r | |
523 | and the size of the allocated buffer is returned in Size. It is the caller's responsibility\r | |
524 | to use FreePool() to free the allocated buffer. See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for\r | |
b75a165d LG |
525 | details on how sections are retrieved from an FFS file based on SectionType and SectionInstance.\r |
526 | \r | |
527 | If the currently executing module was not loaded from an FFS file, then EFI_NOT_FOUND is returned.\r | |
9095d37b | 528 | If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,\r |
b75a165d LG |
529 | the search will be retried with a section type of EFI_SECTION_PE32.\r |
530 | This function must be called with a TPL <= TPL_NOTIFY.\r | |
9095d37b | 531 | \r |
b75a165d | 532 | If Buffer is NULL, then ASSERT().\r |
ff197efb | 533 | If Size is NULL, then ASSERT().\r |
534 | \r | |
b75a165d | 535 | \r |
9095d37b LG |
536 | @param SectionType Indicates the FFS section type to search for within\r |
537 | the FFS file that the currently executing module\r | |
58380e9c | 538 | was loaded from.\r |
9095d37b LG |
539 | @param SectionInstance Indicates which section instance to retrieve within\r |
540 | the FFS file that the currently executing module\r | |
58380e9c | 541 | was loaded from.\r |
9095d37b LG |
542 | @param Buffer On output, a pointer to a callee allocated buffer\r |
543 | containing the FFS file section that was found.\r | |
544 | Is it the caller's responsibility to free this buffer\r | |
58380e9c | 545 | using FreePool().\r |
b75a165d LG |
546 | @param Size On output, a pointer to the size, in bytes, of Buffer.\r |
547 | \r | |
548 | @retval EFI_SUCCESS The specified FFS section was returned.\r | |
549 | @retval EFI_NOT_FOUND The specified FFS section could not be found.\r | |
9095d37b | 550 | @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve\r |
58380e9c | 551 | the matching FFS section.\r |
9095d37b | 552 | @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a\r |
58380e9c | 553 | device error.\r |
9095d37b LG |
554 | @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the\r |
555 | firmware volume that contains the matching FFS\r | |
556 | section does not allow reads.\r | |
557 | \r | |
f80b0830 | 558 | **/\r |
b0d803fe | 559 | EFI_STATUS\r |
560 | EFIAPI\r | |
eb9dd4d0 | 561 | GetSectionFromFfs (\r |
2f88bd3a MK |
562 | IN EFI_SECTION_TYPE SectionType,\r |
563 | IN UINTN SectionInstance,\r | |
564 | OUT VOID **Buffer,\r | |
565 | OUT UINTN *Size\r | |
566 | )\r | |
b0d803fe | 567 | {\r |
2f88bd3a MK |
568 | return InternalGetSectionFromFv (\r |
569 | InternalImageHandleToFvHandle (gImageHandle),\r | |
eb9dd4d0 | 570 | &gEfiCallerIdGuid,\r |
571 | SectionType,\r | |
572 | SectionInstance,\r | |
573 | Buffer,\r | |
574 | Size\r | |
575 | );\r | |
b0d803fe | 576 | }\r |
577 | \r | |
84716614 | 578 | /**\r |
9095d37b LG |
579 | Get the image file buffer data and buffer size by its device path.\r |
580 | \r | |
581 | Access the file either from a firmware volume, from a file system interface,\r | |
84716614 | 582 | or from the load file interface.\r |
9095d37b | 583 | \r |
84716614 LG |
584 | Allocate memory to store the found image. The caller is responsible to free memory.\r |
585 | \r | |
3556c7a2 | 586 | If FilePath is NULL, then NULL is returned.\r |
84716614 LG |
587 | If FileSize is NULL, then NULL is returned.\r |
588 | If AuthenticationStatus is NULL, then NULL is returned.\r | |
589 | \r | |
9095d37b LG |
590 | @param[in] BootPolicy Policy for Open Image File.If TRUE, indicates\r |
591 | that the request originates from the boot\r | |
58380e9c | 592 | manager, and that the boot manager is\r |
593 | attempting to load FilePath as a boot\r | |
9095d37b | 594 | selection. If FALSE, then FilePath must\r |
58380e9c | 595 | match an exact file to be loaded.\r |
596 | @param[in] FilePath The pointer to the device path of the file\r | |
c1d8b697 | 597 | that is abstracted to the file buffer.\r |
9095d37b | 598 | @param[out] FileSize The pointer to the size of the abstracted\r |
58380e9c | 599 | file buffer.\r |
3556c7a2 | 600 | @param[out] AuthenticationStatus Pointer to the authentication status.\r |
58380e9c | 601 | \r |
3556c7a2 | 602 | @retval NULL FilePath is NULL, or FileSize is NULL, or AuthenticationStatus is NULL, or the file can't be found.\r |
84716614 LG |
603 | @retval other The abstracted file buffer. The caller is responsible to free memory.\r |
604 | **/\r | |
605 | VOID *\r | |
606 | EFIAPI\r | |
607 | GetFileBufferByFilePath (\r | |
2f88bd3a MK |
608 | IN BOOLEAN BootPolicy,\r |
609 | IN CONST EFI_DEVICE_PATH_PROTOCOL *FilePath,\r | |
610 | OUT UINTN *FileSize,\r | |
611 | OUT UINT32 *AuthenticationStatus\r | |
84716614 LG |
612 | )\r |
613 | {\r | |
2f88bd3a MK |
614 | EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r |
615 | EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode;\r | |
616 | EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode;\r | |
617 | EFI_HANDLE Handle;\r | |
618 | EFI_GUID *FvNameGuid;\r | |
619 | EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;\r | |
620 | EFI_SECTION_TYPE SectionType;\r | |
621 | UINT8 *ImageBuffer;\r | |
622 | UINTN ImageBufferSize;\r | |
623 | EFI_FV_FILETYPE Type;\r | |
624 | EFI_FV_FILE_ATTRIBUTES Attrib;\r | |
625 | EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r | |
626 | EFI_FILE_HANDLE FileHandle;\r | |
627 | EFI_FILE_HANDLE LastHandle;\r | |
628 | EFI_FILE_INFO *FileInfo;\r | |
629 | UINTN FileInfoSize;\r | |
630 | EFI_LOAD_FILE_PROTOCOL *LoadFile;\r | |
631 | EFI_LOAD_FILE2_PROTOCOL *LoadFile2;\r | |
632 | EFI_STATUS Status;\r | |
84716614 LG |
633 | \r |
634 | //\r | |
635 | // Check input File device path.\r | |
636 | //\r | |
2f88bd3a | 637 | if ((FilePath == NULL) || (FileSize == NULL) || (AuthenticationStatus == NULL)) {\r |
84716614 LG |
638 | return NULL;\r |
639 | }\r | |
640 | \r | |
641 | //\r | |
642 | // Init local variable\r | |
643 | //\r | |
2f88bd3a MK |
644 | TempDevicePathNode = NULL;\r |
645 | FvNameGuid = NULL;\r | |
646 | FileInfo = NULL;\r | |
647 | FileHandle = NULL;\r | |
648 | ImageBuffer = NULL;\r | |
649 | ImageBufferSize = 0;\r | |
84716614 | 650 | *AuthenticationStatus = 0;\r |
9095d37b | 651 | \r |
84716614 LG |
652 | //\r |
653 | // Copy File Device Path\r | |
654 | //\r | |
655 | OrigDevicePathNode = DuplicateDevicePath (FilePath);\r | |
656 | if (OrigDevicePathNode == NULL) {\r | |
657 | return NULL;\r | |
658 | }\r | |
659 | \r | |
660 | //\r | |
661 | // Check whether this device path support FV2 protocol.\r | |
662 | // Is so, this device path may contain a Image.\r | |
663 | //\r | |
664 | DevicePathNode = OrigDevicePathNode;\r | |
2f88bd3a | 665 | Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePathNode, &Handle);\r |
84716614 LG |
666 | if (!EFI_ERROR (Status)) {\r |
667 | //\r | |
668 | // For FwVol File system there is only a single file name that is a GUID.\r | |
669 | //\r | |
2f88bd3a | 670 | FvNameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevicePathNode);\r |
84716614 LG |
671 | if (FvNameGuid == NULL) {\r |
672 | Status = EFI_INVALID_PARAMETER;\r | |
673 | } else {\r | |
674 | //\r | |
675 | // Read image from the firmware file\r | |
676 | //\r | |
2f88bd3a | 677 | Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FwVol);\r |
84716614 LG |
678 | if (!EFI_ERROR (Status)) {\r |
679 | SectionType = EFI_SECTION_PE32;\r | |
680 | ImageBuffer = NULL;\r | |
2f88bd3a MK |
681 | Status = FwVol->ReadSection (\r |
682 | FwVol,\r | |
683 | FvNameGuid,\r | |
684 | SectionType,\r | |
685 | 0,\r | |
686 | (VOID **)&ImageBuffer,\r | |
687 | &ImageBufferSize,\r | |
688 | AuthenticationStatus\r | |
689 | );\r | |
84716614 LG |
690 | if (EFI_ERROR (Status)) {\r |
691 | //\r | |
692 | // Try a raw file, since a PE32 SECTION does not exist\r | |
693 | //\r | |
694 | if (ImageBuffer != NULL) {\r | |
695 | FreePool (ImageBuffer);\r | |
696 | *AuthenticationStatus = 0;\r | |
697 | }\r | |
2f88bd3a | 698 | \r |
84716614 | 699 | ImageBuffer = NULL;\r |
2f88bd3a MK |
700 | Status = FwVol->ReadFile (\r |
701 | FwVol,\r | |
702 | FvNameGuid,\r | |
703 | (VOID **)&ImageBuffer,\r | |
704 | &ImageBufferSize,\r | |
705 | &Type,\r | |
706 | &Attrib,\r | |
707 | AuthenticationStatus\r | |
708 | );\r | |
84716614 LG |
709 | }\r |
710 | }\r | |
711 | }\r | |
2f88bd3a | 712 | \r |
c119933d | 713 | if (!EFI_ERROR (Status)) {\r |
714 | goto Finish;\r | |
715 | }\r | |
84716614 LG |
716 | }\r |
717 | \r | |
718 | //\r | |
719 | // Attempt to access the file via a file system interface\r | |
720 | //\r | |
721 | DevicePathNode = OrigDevicePathNode;\r | |
2f88bd3a | 722 | Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &DevicePathNode, &Handle);\r |
84716614 | 723 | if (!EFI_ERROR (Status)) {\r |
2f88bd3a | 724 | Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Volume);\r |
84716614 LG |
725 | if (!EFI_ERROR (Status)) {\r |
726 | //\r | |
727 | // Open the Volume to get the File System handle\r | |
728 | //\r | |
729 | Status = Volume->OpenVolume (Volume, &FileHandle);\r | |
730 | if (!EFI_ERROR (Status)) {\r | |
95dd343a LG |
731 | //\r |
732 | // Duplicate the device path to avoid the access to unaligned device path node.\r | |
733 | // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH\r | |
734 | // nodes, It assures the fields in device path nodes are 2 byte aligned.\r | |
735 | //\r | |
736 | TempDevicePathNode = DuplicateDevicePath (DevicePathNode);\r | |
737 | if (TempDevicePathNode == NULL) {\r | |
738 | FileHandle->Close (FileHandle);\r | |
c119933d | 739 | //\r |
740 | // Setting Status to an EFI_ERROR value will cause the rest of\r | |
741 | // the file system support below to be skipped.\r | |
742 | //\r | |
95dd343a | 743 | Status = EFI_OUT_OF_RESOURCES;\r |
95dd343a | 744 | }\r |
2f88bd3a | 745 | \r |
84716614 LG |
746 | //\r |
747 | // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the\r | |
c1d8b697 | 748 | // directory information and filename can be separate. The goal is to inch\r |
84716614 LG |
749 | // our way down each device path node and close the previous node\r |
750 | //\r | |
95dd343a | 751 | DevicePathNode = TempDevicePathNode;\r |
c119933d | 752 | while (!EFI_ERROR (Status) && !IsDevicePathEnd (DevicePathNode)) {\r |
2f88bd3a MK |
753 | if ((DevicePathType (DevicePathNode) != MEDIA_DEVICE_PATH) ||\r |
754 | (DevicePathSubType (DevicePathNode) != MEDIA_FILEPATH_DP))\r | |
755 | {\r | |
84716614 LG |
756 | Status = EFI_UNSUPPORTED;\r |
757 | break;\r | |
758 | }\r | |
9095d37b | 759 | \r |
84716614 LG |
760 | LastHandle = FileHandle;\r |
761 | FileHandle = NULL;\r | |
9095d37b | 762 | \r |
84716614 | 763 | Status = LastHandle->Open (\r |
2f88bd3a MK |
764 | LastHandle,\r |
765 | &FileHandle,\r | |
766 | ((FILEPATH_DEVICE_PATH *)DevicePathNode)->PathName,\r | |
767 | EFI_FILE_MODE_READ,\r | |
768 | 0\r | |
769 | );\r | |
9095d37b | 770 | \r |
84716614 LG |
771 | //\r |
772 | // Close the previous node\r | |
773 | //\r | |
774 | LastHandle->Close (LastHandle);\r | |
9095d37b | 775 | \r |
84716614 LG |
776 | DevicePathNode = NextDevicePathNode (DevicePathNode);\r |
777 | }\r | |
9095d37b | 778 | \r |
84716614 LG |
779 | if (!EFI_ERROR (Status)) {\r |
780 | //\r | |
781 | // We have found the file. Now we need to read it. Before we can read the file we need to\r | |
782 | // figure out how big the file is.\r | |
783 | //\r | |
2f88bd3a | 784 | FileInfo = NULL;\r |
84716614 | 785 | FileInfoSize = 0;\r |
2f88bd3a MK |
786 | Status = FileHandle->GetInfo (\r |
787 | FileHandle,\r | |
788 | &gEfiFileInfoGuid,\r | |
789 | &FileInfoSize,\r | |
790 | FileInfo\r | |
791 | );\r | |
9095d37b | 792 | \r |
84716614 LG |
793 | if (Status == EFI_BUFFER_TOO_SMALL) {\r |
794 | FileInfo = AllocatePool (FileInfoSize);\r | |
795 | if (FileInfo == NULL) {\r | |
796 | Status = EFI_OUT_OF_RESOURCES;\r | |
797 | } else {\r | |
798 | Status = FileHandle->GetInfo (\r | |
2f88bd3a MK |
799 | FileHandle,\r |
800 | &gEfiFileInfoGuid,\r | |
801 | &FileInfoSize,\r | |
802 | FileInfo\r | |
803 | );\r | |
84716614 LG |
804 | }\r |
805 | }\r | |
9095d37b | 806 | \r |
e191bb14 | 807 | if (!EFI_ERROR (Status) && (FileInfo != NULL)) {\r |
93e8630a | 808 | if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {\r |
84716614 | 809 | //\r |
93e8630a | 810 | // Allocate space for the file\r |
84716614 | 811 | //\r |
93e8630a RN |
812 | ImageBuffer = AllocatePool ((UINTN)FileInfo->FileSize);\r |
813 | if (ImageBuffer == NULL) {\r | |
814 | Status = EFI_OUT_OF_RESOURCES;\r | |
815 | } else {\r | |
816 | //\r | |
817 | // Read the file into the buffer we allocated\r | |
818 | //\r | |
819 | ImageBufferSize = (UINTN)FileInfo->FileSize;\r | |
820 | Status = FileHandle->Read (FileHandle, &ImageBufferSize, ImageBuffer);\r | |
821 | }\r | |
84716614 LG |
822 | }\r |
823 | }\r | |
824 | }\r | |
2f88bd3a | 825 | \r |
84716614 | 826 | //\r |
95dd343a | 827 | // Close the file and Free FileInfo and TempDevicePathNode since we are done\r |
9095d37b | 828 | //\r |
84716614 LG |
829 | if (FileInfo != NULL) {\r |
830 | FreePool (FileInfo);\r | |
831 | }\r | |
2f88bd3a | 832 | \r |
84716614 LG |
833 | if (FileHandle != NULL) {\r |
834 | FileHandle->Close (FileHandle);\r | |
835 | }\r | |
2f88bd3a | 836 | \r |
c119933d | 837 | if (TempDevicePathNode != NULL) {\r |
838 | FreePool (TempDevicePathNode);\r | |
839 | }\r | |
84716614 LG |
840 | }\r |
841 | }\r | |
2f88bd3a | 842 | \r |
c119933d | 843 | if (!EFI_ERROR (Status)) {\r |
844 | goto Finish;\r | |
845 | }\r | |
84716614 LG |
846 | }\r |
847 | \r | |
848 | //\r | |
849 | // Attempt to access the file via LoadFile2 interface\r | |
850 | //\r | |
851 | if (!BootPolicy) {\r | |
852 | DevicePathNode = OrigDevicePathNode;\r | |
2f88bd3a | 853 | Status = gBS->LocateDevicePath (&gEfiLoadFile2ProtocolGuid, &DevicePathNode, &Handle);\r |
84716614 | 854 | if (!EFI_ERROR (Status)) {\r |
2f88bd3a | 855 | Status = gBS->HandleProtocol (Handle, &gEfiLoadFile2ProtocolGuid, (VOID **)&LoadFile2);\r |
84716614 LG |
856 | if (!EFI_ERROR (Status)) {\r |
857 | //\r | |
858 | // Call LoadFile2 with the correct buffer size\r | |
859 | //\r | |
860 | ImageBufferSize = 0;\r | |
861 | ImageBuffer = NULL;\r | |
2f88bd3a MK |
862 | Status = LoadFile2->LoadFile (\r |
863 | LoadFile2,\r | |
864 | DevicePathNode,\r | |
865 | FALSE,\r | |
866 | &ImageBufferSize,\r | |
867 | ImageBuffer\r | |
868 | );\r | |
84716614 LG |
869 | if (Status == EFI_BUFFER_TOO_SMALL) {\r |
870 | ImageBuffer = AllocatePool (ImageBufferSize);\r | |
871 | if (ImageBuffer == NULL) {\r | |
872 | Status = EFI_OUT_OF_RESOURCES;\r | |
873 | } else {\r | |
874 | Status = LoadFile2->LoadFile (\r | |
2f88bd3a MK |
875 | LoadFile2,\r |
876 | DevicePathNode,\r | |
877 | FALSE,\r | |
878 | &ImageBufferSize,\r | |
879 | ImageBuffer\r | |
880 | );\r | |
84716614 LG |
881 | }\r |
882 | }\r | |
883 | }\r | |
2f88bd3a | 884 | \r |
c119933d | 885 | if (!EFI_ERROR (Status)) {\r |
886 | goto Finish;\r | |
887 | }\r | |
84716614 LG |
888 | }\r |
889 | }\r | |
890 | \r | |
891 | //\r | |
892 | // Attempt to access the file via LoadFile interface\r | |
893 | //\r | |
894 | DevicePathNode = OrigDevicePathNode;\r | |
2f88bd3a | 895 | Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &DevicePathNode, &Handle);\r |
84716614 | 896 | if (!EFI_ERROR (Status)) {\r |
2f88bd3a | 897 | Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFile);\r |
84716614 LG |
898 | if (!EFI_ERROR (Status)) {\r |
899 | //\r | |
900 | // Call LoadFile with the correct buffer size\r | |
901 | //\r | |
902 | ImageBufferSize = 0;\r | |
903 | ImageBuffer = NULL;\r | |
2f88bd3a MK |
904 | Status = LoadFile->LoadFile (\r |
905 | LoadFile,\r | |
906 | DevicePathNode,\r | |
907 | BootPolicy,\r | |
908 | &ImageBufferSize,\r | |
909 | ImageBuffer\r | |
910 | );\r | |
84716614 LG |
911 | if (Status == EFI_BUFFER_TOO_SMALL) {\r |
912 | ImageBuffer = AllocatePool (ImageBufferSize);\r | |
913 | if (ImageBuffer == NULL) {\r | |
914 | Status = EFI_OUT_OF_RESOURCES;\r | |
915 | } else {\r | |
916 | Status = LoadFile->LoadFile (\r | |
917 | LoadFile,\r | |
918 | DevicePathNode,\r | |
919 | BootPolicy,\r | |
920 | &ImageBufferSize,\r | |
921 | ImageBuffer\r | |
922 | );\r | |
923 | }\r | |
924 | }\r | |
925 | }\r | |
926 | }\r | |
927 | \r | |
928 | Finish:\r | |
929 | \r | |
930 | if (EFI_ERROR (Status)) {\r | |
931 | if (ImageBuffer != NULL) {\r | |
932 | FreePool (ImageBuffer);\r | |
933 | ImageBuffer = NULL;\r | |
934 | }\r | |
2f88bd3a | 935 | \r |
84716614 LG |
936 | *FileSize = 0;\r |
937 | } else {\r | |
938 | *FileSize = ImageBufferSize;\r | |
939 | }\r | |
940 | \r | |
941 | FreePool (OrigDevicePathNode);\r | |
942 | \r | |
943 | return ImageBuffer;\r | |
944 | }\r | |
711ef3f6 SC |
945 | \r |
946 | /**\r | |
947 | Searches all the available firmware volumes and returns the file device path of first matching\r | |
948 | FFS section.\r | |
949 | \r | |
950 | This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid.\r | |
951 | The order that the firmware volumes is searched is not deterministic. For each FFS file found a search\r | |
952 | is made for FFS sections of type SectionType.\r | |
953 | \r | |
954 | If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,\r | |
955 | the search will be retried with a section type of EFI_SECTION_PE32.\r | |
956 | This function must be called with a TPL <= TPL_NOTIFY.\r | |
957 | \r | |
958 | If NameGuid is NULL, then ASSERT().\r | |
959 | \r | |
960 | @param NameGuid A pointer to to the FFS filename GUID to search for\r | |
961 | within any of the firmware volumes in the platform.\r | |
962 | @param SectionType Indicates the FFS section type to search for within\r | |
963 | the FFS file specified by NameGuid.\r | |
964 | @param SectionInstance Indicates which section instance within the FFS file\r | |
965 | specified by NameGuid to retrieve.\r | |
966 | @param FvFileDevicePath Device path for the target FFS\r | |
967 | file.\r | |
968 | \r | |
969 | @retval EFI_SUCCESS The specified file device path of FFS section was returned.\r | |
970 | @retval EFI_NOT_FOUND The specified file device path of FFS section could not be found.\r | |
971 | @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a\r | |
972 | device error.\r | |
973 | @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the\r | |
974 | firmware volume that contains the matching FFS section does not\r | |
975 | allow reads.\r | |
976 | @retval EFI_INVALID_PARAMETER FvFileDevicePath is NULL.\r | |
977 | \r | |
978 | **/\r | |
979 | EFI_STATUS\r | |
980 | EFIAPI\r | |
981 | GetFileDevicePathFromAnyFv (\r | |
982 | IN CONST EFI_GUID *NameGuid,\r | |
983 | IN EFI_SECTION_TYPE SectionType,\r | |
984 | IN UINTN SectionInstance,\r | |
985 | OUT EFI_DEVICE_PATH_PROTOCOL **FvFileDevicePath\r | |
986 | )\r | |
987 | {\r | |
2f88bd3a MK |
988 | EFI_STATUS Status;\r |
989 | EFI_HANDLE *HandleBuffer;\r | |
990 | UINTN HandleCount;\r | |
991 | UINTN Index;\r | |
992 | EFI_HANDLE FvHandle;\r | |
993 | EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;\r | |
994 | MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *TempFvFileDevicePath;\r | |
995 | VOID *Buffer;\r | |
996 | UINTN Size;\r | |
711ef3f6 SC |
997 | \r |
998 | if (FvFileDevicePath == NULL) {\r | |
999 | return EFI_INVALID_PARAMETER;\r | |
1000 | }\r | |
1001 | \r | |
1002 | HandleBuffer = NULL;\r | |
1003 | FvDevicePath = NULL;\r | |
1004 | TempFvFileDevicePath = NULL;\r | |
1005 | Buffer = NULL;\r | |
1006 | Size = 0;\r | |
1007 | \r | |
1008 | //\r | |
1009 | // Search the FV that contain the caller's FFS first.\r | |
1010 | // FV builder can choose to build FFS into the this FV\r | |
1011 | // so that this implementation of GetSectionFromAnyFv\r | |
1012 | // will locate the FFS faster.\r | |
1013 | //\r | |
1014 | FvHandle = InternalImageHandleToFvHandle (gImageHandle);\r | |
2f88bd3a MK |
1015 | Status = InternalGetSectionFromFv (\r |
1016 | FvHandle,\r | |
1017 | NameGuid,\r | |
1018 | SectionType,\r | |
1019 | SectionInstance,\r | |
1020 | &Buffer,\r | |
1021 | &Size\r | |
1022 | );\r | |
711ef3f6 SC |
1023 | if (!EFI_ERROR (Status)) {\r |
1024 | goto Done;\r | |
1025 | }\r | |
1026 | \r | |
1027 | Status = gBS->LocateHandleBuffer (\r | |
1028 | ByProtocol,\r | |
1029 | &gEfiFirmwareVolume2ProtocolGuid,\r | |
1030 | NULL,\r | |
1031 | &HandleCount,\r | |
1032 | &HandleBuffer\r | |
1033 | );\r | |
1034 | if (EFI_ERROR (Status)) {\r | |
1035 | goto Done;\r | |
1036 | }\r | |
1037 | \r | |
1038 | for (Index = 0; Index < HandleCount; Index++) {\r | |
1039 | //\r | |
1040 | // Skip the FV that contain the caller's FFS\r | |
1041 | //\r | |
1042 | if (HandleBuffer[Index] != FvHandle) {\r | |
1043 | Status = InternalGetSectionFromFv (\r | |
1044 | HandleBuffer[Index],\r | |
1045 | NameGuid,\r | |
1046 | SectionType,\r | |
1047 | SectionInstance,\r | |
1048 | &Buffer,\r | |
1049 | &Size\r | |
1050 | );\r | |
1051 | \r | |
1052 | if (!EFI_ERROR (Status)) {\r | |
1053 | //\r | |
1054 | // Update FvHandle to the current handle.\r | |
1055 | //\r | |
1056 | FvHandle = HandleBuffer[Index];\r | |
1057 | goto Done;\r | |
1058 | }\r | |
1059 | }\r | |
1060 | }\r | |
1061 | \r | |
1062 | if (Index == HandleCount) {\r | |
1063 | Status = EFI_NOT_FOUND;\r | |
1064 | }\r | |
1065 | \r | |
1066 | Done:\r | |
1067 | if (Status == EFI_SUCCESS) {\r | |
1068 | //\r | |
1069 | // Build a device path to the file in the FV to pass into gBS->LoadImage\r | |
1070 | //\r | |
1071 | Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);\r | |
1072 | if (EFI_ERROR (Status)) {\r | |
1073 | *FvFileDevicePath = NULL;\r | |
1074 | } else {\r | |
1075 | TempFvFileDevicePath = AllocateZeroPool (sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + END_DEVICE_PATH_LENGTH);\r | |
1076 | if (TempFvFileDevicePath == NULL) {\r | |
1077 | *FvFileDevicePath = NULL;\r | |
1078 | return EFI_OUT_OF_RESOURCES;\r | |
1079 | }\r | |
2f88bd3a MK |
1080 | \r |
1081 | EfiInitializeFwVolDevicepathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempFvFileDevicePath, NameGuid);\r | |
711ef3f6 SC |
1082 | SetDevicePathEndNode (NextDevicePathNode (TempFvFileDevicePath));\r |
1083 | *FvFileDevicePath = AppendDevicePath (\r | |
1084 | FvDevicePath,\r | |
1085 | (EFI_DEVICE_PATH_PROTOCOL *)TempFvFileDevicePath\r | |
1086 | );\r | |
1087 | FreePool (TempFvFileDevicePath);\r | |
1088 | }\r | |
1089 | }\r | |
1090 | \r | |
1091 | if (Buffer != NULL) {\r | |
1092 | FreePool (Buffer);\r | |
1093 | }\r | |
1094 | \r | |
1095 | if (HandleBuffer != NULL) {\r | |
1096 | FreePool (HandleBuffer);\r | |
1097 | }\r | |
1098 | \r | |
1099 | return Status;\r | |
1100 | }\r |