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