]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Common/FirmwareVolumeBuffer.c
CorebootPayloadPkg: Fix typos in comments
[mirror_edk2.git] / BaseTools / Source / C / Common / FirmwareVolumeBuffer.c
CommitLineData
30fdf114 1/** @file\r
97fa0ee9 2EFI Firmware Volume routines which work on a Fv image in buffers.\r
30fdf114 3\r
6eff5d22 4Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.<BR>\r
40d841f6 5This program and the accompanying materials\r
30fdf114
LG
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
12\r
30fdf114
LG
13**/\r
14\r
15#include "FirmwareVolumeBufferLib.h"\r
16#include "BinderFuncs.h"\r
17\r
18//\r
19// Local macros\r
20//\r
21#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \\r
22 ( \\r
23 (BOOLEAN) ( \\r
24 (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \\r
25 ) \\r
26 )\r
27\r
97fa0ee9
YL
28\r
29//\r
30// Local prototypes\r
31//\r
32\r
e4ac870f
LG
33STATIC\r
34UINT32\r
35FvBufGetSecHdrLen(\r
36 IN EFI_COMMON_SECTION_HEADER *SectionHeader\r
37 )\r
38{\r
39 if (SectionHeader == NULL) {\r
40 return 0;\r
41 }\r
42 if (FvBufExpand3ByteSize(SectionHeader->Size) == 0xffffff) {\r
43 return sizeof(EFI_COMMON_SECTION_HEADER2);\r
44 }\r
45 return sizeof(EFI_COMMON_SECTION_HEADER);\r
46}\r
47\r
48STATIC\r
49UINT32\r
50FvBufGetSecFileLen (\r
51 IN EFI_COMMON_SECTION_HEADER *SectionHeader\r
52 )\r
53{\r
54 UINT32 Length;\r
55 if (SectionHeader == NULL) {\r
56 return 0;\r
57 }\r
58 Length = FvBufExpand3ByteSize(SectionHeader->Size);\r
59 if (Length == 0xffffff) {\r
60 Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;\r
61 }\r
62 return Length;\r
63}\r
30fdf114
LG
64\r
65//\r
66// Local prototypes\r
67//\r
68\r
69STATIC\r
70UINT16\r
71FvBufCalculateChecksum16 (\r
72 IN UINT16 *Buffer,\r
73 IN UINTN Size\r
74 );\r
75\r
76STATIC\r
77UINT8\r
78FvBufCalculateChecksum8 (\r
79 IN UINT8 *Buffer,\r
80 IN UINTN Size\r
81 );\r
82\r
83//\r
84// Procedures start\r
85//\r
86\r
87EFI_STATUS\r
88FvBufRemoveFileNew (\r
89 IN OUT VOID *Fv,\r
90 IN EFI_GUID *Name\r
91 )\r
92/*++\r
93\r
94Routine Description:\r
95\r
96 Clears out all files from the Fv buffer in memory\r
97\r
98Arguments:\r
99\r
100 SourceFv - Address of the Fv in memory, this firmware volume volume will\r
101 be modified, if SourceFfsFile exists\r
102 SourceFfsFile - Input FFS file to replace\r
103\r
104Returns:\r
105\r
106 EFI_SUCCESS\r
107 EFI_NOT_FOUND\r
108\r
109--*/\r
110{\r
111 EFI_STATUS Status;\r
112 EFI_FFS_FILE_HEADER* FileToRm;\r
113 UINTN FileToRmLength;\r
114\r
115 Status = FvBufFindFileByName(\r
116 Fv,\r
117 Name,\r
118 (VOID **)&FileToRm\r
119 );\r
120 if (EFI_ERROR (Status)) {\r
121 return Status;\r
122 }\r
123\r
e4ac870f 124 FileToRmLength = FvBufGetFfsFileSize (FileToRm);\r
30fdf114
LG
125\r
126 CommonLibBinderSetMem (\r
127 FileToRm,\r
128 FileToRmLength,\r
129 (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY)\r
130 ? 0xFF : 0\r
131 );\r
132\r
133 return EFI_SUCCESS;\r
134}\r
135\r
136\r
137EFI_STATUS\r
138FvBufRemoveFile (\r
139 IN OUT VOID *Fv,\r
140 IN EFI_GUID *Name\r
141 )\r
142/*++\r
143\r
144Routine Description:\r
145\r
146 Clears out all files from the Fv buffer in memory\r
147\r
148Arguments:\r
149\r
150 SourceFv - Address of the Fv in memory, this firmware volume volume will\r
151 be modified, if SourceFfsFile exists\r
152 SourceFfsFile - Input FFS file to replace\r
153\r
154Returns:\r
155\r
156 EFI_SUCCESS\r
157 EFI_NOT_FOUND\r
158\r
159--*/\r
160{\r
161 EFI_STATUS Status;\r
162 EFI_FFS_FILE_HEADER *NextFile;\r
163 EFI_FIRMWARE_VOLUME_HEADER *TempFv;\r
164 UINTN FileKey;\r
165 UINTN FvLength;\r
166\r
167 Status = FvBufFindFileByName(\r
168 Fv,\r
169 Name,\r
170 NULL\r
171 );\r
172 if (EFI_ERROR (Status)) {\r
173 return Status;\r
174 }\r
175\r
176 Status = FvBufGetSize (Fv, &FvLength);\r
177 if (EFI_ERROR (Status)) {\r
178 return Status;\r
179 }\r
180\r
181 TempFv = NULL;\r
182 Status = FvBufDuplicate (Fv, (VOID **)&TempFv);\r
183 if (EFI_ERROR (Status)) {\r
184 return Status;\r
185 }\r
186\r
187 Status = FvBufClearAllFiles (TempFv);\r
188 if (EFI_ERROR (Status)) {\r
189 return Status;\r
190 }\r
191\r
192 // TempFv has been allocated. It must now be freed\r
193 // before returning.\r
194\r
195 FileKey = 0;\r
196 while (TRUE) {\r
197\r
198 Status = FvBufFindNextFile (Fv, &FileKey, (VOID **)&NextFile);\r
199 if (Status == EFI_NOT_FOUND) {\r
200 break;\r
201 } else if (EFI_ERROR (Status)) {\r
202 CommonLibBinderFree (TempFv);\r
203 return Status;\r
204 }\r
205\r
206 if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) {\r
207 continue;\r
208 }\r
209 else {\r
210 Status = FvBufAddFile (TempFv, NextFile);\r
211 if (EFI_ERROR (Status)) {\r
212 CommonLibBinderFree (TempFv);\r
213 return Status;\r
214 }\r
215 }\r
216 }\r
217\r
218 CommonLibBinderCopyMem (Fv, TempFv, FvLength);\r
219 CommonLibBinderFree (TempFv);\r
220\r
221 return EFI_SUCCESS;\r
222}\r
223\r
224\r
225EFI_STATUS\r
226FvBufChecksumFile (\r
227 IN OUT VOID *FfsFile\r
228 )\r
229/*++\r
230\r
231Routine Description:\r
232\r
233 Clears out all files from the Fv buffer in memory\r
234\r
235Arguments:\r
236\r
237 SourceFfsFile - Input FFS file to update the checksum for\r
238\r
239Returns:\r
240\r
241 EFI_SUCCESS\r
242 EFI_NOT_FOUND\r
243\r
244--*/\r
245{\r
246 EFI_FFS_FILE_HEADER* File = (EFI_FFS_FILE_HEADER*)FfsFile;\r
247 EFI_FFS_FILE_STATE StateBackup;\r
248 UINT32 FileSize;\r
249\r
e4ac870f 250 FileSize = FvBufGetFfsFileSize (File);\r
30fdf114
LG
251\r
252 //\r
253 // Fill in checksums and state, they must be 0 for checksumming.\r
254 //\r
255 File->IntegrityCheck.Checksum.Header = 0;\r
256 File->IntegrityCheck.Checksum.File = 0;\r
257 StateBackup = File->State;\r
258 File->State = 0;\r
259\r
260 File->IntegrityCheck.Checksum.Header =\r
261 FvBufCalculateChecksum8 (\r
262 (UINT8 *) File,\r
e4ac870f 263 FvBufGetFfsHeaderSize (File)\r
30fdf114
LG
264 );\r
265\r
266 if (File->Attributes & FFS_ATTRIB_CHECKSUM) {\r
267 File->IntegrityCheck.Checksum.File = FvBufCalculateChecksum8 (\r
e4ac870f
LG
268 (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File)),\r
269 FileSize - FvBufGetFfsHeaderSize (File)\r
30fdf114
LG
270 );\r
271 } else {\r
272 File->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
273 }\r
274\r
275 File->State = StateBackup;\r
276\r
277 return EFI_SUCCESS;\r
278}\r
279\r
280\r
281EFI_STATUS\r
282FvBufChecksumHeader (\r
283 IN OUT VOID *Fv\r
284 )\r
285/*++\r
286\r
287Routine Description:\r
288\r
289 Clears out all files from the Fv buffer in memory\r
290\r
291Arguments:\r
292\r
293 SourceFv - Address of the Fv in memory, this firmware volume volume will\r
294 be modified, if SourceFfsFile exists\r
295 SourceFfsFile - Input FFS file to replace\r
296\r
297Returns:\r
298\r
299 EFI_SUCCESS\r
300 EFI_NOT_FOUND\r
301\r
302--*/\r
303{\r
304 EFI_FIRMWARE_VOLUME_HEADER* FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;\r
305\r
306 FvHeader->Checksum = 0;\r
307 FvHeader->Checksum =\r
308 FvBufCalculateChecksum16 (\r
309 (UINT16*) FvHeader,\r
310 FvHeader->HeaderLength / sizeof (UINT16)\r
311 );\r
312\r
313 return EFI_SUCCESS;\r
314}\r
315\r
316\r
317EFI_STATUS\r
318FvBufDuplicate (\r
319 IN VOID *SourceFv,\r
320 IN OUT VOID **DestinationFv\r
321 )\r
322/*++\r
323\r
324Routine Description:\r
325\r
326 Clears out all files from the Fv buffer in memory\r
327\r
328Arguments:\r
329\r
330 SourceFv - Address of the Fv in memory\r
331 DestinationFv - Output for destination Fv\r
332 DestinationFv == NULL - invalid parameter\r
333 *DestinationFv == NULL - memory will be allocated\r
334 *DestinationFv != NULL - this address will be the destination\r
335\r
336Returns:\r
337\r
338 EFI_SUCCESS\r
339\r
340--*/\r
341{\r
342 EFI_STATUS Status;\r
343 UINTN size;\r
344\r
345 if (DestinationFv == NULL) {\r
346 return EFI_INVALID_PARAMETER;\r
347 }\r
348\r
349 Status = FvBufGetSize (SourceFv, &size);\r
350 if (EFI_ERROR (Status)) {\r
351 return Status;\r
352 }\r
353\r
354 if (*DestinationFv == NULL) {\r
355 *DestinationFv = CommonLibBinderAllocate (size);\r
356 }\r
357\r
358 CommonLibBinderCopyMem (*DestinationFv, SourceFv, size);\r
359\r
360 return EFI_SUCCESS;\r
361}\r
362\r
363\r
364EFI_STATUS\r
365FvBufExtend (\r
366 IN VOID **Fv,\r
367 IN UINTN Size\r
368 )\r
369/*++\r
370\r
371Routine Description:\r
372\r
373 Extends a firmware volume by the given number of bytes.\r
374\r
375 BUGBUG: Does not handle the case where the firmware volume has a\r
376 VTF (Volume Top File). The VTF will not be moved to the\r
377 end of the extended FV.\r
378\r
379Arguments:\r
380\r
381 Fv - Source and destination firmware volume.\r
382 Note: The original firmware volume buffer is freed!\r
383\r
384 Size - The minimum size that the firmware volume is to be extended by.\r
385 The FV may be extended more than this size.\r
386\r
387Returns:\r
388\r
389 EFI_SUCCESS\r
390\r
391--*/\r
392{\r
393 EFI_STATUS Status;\r
394 UINTN OldSize;\r
395 UINTN NewSize;\r
396 UINTN BlockCount;\r
397 VOID* NewFv;\r
398\r
399 EFI_FIRMWARE_VOLUME_HEADER* hdr;\r
400 EFI_FV_BLOCK_MAP_ENTRY* blk;\r
401\r
402 Status = FvBufGetSize (*Fv, &OldSize);\r
403 if (EFI_ERROR (Status)) {\r
404 return Status;\r
405 }\r
406\r
407 //\r
408 // Locate the block map in the fv header\r
409 //\r
410 hdr = (EFI_FIRMWARE_VOLUME_HEADER*)*Fv;\r
411 blk = hdr->BlockMap;\r
412\r
413 //\r
414 // Calculate the number of blocks needed to achieve the requested\r
415 // size extension\r
416 //\r
417 BlockCount = ((Size + (blk->Length - 1)) / blk->Length);\r
418\r
419 //\r
420 // Calculate the new size from the number of blocks that will be added\r
421 //\r
422 NewSize = OldSize + (BlockCount * blk->Length);\r
423\r
424 NewFv = CommonLibBinderAllocate (NewSize);\r
425 if (NewFv == NULL) {\r
426 return EFI_OUT_OF_RESOURCES;\r
427 }\r
428\r
429 //\r
430 // Copy the old data\r
431 //\r
432 CommonLibBinderCopyMem (NewFv, *Fv, OldSize);\r
433\r
434 //\r
435 // Free the old fv buffer\r
436 //\r
437 CommonLibBinderFree (*Fv);\r
438\r
439 //\r
440 // Locate the block map in the new fv header\r
441 //\r
442 hdr = (EFI_FIRMWARE_VOLUME_HEADER*)NewFv;\r
443 hdr->FvLength = NewSize;\r
444 blk = hdr->BlockMap;\r
445\r
446 //\r
447 // Update the block map for the new fv\r
448 //\r
449 blk->NumBlocks += (UINT32)BlockCount;\r
450\r
451 //\r
452 // Update the FV header checksum\r
453 //\r
454 FvBufChecksumHeader (NewFv);\r
455\r
456 //\r
457 // Clear out the new area of the FV\r
458 //\r
459 CommonLibBinderSetMem (\r
460 (UINT8*)NewFv + OldSize,\r
461 (NewSize - OldSize),\r
462 (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0\r
463 );\r
464\r
465 //\r
466 // Set output with new fv that was created\r
467 //\r
468 *Fv = NewFv;\r
469\r
470 return EFI_SUCCESS;\r
471\r
472}\r
473\r
474\r
475EFI_STATUS\r
476FvBufClearAllFiles (\r
477 IN OUT VOID *Fv\r
478 )\r
479/*++\r
480\r
481Routine Description:\r
482\r
483 Clears out all files from the Fv buffer in memory\r
484\r
485Arguments:\r
486\r
487 Fv - Address of the Fv in memory\r
488\r
489Returns:\r
490\r
491 EFI_SUCCESS\r
492\r
493--*/\r
494\r
495{\r
496 EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;\r
497 EFI_STATUS Status;\r
498 UINTN size = 0;\r
499\r
500 Status = FvBufGetSize (Fv, &size);\r
501 if (EFI_ERROR (Status)) {\r
502 return Status;\r
503 }\r
504\r
505 CommonLibBinderSetMem(\r
506 (UINT8*)hdr + hdr->HeaderLength,\r
507 size - hdr->HeaderLength,\r
508 (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0\r
509 );\r
510\r
511 return EFI_SUCCESS;\r
512}\r
513\r
514\r
515EFI_STATUS\r
516FvBufGetSize (\r
517 IN VOID *Fv,\r
518 OUT UINTN *Size\r
519 )\r
520/*++\r
521\r
522Routine Description:\r
523\r
524 Clears out all files from the Fv buffer in memory\r
525\r
526Arguments:\r
527\r
528 Fv - Address of the Fv in memory\r
529\r
530Returns:\r
531\r
532 EFI_SUCCESS\r
533\r
534--*/\r
535\r
536{\r
537 EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;\r
538 EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap;\r
539\r
540 *Size = 0;\r
541\r
542 while (blk->Length != 0 || blk->NumBlocks != 0) {\r
543 *Size = *Size + (blk->Length * blk->NumBlocks);\r
544 if (*Size >= 0x40000000) {\r
545 // If size is greater than 1GB, then assume it is corrupted\r
546 return EFI_VOLUME_CORRUPTED;\r
547 }\r
548 blk++;\r
549 }\r
550\r
551 if (*Size == 0) {\r
552 // If size is 0, then assume the volume is corrupted\r
553 return EFI_VOLUME_CORRUPTED;\r
554 }\r
555\r
556 return EFI_SUCCESS;\r
557}\r
558\r
559\r
560EFI_STATUS\r
561FvBufAddFile (\r
562 IN OUT VOID *Fv,\r
563 IN VOID *File\r
564 )\r
565/*++\r
566\r
567Routine Description:\r
568\r
569 Adds a new FFS file\r
570\r
571Arguments:\r
572\r
573 Fv - Address of the Fv in memory\r
574 File - FFS file to add to Fv\r
575\r
576Returns:\r
577\r
578 EFI_SUCCESS\r
579\r
580--*/\r
581{\r
582 EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;\r
583\r
584 EFI_FFS_FILE_HEADER *fhdr = NULL;\r
2bcc713e 585 EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r
30fdf114
LG
586 UINTN offset;\r
587 UINTN fsize;\r
588 UINTN newSize;\r
589 UINTN clearLoop;\r
590\r
591 EFI_STATUS Status;\r
592 UINTN fvSize;\r
593\r
594 Status = FvBufGetSize (Fv, &fvSize);\r
595 if (EFI_ERROR (Status)) {\r
596 return Status;\r
597 }\r
598\r
599 FvbAttributes = hdr->Attributes;\r
e4ac870f 600 newSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);\r
30fdf114
LG
601\r
602 for(\r
603 offset = (UINTN)ALIGN_POINTER (hdr->HeaderLength, 8);\r
604 offset + newSize <= fvSize;\r
605 offset = (UINTN)ALIGN_POINTER (offset, 8)\r
606 ) {\r
607\r
608 fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + offset);\r
609\r
610 if (EFI_TEST_FFS_ATTRIBUTES_BIT(\r
611 FvbAttributes,\r
612 fhdr->State,\r
613 EFI_FILE_HEADER_VALID\r
614 )\r
615 ) {\r
616 // BUGBUG: Need to make sure that the new file does not already\r
617 // exist.\r
618\r
e4ac870f 619 fsize = FvBufGetFfsFileSize (fhdr);\r
30fdf114
LG
620 if (fsize == 0 || (offset + fsize > fvSize)) {\r
621 return EFI_VOLUME_CORRUPTED;\r
622 }\r
623\r
624 offset = offset + fsize;\r
625 continue;\r
626 }\r
627\r
628 clearLoop = 0;\r
629 while ((clearLoop < newSize) &&\r
630 (((UINT8*)fhdr)[clearLoop] ==\r
631 (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0)\r
632 )\r
633 ) {\r
634 clearLoop++;\r
635 }\r
636\r
637 //\r
638 // We found a place in the FV which is empty and big enough for\r
639 // the new file\r
640 //\r
641 if (clearLoop >= newSize) {\r
642 break;\r
643 }\r
644\r
645 offset = offset + 1; // Make some forward progress\r
646 }\r
647\r
648 if (offset + newSize > fvSize) {\r
649 return EFI_OUT_OF_RESOURCES;\r
650 }\r
651\r
652 CommonLibBinderCopyMem (fhdr, File, newSize);\r
653\r
654 return EFI_SUCCESS;\r
655}\r
656\r
657\r
658EFI_STATUS\r
659FvBufAddFileWithExtend (\r
660 IN OUT VOID **Fv,\r
661 IN VOID *File\r
662 )\r
663/*++\r
664\r
665Routine Description:\r
666\r
667 Adds a new FFS file. Extends the firmware volume if needed.\r
668\r
669Arguments:\r
670\r
671 Fv - Source and destination firmware volume.\r
672 Note: If the FV is extended, then the original firmware volume\r
673 buffer is freed!\r
674\r
675 Size - The minimum size that the firmware volume is to be extended by.\r
676 The FV may be extended more than this size.\r
677\r
678Returns:\r
679\r
680 EFI_SUCCESS\r
681\r
682--*/\r
683{\r
684 EFI_STATUS Status;\r
685 EFI_FFS_FILE_HEADER* NewFile;\r
686\r
687 NewFile = (EFI_FFS_FILE_HEADER*)File;\r
688\r
689 //\r
690 // Try to add to the capsule volume\r
691 //\r
692 Status = FvBufAddFile (*Fv, NewFile);\r
693 if (Status == EFI_OUT_OF_RESOURCES) {\r
694 //\r
695 // Try to extend the capsule volume by the size of the file\r
696 //\r
697 Status = FvBufExtend (Fv, FvBufExpand3ByteSize (NewFile->Size));\r
698 if (EFI_ERROR (Status)) {\r
699 return Status;\r
700 }\r
701\r
702 //\r
703 // Now, try to add the file again\r
704 //\r
705 Status = FvBufAddFile (*Fv, NewFile);\r
706 }\r
707\r
708 return Status;\r
709}\r
710\r
711\r
712EFI_STATUS\r
713FvBufAddVtfFile (\r
714 IN OUT VOID *Fv,\r
715 IN VOID *File\r
716 )\r
717/*++\r
718\r
719Routine Description:\r
720\r
721 Adds a new FFS VFT (Volume Top File) file. In other words, adds the\r
722 file to the end of the firmware volume.\r
723\r
724Arguments:\r
725\r
726 Fv - Address of the Fv in memory\r
727 File - FFS file to add to Fv\r
728\r
729Returns:\r
730\r
731 EFI_SUCCESS\r
732\r
733--*/\r
734{\r
735 EFI_STATUS Status;\r
736\r
737 EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;\r
738\r
739 EFI_FFS_FILE_HEADER* NewFile;\r
740 UINTN NewFileSize;\r
741\r
742 UINT8 erasedUint8;\r
743 UINTN clearLoop;\r
744\r
745 EFI_FFS_FILE_HEADER *LastFile;\r
746 UINTN LastFileSize;\r
747\r
748 UINTN fvSize;\r
749 UINTN Key;\r
750\r
751 Status = FvBufGetSize (Fv, &fvSize);\r
752 if (EFI_ERROR (Status)) {\r
753 return Status;\r
754 }\r
755\r
756 erasedUint8 = (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0);\r
e4ac870f 757 NewFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);\r
30fdf114
LG
758\r
759 if (NewFileSize != (UINTN)ALIGN_POINTER (NewFileSize, 8)) {\r
760 return EFI_INVALID_PARAMETER;\r
761 }\r
762\r
763 //\r
764 // Find the last file in the FV\r
765 //\r
766 Key = 0;\r
767 LastFile = NULL;\r
768 LastFileSize = 0;\r
769 do {\r
770 Status = FvBufFindNextFile (Fv, &Key, (VOID **)&LastFile);\r
e4ac870f 771 LastFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);\r
30fdf114
LG
772 } while (!EFI_ERROR (Status));\r
773\r
774 //\r
775 // If no files were found, then we start at the beginning of the FV\r
776 //\r
777 if (LastFile == NULL) {\r
778 LastFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + hdr->HeaderLength);\r
779 }\r
780\r
781 //\r
782 // We want to put the new file (VTF) at the end of the FV\r
783 //\r
784 NewFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + (fvSize - NewFileSize));\r
785\r
786 //\r
787 // Check to see if there is enough room for the VTF after the last file\r
788 // found in the FV\r
789 //\r
790 if ((UINT8*)NewFile < ((UINT8*)LastFile + LastFileSize)) {\r
791 return EFI_OUT_OF_RESOURCES;\r
792 }\r
793\r
794 //\r
795 // Loop to determine if the end of the FV is empty\r
796 //\r
797 clearLoop = 0;\r
798 while ((clearLoop < NewFileSize) &&\r
799 (((UINT8*)NewFile)[clearLoop] == erasedUint8)\r
800 ) {\r
801 clearLoop++;\r
802 }\r
803\r
804 //\r
805 // Check to see if there was not enough room for the file\r
806 //\r
807 if (clearLoop < NewFileSize) {\r
808 return EFI_OUT_OF_RESOURCES;\r
809 }\r
810\r
811 CommonLibBinderCopyMem (NewFile, File, NewFileSize);\r
812\r
813 return EFI_SUCCESS;\r
814}\r
815\r
816\r
817VOID\r
818FvBufCompact3ByteSize (\r
819 OUT VOID* SizeDest,\r
820 IN UINT32 Size\r
821 )\r
822/*++\r
823\r
824Routine Description:\r
825\r
826 Expands the 3 byte size commonly used in Firmware Volume data structures\r
827\r
828Arguments:\r
829\r
830 Size - Address of the 3 byte array representing the size\r
831\r
832Returns:\r
833\r
834 UINT32\r
835\r
836--*/\r
837{\r
838 ((UINT8*)SizeDest)[0] = (UINT8)Size;\r
839 ((UINT8*)SizeDest)[1] = (UINT8)(Size >> 8);\r
840 ((UINT8*)SizeDest)[2] = (UINT8)(Size >> 16);\r
841}\r
842\r
e4ac870f
LG
843UINT32\r
844FvBufGetFfsFileSize (\r
845 IN EFI_FFS_FILE_HEADER *Ffs\r
846 )\r
847/*++\r
848\r
849Routine Description:\r
850\r
851 Get the FFS file size.\r
852\r
853Arguments:\r
854\r
855 Ffs - Pointer to FFS header\r
856\r
857Returns:\r
858\r
859 UINT32\r
860\r
861--*/\r
862{\r
863 if (Ffs == NULL) {\r
864 return 0;\r
865 }\r
866 if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) {\r
6eff5d22 867 return (UINT32) ((EFI_FFS_FILE_HEADER2 *)Ffs)->ExtendedSize;\r
e4ac870f
LG
868 }\r
869 return FvBufExpand3ByteSize(Ffs->Size);\r
870}\r
871\r
872UINT32\r
873FvBufGetFfsHeaderSize (\r
874 IN EFI_FFS_FILE_HEADER *Ffs\r
875 )\r
876/*++\r
877\r
878Routine Description:\r
879\r
880 Get the FFS header size.\r
881\r
882Arguments:\r
883\r
884 Ffs - Pointer to FFS header\r
885\r
886Returns:\r
887\r
888 UINT32\r
889\r
890--*/\r
891{\r
892 if (Ffs == NULL) {\r
893 return 0;\r
894 }\r
895 if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) {\r
896 return sizeof(EFI_FFS_FILE_HEADER2);\r
897 }\r
898 return sizeof(EFI_FFS_FILE_HEADER);\r
899}\r
900\r
30fdf114
LG
901UINT32\r
902FvBufExpand3ByteSize (\r
903 IN VOID* Size\r
904 )\r
905/*++\r
906\r
907Routine Description:\r
908\r
909 Expands the 3 byte size commonly used in Firmware Volume data structures\r
910\r
911Arguments:\r
912\r
913 Size - Address of the 3 byte array representing the size\r
914\r
915Returns:\r
916\r
917 UINT32\r
918\r
919--*/\r
920{\r
921 return (((UINT8*)Size)[2] << 16) +\r
922 (((UINT8*)Size)[1] << 8) +\r
923 ((UINT8*)Size)[0];\r
924}\r
925\r
926EFI_STATUS\r
927FvBufFindNextFile (\r
928 IN VOID *Fv,\r
929 IN OUT UINTN *Key,\r
930 OUT VOID **File\r
931 )\r
932/*++\r
933\r
934Routine Description:\r
935\r
936 Iterates through the files contained within the firmware volume\r
937\r
938Arguments:\r
939\r
940 Fv - Address of the Fv in memory\r
941 Key - Should be 0 to get the first file. After that, it should be\r
942 passed back in without modifying it's contents to retrieve\r
943 subsequent files.\r
944 File - Output file pointer\r
945 File == NULL - invalid parameter\r
946 otherwise - *File will be update to the location of the file\r
947\r
948Returns:\r
949\r
950 EFI_SUCCESS\r
951 EFI_NOT_FOUND\r
952 EFI_VOLUME_CORRUPTED\r
953\r
954--*/\r
955{\r
956 EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;\r
957\r
958 EFI_FFS_FILE_HEADER *fhdr = NULL;\r
2bcc713e 959 EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r
30fdf114
LG
960 UINTN fsize;\r
961\r
962 EFI_STATUS Status;\r
963 UINTN fvSize;\r
964\r
965 if (Fv == NULL) {\r
966 return EFI_INVALID_PARAMETER;\r
967 }\r
968\r
969 Status = FvBufGetSize (Fv, &fvSize);\r
970 if (EFI_ERROR (Status)) {\r
971 return Status;\r
972 }\r
973\r
974 if (*Key == 0) {\r
975 *Key = hdr->HeaderLength;\r
976 }\r
977\r
978 FvbAttributes = hdr->Attributes;\r
979\r
980 for(\r
981 *Key = (UINTN)ALIGN_POINTER (*Key, 8);\r
982 (*Key + sizeof (*fhdr)) < fvSize;\r
983 *Key = (UINTN)ALIGN_POINTER (*Key, 8)\r
984 ) {\r
985\r
986 fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key);\r
e4ac870f 987 fsize = FvBufGetFfsFileSize (fhdr);\r
30fdf114
LG
988\r
989 if (!EFI_TEST_FFS_ATTRIBUTES_BIT(\r
990 FvbAttributes,\r
991 fhdr->State,\r
992 EFI_FILE_HEADER_VALID\r
993 ) ||\r
994 EFI_TEST_FFS_ATTRIBUTES_BIT(\r
995 FvbAttributes,\r
996 fhdr->State,\r
997 EFI_FILE_HEADER_INVALID\r
998 )\r
999 ) {\r
1000 *Key = *Key + 1; // Make some forward progress\r
1001 continue;\r
1002 } else if(\r
1003 EFI_TEST_FFS_ATTRIBUTES_BIT(\r
1004 FvbAttributes,\r
1005 fhdr->State,\r
1006 EFI_FILE_MARKED_FOR_UPDATE\r
1007 ) ||\r
1008 EFI_TEST_FFS_ATTRIBUTES_BIT(\r
1009 FvbAttributes,\r
1010 fhdr->State,\r
1011 EFI_FILE_DELETED\r
1012 )\r
1013 ) {\r
1014 *Key = *Key + fsize;\r
1015 continue;\r
1016 } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(\r
1017 FvbAttributes,\r
1018 fhdr->State,\r
1019 EFI_FILE_DATA_VALID\r
1020 )\r
1021 ) {\r
1022 *File = (UINT8*)hdr + *Key;\r
1023 *Key = *Key + fsize;\r
1024 return EFI_SUCCESS;\r
1025 }\r
1026\r
1027 *Key = *Key + 1; // Make some forward progress\r
1028 }\r
1029\r
1030 return EFI_NOT_FOUND;\r
1031}\r
1032\r
1033\r
1034EFI_STATUS\r
1035FvBufFindFileByName (\r
1036 IN VOID *Fv,\r
1037 IN EFI_GUID *Name,\r
1038 OUT VOID **File\r
1039 )\r
1040/*++\r
1041\r
1042Routine Description:\r
1043\r
1044 Searches the Fv for a file by its name\r
1045\r
1046Arguments:\r
1047\r
1048 Fv - Address of the Fv in memory\r
1049 Name - Guid filename to search for in the firmware volume\r
1050 File - Output file pointer\r
1051 File == NULL - Only determine if the file exists, based on return\r
1052 value from the function call.\r
1053 otherwise - *File will be update to the location of the file\r
1054\r
1055Returns:\r
1056\r
1057 EFI_SUCCESS\r
1058 EFI_NOT_FOUND\r
1059 EFI_VOLUME_CORRUPTED\r
1060\r
1061--*/\r
1062{\r
1063 EFI_STATUS Status;\r
1064 UINTN Key;\r
1065 EFI_FFS_FILE_HEADER *NextFile;\r
1066\r
1067 Key = 0;\r
1068 while (TRUE) {\r
1069 Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile);\r
1070 if (EFI_ERROR (Status)) {\r
1071 return Status;\r
1072 }\r
1073\r
1074 if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) {\r
1075 if (File != NULL) {\r
1076 *File = NextFile;\r
1077 }\r
1078 return EFI_SUCCESS;\r
1079 }\r
1080 }\r
1081\r
1082 return EFI_NOT_FOUND;\r
1083}\r
1084\r
1085\r
1086EFI_STATUS\r
1087FvBufFindFileByType (\r
1088 IN VOID *Fv,\r
1089 IN EFI_FV_FILETYPE Type,\r
1090 OUT VOID **File\r
1091 )\r
1092/*++\r
1093\r
1094Routine Description:\r
1095\r
1096 Searches the Fv for a file by its type\r
1097\r
1098Arguments:\r
1099\r
1100 Fv - Address of the Fv in memory\r
1101 Type - FFS FILE type to search for\r
1102 File - Output file pointer\r
1103 (File == NULL) -> Only determine if the file exists, based on return\r
1104 value from the function call.\r
1105 otherwise -> *File will be update to the location of the file\r
1106\r
1107Returns:\r
1108\r
1109 EFI_SUCCESS\r
1110 EFI_NOT_FOUND\r
1111 EFI_VOLUME_CORRUPTED\r
1112\r
1113--*/\r
1114{\r
1115 EFI_STATUS Status;\r
1116 UINTN Key;\r
1117 EFI_FFS_FILE_HEADER *NextFile;\r
1118\r
1119 Key = 0;\r
1120 while (TRUE) {\r
1121 Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile);\r
1122 if (EFI_ERROR (Status)) {\r
1123 return Status;\r
1124 }\r
1125\r
1126 if (Type == NextFile->Type) {\r
1127 if (File != NULL) {\r
1128 *File = NextFile;\r
1129 }\r
1130 return EFI_SUCCESS;\r
1131 }\r
1132 }\r
1133\r
1134 return EFI_NOT_FOUND;\r
1135}\r
1136\r
1137\r
1138EFI_STATUS\r
1139FvBufGetFileRawData (\r
1140 IN VOID* FfsFile,\r
1141 OUT VOID** RawData,\r
1142 OUT UINTN* RawDataSize\r
1143 )\r
1144/*++\r
1145\r
1146Routine Description:\r
1147\r
1148 Searches the requested file for raw data.\r
1149\r
1150 This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file,\r
1151 or finds the EFI_SECTION_RAW section within the file and returns its data.\r
1152\r
1153Arguments:\r
1154\r
1155 FfsFile - Address of the FFS file in memory\r
1156 RawData - Pointer to the raw data within the file\r
1157 (This is NOT allocated. It is within the file.)\r
1158 RawDataSize - Size of the raw data within the file\r
1159\r
1160Returns:\r
1161\r
1162 EFI_STATUS\r
1163\r
1164--*/\r
1165{\r
1166 EFI_STATUS Status;\r
1167 EFI_FFS_FILE_HEADER* File;\r
1168 EFI_RAW_SECTION* Section;\r
1169\r
1170 File = (EFI_FFS_FILE_HEADER*)FfsFile;\r
1171\r
1172 //\r
1173 // Is the file type == EFI_FV_FILETYPE_RAW?\r
1174 //\r
1175 if (File->Type == EFI_FV_FILETYPE_RAW) {\r
1176 //\r
1177 // Raw filetypes don't have sections, so we just return the raw data\r
1178 //\r
e4ac870f
LG
1179 *RawData = (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File));\r
1180 *RawDataSize = FvBufGetFfsFileSize (File) - FvBufGetFfsHeaderSize (File);\r
30fdf114
LG
1181 return EFI_SUCCESS;\r
1182 }\r
1183\r
1184 //\r
1185 // Within the file, we now need to find the EFI_SECTION_RAW section.\r
1186 //\r
1187 Status = FvBufFindSectionByType (File, EFI_SECTION_RAW, (VOID **)&Section);\r
1188 if (EFI_ERROR (Status)) {\r
1189 return Status;\r
1190 }\r
1191\r
e4ac870f 1192 *RawData = (VOID*)((UINT8 *)Section + FvBufGetSecHdrLen(Section));\r
30fdf114 1193 *RawDataSize =\r
e4ac870f 1194 FvBufGetSecFileLen (Section) - FvBufGetSecHdrLen(Section);\r
30fdf114
LG
1195\r
1196 return EFI_SUCCESS;\r
1197\r
1198}\r
1199\r
1200\r
1201EFI_STATUS\r
1202FvBufPackageFreeformRawFile (\r
1203 IN EFI_GUID* Filename,\r
1204 IN VOID* RawData,\r
1205 IN UINTN RawDataSize,\r
1206 OUT VOID** FfsFile\r
1207 )\r
1208/*++\r
1209\r
1210Routine Description:\r
1211\r
1212 Packages up a FFS file containing the input raw data.\r
1213\r
1214 The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will\r
1215 contain one EFI_FV_FILETYPE_RAW section.\r
1216\r
1217Arguments:\r
1218\r
1219 RawData - Pointer to the raw data to be packed\r
1220 RawDataSize - Size of the raw data to be packed\r
1221 FfsFile - Address of the packaged FFS file.\r
1222 Note: The called must deallocate this memory!\r
1223\r
1224Returns:\r
1225\r
1226 EFI_STATUS\r
1227\r
1228--*/\r
1229{\r
1230 EFI_FFS_FILE_HEADER* NewFile;\r
1231 UINT32 NewFileSize;\r
1232 EFI_RAW_SECTION* NewSection;\r
1233 UINT32 NewSectionSize;\r
e4ac870f
LG
1234 UINT32 FfsHdrLen;\r
1235 UINT32 SecHdrLen;\r
30fdf114
LG
1236\r
1237 //\r
1238 // The section size is the DataSize + the size of the section header\r
1239 //\r
1240 NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION) + (UINT32)RawDataSize;\r
e4ac870f
LG
1241 SecHdrLen = sizeof (EFI_RAW_SECTION);\r
1242 if (NewSectionSize >= MAX_SECTION_SIZE) {\r
1243 NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION2) + (UINT32)RawDataSize;\r
1244 SecHdrLen = sizeof (EFI_RAW_SECTION2);\r
1245 }\r
30fdf114
LG
1246\r
1247 //\r
1248 // The file size is the size of the file header + the section size\r
1249 //\r
1250 NewFileSize = sizeof (EFI_FFS_FILE_HEADER) + NewSectionSize;\r
e4ac870f
LG
1251 FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER);\r
1252 if (NewFileSize >= MAX_FFS_SIZE) {\r
1253 NewFileSize = sizeof (EFI_FFS_FILE_HEADER2) + NewSectionSize;\r
1254 FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER2);\r
1255 }\r
30fdf114
LG
1256\r
1257 //\r
1258 // Try to allocate a buffer to build the new FFS file in\r
1259 //\r
1260 NewFile = CommonLibBinderAllocate (NewFileSize);\r
1261 if (NewFile == NULL) {\r
1262 return EFI_OUT_OF_RESOURCES;\r
1263 }\r
1264 CommonLibBinderSetMem (NewFile, NewFileSize, 0);\r
1265\r
1266 //\r
1267 // The NewSection follow right after the FFS file header\r
1268 //\r
e4ac870f
LG
1269 NewSection = (EFI_RAW_SECTION*)((UINT8*)NewFile + FfsHdrLen);\r
1270 if (NewSectionSize >= MAX_SECTION_SIZE) {\r
1271 FvBufCompact3ByteSize (NewSection->Size, 0xffffff);\r
1272 ((EFI_RAW_SECTION2 *)NewSection)->ExtendedSize = NewSectionSize;\r
1273 } else {\r
1274 FvBufCompact3ByteSize (NewSection->Size, NewSectionSize);\r
1275 }\r
30fdf114
LG
1276 NewSection->Type = EFI_SECTION_RAW;\r
1277\r
1278 //\r
1279 // Copy the actual file data into the buffer\r
1280 //\r
e4ac870f 1281 CommonLibBinderCopyMem ((UINT8 *)NewSection + SecHdrLen, RawData, RawDataSize);\r
30fdf114
LG
1282\r
1283 //\r
1284 // Initialize the FFS file header\r
1285 //\r
1286 CommonLibBinderCopyMem (&NewFile->Name, Filename, sizeof (EFI_GUID));\r
30fdf114 1287 NewFile->Attributes = 0;\r
e4ac870f
LG
1288 if (NewFileSize >= MAX_FFS_SIZE) {\r
1289 FvBufCompact3ByteSize (NewFile->Size, 0x0);\r
1290 ((EFI_FFS_FILE_HEADER2 *)NewFile)->ExtendedSize = NewFileSize;\r
1291 NewFile->Attributes |= FFS_ATTRIB_LARGE_FILE;\r
1292 } else {\r
1293 FvBufCompact3ByteSize (NewFile->Size, NewFileSize);\r
1294 }\r
1295 NewFile->Type = EFI_FV_FILETYPE_FREEFORM;\r
30fdf114 1296 NewFile->IntegrityCheck.Checksum.Header =\r
e4ac870f 1297 FvBufCalculateChecksum8 ((UINT8*)NewFile, FfsHdrLen);\r
30fdf114
LG
1298 NewFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
1299 NewFile->State = (UINT8)~( EFI_FILE_HEADER_CONSTRUCTION |\r
1300 EFI_FILE_HEADER_VALID |\r
1301 EFI_FILE_DATA_VALID\r
1302 );\r
1303\r
1304 *FfsFile = NewFile;\r
1305\r
1306 return EFI_SUCCESS;\r
1307}\r
1308\r
1309\r
1310EFI_STATUS\r
1311FvBufFindNextSection (\r
1312 IN VOID *SectionsStart,\r
1313 IN UINTN TotalSectionsSize,\r
1314 IN OUT UINTN *Key,\r
1315 OUT VOID **Section\r
1316 )\r
1317/*++\r
1318\r
1319Routine Description:\r
1320\r
1321 Iterates through the sections contained within a given array of sections\r
1322\r
1323Arguments:\r
1324\r
1325 SectionsStart - Address of the start of the FFS sections array\r
1326 TotalSectionsSize - Total size of all the sections\r
1327 Key - Should be 0 to get the first section. After that, it should be\r
1328 passed back in without modifying it's contents to retrieve\r
1329 subsequent files.\r
1330 Section - Output section pointer\r
1331 (Section == NULL) -> invalid parameter\r
1332 otherwise -> *Section will be update to the location of the file\r
1333\r
1334Returns:\r
1335\r
1336 EFI_SUCCESS\r
1337 EFI_NOT_FOUND\r
1338 EFI_VOLUME_CORRUPTED\r
1339\r
1340--*/\r
1341{\r
1342 EFI_COMMON_SECTION_HEADER *sectionHdr;\r
1343 UINTN sectionSize;\r
1344\r
1345 *Key = (UINTN)ALIGN_POINTER (*Key, 4); // Sections are DWORD aligned\r
1346\r
1347 if ((*Key + sizeof (*sectionHdr)) > TotalSectionsSize) {\r
1348 return EFI_NOT_FOUND;\r
1349 }\r
1350\r
1351 sectionHdr = (EFI_COMMON_SECTION_HEADER*)((UINT8*)SectionsStart + *Key);\r
e4ac870f 1352 sectionSize = FvBufGetSecFileLen (sectionHdr);\r
30fdf114
LG
1353\r
1354 if (sectionSize < sizeof (EFI_COMMON_SECTION_HEADER)) {\r
1355 return EFI_NOT_FOUND;\r
1356 }\r
1357\r
1358 if ((*Key + sectionSize) > TotalSectionsSize) {\r
1359 return EFI_NOT_FOUND;\r
1360 }\r
1361\r
1362 *Section = (UINT8*)sectionHdr;\r
1363 *Key = *Key + sectionSize;\r
1364 return EFI_SUCCESS;\r
1365\r
1366}\r
1367\r
1368\r
1369EFI_STATUS\r
1370FvBufCountSections (\r
1371 IN VOID* FfsFile,\r
1372 IN UINTN* Count\r
1373 )\r
1374/*++\r
1375\r
1376Routine Description:\r
1377\r
1378 Searches the FFS file and counts the number of sections found.\r
1379 The sections are NOT recursed.\r
1380\r
1381Arguments:\r
1382\r
1383 FfsFile - Address of the FFS file in memory\r
1384 Count - The location to store the section count in\r
1385\r
1386Returns:\r
1387\r
1388 EFI_SUCCESS\r
1389 EFI_NOT_FOUND\r
1390 EFI_VOLUME_CORRUPTED\r
1391\r
1392--*/\r
1393{\r
1394 EFI_STATUS Status;\r
1395 UINTN Key;\r
1396 VOID* SectionStart;\r
1397 UINTN TotalSectionsSize;\r
1398 EFI_COMMON_SECTION_HEADER* NextSection;\r
1399\r
e4ac870f 1400 SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile));\r
30fdf114 1401 TotalSectionsSize =\r
e4ac870f
LG
1402 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) -\r
1403 FvBufGetFfsHeaderSize(FfsFile);\r
30fdf114
LG
1404 Key = 0;\r
1405 *Count = 0;\r
1406 while (TRUE) {\r
1407 Status = FvBufFindNextSection (\r
1408 SectionStart,\r
1409 TotalSectionsSize,\r
1410 &Key,\r
1411 (VOID **)&NextSection\r
1412 );\r
1413 if (Status == EFI_NOT_FOUND) {\r
1414 return EFI_SUCCESS;\r
1415 } else if (EFI_ERROR (Status)) {\r
1416 return Status;\r
1417 }\r
1418\r
1419 //\r
1420 // Increment the section counter\r
1421 //\r
1422 *Count += 1;\r
1423\r
1424 }\r
1425\r
1426 return EFI_NOT_FOUND;\r
1427}\r
1428\r
1429\r
1430EFI_STATUS\r
1431FvBufFindSectionByType (\r
1432 IN VOID *FfsFile,\r
1433 IN UINT8 Type,\r
1434 OUT VOID **Section\r
1435 )\r
1436/*++\r
1437\r
1438Routine Description:\r
1439\r
1440 Searches the FFS file for a section by its type\r
1441\r
1442Arguments:\r
1443\r
1444 FfsFile - Address of the FFS file in memory\r
1445 Type - FFS FILE section type to search for\r
1446 Section - Output section pointer\r
1447 (Section == NULL) -> Only determine if the section exists, based on return\r
1448 value from the function call.\r
1449 otherwise -> *Section will be update to the location of the file\r
1450\r
1451Returns:\r
1452\r
1453 EFI_SUCCESS\r
1454 EFI_NOT_FOUND\r
1455 EFI_VOLUME_CORRUPTED\r
1456\r
1457--*/\r
1458{\r
1459 EFI_STATUS Status;\r
1460 UINTN Key;\r
1461 VOID* SectionStart;\r
1462 UINTN TotalSectionsSize;\r
1463 EFI_COMMON_SECTION_HEADER* NextSection;\r
1464\r
e4ac870f 1465 SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile));\r
30fdf114 1466 TotalSectionsSize =\r
e4ac870f
LG
1467 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) -\r
1468 FvBufGetFfsHeaderSize(FfsFile);\r
30fdf114
LG
1469 Key = 0;\r
1470 while (TRUE) {\r
1471 Status = FvBufFindNextSection (\r
1472 SectionStart,\r
1473 TotalSectionsSize,\r
1474 &Key,\r
1475 (VOID **)&NextSection\r
1476 );\r
1477 if (EFI_ERROR (Status)) {\r
1478 return Status;\r
1479 }\r
1480\r
1481 if (Type == NextSection->Type) {\r
1482 if (Section != NULL) {\r
1483 *Section = NextSection;\r
1484 }\r
1485 return EFI_SUCCESS;\r
1486 }\r
1487 }\r
1488\r
1489 return EFI_NOT_FOUND;\r
1490}\r
1491\r
1492\r
1493EFI_STATUS\r
1494FvBufShrinkWrap (\r
1495 IN VOID *Fv\r
1496 )\r
1497/*++\r
1498\r
1499Routine Description:\r
1500\r
1501 Shrinks a firmware volume (in place) to provide a minimal FV.\r
1502\r
1503 BUGBUG: Does not handle the case where the firmware volume has a\r
1504 VTF (Volume Top File). The VTF will not be moved to the\r
1505 end of the extended FV.\r
1506\r
1507Arguments:\r
1508\r
1509 Fv - Firmware volume.\r
1510\r
1511Returns:\r
1512\r
1513 EFI_SUCCESS\r
1514\r
1515--*/\r
1516{\r
1517 EFI_STATUS Status;\r
1518 UINTN OldSize;\r
1519 UINT32 BlockCount;\r
1520 UINT32 NewBlockSize = 128;\r
1521 UINTN Key;\r
1522 EFI_FFS_FILE_HEADER* FileIt;\r
1523 VOID* EndOfLastFile;\r
1524\r
1525 EFI_FIRMWARE_VOLUME_HEADER* FvHdr;\r
1526\r
1527 Status = FvBufGetSize (Fv, &OldSize);\r
1528 if (EFI_ERROR (Status)) {\r
1529 return Status;\r
1530 }\r
1531\r
1532 Status = FvBufUnifyBlockSizes (Fv, NewBlockSize);\r
1533 if (EFI_ERROR (Status)) {\r
1534 return Status;\r
1535 }\r
1536\r
1537 //\r
1538 // Locate the block map in the fv header\r
1539 //\r
1540 FvHdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;\r
1541\r
1542 //\r
1543 // Find the end of the last file\r
1544 //\r
1545 Key = 0;\r
1546 EndOfLastFile = (UINT8*)FvHdr + FvHdr->FvLength;\r
1547 while (!EFI_ERROR (FvBufFindNextFile (Fv, &Key, (VOID **)&FileIt))) {\r
1548 EndOfLastFile =\r
e4ac870f 1549 (VOID*)((UINT8*)FileIt + FvBufGetFfsFileSize (FileIt));\r
30fdf114
LG
1550 }\r
1551\r
1552 //\r
1553 // Set the BlockCount to have the minimal number of blocks for the Fv.\r
1554 //\r
1555 BlockCount = (UINT32)((UINTN)EndOfLastFile - (UINTN)Fv);\r
1556 BlockCount = BlockCount + NewBlockSize - 1;\r
1557 BlockCount = BlockCount / NewBlockSize;\r
1558\r
1559 //\r
1560 // Adjust the block count to shrink the Fv in place.\r
1561 //\r
1562 FvHdr->BlockMap[0].NumBlocks = BlockCount;\r
1563 FvHdr->FvLength = BlockCount * NewBlockSize;\r
1564\r
1565 //\r
1566 // Update the FV header checksum\r
1567 //\r
1568 FvBufChecksumHeader (Fv);\r
1569\r
1570 return EFI_SUCCESS;\r
1571\r
1572}\r
1573\r
1574\r
1575EFI_STATUS\r
1576FvBufUnifyBlockSizes (\r
1577 IN OUT VOID *Fv,\r
1578 IN UINTN BlockSize\r
1579 )\r
1580/*++\r
1581\r
1582Routine Description:\r
1583\r
1584 Searches the FFS file for a section by its type\r
1585\r
1586Arguments:\r
1587\r
1588 Fv - Address of the Fv in memory\r
1589 BlockSize - The size of the blocks to convert the Fv to. If the total size\r
1590 of the Fv is not evenly divisible by this size, then\r
1591 EFI_INVALID_PARAMETER will be returned.\r
1592\r
1593Returns:\r
1594\r
1595 EFI_SUCCESS\r
1596 EFI_NOT_FOUND\r
1597 EFI_VOLUME_CORRUPTED\r
1598\r
1599--*/\r
1600{\r
1601 EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;\r
1602 EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap;\r
1603 UINT32 Size;\r
1604\r
1605 Size = 0;\r
1606\r
1607 //\r
1608 // Scan through the block map list, performing error checking, and adding\r
1609 // up the total Fv size.\r
1610 //\r
1611 while( blk->Length != 0 ||\r
1612 blk->NumBlocks != 0\r
1613 ) {\r
1614 Size = Size + (blk->Length * blk->NumBlocks);\r
1615 blk++;\r
1616 if ((UINT8*)blk > ((UINT8*)hdr + hdr->HeaderLength)) {\r
1617 return EFI_VOLUME_CORRUPTED;\r
1618 }\r
1619 }\r
1620\r
1621 //\r
1622 // Make sure that the Fv size is a multiple of the new block size.\r
1623 //\r
1624 if ((Size % BlockSize) != 0) {\r
1625 return EFI_INVALID_PARAMETER;\r
1626 }\r
1627\r
1628 //\r
1629 // Zero out the entire block map.\r
1630 //\r
1631 CommonLibBinderSetMem (\r
1632 &hdr->BlockMap,\r
1633 (UINTN)blk - (UINTN)&hdr->BlockMap,\r
1634 0\r
1635 );\r
1636\r
1637 //\r
1638 // Write out the single block map entry.\r
1639 //\r
1640 hdr->BlockMap[0].Length = (UINT32)BlockSize;\r
1641 hdr->BlockMap[0].NumBlocks = Size / (UINT32)BlockSize;\r
1642\r
1643 return EFI_SUCCESS;\r
1644}\r
1645\r
1646STATIC\r
1647UINT16\r
1648FvBufCalculateSum16 (\r
1649 IN UINT16 *Buffer,\r
1650 IN UINTN Size\r
1651 )\r
1652/*++\r
1653 \r
1654Routine Description:\r
1655\r
1656 This function calculates the UINT16 sum for the requested region.\r
1657\r
1658Arguments:\r
1659\r
1660 Buffer Pointer to buffer containing byte data of component.\r
1661 Size Size of the buffer\r
1662\r
1663Returns:\r
1664\r
1665 The 16 bit checksum\r
1666\r
1667--*/\r
1668{\r
1669 UINTN Index;\r
1670 UINT16 Sum;\r
1671\r
1672 Sum = 0;\r
1673\r
1674 //\r
1675 // Perform the word sum for buffer\r
1676 //\r
1677 for (Index = 0; Index < Size; Index++) {\r
1678 Sum = (UINT16) (Sum + Buffer[Index]);\r
1679 }\r
1680\r
1681 return (UINT16) Sum;\r
1682}\r
1683\r
1684\r
1685STATIC\r
1686UINT16\r
1687FvBufCalculateChecksum16 (\r
1688 IN UINT16 *Buffer,\r
1689 IN UINTN Size\r
1690 )\r
1691/*++\r
1692 \r
1693Routine Description::\r
1694\r
1695 This function calculates the value needed for a valid UINT16 checksum\r
1696\r
1697Arguments:\r
1698\r
1699 Buffer Pointer to buffer containing byte data of component.\r
1700 Size Size of the buffer\r
1701\r
1702Returns:\r
1703\r
1704 The 16 bit checksum value needed.\r
1705\r
1706--*/\r
1707{\r
1708 return (UINT16)(0x10000 - FvBufCalculateSum16 (Buffer, Size));\r
1709}\r
1710\r
1711\r
1712STATIC\r
1713UINT8\r
1714FvBufCalculateSum8 (\r
1715 IN UINT8 *Buffer,\r
1716 IN UINTN Size\r
1717 )\r
1718/*++\r
1719\r
1720Description:\r
1721\r
1722 This function calculates the UINT8 sum for the requested region.\r
1723\r
1724Input:\r
1725\r
1726 Buffer Pointer to buffer containing byte data of component.\r
1727 Size Size of the buffer\r
1728\r
1729Return:\r
1730\r
1731 The 8 bit checksum value needed.\r
1732\r
1733--*/\r
1734{\r
1735 UINTN Index;\r
1736 UINT8 Sum;\r
1737\r
1738 Sum = 0;\r
1739\r
1740 //\r
1741 // Perform the byte sum for buffer\r
1742 //\r
1743 for (Index = 0; Index < Size; Index++) {\r
1744 Sum = (UINT8) (Sum + Buffer[Index]);\r
1745 }\r
1746\r
1747 return Sum;\r
1748}\r
1749\r
1750\r
1751STATIC\r
1752UINT8\r
1753FvBufCalculateChecksum8 (\r
1754 IN UINT8 *Buffer,\r
1755 IN UINTN Size\r
1756 )\r
1757/*++\r
1758\r
1759Description:\r
1760\r
1761 This function calculates the value needed for a valid UINT8 checksum\r
1762\r
1763Input:\r
1764\r
1765 Buffer Pointer to buffer containing byte data of component.\r
1766 Size Size of the buffer\r
1767\r
1768Return:\r
1769\r
1770 The 8 bit checksum value needed.\r
1771\r
1772--*/\r
1773{\r
1774 return (UINT8)(0x100 - FvBufCalculateSum8 (Buffer, Size));\r
1775}\r
1776\r
1777\r