]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/FwVol/FwVolRead.c
MdeModulePkg DxeCore: Fix issue to print GUID value %g without pointer
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / FwVol / FwVolRead.c
CommitLineData
23c98c94 1/** @file\r
504214c4 2 Implements functions to read firmware file\r
28a00297 3\r
2bc08e8c 4Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
23c98c94 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
28a00297 12\r
504214c4 13**/\r
28a00297 14\r
9c4ac31c 15#include "DxeMain.h"\r
ec90508b 16#include "FwVolDriver.h"\r
28a00297 17\r
ec90508b 18/**\r
19Required Alignment Alignment Value in FFS Alignment Value in\r
28a00297 20(bytes) Attributes Field Firmware Volume Interfaces\r
211 0 0\r
28a00297 2216 1 4\r
23128 2 7\r
24512 3 9\r
251 KB 4 10\r
264 KB 5 12\r
2732 KB 6 15\r
2864 KB 7 16\r
ec90508b 29**/\r
022c6d45 30UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16};\r
28a00297 31\r
162ed594 32/**\r
33 Convert the FFS File Attributes to FV File Attributes\r
34\r
022c6d45 35 @param FfsAttributes The attributes of UINT8 type.\r
162ed594 36\r
37 @return The attributes of EFI_FV_FILE_ATTRIBUTES\r
38\r
39**/\r
28a00297 40EFI_FV_FILE_ATTRIBUTES\r
41FfsAttributes2FvFileAttributes (\r
42 IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes\r
43 )\r
28a00297 44{\r
795bb9b6
SZ
45 UINT8 DataAlignment;\r
46 EFI_FV_FILE_ATTRIBUTES FileAttribute;\r
28a00297 47\r
795bb9b6
SZ
48 DataAlignment = (UINT8) ((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);\r
49 ASSERT (DataAlignment < 8);\r
28a00297 50\r
795bb9b6 51 FileAttribute = (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[DataAlignment];\r
28a00297 52\r
795bb9b6
SZ
53 if ((FfsAttributes & FFS_ATTRIB_FIXED) == FFS_ATTRIB_FIXED) {\r
54 FileAttribute |= EFI_FV_FILE_ATTRIB_FIXED;\r
55 }\r
56\r
57 return FileAttribute;\r
58}\r
162ed594 59\r
60/**\r
61 Given the input key, search for the next matching file in the volume.\r
62\r
022c6d45 63 @param This Indicates the calling context.\r
64 @param Key Key is a pointer to a caller allocated\r
65 buffer that contains implementation specific\r
66 data that is used to track where to begin\r
67 the search for the next file. The size of\r
68 the buffer must be at least This->KeySize\r
69 bytes long. To reinitialize the search and\r
70 begin from the beginning of the firmware\r
71 volume, the entire buffer must be cleared to\r
72 zero. Other than clearing the buffer to\r
73 initiate a new search, the caller must not\r
74 modify the data in the buffer between calls\r
75 to GetNextFile().\r
76 @param FileType FileType is a pointer to a caller allocated\r
77 EFI_FV_FILETYPE. The GetNextFile() API can\r
78 filter it's search for files based on the\r
79 value of *FileType input. A *FileType input\r
80 of 0 causes GetNextFile() to search for\r
81 files of all types. If a file is found, the\r
82 file's type is returned in *FileType.\r
83 *FileType is not modified if no file is\r
84 found.\r
85 @param NameGuid NameGuid is a pointer to a caller allocated\r
86 EFI_GUID. If a file is found, the file's\r
87 name is returned in *NameGuid. *NameGuid is\r
88 not modified if no file is found.\r
89 @param Attributes Attributes is a pointer to a caller\r
90 allocated EFI_FV_FILE_ATTRIBUTES. If a file\r
91 is found, the file's attributes are returned\r
92 in *Attributes. *Attributes is not modified\r
93 if no file is found.\r
94 @param Size Size is a pointer to a caller allocated\r
95 UINTN. If a file is found, the file's size\r
96 is returned in *Size. *Size is not modified\r
97 if no file is found.\r
98\r
99 @retval EFI_SUCCESS Successfully find the file.\r
100 @retval EFI_DEVICE_ERROR Device error.\r
101 @retval EFI_ACCESS_DENIED Fv could not read.\r
102 @retval EFI_NOT_FOUND No matching file found.\r
162ed594 103 @retval EFI_INVALID_PARAMETER Invalid parameter\r
104\r
105**/\r
28a00297 106EFI_STATUS\r
107EFIAPI\r
108FvGetNextFile (\r
0c2b5da8 109 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,\r
110 IN OUT VOID *Key,\r
111 IN OUT EFI_FV_FILETYPE *FileType,\r
28a00297 112 OUT EFI_GUID *NameGuid,\r
113 OUT EFI_FV_FILE_ATTRIBUTES *Attributes,\r
162ed594 114 OUT UINTN *Size\r
28a00297 115 )\r
28a00297 116{\r
117 EFI_STATUS Status;\r
118 FV_DEVICE *FvDevice;\r
119 EFI_FV_ATTRIBUTES FvAttributes;\r
120 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
121 UINTN *KeyValue;\r
122 LIST_ENTRY *Link;\r
123 FFS_FILE_LIST_ENTRY *FfsFileEntry;\r
28a00297 124\r
125 FvDevice = FV_DEVICE_FROM_THIS (This);\r
126\r
127 Status = FvGetVolumeAttributes (This, &FvAttributes);\r
128 if (EFI_ERROR (Status)){\r
129 return Status;\r
130 }\r
131\r
132 //\r
133 // Check if read operation is enabled\r
134 //\r
0c2b5da8 135 if ((FvAttributes & EFI_FV2_READ_STATUS) == 0) {\r
28a00297 136 return EFI_ACCESS_DENIED;\r
137 }\r
138\r
202c3279 139 if (*FileType > EFI_FV_FILETYPE_SMM_CORE) {\r
28a00297 140 //\r
202c3279 141 // File type needs to be in 0 - 0x0D\r
28a00297 142 //\r
26fa3b49 143 return EFI_NOT_FOUND;\r
28a00297 144 }\r
145\r
146 KeyValue = (UINTN *)Key;\r
147 for (;;) {\r
148 if (*KeyValue == 0) {\r
149 //\r
150 // Search for 1st matching file\r
151 //\r
152 Link = &FvDevice->FfsFileListHeader;\r
153 } else {\r
154 //\r
155 // Key is pointer to FFsFileEntry, so get next one\r
156 //\r
157 Link = (LIST_ENTRY *)(*KeyValue);\r
158 }\r
159\r
160 if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {\r
161 //\r
162 // Next is end of list so we did not find data\r
163 //\r
164 return EFI_NOT_FOUND;\r
165 }\r
166\r
167 FfsFileEntry = (FFS_FILE_LIST_ENTRY *)Link->ForwardLink;\r
168 FfsFileHeader = (EFI_FFS_FILE_HEADER *)FfsFileEntry->FfsHeader;\r
169\r
170 //\r
171 // remember the key\r
172 //\r
173 *KeyValue = (UINTN)FfsFileEntry;\r
174\r
175 if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {\r
176 //\r
177 // we ignore pad files\r
178 //\r
179 continue;\r
180 }\r
181\r
ef816997 182 if (*FileType == EFI_FV_FILETYPE_ALL) {\r
28a00297 183 //\r
184 // Process all file types so we have a match\r
185 //\r
186 break;\r
187 }\r
188\r
189 if (*FileType == FfsFileHeader->Type) {\r
190 //\r
191 // Found a matching file type\r
192 //\r
193 break;\r
194 }\r
195\r
022c6d45 196 }\r
28a00297 197\r
198 //\r
199 // Return FileType, NameGuid, and Attributes\r
200 //\r
201 *FileType = FfsFileHeader->Type;\r
e94a9ff7 202 CopyGuid (NameGuid, &FfsFileHeader->Name);\r
28a00297 203 *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes);\r
795bb9b6
SZ
204 if ((FvDevice->FwVolHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {\r
205 *Attributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;\r
206 }\r
28a00297 207\r
28a00297 208 //\r
209 // we need to substract the header size\r
210 //\r
6c85d162
SZ
211 if (IS_FFS_FILE2 (FfsFileHeader)) {\r
212 *Size = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);\r
213 } else {\r
214 *Size = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);\r
215 }\r
28a00297 216\r
28a00297 217 return EFI_SUCCESS;\r
218}\r
219\r
220\r
162ed594 221\r
222/**\r
223 Locates a file in the firmware volume and\r
224 copies it to the supplied buffer.\r
225\r
022c6d45 226 @param This Indicates the calling context.\r
227 @param NameGuid Pointer to an EFI_GUID, which is the\r
228 filename.\r
229 @param Buffer Buffer is a pointer to pointer to a buffer\r
230 in which the file or section contents or are\r
231 returned.\r
232 @param BufferSize BufferSize is a pointer to caller allocated\r
233 UINTN. On input *BufferSize indicates the\r
234 size in bytes of the memory region pointed\r
235 to by Buffer. On output, *BufferSize\r
236 contains the number of bytes required to\r
237 read the file.\r
238 @param FoundType FoundType is a pointer to a caller allocated\r
239 EFI_FV_FILETYPE that on successful return\r
240 from Read() contains the type of file read.\r
241 This output reflects the file type\r
242 irrespective of the value of the SectionType\r
243 input.\r
244 @param FileAttributes FileAttributes is a pointer to a caller\r
245 allocated EFI_FV_FILE_ATTRIBUTES. On\r
246 successful return from Read(),\r
247 *FileAttributes contains the attributes of\r
248 the file read.\r
249 @param AuthenticationStatus AuthenticationStatus is a pointer to a\r
250 caller allocated UINTN in which the\r
251 authentication status is returned.\r
252\r
253 @retval EFI_SUCCESS Successfully read to memory buffer.\r
254 @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.\r
255 @retval EFI_NOT_FOUND Not found.\r
256 @retval EFI_DEVICE_ERROR Device error.\r
257 @retval EFI_ACCESS_DENIED Could not read.\r
258 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
162ed594 259 @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated.\r
260\r
261**/\r
28a00297 262EFI_STATUS\r
263EFIAPI\r
264FvReadFile (\r
0c2b5da8 265 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,\r
266 IN CONST EFI_GUID *NameGuid,\r
267 IN OUT VOID **Buffer,\r
268 IN OUT UINTN *BufferSize,\r
269 OUT EFI_FV_FILETYPE *FoundType,\r
270 OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,\r
271 OUT UINT32 *AuthenticationStatus\r
28a00297 272 )\r
28a00297 273{\r
274 EFI_STATUS Status;\r
275 FV_DEVICE *FvDevice;\r
276 EFI_GUID SearchNameGuid;\r
277 EFI_FV_FILETYPE LocalFoundType;\r
278 EFI_FV_FILE_ATTRIBUTES LocalAttributes;\r
279 UINTN FileSize;\r
280 UINT8 *SrcPtr;\r
281 EFI_FFS_FILE_HEADER *FfsHeader;\r
282 UINTN InputBufferSize;\r
eb1cace2 283 UINTN WholeFileSize;\r
022c6d45 284\r
e94a9ff7 285 if (NameGuid == NULL) {\r
28a00297 286 return EFI_INVALID_PARAMETER;\r
287 }\r
288\r
289 FvDevice = FV_DEVICE_FROM_THIS (This);\r
022c6d45 290\r
28a00297 291\r
292 //\r
293 // Keep looking until we find the matching NameGuid.\r
eb1cace2 294 // The Key is really a FfsFileEntry\r
28a00297 295 //\r
296 FvDevice->LastKey = 0;\r
297 do {\r
298 LocalFoundType = 0;\r
299 Status = FvGetNextFile (\r
300 This,\r
301 &FvDevice->LastKey,\r
302 &LocalFoundType,\r
303 &SearchNameGuid,\r
304 &LocalAttributes,\r
305 &FileSize\r
306 );\r
307 if (EFI_ERROR (Status)) {\r
308 return EFI_NOT_FOUND;\r
309 }\r
310 } while (!CompareGuid (&SearchNameGuid, NameGuid));\r
311\r
312 //\r
313 // Get a pointer to the header\r
314 //\r
315 FfsHeader = FvDevice->LastKey->FfsHeader;\r
eb1cace2
SZ
316 if (FvDevice->IsMemoryMapped) {\r
317 //\r
318 // Memory mapped FV has not been cached, so here is to cache by file.\r
319 //\r
320 if (!FvDevice->LastKey->FileCached) {\r
321 //\r
322 // Cache FFS file to memory buffer.\r
323 //\r
324 WholeFileSize = IS_FFS_FILE2 (FfsHeader) ? FFS_FILE2_SIZE (FfsHeader): FFS_FILE_SIZE (FfsHeader);\r
325 FfsHeader = AllocateCopyPool (WholeFileSize, FfsHeader);\r
326 if (FfsHeader == NULL) {\r
327 return EFI_OUT_OF_RESOURCES;\r
328 }\r
329 //\r
330 // Let FfsHeader in FfsFileEntry point to the cached file buffer.\r
331 //\r
332 FvDevice->LastKey->FfsHeader = FfsHeader;\r
333 FvDevice->LastKey->FileCached = TRUE;\r
334 }\r
335 }\r
28a00297 336\r
337 //\r
338 // Remember callers buffer size\r
339 //\r
340 InputBufferSize = *BufferSize;\r
341\r
342 //\r
343 // Calculate return values\r
344 //\r
345 *FoundType = FfsHeader->Type;\r
346 *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes);\r
795bb9b6
SZ
347 if ((FvDevice->FwVolHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {\r
348 *FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;\r
349 }\r
2bc08e8c
SZ
350 //\r
351 // Inherit the authentication status.\r
352 //\r
353 *AuthenticationStatus = FvDevice->AuthenticationStatus;\r
28a00297 354 *BufferSize = FileSize;\r
355\r
356 if (Buffer == NULL) {\r
357 //\r
d613c2a8 358 // If Buffer is NULL, we only want to get the information collected so far\r
28a00297 359 //\r
360 return EFI_SUCCESS;\r
361 }\r
362\r
363 //\r
364 // Skip over file header\r
365 //\r
6c85d162
SZ
366 if (IS_FFS_FILE2 (FfsHeader)) {\r
367 SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER2);\r
368 } else {\r
369 SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);\r
370 }\r
28a00297 371\r
372 Status = EFI_SUCCESS;\r
373 if (*Buffer == NULL) {\r
374 //\r
375 // Caller passed in a pointer so allocate buffer for them\r
376 //\r
9c4ac31c 377 *Buffer = AllocatePool (FileSize);\r
28a00297 378 if (*Buffer == NULL) {\r
379 return EFI_OUT_OF_RESOURCES;\r
380 }\r
381 } else if (FileSize > InputBufferSize) {\r
382 //\r
383 // Callers buffer was not big enough\r
022c6d45 384 //\r
28a00297 385 Status = EFI_WARN_BUFFER_TOO_SMALL;\r
386 FileSize = InputBufferSize;\r
387 }\r
022c6d45 388\r
28a00297 389 //\r
022c6d45 390 // Copy data into callers buffer\r
28a00297 391 //\r
392 CopyMem (*Buffer, SrcPtr, FileSize);\r
393\r
394 return Status;\r
395}\r
396\r
397\r
162ed594 398\r
399/**\r
400 Locates a section in a given FFS File and\r
401 copies it to the supplied buffer (not including section header).\r
402\r
022c6d45 403 @param This Indicates the calling context.\r
404 @param NameGuid Pointer to an EFI_GUID, which is the\r
405 filename.\r
406 @param SectionType Indicates the section type to return.\r
407 @param SectionInstance Indicates which instance of sections with a\r
408 type of SectionType to return.\r
409 @param Buffer Buffer is a pointer to pointer to a buffer\r
410 in which the file or section contents or are\r
411 returned.\r
412 @param BufferSize BufferSize is a pointer to caller allocated\r
162ed594 413 UINTN.\r
022c6d45 414 @param AuthenticationStatus AuthenticationStatus is a pointer to a\r
415 caller allocated UINT32 in which the\r
416 authentication status is returned.\r
417\r
418 @retval EFI_SUCCESS Successfully read the file section into\r
419 buffer.\r
420 @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.\r
421 @retval EFI_NOT_FOUND Section not found.\r
422 @retval EFI_DEVICE_ERROR Device error.\r
423 @retval EFI_ACCESS_DENIED Could not read.\r
162ed594 424 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
425\r
426**/\r
28a00297 427EFI_STATUS\r
428EFIAPI\r
429FvReadFileSection (\r
0c2b5da8 430 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,\r
431 IN CONST EFI_GUID *NameGuid,\r
432 IN EFI_SECTION_TYPE SectionType,\r
433 IN UINTN SectionInstance,\r
434 IN OUT VOID **Buffer,\r
435 IN OUT UINTN *BufferSize,\r
436 OUT UINT32 *AuthenticationStatus\r
28a00297 437 )\r
28a00297 438{\r
439 EFI_STATUS Status;\r
440 FV_DEVICE *FvDevice;\r
441 EFI_FV_FILETYPE FileType;\r
442 EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
443 UINTN FileSize;\r
444 UINT8 *FileBuffer;\r
28a00297 445 FFS_FILE_LIST_ENTRY *FfsEntry;\r
022c6d45 446\r
e94a9ff7 447 if (NameGuid == NULL || Buffer == NULL) {\r
28a00297 448 return EFI_INVALID_PARAMETER;\r
449 }\r
450\r
451 FvDevice = FV_DEVICE_FROM_THIS (This);\r
452\r
453 //\r
eb1cace2 454 // Read the file\r
28a00297 455 //\r
28a00297 456 Status = FvReadFile (\r
457 This,\r
458 NameGuid,\r
eb1cace2 459 NULL,\r
28a00297 460 &FileSize,\r
461 &FileType,\r
462 &FileAttributes,\r
463 AuthenticationStatus\r
022c6d45 464 );\r
28a00297 465 //\r
466 // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file.\r
022c6d45 467 //\r
e94a9ff7 468 FfsEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->LastKey;\r
28a00297 469\r
470 if (EFI_ERROR (Status)) {\r
471 return Status;\r
472 }\r
eb1cace2
SZ
473 if (IS_FFS_FILE2 (FfsEntry->FfsHeader)) {\r
474 FileBuffer = ((UINT8 *) FfsEntry->FfsHeader) + sizeof (EFI_FFS_FILE_HEADER2);\r
475 } else {\r
476 FileBuffer = ((UINT8 *) FfsEntry->FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);\r
477 }\r
28a00297 478 //\r
479 // Check to see that the file actually HAS sections before we go any further.\r
480 //\r
481 if (FileType == EFI_FV_FILETYPE_RAW) {\r
482 Status = EFI_NOT_FOUND;\r
483 goto Done;\r
484 }\r
485\r
486 //\r
6c85d162 487 // Use FfsEntry to cache Section Extraction Protocol Information\r
28a00297 488 //\r
489 if (FfsEntry->StreamHandle == 0) {\r
797a9d67 490 Status = OpenSectionStream (\r
e94a9ff7 491 FileSize,\r
492 FileBuffer,\r
493 &FfsEntry->StreamHandle\r
494 );\r
28a00297 495 if (EFI_ERROR (Status)) {\r
496 goto Done;\r
497 }\r
28a00297 498 }\r
499\r
500 //\r
501 // If SectionType == 0 We need the whole section stream\r
502 //\r
797a9d67 503 Status = GetSection (\r
504 FfsEntry->StreamHandle,\r
505 (SectionType == 0) ? NULL : &SectionType,\r
506 NULL,\r
507 (SectionType == 0) ? 0 : SectionInstance,\r
508 Buffer,\r
509 BufferSize,\r
6c85d162
SZ
510 AuthenticationStatus,\r
511 FvDevice->IsFfs3Fv\r
797a9d67 512 );\r
28a00297 513\r
0c3a1db4
SZ
514 if (!EFI_ERROR (Status)) {\r
515 //\r
516 // Inherit the authentication status.\r
517 //\r
518 *AuthenticationStatus |= FvDevice->AuthenticationStatus;\r
519 }\r
520\r
28a00297 521 //\r
522 // Close of stream defered to close of FfsHeader list to allow SEP to cache data\r
523 //\r
524\r
525Done:\r
28a00297 526 return Status;\r
527}\r
528\r
162ed594 529\r