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