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