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