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