1 /** @file
2   Implements functions to pad firmware file.
3 
4   Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "FwVolDriver.h"
11 
12 /**
13   Calculate the checksum for a PAD file.
14 
15   @param PadFileHeader   The Pad File to be caculeted the checksum.
16 
17 **/
18 VOID
SetPadFileChecksum(IN EFI_FFS_FILE_HEADER * PadFileHeader)19 SetPadFileChecksum (
20   IN EFI_FFS_FILE_HEADER *PadFileHeader
21   )
22 {
23   if ((PadFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) {
24 
25     if (IS_FFS_FILE2 (PadFileHeader)) {
26       //
27       // Calculate checksum of Pad File Data
28       //
29       PadFileHeader->IntegrityCheck.Checksum.File =
30         CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2));
31 
32       } else {
33       //
34       // Calculate checksum of Pad File Data
35       //
36       PadFileHeader->IntegrityCheck.Checksum.File =
37         CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER));
38     }
39 
40   } else {
41 
42     PadFileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
43 
44   }
45 
46   return ;
47 }
48 
49 /**
50   Create a PAD File in the Free Space.
51 
52   @param FvDevice        Firmware Volume Device.
53   @param FreeSpaceEntry  Indicating in which Free Space(Cache) the Pad file will be inserted.
54   @param Size            Pad file Size, not include the header.
55   @param PadFileEntry    The Ffs File Entry that points to this Pad File.
56 
57   @retval EFI_SUCCESS            Successfully create a PAD file.
58   @retval EFI_OUT_OF_RESOURCES   No enough free space to create a PAD file.
59   @retval EFI_INVALID_PARAMETER  Size is not 8 byte alignment.
60   @retval EFI_DEVICE_ERROR       Free space is not erased.
61 **/
62 EFI_STATUS
FvCreatePadFileInFreeSpace(IN FV_DEVICE * FvDevice,IN FREE_SPACE_ENTRY * FreeSpaceEntry,IN UINTN Size,OUT FFS_FILE_LIST_ENTRY ** PadFileEntry)63 FvCreatePadFileInFreeSpace (
64   IN  FV_DEVICE           *FvDevice,
65   IN  FREE_SPACE_ENTRY    *FreeSpaceEntry,
66   IN  UINTN               Size,
67   OUT FFS_FILE_LIST_ENTRY **PadFileEntry
68   )
69 {
70   EFI_STATUS                          Status;
71   EFI_FFS_FILE_HEADER                 *PadFileHeader;
72   UINTN                               Offset;
73   UINTN                               NumBytesWritten;
74   UINTN                               StateOffset;
75   UINT8                               *StartPos;
76   FFS_FILE_LIST_ENTRY                 *FfsFileEntry;
77   UINTN                               HeaderSize;
78   UINTN                               FileSize;
79 
80   HeaderSize = sizeof (EFI_FFS_FILE_HEADER);
81   FileSize = Size + HeaderSize;
82   if (FileSize > 0x00FFFFFF) {
83     HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
84     FileSize = Size + HeaderSize;
85   }
86 
87   if (FreeSpaceEntry->Length < FileSize) {
88     return EFI_OUT_OF_RESOURCES;
89   }
90 
91   if ((Size & 0x07) != 0) {
92     return EFI_INVALID_PARAMETER;
93   }
94 
95   StartPos = FreeSpaceEntry->StartingAddress;
96 
97   //
98   // First double check the space
99   //
100   if (!IsBufferErased (
101         FvDevice->ErasePolarity,
102         StartPos,
103         FileSize
104         )) {
105     return EFI_DEVICE_ERROR;
106   }
107 
108   PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos;
109 
110   //
111   // Create File Step 1
112   //
113   SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
114 
115   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
116   StateOffset     = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader;
117 
118   NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
119   Status = FvcWrite (
120             FvDevice,
121             StateOffset,
122             &NumBytesWritten,
123             &PadFileHeader->State
124             );
125   if (EFI_ERROR (Status)) {
126     SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
127     return Status;
128   }
129   //
130   // Update Free Space Entry, since header is allocated
131   //
132   FreeSpaceEntry->Length -= HeaderSize;
133   FreeSpaceEntry->StartingAddress += HeaderSize;
134 
135   //
136   // Fill File Name Guid, here we assign a NULL-GUID to Pad files
137   //
138   ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID));
139 
140   //
141   // Fill File Type, checksum(0), Attributes(0), Size
142   //
143   PadFileHeader->Type       = EFI_FV_FILETYPE_FFS_PAD;
144   PadFileHeader->Attributes = 0;
145   if ((FileSize) > 0x00FFFFFF) {
146     ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) FileSize;
147     *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
148     PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
149   } else {
150     *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
151     *(UINT32 *) PadFileHeader->Size |= FileSize;
152   }
153 
154   SetHeaderChecksum (PadFileHeader);
155   SetPadFileChecksum (PadFileHeader);
156 
157   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
158 
159   NumBytesWritten = HeaderSize;
160   Status = FvcWrite (
161             FvDevice,
162             Offset,
163             &NumBytesWritten,
164             (UINT8 *) PadFileHeader
165             );
166   if (EFI_ERROR (Status)) {
167     return Status;
168   }
169 
170   //
171   // Step 2, then Mark header valid, since no data write,
172   // mark the data valid at the same time.
173   //
174   SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
175   SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
176 
177   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
178   StateOffset     = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader;
179 
180   NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
181   Status = FvcWrite (
182             FvDevice,
183             StateOffset,
184             &NumBytesWritten,
185             &PadFileHeader->State
186             );
187   if (EFI_ERROR (Status)) {
188     SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
189     SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
190     return Status;
191   }
192   //
193   // Update Free Space Entry, since header is allocated
194   //
195   FreeSpaceEntry->Length -= Size;
196   FreeSpaceEntry->StartingAddress += Size;
197 
198   //
199   // If successfully, insert an FfsFileEntry at the end of ffs file list
200   //
201   FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));
202   ASSERT (FfsFileEntry != NULL);
203 
204   FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) StartPos;
205   InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
206 
207   *PadFileEntry             = FfsFileEntry;
208   FvDevice->CurrentFfsFile  = FfsFileEntry;
209 
210   return EFI_SUCCESS;
211 }
212 
213 /**
214   Fill pad file header within firmware cache.
215 
216   @param PadFileHeader    The start of the Pad File Buffer.
217   @param PadFileLength    The length of the pad file including the header.
218 
219 **/
220 VOID
FvFillPadFile(IN EFI_FFS_FILE_HEADER * PadFileHeader,IN UINTN PadFileLength)221 FvFillPadFile (
222   IN EFI_FFS_FILE_HEADER  *PadFileHeader,
223   IN UINTN                PadFileLength
224   )
225 {
226   //
227   // Fill File Name Guid, here we assign a NULL-GUID to Pad files
228   //
229   ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID));
230 
231   //
232   // Fill File Type, checksum(0), Attributes(0), Size
233   //
234   PadFileHeader->Type       = EFI_FV_FILETYPE_FFS_PAD;
235   PadFileHeader->Attributes = 0;
236   if (PadFileLength > 0x00FFFFFF) {
237     ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) PadFileLength;
238     *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
239     PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
240   } else {
241     *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
242     *(UINT32 *) PadFileHeader->Size |= PadFileLength;
243   }
244 
245   SetHeaderChecksum (PadFileHeader);
246   SetPadFileChecksum (PadFileHeader);
247 
248   //
249   // Set File State to 0x00000111
250   //
251   SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
252   SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
253   SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
254 
255   return ;
256 }
257 
258 /**
259   Create entire FFS file.
260 
261   @param FileHeader      Starting Address of a Buffer that hold the FFS File image.
262   @param FfsFileBuffer   The source buffer that contains the File Data.
263   @param BufferSize      The length of FfsFileBuffer.
264   @param ActualFileSize  Size of FFS file.
265   @param FileName        The Guid of Ffs File.
266   @param FileType        The type of the written Ffs File.
267   @param FileAttributes  The attributes of the written Ffs File.
268 
269   @retval EFI_INVALID_PARAMETER  File type is not valid.
270   @retval EFI_SUCCESS            FFS file is successfully created.
271 
272 **/
273 EFI_STATUS
FvFillFfsFile(OUT EFI_FFS_FILE_HEADER * FileHeader,IN UINT8 * FfsFileBuffer,IN UINTN BufferSize,IN UINTN ActualFileSize,IN EFI_GUID * FileName,IN EFI_FV_FILETYPE FileType,IN EFI_FV_FILE_ATTRIBUTES FileAttributes)274 FvFillFfsFile (
275   OUT EFI_FFS_FILE_HEADER   *FileHeader,
276   IN UINT8                  *FfsFileBuffer,
277   IN UINTN                  BufferSize,
278   IN UINTN                  ActualFileSize,
279   IN EFI_GUID               *FileName,
280   IN EFI_FV_FILETYPE        FileType,
281   IN EFI_FV_FILE_ATTRIBUTES FileAttributes
282   )
283 {
284   EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute;
285   EFI_FFS_FILE_HEADER     *TmpFileHeader;
286 
287   //
288   // File Type value 0x0E~0xE0 are reserved
289   //
290   if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) {
291     return EFI_INVALID_PARAMETER;
292   }
293 
294   TmpFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer;
295   //
296   // First fill all fields ready in FfsFileBuffer
297   //
298   CopyGuid (&TmpFileHeader->Name, FileName);
299   TmpFileHeader->Type = FileType;
300 
301   //
302   // Convert the FileAttributes to FFSFileAttributes
303   //
304   FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute);
305 
306   TmpFileHeader->Attributes = TmpFileAttribute;
307 
308   if (ActualFileSize > 0x00FFFFFF) {
309     ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize;
310     *(UINT32 *) FileHeader->Size &= 0xFF000000;
311     FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
312   } else {
313     *(UINT32 *) FileHeader->Size &= 0xFF000000;
314     *(UINT32 *) FileHeader->Size |= ActualFileSize;
315   }
316 
317   SetHeaderChecksum (TmpFileHeader);
318   SetFileChecksum (TmpFileHeader, ActualFileSize);
319 
320   SetFileState (EFI_FILE_HEADER_CONSTRUCTION, TmpFileHeader);
321   SetFileState (EFI_FILE_HEADER_VALID, TmpFileHeader);
322   SetFileState (EFI_FILE_DATA_VALID, TmpFileHeader);
323 
324   //
325   // Copy data from FfsFileBuffer to FileHeader(cache)
326   //
327   CopyMem (FileHeader, FfsFileBuffer, BufferSize);
328 
329   return EFI_SUCCESS;
330 }
331 
332 /**
333   Fill some other extra space using 0xFF(Erase Value).
334 
335   @param  ErasePolarity  Fv erase value.
336   @param  FileHeader     Point to the start of FFS File.
337   @param  ExtraLength    The pading length.
338 
339 **/
340 VOID
FvAdjustFfsFile(IN UINT8 ErasePolarity,IN EFI_FFS_FILE_HEADER * FileHeader,IN UINTN ExtraLength)341 FvAdjustFfsFile (
342   IN  UINT8                 ErasePolarity,
343   IN  EFI_FFS_FILE_HEADER   *FileHeader,
344   IN  UINTN                 ExtraLength
345   )
346 {
347   UINT8 *Ptr;
348   UINT8 PadingByte;
349 
350   if (IS_FFS_FILE2 (FileHeader)) {
351     Ptr         = (UINT8 *) FileHeader + FFS_FILE2_SIZE (FileHeader);
352   } else {
353     Ptr         = (UINT8 *) FileHeader + FFS_FILE_SIZE (FileHeader);
354   }
355 
356   if (ErasePolarity == 0) {
357     PadingByte = 0;
358   } else {
359     PadingByte = 0xFF;
360   }
361   //
362   // Fill the non-used space with Padding Byte
363   //
364   SetMem (Ptr, ExtraLength, PadingByte);
365 
366   return ;
367 }
368 
369 /**
370   Free File List entry pointed by FileListHead.
371 
372   @param FileListHeader   FileListEntry Header.
373 
374 **/
375 VOID
FreeFileList(IN LIST_ENTRY * FileListHead)376 FreeFileList (
377   IN  LIST_ENTRY  *FileListHead
378   )
379 {
380   FFS_FILE_LIST_ENTRY *FfsFileEntry;
381   LIST_ENTRY      *NextEntry;
382 
383   FfsFileEntry = (FFS_FILE_LIST_ENTRY *) (FileListHead->ForwardLink);
384 
385   //
386   // Loop the whole list entry to free resources
387   //
388   while (&FfsFileEntry->Link != FileListHead) {
389     NextEntry = (&FfsFileEntry->Link)->ForwardLink;
390     FreePool (FfsFileEntry);
391     FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;
392   }
393 
394   return ;
395 }
396 
397 /**
398   Create a new file within a PAD file area.
399 
400   @param FvDevice        Firmware Volume Device.
401   @param FfsFileBuffer   A buffer that holds an FFS file,(it contains a File Header which is in init state).
402   @param BufferSize      The size of FfsFileBuffer.
403   @param ActualFileSize  The actual file length, it may not be multiples of 8.
404   @param FileName        The FFS File Name.
405   @param FileType        The FFS File Type.
406   @param FileAttributes  The Attributes of the FFS File to be created.
407 
408   @retval EFI_SUCCESS           Successfully create a new file within the found PAD file area.
409   @retval EFI_OUT_OF_RESOURCES  No suitable PAD file is found.
410   @retval other errors          New file is created failed.
411 
412 **/
413 EFI_STATUS
FvCreateNewFileInsidePadFile(IN FV_DEVICE * FvDevice,IN UINT8 * FfsFileBuffer,IN UINTN BufferSize,IN UINTN ActualFileSize,IN EFI_GUID * FileName,IN EFI_FV_FILETYPE FileType,IN EFI_FV_FILE_ATTRIBUTES FileAttributes)414 FvCreateNewFileInsidePadFile (
415   IN  FV_DEVICE               *FvDevice,
416   IN  UINT8                   *FfsFileBuffer,
417   IN  UINTN                   BufferSize,
418   IN  UINTN                   ActualFileSize,
419   IN  EFI_GUID                *FileName,
420   IN  EFI_FV_FILETYPE         FileType,
421   IN  EFI_FV_FILE_ATTRIBUTES  FileAttributes
422   )
423 {
424   UINTN                               RequiredAlignment;
425   FFS_FILE_LIST_ENTRY                 *PadFileEntry;
426   EFI_STATUS                          Status;
427   UINTN                               PadAreaLength;
428   UINTN                               PadSize;
429   EFI_FFS_FILE_HEADER                 *FileHeader;
430   EFI_FFS_FILE_HEADER                 *OldPadFileHeader;
431   EFI_FFS_FILE_HEADER                 *PadFileHeader;
432   EFI_FFS_FILE_HEADER                 *TailPadFileHeader;
433   UINTN                               StateOffset;
434   UINTN                               Offset;
435   UINTN                               NumBytesWritten;
436   UINT8                               *StartPos;
437   LIST_ENTRY                          NewFileList;
438   FFS_FILE_LIST_ENTRY                 *NewFileListEntry;
439   FFS_FILE_LIST_ENTRY                 *FfsEntry;
440   FFS_FILE_LIST_ENTRY                 *NextFfsEntry;
441 
442   //
443   // First get the required alignment from the File Attributes
444   //
445   RequiredAlignment = GetRequiredAlignment (FileAttributes);
446 
447   //
448   // Find a suitable PAD File
449   //
450   Status = FvLocatePadFile (
451             FvDevice,
452             BufferSize,
453             RequiredAlignment,
454             &PadSize,
455             &PadFileEntry
456             );
457 
458   if (EFI_ERROR (Status)) {
459     return EFI_OUT_OF_RESOURCES;
460   }
461 
462   OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader;
463 
464   //
465   // Step 1: Update Pad File Header
466   //
467   SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldPadFileHeader);
468 
469   StartPos = PadFileEntry->FfsHeader;
470 
471   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
472   StateOffset     = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader;
473 
474   NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
475   Status = FvcWrite (
476             FvDevice,
477             StateOffset,
478             &NumBytesWritten,
479             &OldPadFileHeader->State
480             );
481   if (EFI_ERROR (Status)) {
482     SetFileState (EFI_FILE_HEADER_CONSTRUCTION, OldPadFileHeader);
483     return Status;
484   }
485 
486   //
487   // Step 2: Update Pad area
488   //
489   InitializeListHead (&NewFileList);
490 
491   if (IS_FFS_FILE2 (OldPadFileHeader)) {
492     PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
493     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
494   } else {
495     PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
496     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER));
497   }
498 
499   if (PadSize != 0) {
500     //
501     // Insert a PAD file before to achieve required alignment
502     //
503     FvFillPadFile (PadFileHeader, PadSize);
504     NewFileListEntry            = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
505     ASSERT (NewFileListEntry   != NULL);
506     NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
507     InsertTailList (&NewFileList, &NewFileListEntry->Link);
508   }
509 
510   FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize);
511 
512   Status = FvFillFfsFile (
513             FileHeader,
514             FfsFileBuffer,
515             BufferSize,
516             ActualFileSize,
517             FileName,
518             FileType,
519             FileAttributes
520             );
521   if (EFI_ERROR (Status)) {
522     FreeFileList (&NewFileList);
523     return Status;
524   }
525 
526   NewFileListEntry            = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
527   ASSERT (NewFileListEntry   != NULL);
528 
529   NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
530   InsertTailList (&NewFileList, &NewFileListEntry->Link);
531 
532   FvDevice->CurrentFfsFile = NewFileListEntry;
533 
534   if (PadAreaLength > (BufferSize + PadSize)) {
535     if ((PadAreaLength - BufferSize - PadSize) >= sizeof (EFI_FFS_FILE_HEADER)) {
536       //
537       // we can insert another PAD file
538       //
539       TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize);
540       FvFillPadFile (TailPadFileHeader, PadAreaLength - BufferSize - PadSize);
541 
542       NewFileListEntry            = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
543       ASSERT (NewFileListEntry   != NULL);
544 
545       NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader;
546       InsertTailList (&NewFileList, &NewFileListEntry->Link);
547     } else {
548       //
549       // because left size cannot hold another PAD file header,
550       // adjust the writing file size (just in cache)
551       //
552       FvAdjustFfsFile (
553         FvDevice->ErasePolarity,
554         FileHeader,
555         PadAreaLength - BufferSize - PadSize
556         );
557     }
558   }
559   //
560   // Start writing to FV
561   //
562   if (IS_FFS_FILE2 (OldPadFileHeader)) {
563     StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2);
564   } else {
565     StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER);
566   }
567 
568   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
569 
570   NumBytesWritten = PadAreaLength;
571   Status = FvcWrite (
572             FvDevice,
573             Offset,
574             &NumBytesWritten,
575             StartPos
576             );
577   if (EFI_ERROR (Status)) {
578     FreeFileList (&NewFileList);
579     FvDevice->CurrentFfsFile = NULL;
580     return Status;
581   }
582 
583   //
584   // Step 3: Mark Pad file header as EFI_FILE_HEADER_INVALID
585   //
586   SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader);
587 
588   StartPos = PadFileEntry->FfsHeader;
589 
590   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
591   StateOffset     = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader;
592 
593   NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
594   Status = FvcWrite (
595             FvDevice,
596             StateOffset,
597             &NumBytesWritten,
598             &OldPadFileHeader->State
599             );
600   if (EFI_ERROR (Status)) {
601     SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader);
602     FreeFileList (&NewFileList);
603     FvDevice->CurrentFfsFile = NULL;
604     return Status;
605   }
606 
607   //
608   // If all successfully, update FFS_FILE_LIST
609   //
610 
611   //
612   // Delete old pad file entry
613   //
614   FfsEntry      = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink;
615   NextFfsEntry  = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink;
616 
617   FreePool (PadFileEntry);
618 
619   FfsEntry->Link.ForwardLink          = NewFileList.ForwardLink;
620   (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link;
621   NextFfsEntry->Link.BackLink         = NewFileList.BackLink;
622   (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link;
623 
624   return EFI_SUCCESS;
625 }
626 
627 /**
628   Free all FfsBuffer.
629 
630   @param NumOfFiles      Number of FfsBuffer.
631   @param FfsBuffer       An array of pointer to an FFS File Buffer
632 
633 **/
634 VOID
FreeFfsBuffer(IN UINTN NumOfFiles,IN UINT8 ** FfsBuffer)635 FreeFfsBuffer (
636   IN UINTN    NumOfFiles,
637   IN UINT8    **FfsBuffer
638   )
639 {
640   UINTN Index;
641   for (Index = 0; Index < NumOfFiles; Index++) {
642     if (FfsBuffer[Index] != NULL) {
643       FreePool (FfsBuffer[Index]);
644     }
645   }
646 }
647 
648 /**
649   Create multiple files within a PAD File area.
650 
651   @param FvDevice        Firmware Volume Device.
652   @param PadFileEntry    The pad file entry to be written in.
653   @param NumOfFiles      Total File number to be written.
654   @param BufferSize      The array of buffer size of each FfsBuffer.
655   @param ActualFileSize  The array of actual file size.
656   @param PadSize         The array of leading pad file size for each FFS File
657   @param FfsBuffer       The array of Ffs Buffer pointer.
658   @param FileData        The array of EFI_FV_WRITE_FILE_DATA structure,
659                          used to get name, attributes, type, etc.
660 
661   @retval EFI_SUCCESS           Add the input multiple files into PAD file area.
662   @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
663   @retval other error           Files can't be added into PAD file area.
664 
665 **/
666 EFI_STATUS
FvCreateMultipleFilesInsidePadFile(IN FV_DEVICE * FvDevice,IN FFS_FILE_LIST_ENTRY * PadFileEntry,IN UINTN NumOfFiles,IN UINTN * BufferSize,IN UINTN * ActualFileSize,IN UINTN * PadSize,IN UINT8 ** FfsBuffer,IN EFI_FV_WRITE_FILE_DATA * FileData)667 FvCreateMultipleFilesInsidePadFile (
668   IN FV_DEVICE              *FvDevice,
669   IN FFS_FILE_LIST_ENTRY    *PadFileEntry,
670   IN UINTN                  NumOfFiles,
671   IN UINTN                  *BufferSize,
672   IN UINTN                  *ActualFileSize,
673   IN UINTN                  *PadSize,
674   IN UINT8                  **FfsBuffer,
675   IN EFI_FV_WRITE_FILE_DATA *FileData
676   )
677 {
678   EFI_STATUS                          Status;
679   EFI_FFS_FILE_HEADER                 *OldPadFileHeader;
680   UINTN                               Index;
681   EFI_FFS_FILE_HEADER                 *PadFileHeader;
682   EFI_FFS_FILE_HEADER                 *FileHeader;
683   EFI_FFS_FILE_HEADER                 *TailPadFileHeader;
684   UINTN                               TotalSize;
685   UINTN                               PadAreaLength;
686   LIST_ENTRY                          NewFileList;
687   FFS_FILE_LIST_ENTRY                 *NewFileListEntry;
688   UINTN                               Offset;
689   UINTN                               NumBytesWritten;
690   UINT8                               *StartPos;
691   FFS_FILE_LIST_ENTRY                 *FfsEntry;
692   FFS_FILE_LIST_ENTRY                 *NextFfsEntry;
693 
694   InitializeListHead (&NewFileList);
695 
696   NewFileListEntry  = NULL;
697 
698   OldPadFileHeader  = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader;
699   if (IS_FFS_FILE2 (OldPadFileHeader)) {
700     PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
701   } else {
702     PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
703   }
704 
705   Status = UpdateHeaderBit (
706             FvDevice,
707             OldPadFileHeader,
708             EFI_FILE_MARKED_FOR_UPDATE
709             );
710   if (EFI_ERROR (Status)) {
711     return Status;
712   }
713   //
714   // Update PAD area
715   //
716   TotalSize     = 0;
717   if (IS_FFS_FILE2 (OldPadFileHeader)) {
718     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
719   } else {
720     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER));
721   }
722   FileHeader    = PadFileHeader;
723 
724   for (Index = 0; Index < NumOfFiles; Index++) {
725     if (PadSize[Index] != 0) {
726       FvFillPadFile (PadFileHeader, PadSize[Index]);
727       NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
728       if (NewFileListEntry == NULL) {
729         FreeFileList (&NewFileList);
730         return EFI_OUT_OF_RESOURCES;
731       }
732 
733       NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
734       InsertTailList (&NewFileList, &NewFileListEntry->Link);
735     }
736 
737     FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]);
738     Status = FvFillFfsFile (
739               FileHeader,
740               FfsBuffer[Index],
741               BufferSize[Index],
742               ActualFileSize[Index],
743               FileData[Index].NameGuid,
744               FileData[Index].Type,
745               FileData[Index].FileAttributes
746               );
747     if (EFI_ERROR (Status)) {
748       FreeFileList (&NewFileList);
749       return Status;
750     }
751 
752     NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
753     if (NewFileListEntry == NULL) {
754       FreeFileList (&NewFileList);
755       return EFI_OUT_OF_RESOURCES;
756     }
757 
758     NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
759     InsertTailList (&NewFileList, &NewFileListEntry->Link);
760 
761     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]);
762     TotalSize += PadSize[Index];
763     TotalSize += BufferSize[Index];
764   }
765 
766   FvDevice->CurrentFfsFile = NewFileListEntry;
767   //
768   // Maybe we need a tail pad file
769   //
770   if (PadAreaLength > TotalSize) {
771     if ((PadAreaLength - TotalSize) >= sizeof (EFI_FFS_FILE_HEADER)) {
772       //
773       // we can insert another PAD file
774       //
775       TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[NumOfFiles - 1]);
776       FvFillPadFile (TailPadFileHeader, PadAreaLength - TotalSize);
777 
778       NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
779       if (NewFileListEntry == NULL) {
780         FreeFileList (&NewFileList);
781         FvDevice->CurrentFfsFile = NULL;
782         return EFI_OUT_OF_RESOURCES;
783       }
784 
785       NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader;
786       InsertTailList (&NewFileList, &NewFileListEntry->Link);
787     } else {
788       //
789       // because left size cannot hold another PAD file header,
790       // adjust the writing file size (just in cache)
791       //
792       FvAdjustFfsFile (
793         FvDevice->ErasePolarity,
794         FileHeader,
795         PadAreaLength - TotalSize
796         );
797     }
798   }
799   //
800   // Start writing to FV
801   //
802   if (IS_FFS_FILE2 (OldPadFileHeader)) {
803     StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2);
804   } else {
805     StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER);
806   }
807 
808   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
809 
810   NumBytesWritten = PadAreaLength;
811   Status = FvcWrite (
812             FvDevice,
813             Offset,
814             &NumBytesWritten,
815             StartPos
816             );
817   if (EFI_ERROR (Status)) {
818     FreeFileList (&NewFileList);
819     FvDevice->CurrentFfsFile = NULL;
820     return Status;
821   }
822 
823   Status = UpdateHeaderBit (
824             FvDevice,
825             OldPadFileHeader,
826             EFI_FILE_HEADER_INVALID
827             );
828   if (EFI_ERROR (Status)) {
829     FreeFileList (&NewFileList);
830     FvDevice->CurrentFfsFile = NULL;
831     return Status;
832   }
833 
834   //
835   // Update File List Link
836   //
837 
838   //
839   // First delete old pad file entry
840   //
841   FfsEntry      = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink;
842   NextFfsEntry  = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink;
843 
844   FreePool (PadFileEntry);
845 
846   FfsEntry->Link.ForwardLink          = NewFileList.ForwardLink;
847   (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link;
848   NextFfsEntry->Link.BackLink         = NewFileList.BackLink;
849   (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link;
850 
851   return EFI_SUCCESS;
852 }
853 
854 /**
855   Create multiple files within the Free Space.
856 
857   @param FvDevice        Firmware Volume Device.
858   @param FreeSpaceEntry  Indicating in which Free Space(Cache) the multiple files will be inserted.
859   @param NumOfFiles      Total File number to be written.
860   @param BufferSize      The array of buffer size of each FfsBuffer.
861   @param ActualFileSize  The array of actual file size.
862   @param PadSize         The array of leading pad file size for each FFS File
863   @param FfsBuffer       The array of Ffs Buffer pointer.
864   @param FileData        The array of EFI_FV_WRITE_FILE_DATA structure,
865                          used to get name, attributes, type, etc.
866 
867   @retval EFI_SUCCESS           Add the input multiple files into PAD file area.
868   @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
869   @retval other error           Files can't be added into PAD file area.
870 
871 **/
872 EFI_STATUS
FvCreateMultipleFilesInsideFreeSpace(IN FV_DEVICE * FvDevice,IN FREE_SPACE_ENTRY * FreeSpaceEntry,IN UINTN NumOfFiles,IN UINTN * BufferSize,IN UINTN * ActualFileSize,IN UINTN * PadSize,IN UINT8 ** FfsBuffer,IN EFI_FV_WRITE_FILE_DATA * FileData)873 FvCreateMultipleFilesInsideFreeSpace (
874   IN FV_DEVICE              *FvDevice,
875   IN FREE_SPACE_ENTRY       *FreeSpaceEntry,
876   IN UINTN                  NumOfFiles,
877   IN UINTN                  *BufferSize,
878   IN UINTN                  *ActualFileSize,
879   IN UINTN                  *PadSize,
880   IN UINT8                  **FfsBuffer,
881   IN EFI_FV_WRITE_FILE_DATA *FileData
882   )
883 {
884   EFI_STATUS                          Status;
885   UINTN                               Index;
886   EFI_FFS_FILE_HEADER                 *PadFileHeader;
887   EFI_FFS_FILE_HEADER                 *FileHeader;
888   UINTN                               TotalSize;
889   LIST_ENTRY                          NewFileList;
890   FFS_FILE_LIST_ENTRY                 *NewFileListEntry;
891   UINTN                               Offset;
892   UINTN                               NumBytesWritten;
893   UINT8                               *StartPos;
894 
895   InitializeListHead (&NewFileList);
896 
897   NewFileListEntry  = NULL;
898 
899   TotalSize     = 0;
900   StartPos      = FreeSpaceEntry->StartingAddress;
901   PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos;
902   FileHeader    = PadFileHeader;
903 
904   for (Index = 0; Index < NumOfFiles; Index++) {
905     if (PadSize[Index] != 0) {
906       FvFillPadFile (PadFileHeader, PadSize[Index]);
907       NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
908       if (NewFileListEntry == NULL) {
909         FreeFileList (&NewFileList);
910         return EFI_OUT_OF_RESOURCES;
911       }
912 
913       NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
914       InsertTailList (&NewFileList, &NewFileListEntry->Link);
915     }
916 
917     FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]);
918     Status = FvFillFfsFile (
919               FileHeader,
920               FfsBuffer[Index],
921               BufferSize[Index],
922               ActualFileSize[Index],
923               FileData[Index].NameGuid,
924               FileData[Index].Type,
925               FileData[Index].FileAttributes
926               );
927     if (EFI_ERROR (Status)) {
928       FreeFileList (&NewFileList);
929       return Status;
930     }
931 
932     NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
933     if (NewFileListEntry == NULL) {
934       FreeFileList (&NewFileList);
935       return EFI_OUT_OF_RESOURCES;
936     }
937 
938     NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
939     InsertTailList (&NewFileList, &NewFileListEntry->Link);
940 
941     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]);
942     TotalSize += PadSize[Index];
943     TotalSize += BufferSize[Index];
944   }
945 
946   if (FreeSpaceEntry->Length < TotalSize) {
947     FreeFileList (&NewFileList);
948     return EFI_OUT_OF_RESOURCES;
949   }
950 
951   FvDevice->CurrentFfsFile = NewFileListEntry;
952 
953   //
954   // Start writing to FV
955   //
956   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
957 
958   NumBytesWritten = TotalSize;
959   Status = FvcWrite (
960             FvDevice,
961             Offset,
962             &NumBytesWritten,
963             StartPos
964             );
965   if (EFI_ERROR (Status)) {
966     FreeFileList (&NewFileList);
967     FvDevice->CurrentFfsFile = NULL;
968     return Status;
969   }
970 
971   FreeSpaceEntry->Length -= TotalSize;
972   FreeSpaceEntry->StartingAddress += TotalSize;
973 
974   NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileList.ForwardLink);
975 
976   while (NewFileListEntry != (FFS_FILE_LIST_ENTRY *) &NewFileList) {
977     InsertTailList (&FvDevice->FfsFileListHeader, &NewFileListEntry->Link);
978     NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileListEntry->Link.ForwardLink);
979   }
980 
981   return EFI_SUCCESS;
982 }
983 
984 /**
985   Write multiple files into FV in reliable method.
986 
987   @param FvDevice        Firmware Volume Device.
988   @param NumOfFiles      Total File number to be written.
989   @param FileData        The array of EFI_FV_WRITE_FILE_DATA structure,
990                          used to get name, attributes, type, etc
991   @param FileOperation   The array of operation for each file.
992 
993   @retval EFI_SUCCESS            Files are added into FV.
994   @retval EFI_OUT_OF_RESOURCES   No enough free PAD files to add the input files.
995   @retval EFI_INVALID_PARAMETER  File number is less than or equal to 1.
996   @retval EFI_UNSUPPORTED        File number exceeds the supported max numbers of files.
997 
998 **/
999 EFI_STATUS
FvCreateMultipleFiles(IN FV_DEVICE * FvDevice,IN UINTN NumOfFiles,IN EFI_FV_WRITE_FILE_DATA * FileData,IN BOOLEAN * FileOperation)1000 FvCreateMultipleFiles (
1001   IN  FV_DEVICE               *FvDevice,
1002   IN  UINTN                   NumOfFiles,
1003   IN  EFI_FV_WRITE_FILE_DATA  *FileData,
1004   IN  BOOLEAN                 *FileOperation
1005   )
1006 {
1007   EFI_STATUS                    Status;
1008   UINT8                         *FfsBuffer[MAX_FILES];
1009   UINTN                         Index1;
1010   UINTN                         Index2;
1011   UINTN                         BufferSize[MAX_FILES];
1012   UINTN                         ActualFileSize[MAX_FILES];
1013   UINTN                         RequiredAlignment[MAX_FILES];
1014   UINTN                         PadSize[MAX_FILES];
1015   FFS_FILE_LIST_ENTRY           *PadFileEntry;
1016   UINTN                         TotalSizeNeeded;
1017   FREE_SPACE_ENTRY              *FreeSpaceEntry;
1018   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
1019   UINTN                         Key;
1020   EFI_GUID                      FileNameGuid;
1021   EFI_FV_FILETYPE               OldFileType;
1022   EFI_FV_FILE_ATTRIBUTES        OldFileAttributes;
1023   UINTN                         OldFileSize;
1024   FFS_FILE_LIST_ENTRY           *OldFfsFileEntry[MAX_FILES];
1025   EFI_FFS_FILE_HEADER           *OldFileHeader[MAX_FILES];
1026   BOOLEAN                       IsCreateFile;
1027   UINTN                         HeaderSize;
1028 
1029   //
1030   // To use this function, we must ensure that the NumOfFiles is great
1031   // than 1
1032   //
1033   if (NumOfFiles <= 1) {
1034     return EFI_INVALID_PARAMETER;
1035   }
1036 
1037   if (NumOfFiles > MAX_FILES) {
1038     return EFI_UNSUPPORTED;
1039   }
1040 
1041   Fv = &FvDevice->Fv;
1042 
1043   SetMem (FfsBuffer, NumOfFiles, 0);
1044   SetMem (RequiredAlignment, NumOfFiles, 8);
1045   SetMem (PadSize, NumOfFiles, 0);
1046   ZeroMem (OldFfsFileEntry, sizeof (OldFfsFileEntry));
1047   ZeroMem (OldFileHeader, sizeof (OldFileHeader));
1048 
1049   //
1050   // Adjust file size
1051   //
1052   for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
1053     HeaderSize = sizeof (EFI_FFS_FILE_HEADER);
1054     ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize;
1055     if (ActualFileSize[Index1] > 0x00FFFFFF) {
1056       HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
1057       ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize;
1058     }
1059     BufferSize[Index1]     = ActualFileSize[Index1];
1060 
1061     if (BufferSize[Index1] == HeaderSize) {
1062       //
1063       // clear file attributes, zero-length file does not have any attributes
1064       //
1065       FileData[Index1].FileAttributes = 0;
1066     }
1067 
1068     while ((BufferSize[Index1] & 0x07) != 0) {
1069       BufferSize[Index1]++;
1070     }
1071 
1072     FfsBuffer[Index1] = AllocateZeroPool (BufferSize[Index1]);
1073 
1074     //
1075     // Copy File Data into FileBuffer
1076     //
1077     CopyMem (
1078       FfsBuffer[Index1] + HeaderSize,
1079       FileData[Index1].Buffer,
1080       FileData[Index1].BufferSize
1081       );
1082 
1083     if (FvDevice->ErasePolarity == 1) {
1084       for (Index2 = 0; Index2 < HeaderSize; Index2++) {
1085         FfsBuffer[Index1][Index2] = (UINT8)~FfsBuffer[Index1][Index2];
1086       }
1087     }
1088 
1089     if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) {
1090       RequiredAlignment[Index1] = GetRequiredAlignment (FileData[Index1].FileAttributes);
1091     }
1092     //
1093     // If update file, mark the original file header to
1094     // EFI_FILE_MARKED_FOR_UPDATE
1095     //
1096     IsCreateFile = FileOperation[Index1];
1097     if (!IsCreateFile) {
1098 
1099       Key = 0;
1100       do {
1101         OldFileType = 0;
1102         Status = Fv->GetNextFile (
1103                       Fv,
1104                       &Key,
1105                       &OldFileType,
1106                       &FileNameGuid,
1107                       &OldFileAttributes,
1108                       &OldFileSize
1109                       );
1110         if (EFI_ERROR (Status)) {
1111           FreeFfsBuffer (NumOfFiles, FfsBuffer);
1112           return Status;
1113         }
1114       } while (!CompareGuid (&FileNameGuid, FileData[Index1].NameGuid));
1115 
1116       //
1117       // Get FfsFileEntry from the search key
1118       //
1119       OldFfsFileEntry[Index1]  = (FFS_FILE_LIST_ENTRY *) Key;
1120       OldFileHeader[Index1]    = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry[Index1]->FfsHeader;
1121       Status = UpdateHeaderBit (
1122                 FvDevice,
1123                 OldFileHeader[Index1],
1124                 EFI_FILE_MARKED_FOR_UPDATE
1125                 );
1126       if (EFI_ERROR (Status)) {
1127         FreeFfsBuffer (NumOfFiles, FfsBuffer);
1128         return Status;
1129       }
1130     }
1131   }
1132   //
1133   // First to search a suitable pad file that can hold so
1134   // many files
1135   //
1136   Status = FvSearchSuitablePadFile (
1137             FvDevice,
1138             NumOfFiles,
1139             BufferSize,
1140             RequiredAlignment,
1141             PadSize,
1142             &TotalSizeNeeded,
1143             &PadFileEntry
1144             );
1145 
1146   if (Status == EFI_NOT_FOUND) {
1147     //
1148     // Try to find a free space that can hold these files
1149     //
1150     Status = FvSearchSuitableFreeSpace (
1151               FvDevice,
1152               NumOfFiles,
1153               BufferSize,
1154               RequiredAlignment,
1155               PadSize,
1156               &TotalSizeNeeded,
1157               &FreeSpaceEntry
1158               );
1159     if (EFI_ERROR (Status)) {
1160       FreeFfsBuffer (NumOfFiles, FfsBuffer);
1161       return EFI_OUT_OF_RESOURCES;
1162     }
1163     Status = FvCreateMultipleFilesInsideFreeSpace (
1164               FvDevice,
1165               FreeSpaceEntry,
1166               NumOfFiles,
1167               BufferSize,
1168               ActualFileSize,
1169               PadSize,
1170               FfsBuffer,
1171               FileData
1172               );
1173 
1174   } else {
1175     //
1176     // Create multiple files inside such a pad file
1177     // to achieve lock-step update
1178     //
1179     Status = FvCreateMultipleFilesInsidePadFile (
1180               FvDevice,
1181               PadFileEntry,
1182               NumOfFiles,
1183               BufferSize,
1184               ActualFileSize,
1185               PadSize,
1186               FfsBuffer,
1187               FileData
1188               );
1189   }
1190 
1191   FreeFfsBuffer (NumOfFiles, FfsBuffer);
1192 
1193   if (EFI_ERROR (Status)) {
1194     return Status;
1195   }
1196   //
1197   // Delete those updated files
1198   //
1199   for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
1200     IsCreateFile = FileOperation[Index1];
1201     if (!IsCreateFile && OldFfsFileEntry[Index1] != NULL) {
1202       (OldFfsFileEntry[Index1]->Link.BackLink)->ForwardLink  = OldFfsFileEntry[Index1]->Link.ForwardLink;
1203       (OldFfsFileEntry[Index1]->Link.ForwardLink)->BackLink  = OldFfsFileEntry[Index1]->Link.BackLink;
1204       FreePool (OldFfsFileEntry[Index1]);
1205     }
1206   }
1207   //
1208   // Set those files' state to EFI_FILE_DELETED
1209   //
1210   for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
1211     IsCreateFile = FileOperation[Index1];
1212     if (!IsCreateFile && OldFileHeader[Index1] != NULL) {
1213       Status = UpdateHeaderBit (FvDevice, OldFileHeader[Index1], EFI_FILE_DELETED);
1214       if (EFI_ERROR (Status)) {
1215         return Status;
1216       }
1217     }
1218   }
1219 
1220   return EFI_SUCCESS;
1221 }
1222