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