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