]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/DxePiLib/DxePiLib.c
Merge branch of PI tree to main trunk
[mirror_edk2.git] / MdePkg / Library / DxePiLib / DxePiLib.c
1 /** @file
2 Mde PI library functions.
3
4 Copyright (c) 2007, Intel Corporation<BR>
5 All rights reserved. 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 <PiDxe.h>
16 #include <Library/DebugLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/PiLib.h>
20 #include <Protocol/FirmwareVolume2.h>
21 #include <Protocol/LoadedImage.h>
22
23
24 /**
25 Internal function which read the image specified by Firmware File GUID name and
26 the Firmware Section tyep from a specified Firmware Volume
27
28
29 @param Fv The Firmware Volume Protocol instance.
30 @param NameGuid The GUID name of a Firmware File.
31 @param SectionType The Firmware Section type.
32 @param Buffer On output, Buffer contains the the data read from the section in the Firmware File found.
33 @param Size On output, the size of Buffer.
34
35 @retval EFI_SUCCESS The image is found and data and size is returned.
36 @retval EFI_NOT_FOUND The image specified by NameGuid and SectionType can't be found.
37 @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the output data buffer or complete the operations.
38 @retval EFI_DEVICE_ERROR A hardware error occurs during reading from the Firmware Volume.
39 @retval EFI_ACCESS_DENIED The firmware volume containing the searched Firmware File is configured to disallow reads.
40
41 **/
42 STATIC
43 EFI_STATUS
44 InternalGetImageFromFv (
45 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
46 IN CONST EFI_GUID *NameGuid,
47 IN EFI_SECTION_TYPE SectionType,
48 OUT VOID **Buffer,
49 OUT UINTN *Size
50 )
51 {
52 EFI_STATUS Status;
53 EFI_FV_FILETYPE FileType;
54 EFI_FV_FILE_ATTRIBUTES Attributes;
55 UINT32 AuthenticationStatus;
56
57 //
58 // Read desired section content in NameGuid file
59 //
60 *Buffer = NULL;
61 *Size = 0;
62 Status = Fv->ReadSection (
63 Fv,
64 NameGuid,
65 SectionType,
66 0,
67 Buffer,
68 Size,
69 &AuthenticationStatus
70 );
71
72 if (EFI_ERROR (Status) && (SectionType == EFI_SECTION_TE)) {
73 //
74 // Try reading PE32 section, since the TE section does not exist
75 //
76 *Buffer = NULL;
77 *Size = 0;
78 Status = Fv->ReadSection (
79 Fv,
80 NameGuid,
81 EFI_SECTION_PE32,
82 0,
83 Buffer,
84 Size,
85 &AuthenticationStatus
86 );
87 }
88
89 if (EFI_ERROR (Status) &&
90 ((SectionType == EFI_SECTION_TE) || (SectionType == EFI_SECTION_PE32))) {
91 //
92 // Try reading raw file, since the desired section does not exist
93 //
94 *Buffer = NULL;
95 *Size = 0;
96 Status = Fv->ReadFile (
97 Fv,
98 NameGuid,
99 Buffer,
100 Size,
101 &FileType,
102 &Attributes,
103 &AuthenticationStatus
104 );
105 }
106
107 return Status;
108 }
109
110 /**
111 Allocate and fill a buffer with an image identified by a Firmware File GUID name and a Firmware Section type.
112 The Firmware Volumes to search for the Firmware File can be specified to be either all Firmware Volumes
113 in the system, or the Firmware Volume which contains the Firmware File specified by an image handle.
114
115 If ImageHandle is NULL, all Firmware Volumes in the system will be searched. If ImageHandle is not NULL,
116 ImageHandle is interpreted as EFI_PEI_FILE_HANDLE for the implementation of this function for PEI phase.
117 The input parameter ImageHandle is interpreted as EFI_HANDLE, on which an EFI_LOADED_IMAGE_PROTOCOL
118 is installed, for the implementation of this function for DXE phase. The search always starts from the FV
119 identified by ImageHandle. If WithinImageFv is TRUE, search will only be performed on the first FV. If WithinImageFv
120 is FALSE, search will continue on other FVs if it fails on the first FV. The search order of Firmware Volumes is
121 deterministic but arbitrary if no new firmware volume is added into the system between each search.
122
123 The search order for the section type specified by SectionType in the Firmware File is using a depth-first
124 and left-to-right algorithm through all sections. The first section found to match SectionType will be returned.
125
126 If SectionType is EFI_SECTION_PE32, EFI_SECTION_PE32 will be used as Firmware Section type
127 to read Firmware Section data from the Firmware File. If no such section exists, the function will try
128 to read a Firmware File named with NameGuid. If no such file exists, EFI_NOT_FOUND is returned.
129
130 If SectionType is EFI_SECTION_TE, EFI_SECTION_TE will be used as Firmware Section type to read Firmware Section
131 data from the Firmware File. If no such section exists, EFI_SECTION_PE32 will be used as Firmware Section type to
132 read Firmware Section data from the Firmware File. If no such section exists, the function will try to read a Firmware
133 File named with NameGuid. If no such file exists, EFI_NOT_FOUND is returned.
134
135 The data and size is returned by Buffer and Size. The caller is responsible to free the Buffer allocated
136 by this function. This function can only be called at TPL_NOTIFY and below.
137
138 If ImageHandle is NULL and WithinImage is TRUE, then ASSERT ();
139 If NameGuid is NULL, then ASSERT();
140 If Buffer is NULL, then ASSERT();
141 If Size is NULL, then ASSERT().
142
143 @param NameGuid The GUID name of a Firmware File.
144 @param SectionType The Firmware Section type.
145 @param Buffer On output, Buffer contains the the data read from the section in the Firmware File found.
146 @param Size On output, the size of Buffer.
147
148 @retval EFI_SUCCESS The image is found and data and size is returned.
149 @retval EFI_NOT_FOUND The image specified by NameGuid and SectionType can't be found.
150 @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the output data buffer or complete the operations.
151 @retval EFI_DEVICE_ERROR A hardware error occurs during reading from the Firmware Volume.
152 @retval EFI_ACCESS_DENIED The firmware volume containing the searched Firmware File is configured to disallow reads.
153
154 **/
155
156 EFI_STATUS
157 EFIAPI
158 GetSectionFromFvFile (
159 IN CONST VOID *ImageHandle,
160 IN CONST EFI_GUID *NameGuid,
161 IN EFI_SECTION_TYPE SectionType,
162 OUT VOID **Buffer,
163 OUT UINTN *Size,
164 IN BOOLEAN WithinImageFv
165 )
166 {
167 EFI_STATUS Status;
168 EFI_HANDLE *HandleBuffer;
169 UINTN HandleCount;
170 UINTN Index;
171 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
172 EFI_FIRMWARE_VOLUME2_PROTOCOL *ImageFv;
173 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
174
175 ASSERT (NameGuid != NULL);
176 ASSERT (Buffer != NULL);
177 ASSERT (Size != NULL);
178 ASSERT (!(ImageHandle == NULL && WithinImageFv));
179
180 Status = EFI_NOT_FOUND;
181 ImageFv = NULL;
182 if (ImageHandle != NULL) {
183 Status = gBS->HandleProtocol (
184 (EFI_HANDLE *) ImageHandle,
185 &gEfiLoadedImageProtocolGuid,
186 (VOID **) &LoadedImage
187 );
188 if (EFI_ERROR (Status)) {
189 return Status;
190 }
191 Status = gBS->HandleProtocol (
192 LoadedImage->DeviceHandle,
193 &gEfiFirmwareVolume2ProtocolGuid,
194 (VOID **) &ImageFv
195 );
196 if (!EFI_ERROR (Status)) {
197 Status = InternalGetImageFromFv (ImageFv, NameGuid, SectionType, Buffer, Size);
198 }
199 }
200
201 if (Status == EFI_SUCCESS || WithinImageFv) {
202 return Status;
203 }
204
205 HandleBuffer = NULL;
206 Status = gBS->LocateHandleBuffer (
207 ByProtocol,
208 &gEfiFirmwareVolume2ProtocolGuid,
209 NULL,
210 &HandleCount,
211 &HandleBuffer
212 );
213 if (EFI_ERROR (Status)) {
214 goto Done;
215 }
216
217 //
218 // Find desired image in all Fvs
219 //
220 for (Index = 0; Index < HandleCount; ++Index) {
221 Status = gBS->HandleProtocol (
222 HandleBuffer[Index],
223 &gEfiFirmwareVolume2ProtocolGuid,
224 (VOID**)&Fv
225 );
226
227 if (EFI_ERROR (Status)) {
228 goto Done;
229 }
230
231 if (ImageFv != NULL && Fv == ImageFv) {
232 continue;
233 }
234
235 Status = InternalGetImageFromFv (Fv, NameGuid, SectionType, Buffer, Size);
236
237 if (!EFI_ERROR (Status)) {
238 goto Done;
239 }
240 }
241
242 //
243 // Not found image
244 //
245 if (Index == HandleCount) {
246 Status = EFI_NOT_FOUND;
247 }
248
249 Done:
250
251 if (HandleBuffer != NULL) {
252 FreePool(HandleBuffer);
253 }
254
255 return Status;
256 }
257
258 EFI_HANDLE
259 EFIAPI
260 ImageHandleToFvHandle (
261 EFI_HANDLE ImageHandle
262 )
263 {
264 EFI_STATUS Status;
265 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
266
267 ASSERT (ImageHandle != NULL);
268
269 Status = gBS->HandleProtocol (
270 (EFI_HANDLE *) ImageHandle,
271 &gEfiLoadedImageProtocolGuid,
272 (VOID **) &LoadedImage
273 );
274
275 ASSERT_EFI_ERROR (Status);
276
277 return LoadedImage->DeviceHandle;
278
279 }
280
281 EFI_STATUS
282 EFIAPI
283 GetSectionFromAnyFv (
284 IN CONST EFI_GUID *NameGuid,
285 IN EFI_SECTION_TYPE SectionType,
286 IN UINTN Instance,
287 OUT VOID **Buffer,
288 OUT UINTN *Size
289 )
290 {
291 EFI_STATUS Status;
292 EFI_HANDLE *HandleBuffer;
293 UINTN HandleCount;
294 UINTN Index;
295 EFI_HANDLE FvHandle;
296 EFI_TPL OldTpl;
297
298 //
299 // Search the FV that contain the caller's FFS first.
300 // FV builder can choose to build FFS into the this FV
301 // so that this implementation of GetSectionFromAnyFv
302 // will locate the FFS faster.
303 //
304 FvHandle = ImageHandleToFvHandle (gImageHandle);
305 Status = GetSectionFromFv (
306 FvHandle,
307 NameGuid,
308 SectionType,
309 Instance,
310 Buffer,
311 Size
312 );
313 if (!EFI_ERROR (Status)) {
314 return EFI_SUCCESS;
315 }
316
317 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
318
319 HandleBuffer = NULL;
320 Status = gBS->LocateHandleBuffer (
321 ByProtocol,
322 &gEfiFirmwareVolume2ProtocolGuid,
323 NULL,
324 &HandleCount,
325 &HandleBuffer
326 );
327 if (EFI_ERROR (Status)) {
328 goto Done;
329 }
330
331 for (Index = 0; Index < HandleCount; ++Index) {
332 //
333 // Skip the FV that contain the caller's FFS
334 //
335 if (HandleBuffer[Index] == FvHandle) {
336 continue;
337 }
338
339 Status = GetSectionFromFv (
340 HandleBuffer[Index],
341 NameGuid,
342 SectionType,
343 Instance,
344 Buffer,
345 Size
346 );
347
348 if (!EFI_ERROR (Status)) {
349 goto Done;
350 }
351 }
352
353 if (Index == HandleCount) {
354 Status = EFI_NOT_FOUND;
355 }
356
357 Done:
358
359 gBS->RestoreTPL (OldTpl);
360
361 if (HandleBuffer != NULL) {
362 FreePool(HandleBuffer);
363 }
364 return Status;
365
366 }
367
368 EFI_STATUS
369 EFIAPI
370 GetSectionFromFv (
371 IN EFI_HANDLE FvHandle,
372 IN CONST EFI_GUID *NameGuid,
373 IN EFI_SECTION_TYPE SectionType,
374 IN UINTN Instance,
375 OUT VOID **Buffer,
376 OUT UINTN *Size
377 )
378 {
379 EFI_STATUS Status;
380 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
381 UINT32 AuthenticationStatus;
382
383 ASSERT (FvHandle != NULL);
384
385 Status = gBS->HandleProtocol (
386 FvHandle,
387 &gEfiFirmwareVolume2ProtocolGuid,
388 (VOID **) &Fv
389 );
390 if (EFI_ERROR (Status)) {
391 return Status;
392 }
393
394 //
395 // Read desired section content in NameGuid file
396 //
397 *Buffer = NULL;
398 *Size = 0;
399 Status = Fv->ReadSection (
400 Fv,
401 NameGuid,
402 SectionType,
403 0,
404 Buffer,
405 Size,
406 &AuthenticationStatus
407 );
408
409 if (EFI_ERROR (Status) && (SectionType == EFI_SECTION_TE)) {
410 //
411 // Try reading PE32 section, if the required section is TE type
412 //
413 *Buffer = NULL;
414 *Size = 0;
415 Status = Fv->ReadSection (
416 Fv,
417 NameGuid,
418 EFI_SECTION_PE32,
419 0,
420 Buffer,
421 Size,
422 &AuthenticationStatus
423 );
424 }
425
426 return Status;
427 }
428
429
430 EFI_STATUS
431 EFIAPI
432 GetSectionFromCurrentFv (
433 IN CONST EFI_GUID *NameGuid,
434 IN EFI_SECTION_TYPE SectionType,
435 IN UINTN Instance,
436 OUT VOID **Buffer,
437 OUT UINTN *Size
438 )
439 {
440 return GetSectionFromFv(
441 ImageHandleToFvHandle(gImageHandle),
442 NameGuid,
443 SectionType,
444 Instance,
445 Buffer,
446 Size
447 );
448 }
449
450
451
452 EFI_STATUS
453 EFIAPI
454 GetSectionFromCurrentFfs (
455 IN EFI_SECTION_TYPE SectionType,
456 IN UINTN Instance,
457 OUT VOID **Buffer,
458 OUT UINTN *Size
459 )
460 {
461 return GetSectionFromFv(
462 ImageHandleToFvHandle(gImageHandle),
463 &gEfiCallerIdGuid,
464 SectionType,
465 Instance,
466 Buffer,
467 Size
468 );
469 }
470