]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/FwVol/FwVolRead.c
MdeModulePkg DxeCore: Handle FFS file with FFS_ATTRIB_CHECKSUM set for not cache...
[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
523f48e7 4Copyright (c) 2006 - 2014, 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
28a00297 350 *AuthenticationStatus = 0;\r
351 *BufferSize = FileSize;\r
352\r
353 if (Buffer == NULL) {\r
354 //\r
d613c2a8 355 // If Buffer is NULL, we only want to get the information collected so far\r
28a00297 356 //\r
357 return EFI_SUCCESS;\r
358 }\r
359\r
360 //\r
361 // Skip over file header\r
362 //\r
6c85d162
SZ
363 if (IS_FFS_FILE2 (FfsHeader)) {\r
364 SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER2);\r
365 } else {\r
366 SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);\r
367 }\r
28a00297 368\r
369 Status = EFI_SUCCESS;\r
370 if (*Buffer == NULL) {\r
371 //\r
372 // Caller passed in a pointer so allocate buffer for them\r
373 //\r
9c4ac31c 374 *Buffer = AllocatePool (FileSize);\r
28a00297 375 if (*Buffer == NULL) {\r
376 return EFI_OUT_OF_RESOURCES;\r
377 }\r
378 } else if (FileSize > InputBufferSize) {\r
379 //\r
380 // Callers buffer was not big enough\r
022c6d45 381 //\r
28a00297 382 Status = EFI_WARN_BUFFER_TOO_SMALL;\r
383 FileSize = InputBufferSize;\r
384 }\r
022c6d45 385\r
28a00297 386 //\r
022c6d45 387 // Copy data into callers buffer\r
28a00297 388 //\r
389 CopyMem (*Buffer, SrcPtr, FileSize);\r
390\r
391 return Status;\r
392}\r
393\r
394\r
162ed594 395\r
396/**\r
397 Locates a section in a given FFS File and\r
398 copies it to the supplied buffer (not including section header).\r
399\r
022c6d45 400 @param This Indicates the calling context.\r
401 @param NameGuid Pointer to an EFI_GUID, which is the\r
402 filename.\r
403 @param SectionType Indicates the section type to return.\r
404 @param SectionInstance Indicates which instance of sections with a\r
405 type of SectionType to return.\r
406 @param Buffer Buffer is a pointer to pointer to a buffer\r
407 in which the file or section contents or are\r
408 returned.\r
409 @param BufferSize BufferSize is a pointer to caller allocated\r
162ed594 410 UINTN.\r
022c6d45 411 @param AuthenticationStatus AuthenticationStatus is a pointer to a\r
412 caller allocated UINT32 in which the\r
413 authentication status is returned.\r
414\r
415 @retval EFI_SUCCESS Successfully read the file section into\r
416 buffer.\r
417 @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.\r
418 @retval EFI_NOT_FOUND Section not found.\r
419 @retval EFI_DEVICE_ERROR Device error.\r
420 @retval EFI_ACCESS_DENIED Could not read.\r
162ed594 421 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
422\r
423**/\r
28a00297 424EFI_STATUS\r
425EFIAPI\r
426FvReadFileSection (\r
0c2b5da8 427 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,\r
428 IN CONST EFI_GUID *NameGuid,\r
429 IN EFI_SECTION_TYPE SectionType,\r
430 IN UINTN SectionInstance,\r
431 IN OUT VOID **Buffer,\r
432 IN OUT UINTN *BufferSize,\r
433 OUT UINT32 *AuthenticationStatus\r
28a00297 434 )\r
28a00297 435{\r
436 EFI_STATUS Status;\r
437 FV_DEVICE *FvDevice;\r
438 EFI_FV_FILETYPE FileType;\r
439 EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
440 UINTN FileSize;\r
441 UINT8 *FileBuffer;\r
28a00297 442 FFS_FILE_LIST_ENTRY *FfsEntry;\r
022c6d45 443\r
e94a9ff7 444 if (NameGuid == NULL || Buffer == NULL) {\r
28a00297 445 return EFI_INVALID_PARAMETER;\r
446 }\r
447\r
448 FvDevice = FV_DEVICE_FROM_THIS (This);\r
449\r
450 //\r
eb1cace2 451 // Read the file\r
28a00297 452 //\r
28a00297 453 Status = FvReadFile (\r
454 This,\r
455 NameGuid,\r
eb1cace2 456 NULL,\r
28a00297 457 &FileSize,\r
458 &FileType,\r
459 &FileAttributes,\r
460 AuthenticationStatus\r
022c6d45 461 );\r
28a00297 462 //\r
463 // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file.\r
022c6d45 464 //\r
e94a9ff7 465 FfsEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->LastKey;\r
28a00297 466\r
467 if (EFI_ERROR (Status)) {\r
468 return Status;\r
469 }\r
eb1cace2
SZ
470 if (IS_FFS_FILE2 (FfsEntry->FfsHeader)) {\r
471 FileBuffer = ((UINT8 *) FfsEntry->FfsHeader) + sizeof (EFI_FFS_FILE_HEADER2);\r
472 } else {\r
473 FileBuffer = ((UINT8 *) FfsEntry->FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);\r
474 }\r
28a00297 475 //\r
476 // Check to see that the file actually HAS sections before we go any further.\r
477 //\r
478 if (FileType == EFI_FV_FILETYPE_RAW) {\r
479 Status = EFI_NOT_FOUND;\r
480 goto Done;\r
481 }\r
482\r
483 //\r
6c85d162 484 // Use FfsEntry to cache Section Extraction Protocol Information\r
28a00297 485 //\r
486 if (FfsEntry->StreamHandle == 0) {\r
797a9d67 487 Status = OpenSectionStream (\r
e94a9ff7 488 FileSize,\r
489 FileBuffer,\r
490 &FfsEntry->StreamHandle\r
491 );\r
28a00297 492 if (EFI_ERROR (Status)) {\r
493 goto Done;\r
494 }\r
28a00297 495 }\r
496\r
497 //\r
498 // If SectionType == 0 We need the whole section stream\r
499 //\r
797a9d67 500 Status = GetSection (\r
501 FfsEntry->StreamHandle,\r
502 (SectionType == 0) ? NULL : &SectionType,\r
503 NULL,\r
504 (SectionType == 0) ? 0 : SectionInstance,\r
505 Buffer,\r
506 BufferSize,\r
6c85d162
SZ
507 AuthenticationStatus,\r
508 FvDevice->IsFfs3Fv\r
797a9d67 509 );\r
28a00297 510\r
0c3a1db4
SZ
511 if (!EFI_ERROR (Status)) {\r
512 //\r
513 // Inherit the authentication status.\r
514 //\r
515 *AuthenticationStatus |= FvDevice->AuthenticationStatus;\r
516 }\r
517\r
28a00297 518 //\r
519 // Close of stream defered to close of FfsHeader list to allow SEP to cache data\r
520 //\r
521\r
522Done:\r
28a00297 523 return Status;\r
524}\r
525\r
162ed594 526\r