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