]>
Commit | Line | Data |
---|---|---|
c2df8e13 | 1 | /** @file\r |
2 | Implements write 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 | |
207f0479 | 13 | Calculate the checksum for the FFS header.\r |
c2df8e13 | 14 | \r |
207f0479 | 15 | @param FfsHeader FFS File Header which needs to calculate the checksum\r |
c2df8e13 | 16 | \r |
17 | **/\r | |
18 | VOID\r | |
19 | SetHeaderChecksum (\r | |
20 | IN EFI_FFS_FILE_HEADER *FfsHeader\r | |
21 | )\r | |
22 | {\r | |
23 | EFI_FFS_FILE_STATE State;\r | |
c2df8e13 | 24 | UINT8 FileChecksum;\r |
25 | \r | |
26 | //\r | |
27 | // The state and the File checksum are not included\r | |
28 | //\r | |
29 | State = FfsHeader->State;\r | |
30 | FfsHeader->State = 0;\r | |
31 | \r | |
32 | FileChecksum = FfsHeader->IntegrityCheck.Checksum.File;\r | |
33 | FfsHeader->IntegrityCheck.Checksum.File = 0;\r | |
34 | \r | |
35 | FfsHeader->IntegrityCheck.Checksum.Header = 0;\r | |
36 | \r | |
23491d5c SZ |
37 | if (IS_FFS_FILE2 (FfsHeader)) {\r |
38 | FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 (\r | |
39 | (UINT8 *) FfsHeader,\r | |
40 | sizeof (EFI_FFS_FILE_HEADER2)\r | |
41 | );\r | |
42 | } else {\r | |
43 | FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 (\r | |
44 | (UINT8 *) FfsHeader,\r | |
45 | sizeof (EFI_FFS_FILE_HEADER)\r | |
46 | );\r | |
47 | }\r | |
c2df8e13 | 48 | \r |
49 | FfsHeader->State = State;\r | |
50 | FfsHeader->IntegrityCheck.Checksum.File = FileChecksum;\r | |
51 | \r | |
52 | return ;\r | |
53 | }\r | |
54 | \r | |
55 | /**\r | |
207f0479 | 56 | Calculate the checksum for the FFS File.\r |
c2df8e13 | 57 | \r |
207f0479 | 58 | @param FfsHeader FFS File Header which needs to calculate the checksum\r |
c2df8e13 | 59 | @param ActualFileSize The whole Ffs File Length.\r |
60 | \r | |
61 | **/\r | |
62 | VOID\r | |
63 | SetFileChecksum (\r | |
64 | IN EFI_FFS_FILE_HEADER *FfsHeader,\r | |
65 | IN UINTN ActualFileSize\r | |
66 | )\r | |
67 | {\r | |
c2df8e13 | 68 | if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) {\r |
c2df8e13 | 69 | \r |
70 | FfsHeader->IntegrityCheck.Checksum.File = 0;\r | |
71 | \r | |
23491d5c SZ |
72 | if (IS_FFS_FILE2 (FfsHeader)) {\r |
73 | FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 (\r | |
74 | (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2),\r | |
75 | ActualFileSize - sizeof (EFI_FFS_FILE_HEADER2)\r | |
76 | );\r | |
77 | } else {\r | |
78 | FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 (\r | |
79 | (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER),\r | |
80 | ActualFileSize - sizeof (EFI_FFS_FILE_HEADER)\r | |
81 | );\r | |
82 | }\r | |
c2df8e13 | 83 | \r |
84 | } else {\r | |
85 | \r | |
86 | FfsHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r | |
87 | \r | |
88 | }\r | |
89 | \r | |
90 | return ;\r | |
91 | }\r | |
92 | \r | |
93 | /**\r | |
94 | Get the alignment value from File Attributes.\r | |
95 | \r | |
96 | @param FfsAttributes FFS attribute\r | |
97 | \r | |
98 | @return Alignment value.\r | |
99 | \r | |
100 | **/\r | |
101 | UINTN\r | |
102 | GetRequiredAlignment (\r | |
103 | IN EFI_FV_FILE_ATTRIBUTES FfsAttributes\r | |
104 | )\r | |
105 | {\r | |
106 | UINTN AlignmentValue;\r | |
107 | \r | |
108 | AlignmentValue = FfsAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT;\r | |
109 | \r | |
110 | if (AlignmentValue <= 3) {\r | |
111 | return 0x08;\r | |
112 | }\r | |
113 | \r | |
114 | if (AlignmentValue > 16) {\r | |
115 | //\r | |
116 | // Anyway, we won't reach this code\r | |
117 | //\r | |
118 | return 0x08;\r | |
119 | }\r | |
120 | \r | |
121 | return (UINTN)1 << AlignmentValue;\r | |
122 | \r | |
123 | }\r | |
124 | \r | |
125 | /**\r | |
207f0479 | 126 | Calculate the leading Pad file size to meet the alignment requirement.\r |
c2df8e13 | 127 | \r |
128 | @param FvDevice Cached Firmware Volume.\r | |
129 | @param StartAddress The starting address to write the FFS File.\r | |
23491d5c | 130 | @param BufferSize The FFS File Buffer Size.\r |
c2df8e13 | 131 | @param RequiredAlignment FFS File Data alignment requirement.\r |
132 | \r | |
133 | @return The required Pad File Size.\r | |
134 | \r | |
135 | **/\r | |
136 | UINTN\r | |
207f0479 | 137 | CalculatePadFileSize (\r |
c2df8e13 | 138 | IN FV_DEVICE *FvDevice,\r |
139 | IN EFI_PHYSICAL_ADDRESS StartAddress,\r | |
23491d5c | 140 | IN UINTN BufferSize,\r |
c2df8e13 | 141 | IN UINTN RequiredAlignment\r |
142 | )\r | |
143 | {\r | |
144 | UINTN DataStartPos;\r | |
145 | UINTN RelativePos;\r | |
146 | UINTN PadSize;\r | |
147 | \r | |
23491d5c SZ |
148 | if (BufferSize > 0x00FFFFFF) {\r |
149 | DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER2);\r | |
150 | } else {\r | |
151 | DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER);\r | |
152 | }\r | |
c2df8e13 | 153 | RelativePos = DataStartPos - (UINTN) FvDevice->CachedFv;\r |
154 | \r | |
155 | PadSize = 0;\r | |
156 | \r | |
157 | while ((RelativePos & (RequiredAlignment - 1)) != 0) {\r | |
158 | RelativePos++;\r | |
159 | PadSize++;\r | |
160 | }\r | |
161 | //\r | |
162 | // If padsize is 0, no pad file needed;\r | |
163 | // If padsize is great than 24, then pad file can be created\r | |
164 | //\r | |
165 | if ((PadSize == 0) || (PadSize >= sizeof (EFI_FFS_FILE_HEADER))) {\r | |
166 | return PadSize;\r | |
167 | }\r | |
168 | \r | |
169 | //\r | |
170 | // Perhaps following method can save space\r | |
171 | //\r | |
172 | RelativePos = DataStartPos - (UINTN) FvDevice->CachedFv + sizeof (EFI_FFS_FILE_HEADER);\r | |
173 | PadSize = sizeof (EFI_FFS_FILE_HEADER);\r | |
174 | \r | |
175 | while ((RelativePos & (RequiredAlignment - 1)) != 0) {\r | |
176 | RelativePos++;\r | |
177 | PadSize++;\r | |
178 | }\r | |
179 | \r | |
180 | return PadSize;\r | |
181 | }\r | |
182 | \r | |
183 | /**\r | |
184 | Convert EFI_FV_FILE_ATTRIBUTES to FFS_FILE_ATTRIBUTES.\r | |
185 | \r | |
186 | @param FvFileAttrib The value of EFI_FV_FILE_ATTRIBUTES\r | |
187 | @param FfsFileAttrib Pointer to the got FFS_FILE_ATTRIBUTES value.\r | |
188 | \r | |
189 | **/\r | |
190 | VOID\r | |
191 | FvFileAttrib2FfsFileAttrib (\r | |
192 | IN EFI_FV_FILE_ATTRIBUTES FvFileAttrib,\r | |
193 | OUT UINT8 *FfsFileAttrib\r | |
194 | )\r | |
195 | {\r | |
196 | UINT8 FvFileAlignment;\r | |
197 | UINT8 FfsFileAlignment;\r | |
67a6cf6d | 198 | UINT8 FfsFileAlignment2;\r |
c2df8e13 | 199 | \r |
200 | FvFileAlignment = (UINT8) (FvFileAttrib & EFI_FV_FILE_ATTRIB_ALIGNMENT);\r | |
201 | FfsFileAlignment = 0;\r | |
67a6cf6d | 202 | FfsFileAlignment2 = 0;\r |
c2df8e13 | 203 | \r |
204 | switch (FvFileAlignment) {\r | |
205 | case 0:\r | |
206 | //\r | |
207 | // fall through\r | |
208 | //\r | |
209 | case 1:\r | |
210 | //\r | |
211 | // fall through\r | |
212 | //\r | |
213 | case 2:\r | |
214 | //\r | |
215 | // fall through\r | |
216 | //\r | |
217 | case 3:\r | |
218 | //\r | |
219 | // fall through\r | |
220 | //\r | |
221 | FfsFileAlignment = 0;\r | |
222 | break;\r | |
223 | \r | |
224 | case 4:\r | |
225 | //\r | |
226 | // fall through\r | |
227 | //\r | |
228 | case 5:\r | |
229 | //\r | |
230 | // fall through\r | |
231 | //\r | |
232 | case 6:\r | |
233 | //\r | |
234 | // fall through\r | |
235 | //\r | |
236 | FfsFileAlignment = 1;\r | |
237 | break;\r | |
238 | \r | |
239 | case 7:\r | |
240 | //\r | |
241 | // fall through\r | |
242 | //\r | |
243 | case 8:\r | |
244 | //\r | |
245 | // fall through\r | |
246 | //\r | |
247 | FfsFileAlignment = 2;\r | |
248 | break;\r | |
249 | \r | |
250 | case 9:\r | |
251 | FfsFileAlignment = 3;\r | |
252 | break;\r | |
253 | \r | |
254 | case 10:\r | |
255 | //\r | |
256 | // fall through\r | |
257 | //\r | |
258 | case 11:\r | |
259 | //\r | |
260 | // fall through\r | |
261 | //\r | |
262 | FfsFileAlignment = 4;\r | |
263 | break;\r | |
264 | \r | |
265 | case 12:\r | |
266 | //\r | |
267 | // fall through\r | |
268 | //\r | |
269 | case 13:\r | |
270 | //\r | |
271 | // fall through\r | |
272 | //\r | |
273 | case 14:\r | |
274 | //\r | |
275 | // fall through\r | |
276 | //\r | |
277 | FfsFileAlignment = 5;\r | |
278 | break;\r | |
279 | \r | |
280 | case 15:\r | |
281 | FfsFileAlignment = 6;\r | |
282 | break;\r | |
283 | \r | |
284 | case 16:\r | |
285 | FfsFileAlignment = 7;\r | |
286 | break;\r | |
67a6cf6d SZ |
287 | \r |
288 | case 17:\r | |
289 | FfsFileAlignment = 0;\r | |
290 | FfsFileAlignment2 = 1;\r | |
291 | break;\r | |
292 | case 18:\r | |
293 | FfsFileAlignment = 1;\r | |
294 | FfsFileAlignment2 = 1;\r | |
295 | break;\r | |
296 | case 19:\r | |
297 | FfsFileAlignment = 2;\r | |
298 | FfsFileAlignment2 = 1;\r | |
299 | break;\r | |
300 | case 20:\r | |
301 | FfsFileAlignment = 3;\r | |
302 | FfsFileAlignment2 = 1;\r | |
303 | break;\r | |
304 | case 21:\r | |
305 | FfsFileAlignment = 4;\r | |
306 | FfsFileAlignment2 = 1;\r | |
307 | break;\r | |
308 | case 22:\r | |
309 | FfsFileAlignment = 5;\r | |
310 | FfsFileAlignment2 = 1;\r | |
311 | break;\r | |
312 | case 23:\r | |
313 | FfsFileAlignment = 6;\r | |
314 | FfsFileAlignment2 = 1;\r | |
315 | break;\r | |
316 | case 24:\r | |
317 | FfsFileAlignment = 7;\r | |
318 | FfsFileAlignment2 = 1;\r | |
319 | break;\r | |
c2df8e13 | 320 | }\r |
321 | \r | |
67a6cf6d | 322 | *FfsFileAttrib = (UINT8) ((FfsFileAlignment << 3) | (FfsFileAlignment2 << 1));\r |
c2df8e13 | 323 | \r |
324 | return ;\r | |
325 | }\r | |
326 | \r | |
327 | /**\r | |
328 | Locate a free space entry that can hold this FFS file.\r | |
329 | \r | |
330 | @param FvDevice Cached Firmware Volume.\r | |
331 | @param Size The FFS file size.\r | |
332 | @param RequiredAlignment FFS File Data alignment requirement.\r | |
333 | @param PadSize Pointer to the size of leading Pad File.\r | |
334 | @param FreeSpaceEntry Pointer to the Free Space Entry that meets the requirement.\r | |
335 | \r | |
336 | @retval EFI_SUCCESS The free space entry is found.\r | |
337 | @retval EFI_NOT_FOUND The free space entry can't be found.\r | |
338 | \r | |
339 | **/\r | |
340 | EFI_STATUS\r | |
341 | FvLocateFreeSpaceEntry (\r | |
342 | IN FV_DEVICE *FvDevice,\r | |
343 | IN UINTN Size,\r | |
344 | IN UINTN RequiredAlignment,\r | |
345 | OUT UINTN *PadSize,\r | |
346 | OUT FREE_SPACE_ENTRY **FreeSpaceEntry\r | |
347 | )\r | |
348 | {\r | |
349 | FREE_SPACE_ENTRY *FreeSpaceListEntry;\r | |
350 | LIST_ENTRY *Link;\r | |
351 | UINTN PadFileSize;\r | |
352 | \r | |
353 | Link = FvDevice->FreeSpaceHeader.ForwardLink;\r | |
354 | FreeSpaceListEntry = (FREE_SPACE_ENTRY *) Link;\r | |
355 | \r | |
356 | //\r | |
357 | // Loop the free space entry list to find one that can hold the\r | |
358 | // required the file size\r | |
359 | //\r | |
360 | while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) {\r | |
207f0479 | 361 | PadFileSize = CalculatePadFileSize (\r |
c2df8e13 | 362 | FvDevice,\r |
363 | (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceListEntry->StartingAddress,\r | |
23491d5c | 364 | Size,\r |
c2df8e13 | 365 | RequiredAlignment\r |
366 | );\r | |
367 | if (FreeSpaceListEntry->Length >= Size + PadFileSize) {\r | |
368 | *FreeSpaceEntry = FreeSpaceListEntry;\r | |
369 | *PadSize = PadFileSize;\r | |
370 | return EFI_SUCCESS;\r | |
371 | }\r | |
372 | \r | |
373 | FreeSpaceListEntry = (FREE_SPACE_ENTRY *) FreeSpaceListEntry->Link.ForwardLink;\r | |
374 | }\r | |
375 | \r | |
376 | return EFI_NOT_FOUND;\r | |
377 | \r | |
378 | }\r | |
379 | \r | |
c2df8e13 | 380 | /**\r |
381 | Locate Pad File for writing, this is got from FV Cache.\r | |
382 | \r | |
383 | @param FvDevice Cached Firmware Volume.\r | |
384 | @param Size The required FFS file size.\r | |
385 | @param RequiredAlignment FFS File Data alignment requirement.\r | |
386 | @param PadSize Pointer to the size of leading Pad File.\r | |
387 | @param PadFileEntry Pointer to the Pad File Entry that meets the requirement.\r | |
388 | \r | |
389 | @retval EFI_SUCCESS The required pad file is found.\r | |
390 | @retval EFI_NOT_FOUND The required pad file can't be found.\r | |
391 | \r | |
392 | **/\r | |
393 | EFI_STATUS\r | |
394 | FvLocatePadFile (\r | |
395 | IN FV_DEVICE *FvDevice,\r | |
396 | IN UINTN Size,\r | |
397 | IN UINTN RequiredAlignment,\r | |
398 | OUT UINTN *PadSize,\r | |
399 | OUT FFS_FILE_LIST_ENTRY **PadFileEntry\r | |
400 | )\r | |
401 | {\r | |
402 | FFS_FILE_LIST_ENTRY *FileEntry;\r | |
403 | EFI_FFS_FILE_STATE FileState;\r | |
404 | EFI_FFS_FILE_HEADER *FileHeader;\r | |
c2df8e13 | 405 | UINTN PadAreaLength;\r |
406 | UINTN PadFileSize;\r | |
23491d5c | 407 | UINTN HeaderSize;\r |
c2df8e13 | 408 | \r |
409 | FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;\r | |
410 | \r | |
411 | //\r | |
412 | // travel through the whole file list to get the pad file entry\r | |
413 | //\r | |
414 | while (FileEntry != (FFS_FILE_LIST_ENTRY *) &FvDevice->FfsFileListHeader) {\r | |
415 | \r | |
416 | FileHeader = (EFI_FFS_FILE_HEADER *) FileEntry->FfsHeader;\r | |
417 | FileState = GetFileState (FvDevice->ErasePolarity, FileHeader);\r | |
418 | \r | |
419 | if ((FileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) && (FileState == EFI_FILE_DATA_VALID)) {\r | |
420 | //\r | |
421 | // we find one valid pad file, check its free area length\r | |
422 | //\r | |
23491d5c SZ |
423 | if (IS_FFS_FILE2 (FileHeader)) {\r |
424 | HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r | |
425 | PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize;\r | |
426 | } else {\r | |
427 | HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r | |
428 | PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize;\r | |
429 | }\r | |
c2df8e13 | 430 | \r |
207f0479 | 431 | PadFileSize = CalculatePadFileSize (\r |
c2df8e13 | 432 | FvDevice,\r |
23491d5c SZ |
433 | (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize,\r |
434 | Size,\r | |
c2df8e13 | 435 | RequiredAlignment\r |
436 | );\r | |
437 | if (PadAreaLength >= (Size + PadFileSize)) {\r | |
438 | *PadSize = PadFileSize;\r | |
439 | *PadFileEntry = FileEntry;\r | |
440 | return EFI_SUCCESS;\r | |
441 | }\r | |
442 | }\r | |
443 | \r | |
444 | FileEntry = (FFS_FILE_LIST_ENTRY *) (FileEntry->Link.ForwardLink);\r | |
445 | }\r | |
446 | \r | |
447 | return EFI_NOT_FOUND;\r | |
448 | }\r | |
449 | \r | |
450 | /**\r | |
451 | Locate a suitable pad file for multiple file writing.\r | |
452 | \r | |
453 | @param FvDevice Cached Firmware Volume.\r | |
454 | @param NumOfFiles The number of Files that needed updating\r | |
455 | @param BufferSize The array of each file size.\r | |
456 | @param RequiredAlignment The array of of FFS File Data alignment requirement.\r | |
457 | @param PadSize The array of size of each leading Pad File.\r | |
458 | @param TotalSizeNeeded The totalsize that can hold these files.\r | |
459 | @param PadFileEntry Pointer to the Pad File Entry that meets the requirement.\r | |
460 | \r | |
461 | @retval EFI_SUCCESS The required pad file is found.\r | |
462 | @retval EFI_NOT_FOUND The required pad file can't be found.\r | |
463 | \r | |
464 | **/\r | |
465 | EFI_STATUS\r | |
466 | FvSearchSuitablePadFile (\r | |
467 | IN FV_DEVICE *FvDevice,\r | |
468 | IN UINTN NumOfFiles,\r | |
469 | IN UINTN *BufferSize,\r | |
470 | IN UINTN *RequiredAlignment,\r | |
471 | OUT UINTN *PadSize,\r | |
472 | OUT UINTN *TotalSizeNeeded,\r | |
473 | OUT FFS_FILE_LIST_ENTRY **PadFileEntry\r | |
474 | )\r | |
475 | {\r | |
476 | FFS_FILE_LIST_ENTRY *FileEntry;\r | |
477 | EFI_FFS_FILE_STATE FileState;\r | |
478 | EFI_FFS_FILE_HEADER *FileHeader;\r | |
c2df8e13 | 479 | UINTN PadAreaLength;\r |
480 | UINTN TotalSize;\r | |
481 | UINTN Index;\r | |
23491d5c | 482 | UINTN HeaderSize;\r |
c2df8e13 | 483 | \r |
484 | FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;\r | |
485 | \r | |
486 | //\r | |
487 | // travel through the whole file list to get the pad file entry\r | |
488 | //\r | |
489 | while (FileEntry != (FFS_FILE_LIST_ENTRY *) &FvDevice->FfsFileListHeader) {\r | |
490 | \r | |
491 | FileHeader = (EFI_FFS_FILE_HEADER *) FileEntry->FfsHeader;\r | |
492 | FileState = GetFileState (FvDevice->ErasePolarity, FileHeader);\r | |
493 | \r | |
494 | if ((FileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) && (FileState == EFI_FILE_DATA_VALID)) {\r | |
495 | //\r | |
496 | // we find one valid pad file, check its length\r | |
497 | //\r | |
23491d5c SZ |
498 | if (IS_FFS_FILE2 (FileHeader)) {\r |
499 | HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r | |
500 | PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize;\r | |
501 | } else {\r | |
502 | HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r | |
503 | PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize;\r | |
504 | }\r | |
c2df8e13 | 505 | TotalSize = 0;\r |
506 | \r | |
507 | for (Index = 0; Index < NumOfFiles; Index++) {\r | |
207f0479 | 508 | PadSize[Index] = CalculatePadFileSize (\r |
c2df8e13 | 509 | FvDevice,\r |
23491d5c SZ |
510 | (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize + TotalSize,\r |
511 | BufferSize[Index],\r | |
c2df8e13 | 512 | RequiredAlignment[Index]\r |
513 | );\r | |
514 | TotalSize += PadSize[Index];\r | |
515 | TotalSize += BufferSize[Index];\r | |
516 | \r | |
517 | if (TotalSize > PadAreaLength) {\r | |
518 | break;\r | |
519 | }\r | |
520 | }\r | |
521 | \r | |
522 | if (PadAreaLength >= TotalSize) {\r | |
523 | *PadFileEntry = FileEntry;\r | |
524 | *TotalSizeNeeded = TotalSize;\r | |
525 | return EFI_SUCCESS;\r | |
526 | }\r | |
527 | }\r | |
528 | \r | |
529 | FileEntry = (FFS_FILE_LIST_ENTRY *) (FileEntry->Link.ForwardLink);\r | |
530 | }\r | |
531 | \r | |
532 | return EFI_NOT_FOUND;\r | |
533 | }\r | |
534 | \r | |
535 | /**\r | |
536 | Locate a Free Space entry which can hold these files, including\r | |
537 | meeting the alignment requirements.\r | |
538 | \r | |
539 | @param FvDevice Cached Firmware Volume.\r | |
540 | @param NumOfFiles The number of Files that needed updating\r | |
541 | @param BufferSize The array of each file size.\r | |
542 | @param RequiredAlignment The array of of FFS File Data alignment requirement.\r | |
543 | @param PadSize The array of size of each leading Pad File.\r | |
544 | @param TotalSizeNeeded The got total size that can hold these files.\r | |
545 | @param FreeSpaceEntry The Free Space Entry that can hold these files.\r | |
546 | \r | |
547 | @retval EFI_SUCCESS The free space entry is found.\r | |
548 | @retval EFI_NOT_FOUND The free space entry can't be found.\r | |
549 | \r | |
550 | **/\r | |
551 | EFI_STATUS\r | |
552 | FvSearchSuitableFreeSpace (\r | |
553 | IN FV_DEVICE *FvDevice,\r | |
554 | IN UINTN NumOfFiles,\r | |
555 | IN UINTN *BufferSize,\r | |
556 | IN UINTN *RequiredAlignment,\r | |
557 | OUT UINTN *PadSize,\r | |
558 | OUT UINTN *TotalSizeNeeded,\r | |
559 | OUT FREE_SPACE_ENTRY **FreeSpaceEntry\r | |
560 | )\r | |
561 | {\r | |
562 | FREE_SPACE_ENTRY *FreeSpaceListEntry;\r | |
563 | LIST_ENTRY *Link;\r | |
564 | UINTN TotalSize;\r | |
565 | UINTN Index;\r | |
566 | UINT8 *StartAddr;\r | |
567 | \r | |
568 | Link = FvDevice->FreeSpaceHeader.ForwardLink;\r | |
569 | \r | |
570 | FreeSpaceListEntry = (FREE_SPACE_ENTRY *) Link;\r | |
571 | \r | |
572 | while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) {\r | |
573 | TotalSize = 0;\r | |
574 | StartAddr = FreeSpaceListEntry->StartingAddress;\r | |
575 | \r | |
576 | //\r | |
207f0479 | 577 | // Calculate the totalsize we need\r |
c2df8e13 | 578 | //\r |
579 | for (Index = 0; Index < NumOfFiles; Index++) {\r | |
580 | //\r | |
581 | // Perhaps we don't need an EFI_FFS_FILE_HEADER, the first file\r | |
582 | // have had its leading pad file.\r | |
583 | //\r | |
207f0479 | 584 | PadSize[Index] = CalculatePadFileSize (\r |
c2df8e13 | 585 | FvDevice,\r |
586 | (EFI_PHYSICAL_ADDRESS) (UINTN) StartAddr + TotalSize,\r | |
23491d5c | 587 | BufferSize[Index],\r |
c2df8e13 | 588 | RequiredAlignment[Index]\r |
589 | );\r | |
590 | \r | |
591 | TotalSize += PadSize[Index];\r | |
592 | TotalSize += BufferSize[Index];\r | |
593 | \r | |
594 | if (TotalSize > FreeSpaceListEntry->Length) {\r | |
595 | break;\r | |
596 | }\r | |
597 | }\r | |
598 | \r | |
599 | if (FreeSpaceListEntry->Length >= TotalSize) {\r | |
600 | *FreeSpaceEntry = FreeSpaceListEntry;\r | |
601 | *TotalSizeNeeded = TotalSize;\r | |
602 | return EFI_SUCCESS;\r | |
603 | }\r | |
604 | \r | |
605 | FreeSpaceListEntry = (FREE_SPACE_ENTRY *) FreeSpaceListEntry->Link.ForwardLink;\r | |
606 | }\r | |
607 | \r | |
608 | return EFI_NOT_FOUND;\r | |
609 | }\r | |
610 | \r | |
611 | /**\r | |
612 | Calculate the length of the remaining space in FV.\r | |
613 | \r | |
614 | @param FvDevice Cached Firmware Volume\r | |
615 | @param Offset Current offset to FV base address.\r | |
616 | @param Lba LBA number for the current offset.\r | |
617 | @param LOffset Offset in block for the current offset.\r | |
618 | \r | |
619 | @return the length of remaining space.\r | |
620 | \r | |
621 | **/\r | |
622 | UINTN\r | |
623 | CalculateRemainingLength (\r | |
624 | IN FV_DEVICE *FvDevice,\r | |
625 | IN UINTN Offset,\r | |
626 | OUT EFI_LBA *Lba,\r | |
627 | OUT UINTN *LOffset\r | |
628 | )\r | |
629 | {\r | |
630 | LIST_ENTRY *Link;\r | |
631 | LBA_ENTRY *LbaEntry;\r | |
632 | UINTN Count;\r | |
633 | \r | |
634 | Count = 0;\r | |
635 | *Lba = 0;\r | |
636 | Link = FvDevice->LbaHeader.ForwardLink;\r | |
637 | LbaEntry = (LBA_ENTRY *) Link;\r | |
638 | \r | |
639 | while (&LbaEntry->Link != &FvDevice->LbaHeader) {\r | |
640 | if (Count > Offset) {\r | |
641 | break;\r | |
642 | }\r | |
643 | \r | |
644 | Count += LbaEntry->BlockLength;\r | |
645 | (*Lba)++;\r | |
646 | Link = LbaEntry->Link.ForwardLink;\r | |
647 | LbaEntry = (LBA_ENTRY *) Link;\r | |
648 | }\r | |
649 | \r | |
650 | if (Count <= Offset) {\r | |
651 | return 0;\r | |
652 | }\r | |
653 | \r | |
654 | Link = LbaEntry->Link.BackLink;\r | |
655 | LbaEntry = (LBA_ENTRY *) Link;\r | |
656 | \r | |
657 | (*Lba)--;\r | |
658 | *LOffset = (UINTN) (LbaEntry->BlockLength - (Count - Offset));\r | |
659 | \r | |
660 | Count = 0;\r | |
661 | while (&LbaEntry->Link != &FvDevice->LbaHeader) {\r | |
662 | \r | |
663 | Count += LbaEntry->BlockLength;\r | |
664 | \r | |
665 | Link = LbaEntry->Link.ForwardLink;\r | |
666 | LbaEntry = (LBA_ENTRY *) Link;\r | |
667 | }\r | |
668 | \r | |
669 | Count -= *LOffset;\r | |
670 | \r | |
671 | return Count;\r | |
672 | }\r | |
673 | \r | |
674 | /**\r | |
675 | Writes data beginning at Lba:Offset from FV. The write terminates either\r | |
676 | when *NumBytes of data have been written, or when the firmware end is\r | |
677 | reached. *NumBytes is updated to reflect the actual number of bytes\r | |
678 | written.\r | |
679 | \r | |
680 | @param FvDevice Cached Firmware Volume\r | |
681 | @param Offset Offset in the block at which to begin write\r | |
682 | @param NumBytes At input, indicates the requested write size.\r | |
683 | At output, indicates the actual number of bytes written.\r | |
684 | @param Buffer Buffer containing source data for the write.\r | |
685 | \r | |
686 | @retval EFI_SUCCESS Data is successfully written into FV.\r | |
687 | @return error Data is failed written.\r | |
688 | \r | |
689 | **/\r | |
690 | EFI_STATUS\r | |
691 | FvcWrite (\r | |
692 | IN FV_DEVICE *FvDevice,\r | |
693 | IN UINTN Offset,\r | |
694 | IN OUT UINTN *NumBytes,\r | |
695 | IN UINT8 *Buffer\r | |
696 | )\r | |
697 | {\r | |
698 | EFI_STATUS Status;\r | |
699 | EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r | |
700 | EFI_LBA Lba;\r | |
701 | UINTN LOffset;\r | |
702 | EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r | |
703 | UINTN RemainingLength;\r | |
704 | UINTN WriteLength;\r | |
705 | UINT8 *TmpBuffer;\r | |
0a6f4824 | 706 | \r |
c2df8e13 | 707 | LOffset = 0;\r |
708 | RemainingLength = CalculateRemainingLength (FvDevice, Offset, &Lba, &LOffset);\r | |
709 | if ((UINTN) (*NumBytes) > RemainingLength) {\r | |
710 | *NumBytes = (UINTN) RemainingLength;\r | |
711 | return EFI_INVALID_PARAMETER;\r | |
712 | }\r | |
713 | \r | |
714 | Fvb = FvDevice->Fvb;\r | |
715 | \r | |
716 | Status = Fvb->GetAttributes (\r | |
717 | Fvb,\r | |
718 | &FvbAttributes\r | |
719 | );\r | |
720 | if (EFI_ERROR (Status)) {\r | |
721 | return Status;\r | |
722 | }\r | |
723 | \r | |
c4487989 | 724 | if ((FvbAttributes & EFI_FV2_WRITE_STATUS) == 0) {\r |
c2df8e13 | 725 | return EFI_ACCESS_DENIED;\r |
726 | }\r | |
727 | \r | |
728 | RemainingLength = *NumBytes;\r | |
729 | WriteLength = RemainingLength;\r | |
730 | TmpBuffer = Buffer;\r | |
731 | \r | |
732 | do {\r | |
733 | Status = Fvb->Write (\r | |
734 | Fvb,\r | |
735 | Lba,\r | |
736 | LOffset,\r | |
737 | &WriteLength,\r | |
738 | TmpBuffer\r | |
739 | );\r | |
740 | if (!EFI_ERROR (Status)) {\r | |
741 | goto Done;\r | |
742 | }\r | |
743 | \r | |
744 | if (Status == EFI_BAD_BUFFER_SIZE) {\r | |
745 | Lba++;\r | |
746 | LOffset = 0;\r | |
747 | TmpBuffer += WriteLength;\r | |
748 | RemainingLength -= WriteLength;\r | |
749 | WriteLength = (UINTN) RemainingLength;\r | |
750 | \r | |
751 | continue;\r | |
752 | } else {\r | |
753 | return Status;\r | |
754 | }\r | |
755 | } while (1);\r | |
756 | \r | |
757 | Done:\r | |
758 | return EFI_SUCCESS;\r | |
759 | }\r | |
760 | \r | |
761 | /**\r | |
762 | Create a new FFS file into Firmware Volume device.\r | |
763 | \r | |
764 | @param FvDevice Cached Firmware Volume.\r | |
765 | @param FfsFileBuffer A buffer that holds an FFS file,(it contains\r | |
766 | a File Header which is in init state).\r | |
767 | @param BufferSize The size of FfsFileBuffer.\r | |
768 | @param ActualFileSize The actual file length, it may not be multiples of 8.\r | |
769 | @param FileName The FFS File Name.\r | |
770 | @param FileType The FFS File Type.\r | |
771 | @param FileAttributes The Attributes of the FFS File to be created.\r | |
772 | \r | |
773 | @retval EFI_SUCCESS FFS fle is added into FV.\r | |
774 | @retval EFI_INVALID_PARAMETER File type is not valid.\r | |
775 | @retval EFI_DEVICE_ERROR FV doesn't set writable attribute.\r | |
776 | @retval EFI_NOT_FOUND FV has no enough space for the added file.\r | |
777 | \r | |
778 | **/\r | |
779 | EFI_STATUS\r | |
780 | FvCreateNewFile (\r | |
781 | IN FV_DEVICE *FvDevice,\r | |
782 | IN UINT8 *FfsFileBuffer,\r | |
783 | IN UINTN BufferSize,\r | |
784 | IN UINTN ActualFileSize,\r | |
785 | IN EFI_GUID *FileName,\r | |
786 | IN EFI_FV_FILETYPE FileType,\r | |
787 | IN EFI_FV_FILE_ATTRIBUTES FileAttributes\r | |
788 | )\r | |
789 | {\r | |
790 | EFI_STATUS Status;\r | |
791 | EFI_FFS_FILE_HEADER *FileHeader;\r | |
792 | EFI_PHYSICAL_ADDRESS BufferPtr;\r | |
793 | UINTN Offset;\r | |
794 | UINTN NumBytesWritten;\r | |
795 | UINTN StateOffset;\r | |
796 | FREE_SPACE_ENTRY *FreeSpaceEntry;\r | |
797 | UINTN RequiredAlignment;\r | |
798 | UINTN PadFileSize;\r | |
799 | FFS_FILE_LIST_ENTRY *PadFileEntry;\r | |
800 | EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute;\r | |
801 | FFS_FILE_LIST_ENTRY *FfsFileEntry;\r | |
23491d5c | 802 | UINTN HeaderSize;\r |
c2df8e13 | 803 | \r |
804 | //\r | |
805 | // File Type: 0x0E~0xE0 are reserved\r | |
806 | //\r | |
807 | if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) {\r | |
808 | return EFI_INVALID_PARAMETER;\r | |
809 | }\r | |
810 | \r | |
811 | //\r | |
812 | // First find a free space that can hold this image.\r | |
70d3fe9d | 813 | // Check alignment, FFS at least must be aligned at 8-byte boundary\r |
c2df8e13 | 814 | //\r |
815 | RequiredAlignment = GetRequiredAlignment (FileAttributes);\r | |
816 | \r | |
817 | Status = FvLocateFreeSpaceEntry (\r | |
818 | FvDevice,\r | |
819 | BufferSize,\r | |
820 | RequiredAlignment,\r | |
821 | &PadFileSize,\r | |
822 | &FreeSpaceEntry\r | |
823 | );\r | |
824 | if (EFI_ERROR (Status)) {\r | |
825 | //\r | |
826 | // Maybe we need to find a PAD file that can hold this image\r | |
827 | //\r | |
828 | Status = FvCreateNewFileInsidePadFile (\r | |
829 | FvDevice,\r | |
830 | FfsFileBuffer,\r | |
831 | BufferSize,\r | |
832 | ActualFileSize,\r | |
833 | FileName,\r | |
834 | FileType,\r | |
835 | FileAttributes\r | |
836 | );\r | |
837 | \r | |
838 | return Status;\r | |
839 | }\r | |
840 | \r | |
841 | BufferPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress;\r | |
842 | \r | |
843 | //\r | |
844 | // If we need a leading PAD File, create it first.\r | |
845 | //\r | |
846 | if (PadFileSize != 0) {\r | |
847 | Status = FvCreatePadFileInFreeSpace (\r | |
848 | FvDevice,\r | |
849 | FreeSpaceEntry,\r | |
850 | PadFileSize - sizeof (EFI_FFS_FILE_HEADER),\r | |
851 | &PadFileEntry\r | |
852 | );\r | |
853 | if (EFI_ERROR (Status)) {\r | |
854 | return Status;\r | |
855 | }\r | |
856 | }\r | |
857 | //\r | |
858 | // Maybe we create a pad file, so re-get the free space starting address\r | |
859 | // and length\r | |
860 | //\r | |
861 | BufferPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress;\r | |
862 | \r | |
863 | //\r | |
864 | // File creation step 1: Allocate File Header,\r | |
865 | // Mark EFI_FILE_HEADER_CONSTRUCTION bit to TRUE,\r | |
866 | // Write Name, IntegrityCheck.Header, Type, Attributes, and Size\r | |
867 | //\r | |
868 | FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer;\r | |
23491d5c SZ |
869 | if (ActualFileSize > 0x00FFFFFF) {\r |
870 | HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r | |
871 | } else {\r | |
872 | HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r | |
873 | }\r | |
c2df8e13 | 874 | SetFileState (EFI_FILE_HEADER_CONSTRUCTION, FileHeader);\r |
875 | \r | |
876 | Offset = (UINTN) (BufferPtr - FvDevice->CachedFv);\r | |
877 | StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader;\r | |
878 | \r | |
879 | NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r | |
880 | Status = FvcWrite (\r | |
881 | FvDevice,\r | |
882 | StateOffset,\r | |
883 | &NumBytesWritten,\r | |
884 | &FileHeader->State\r | |
885 | );\r | |
886 | if (EFI_ERROR (Status)) {\r | |
887 | return Status;\r | |
888 | }\r | |
889 | //\r | |
890 | // update header 2 cache\r | |
891 | //\r | |
892 | CopyMem (\r | |
893 | (UINT8 *) (UINTN) BufferPtr,\r | |
894 | FileHeader,\r | |
23491d5c | 895 | HeaderSize\r |
c2df8e13 | 896 | );\r |
897 | \r | |
898 | //\r | |
23491d5c | 899 | // update Free Space Entry, now need to substract the file header length\r |
c2df8e13 | 900 | //\r |
23491d5c SZ |
901 | FreeSpaceEntry->StartingAddress += HeaderSize;\r |
902 | FreeSpaceEntry->Length -= HeaderSize;\r | |
c2df8e13 | 903 | \r |
904 | CopyGuid (&FileHeader->Name, FileName);\r | |
905 | FileHeader->Type = FileType;\r | |
906 | \r | |
907 | //\r | |
908 | // Convert FvFileAttribute to FfsFileAttributes\r | |
909 | //\r | |
910 | FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute);\r | |
911 | \r | |
912 | FileHeader->Attributes = TmpFileAttribute;\r | |
913 | \r | |
914 | //\r | |
915 | // File size is including the FFS File Header.\r | |
916 | //\r | |
23491d5c SZ |
917 | if (ActualFileSize > 0x00FFFFFF) {\r |
918 | ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize;\r | |
919 | *(UINT32 *) FileHeader->Size &= 0xFF000000;\r | |
920 | FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;\r | |
921 | } else {\r | |
922 | *(UINT32 *) FileHeader->Size &= 0xFF000000;\r | |
923 | *(UINT32 *) FileHeader->Size |= ActualFileSize;\r | |
924 | }\r | |
c2df8e13 | 925 | \r |
926 | SetHeaderChecksum (FileHeader);\r | |
927 | \r | |
928 | Offset = (UINTN) (BufferPtr - FvDevice->CachedFv);\r | |
929 | \r | |
23491d5c | 930 | NumBytesWritten = HeaderSize;\r |
c2df8e13 | 931 | Status = FvcWrite (\r |
932 | FvDevice,\r | |
933 | Offset,\r | |
934 | &NumBytesWritten,\r | |
935 | (UINT8 *) FileHeader\r | |
936 | );\r | |
937 | if (EFI_ERROR (Status)) {\r | |
938 | return Status;\r | |
939 | }\r | |
940 | //\r | |
941 | // update header 2 cache\r | |
942 | //\r | |
943 | CopyMem (\r | |
944 | (UINT8 *) (UINTN) BufferPtr,\r | |
945 | FileHeader,\r | |
23491d5c | 946 | HeaderSize\r |
c2df8e13 | 947 | );\r |
948 | \r | |
949 | //\r | |
950 | // end of step 1\r | |
951 | //\r | |
952 | // File creation step 2:\r | |
953 | // MARK EFI_FILE_HEADER_VALID bit to TRUE,\r | |
954 | // Write IntegrityCheck.File, File Data\r | |
955 | //\r | |
956 | SetFileState (EFI_FILE_HEADER_VALID, FileHeader);\r | |
957 | \r | |
958 | Offset = (UINTN) (BufferPtr - FvDevice->CachedFv);\r | |
959 | StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader;\r | |
960 | \r | |
961 | NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r | |
962 | Status = FvcWrite (\r | |
963 | FvDevice,\r | |
964 | StateOffset,\r | |
965 | &NumBytesWritten,\r | |
966 | &FileHeader->State\r | |
967 | );\r | |
968 | if (EFI_ERROR (Status)) {\r | |
969 | return Status;\r | |
970 | }\r | |
971 | //\r | |
972 | // update header 2 cache\r | |
973 | //\r | |
974 | CopyMem (\r | |
975 | (UINT8 *) (UINTN) BufferPtr,\r | |
976 | FileHeader,\r | |
23491d5c | 977 | HeaderSize\r |
c2df8e13 | 978 | );\r |
979 | \r | |
980 | //\r | |
981 | // update Free Space Entry, now need to substract the file data length\r | |
982 | //\r | |
23491d5c SZ |
983 | FreeSpaceEntry->StartingAddress += (BufferSize - HeaderSize);\r |
984 | FreeSpaceEntry->Length -= (BufferSize - HeaderSize);\r | |
c2df8e13 | 985 | \r |
986 | //\r | |
207f0479 | 987 | // Calculate File Checksum\r |
c2df8e13 | 988 | //\r |
989 | SetFileChecksum (FileHeader, ActualFileSize);\r | |
990 | \r | |
991 | Offset = (UINTN) (BufferPtr - FvDevice->CachedFv);\r | |
992 | \r | |
993 | NumBytesWritten = BufferSize;\r | |
994 | Status = FvcWrite (\r | |
995 | FvDevice,\r | |
996 | Offset,\r | |
997 | &NumBytesWritten,\r | |
998 | FfsFileBuffer\r | |
999 | );\r | |
1000 | if (EFI_ERROR (Status)) {\r | |
1001 | return Status;\r | |
1002 | }\r | |
1003 | //\r | |
1004 | // each time write block successfully, write also to cache\r | |
1005 | //\r | |
1006 | CopyMem (\r | |
1007 | (UINT8 *) (UINTN) BufferPtr,\r | |
1008 | FfsFileBuffer,\r | |
1009 | NumBytesWritten\r | |
1010 | );\r | |
1011 | \r | |
1012 | //\r | |
1013 | // Step 3: Mark EFI_FILE_DATA_VALID to TRUE\r | |
1014 | //\r | |
1015 | SetFileState (EFI_FILE_DATA_VALID, FileHeader);\r | |
1016 | \r | |
1017 | Offset = (UINTN) (BufferPtr - FvDevice->CachedFv);\r | |
1018 | StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader;\r | |
1019 | \r | |
1020 | NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r | |
1021 | Status = FvcWrite (\r | |
1022 | FvDevice,\r | |
1023 | StateOffset,\r | |
1024 | &NumBytesWritten,\r | |
1025 | &FileHeader->State\r | |
1026 | );\r | |
1027 | if (EFI_ERROR (Status)) {\r | |
1028 | return Status;\r | |
1029 | }\r | |
1030 | //\r | |
1031 | // update header 2 cache\r | |
1032 | //\r | |
1033 | CopyMem (\r | |
1034 | (UINT8 *) (UINTN) BufferPtr,\r | |
1035 | FileHeader,\r | |
23491d5c | 1036 | HeaderSize\r |
c2df8e13 | 1037 | );\r |
1038 | \r | |
1039 | //\r | |
1040 | // If successfully, insert an FfsFileEntry at the end of ffs file list\r | |
1041 | //\r | |
1042 | \r | |
1043 | FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));\r | |
1044 | ASSERT (FfsFileEntry != NULL);\r | |
1045 | FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) BufferPtr;\r | |
1046 | InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);\r | |
1047 | \r | |
1048 | //\r | |
1049 | // Set cache file to this file\r | |
1050 | //\r | |
1051 | FvDevice->CurrentFfsFile = FfsFileEntry;\r | |
1052 | \r | |
1053 | return EFI_SUCCESS;\r | |
1054 | }\r | |
1055 | \r | |
1056 | /**\r | |
1057 | Update a File, so after successful update, there are 2 files existing\r | |
1058 | in FV, one is marked for deleted, and another one is valid.\r | |
1059 | \r | |
1060 | @param FvDevice Cached Firmware Volume.\r | |
1061 | @param FfsFileBuffer A buffer that holds an FFS file,(it contains\r | |
1062 | a File Header which is in init state).\r | |
1063 | @param BufferSize The size of FfsFileBuffer.\r | |
1064 | @param ActualFileSize The actual file length, it may not be multiples of 8.\r | |
1065 | @param FileName The FFS File Name.\r | |
1066 | @param NewFileType The FFS File Type.\r | |
1067 | @param NewFileAttributes The Attributes of the FFS File to be created.\r | |
1068 | \r | |
1069 | @retval EFI_SUCCESS FFS fle is updated into FV.\r | |
1070 | @retval EFI_INVALID_PARAMETER File type is not valid.\r | |
1071 | @retval EFI_DEVICE_ERROR FV doesn't set writable attribute.\r | |
1072 | @retval EFI_NOT_FOUND FV has no enough space for the added file.\r | |
1073 | FFS with same file name is not found in FV.\r | |
1074 | \r | |
1075 | **/\r | |
1076 | EFI_STATUS\r | |
1077 | FvUpdateFile (\r | |
1078 | IN FV_DEVICE *FvDevice,\r | |
1079 | IN UINT8 *FfsFileBuffer,\r | |
1080 | IN UINTN BufferSize,\r | |
1081 | IN UINTN ActualFileSize,\r | |
1082 | IN EFI_GUID *FileName,\r | |
1083 | IN EFI_FV_FILETYPE NewFileType,\r | |
1084 | IN EFI_FV_FILE_ATTRIBUTES NewFileAttributes\r | |
1085 | )\r | |
1086 | {\r | |
1087 | EFI_STATUS Status;\r | |
1088 | EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r | |
1089 | UINTN NumBytesWritten;\r | |
1090 | EFI_FV_FILETYPE OldFileType;\r | |
1091 | EFI_FV_FILE_ATTRIBUTES OldFileAttributes;\r | |
1092 | UINTN OldFileSize;\r | |
1093 | EFI_FFS_FILE_HEADER *OldFileHeader;\r | |
1094 | UINTN OldOffset;\r | |
1095 | UINTN OldStateOffset;\r | |
1096 | FFS_FILE_LIST_ENTRY *OldFfsFileEntry;\r | |
1097 | UINTN Key;\r | |
1098 | EFI_GUID FileNameGuid;\r | |
1099 | \r | |
1100 | Fv = &FvDevice->Fv;\r | |
1101 | \r | |
1102 | //\r | |
1103 | // Step 1, find old file,\r | |
1104 | // Mark EFI_FILE_MARKED_FOR_UPDATE to TRUE in the older header\r | |
1105 | //\r | |
1106 | \r | |
1107 | //\r | |
1108 | // Check if the file was read last time.\r | |
1109 | //\r | |
1110 | OldFileHeader = NULL;\r | |
1111 | OldFfsFileEntry = FvDevice->CurrentFfsFile;\r | |
1112 | \r | |
1113 | if (OldFfsFileEntry != NULL) {\r | |
1114 | OldFileHeader = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry->FfsHeader;\r | |
1115 | }\r | |
1116 | \r | |
1117 | if ((OldFfsFileEntry == NULL) || (!CompareGuid (&OldFileHeader->Name, FileName))) {\r | |
1118 | Key = 0;\r | |
1119 | do {\r | |
1120 | OldFileType = 0;\r | |
1121 | Status = Fv->GetNextFile (\r | |
1122 | Fv,\r | |
1123 | &Key,\r | |
1124 | &OldFileType,\r | |
1125 | &FileNameGuid,\r | |
1126 | &OldFileAttributes,\r | |
1127 | &OldFileSize\r | |
1128 | );\r | |
1129 | if (EFI_ERROR (Status)) {\r | |
1130 | return Status;\r | |
1131 | }\r | |
1132 | } while (!CompareGuid (&FileNameGuid, FileName));\r | |
1133 | \r | |
1134 | //\r | |
1135 | // Get FfsFileEntry from the search key\r | |
1136 | //\r | |
1137 | OldFfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key;\r | |
1138 | \r | |
1139 | //\r | |
1140 | // Double check file state before being ready to be removed\r | |
1141 | //\r | |
1142 | OldFileHeader = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry->FfsHeader;\r | |
1143 | } else {\r | |
1144 | //\r | |
1145 | // Mark the cache file to invalid\r | |
1146 | //\r | |
1147 | FvDevice->CurrentFfsFile = NULL;\r | |
1148 | }\r | |
1149 | //\r | |
1150 | // Update File: Mark EFI_FILE_MARKED_FOR_UPDATE to TRUE\r | |
1151 | //\r | |
1152 | SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldFileHeader);\r | |
1153 | \r | |
1154 | OldOffset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) OldFileHeader - FvDevice->CachedFv);\r | |
1155 | OldStateOffset = OldOffset + (UINT8 *) &OldFileHeader->State - (UINT8 *) OldFileHeader;\r | |
1156 | \r | |
1157 | NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r | |
1158 | Status = FvcWrite (\r | |
1159 | FvDevice,\r | |
1160 | OldStateOffset,\r | |
1161 | &NumBytesWritten,\r | |
1162 | &OldFileHeader->State\r | |
1163 | );\r | |
1164 | if (EFI_ERROR (Status)) {\r | |
1165 | //\r | |
1166 | // if failed, write the bit back in the cache, its XOR operation.\r | |
1167 | //\r | |
1168 | SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldFileHeader);\r | |
1169 | \r | |
1170 | return Status;\r | |
1171 | }\r | |
1172 | \r | |
1173 | //\r | |
1174 | // Step 2, Create New Files\r | |
1175 | //\r | |
1176 | Status = FvCreateNewFile (\r | |
1177 | FvDevice,\r | |
1178 | FfsFileBuffer,\r | |
1179 | BufferSize,\r | |
1180 | ActualFileSize,\r | |
1181 | FileName,\r | |
1182 | NewFileType,\r | |
1183 | NewFileAttributes\r | |
1184 | );\r | |
1185 | if (EFI_ERROR (Status)) {\r | |
1186 | return Status;\r | |
1187 | }\r | |
1188 | \r | |
1189 | //\r | |
1190 | // If successfully, remove this file entry,\r | |
1191 | // although delete file may fail.\r | |
1192 | //\r | |
1193 | (OldFfsFileEntry->Link.BackLink)->ForwardLink = OldFfsFileEntry->Link.ForwardLink;\r | |
1194 | (OldFfsFileEntry->Link.ForwardLink)->BackLink = OldFfsFileEntry->Link.BackLink;\r | |
1195 | FreePool (OldFfsFileEntry);\r | |
1196 | \r | |
1197 | //\r | |
1198 | // Step 3: Delete old files,\r | |
1199 | // by marking EFI_FILE_DELETED to TRUE\r | |
1200 | //\r | |
1201 | SetFileState (EFI_FILE_DELETED, OldFileHeader);\r | |
1202 | \r | |
1203 | OldOffset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) OldFileHeader - FvDevice->CachedFv);\r | |
1204 | OldStateOffset = OldOffset + (UINT8 *) &OldFileHeader->State - (UINT8 *) OldFileHeader;\r | |
1205 | \r | |
1206 | NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r | |
1207 | Status = FvcWrite (\r | |
1208 | FvDevice,\r | |
1209 | OldStateOffset,\r | |
1210 | &NumBytesWritten,\r | |
1211 | &OldFileHeader->State\r | |
1212 | );\r | |
1213 | if (EFI_ERROR (Status)) {\r | |
1214 | //\r | |
1215 | // if failed, write the bit back in the cache, its XOR operation.\r | |
1216 | //\r | |
1217 | SetFileState (EFI_FILE_DELETED, OldFileHeader);\r | |
1218 | \r | |
1219 | return Status;\r | |
1220 | }\r | |
1221 | \r | |
1222 | return EFI_SUCCESS;\r | |
1223 | }\r | |
1224 | \r | |
1225 | /**\r | |
1226 | Deleted a given file from FV device.\r | |
1227 | \r | |
1228 | @param FvDevice Cached Firmware Volume.\r | |
1229 | @param NameGuid The FFS File Name.\r | |
1230 | \r | |
1231 | @retval EFI_SUCCESS FFS file with the specified FFS name is removed.\r | |
1232 | @retval EFI_NOT_FOUND FFS file with the specified FFS name is not found.\r | |
1233 | \r | |
1234 | **/\r | |
1235 | EFI_STATUS\r | |
1236 | FvDeleteFile (\r | |
1237 | IN FV_DEVICE *FvDevice,\r | |
1238 | IN EFI_GUID *NameGuid\r | |
1239 | )\r | |
1240 | {\r | |
1241 | EFI_STATUS Status;\r | |
1242 | UINTN Key;\r | |
1243 | EFI_GUID FileNameGuid;\r | |
1244 | EFI_FV_FILETYPE FileType;\r | |
1245 | EFI_FV_FILE_ATTRIBUTES FileAttributes;\r | |
1246 | UINTN FileSize;\r | |
1247 | EFI_FFS_FILE_HEADER *FileHeader;\r | |
1248 | FFS_FILE_LIST_ENTRY *FfsFileEntry;\r | |
1249 | EFI_FFS_FILE_STATE FileState;\r | |
1250 | EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r | |
1251 | UINTN Offset;\r | |
1252 | UINTN StateOffset;\r | |
1253 | UINTN NumBytesWritten;\r | |
1254 | \r | |
1255 | Fv = &FvDevice->Fv;\r | |
1256 | \r | |
1257 | //\r | |
1258 | // Check if the file was read last time.\r | |
1259 | //\r | |
1260 | FileHeader = NULL;\r | |
1261 | FfsFileEntry = FvDevice->CurrentFfsFile;\r | |
1262 | \r | |
1263 | if (FfsFileEntry != NULL) {\r | |
1264 | FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;\r | |
1265 | }\r | |
1266 | \r | |
1267 | if ((FfsFileEntry == NULL) || (!CompareGuid (&FileHeader->Name, NameGuid))) {\r | |
1268 | //\r | |
1269 | // Next search for the file using GetNextFile\r | |
1270 | //\r | |
1271 | Key = 0;\r | |
1272 | do {\r | |
1273 | FileType = 0;\r | |
1274 | Status = Fv->GetNextFile (\r | |
1275 | Fv,\r | |
1276 | &Key,\r | |
1277 | &FileType,\r | |
1278 | &FileNameGuid,\r | |
1279 | &FileAttributes,\r | |
1280 | &FileSize\r | |
1281 | );\r | |
1282 | if (EFI_ERROR (Status)) {\r | |
1283 | return Status;\r | |
1284 | }\r | |
1285 | } while (!CompareGuid (&FileNameGuid, NameGuid));\r | |
1286 | \r | |
1287 | //\r | |
1288 | // Get FfsFileEntry from the search key\r | |
1289 | //\r | |
1290 | FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key;\r | |
1291 | \r | |
1292 | //\r | |
1293 | // Double check file state before being ready to be removed\r | |
1294 | //\r | |
1295 | FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;\r | |
1296 | } else {\r | |
1297 | //\r | |
1298 | // Mark the cache file to NULL\r | |
1299 | //\r | |
1300 | FvDevice->CurrentFfsFile = NULL;\r | |
1301 | }\r | |
1302 | \r | |
1303 | FileState = GetFileState (FvDevice->ErasePolarity, FileHeader);\r | |
1304 | \r | |
1305 | if (FileState == EFI_FILE_HEADER_INVALID) {\r | |
1306 | return EFI_NOT_FOUND;\r | |
1307 | }\r | |
1308 | \r | |
1309 | if (FileState == EFI_FILE_DELETED) {\r | |
1310 | return EFI_NOT_FOUND;\r | |
1311 | }\r | |
1312 | //\r | |
1313 | // Delete File: Mark EFI_FILE_DELETED to TRUE\r | |
1314 | //\r | |
1315 | SetFileState (EFI_FILE_DELETED, FileHeader);\r | |
1316 | \r | |
1317 | Offset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader - FvDevice->CachedFv);\r | |
1318 | StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader;\r | |
1319 | \r | |
1320 | NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r | |
1321 | Status = FvcWrite (\r | |
1322 | FvDevice,\r | |
1323 | StateOffset,\r | |
1324 | &NumBytesWritten,\r | |
1325 | &FileHeader->State\r | |
1326 | );\r | |
1327 | if (EFI_ERROR (Status)) {\r | |
1328 | //\r | |
1329 | // if failed, write the bit back in the cache, its XOR operation.\r | |
1330 | //\r | |
1331 | SetFileState (EFI_FILE_DELETED, FileHeader);\r | |
1332 | \r | |
1333 | return Status;\r | |
1334 | }\r | |
1335 | //\r | |
1336 | // If successfully, remove this file entry\r | |
1337 | //\r | |
1338 | FvDevice->CurrentFfsFile = NULL;\r | |
1339 | \r | |
1340 | (FfsFileEntry->Link.BackLink)->ForwardLink = FfsFileEntry->Link.ForwardLink;\r | |
1341 | (FfsFileEntry->Link.ForwardLink)->BackLink = FfsFileEntry->Link.BackLink;\r | |
1342 | FreePool (FfsFileEntry);\r | |
1343 | \r | |
1344 | return EFI_SUCCESS;\r | |
1345 | }\r | |
1346 | \r | |
1347 | /**\r | |
1348 | Writes one or more files to the firmware volume.\r | |
1349 | \r | |
1350 | @param This Indicates the calling context.\r | |
1351 | @param NumberOfFiles Number of files.\r | |
1352 | @param WritePolicy WritePolicy indicates the level of reliability\r | |
1353 | for the write in the event of a power failure or\r | |
1354 | other system failure during the write operation.\r | |
1355 | @param FileData FileData is an pointer to an array of\r | |
1356 | EFI_FV_WRITE_DATA. Each element of array\r | |
1357 | FileData represents a file to be written.\r | |
1358 | \r | |
1359 | @retval EFI_SUCCESS Files successfully written to firmware volume\r | |
1360 | @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated.\r | |
1361 | @retval EFI_DEVICE_ERROR Device error.\r | |
1362 | @retval EFI_WRITE_PROTECTED Write protected.\r | |
1363 | @retval EFI_NOT_FOUND Not found.\r | |
1364 | @retval EFI_INVALID_PARAMETER Invalid parameter.\r | |
1365 | @retval EFI_UNSUPPORTED This function not supported.\r | |
1366 | \r | |
1367 | **/\r | |
1368 | EFI_STATUS\r | |
1369 | EFIAPI\r | |
1370 | FvWriteFile (\r | |
1371 | IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,\r | |
1372 | IN UINT32 NumberOfFiles,\r | |
1373 | IN EFI_FV_WRITE_POLICY WritePolicy,\r | |
1374 | IN EFI_FV_WRITE_FILE_DATA *FileData\r | |
1375 | )\r | |
1376 | {\r | |
1377 | EFI_STATUS Status;\r | |
1378 | UINTN Index1;\r | |
1379 | UINTN Index2;\r | |
1380 | UINT8 *FileBuffer;\r | |
1381 | UINTN BufferSize;\r | |
1382 | UINTN ActualSize;\r | |
1383 | UINT8 ErasePolarity;\r | |
1384 | FV_DEVICE *FvDevice;\r | |
1385 | EFI_FV_FILETYPE FileType;\r | |
1386 | EFI_FV_FILE_ATTRIBUTES FileAttributes;\r | |
1387 | UINTN Size;\r | |
1388 | BOOLEAN CreateNewFile[MAX_FILES];\r | |
1389 | UINTN NumDelete;\r | |
1390 | EFI_FV_ATTRIBUTES FvAttributes;\r | |
1391 | UINT32 AuthenticationStatus;\r | |
23491d5c | 1392 | UINTN HeaderSize;\r |
c2df8e13 | 1393 | \r |
1394 | if (NumberOfFiles > MAX_FILES) {\r | |
1395 | return EFI_UNSUPPORTED;\r | |
1396 | }\r | |
1397 | \r | |
1398 | Status = EFI_SUCCESS;\r | |
1399 | \r | |
1400 | SetMem (CreateNewFile, NumberOfFiles, TRUE);\r | |
1401 | \r | |
1402 | FvDevice = FV_DEVICE_FROM_THIS (This);\r | |
1403 | \r | |
1404 | //\r | |
1405 | // First check the volume attributes.\r | |
1406 | //\r | |
1407 | Status = This->GetVolumeAttributes (\r | |
1408 | This,\r | |
1409 | &FvAttributes\r | |
1410 | );\r | |
1411 | if (EFI_ERROR (Status)) {\r | |
1412 | return Status;\r | |
1413 | }\r | |
1414 | //\r | |
1415 | // Can we have write right?\r | |
1416 | //\r | |
c4487989 | 1417 | if ((FvAttributes & EFI_FV2_WRITE_STATUS) == 0) {\r |
c2df8e13 | 1418 | return EFI_WRITE_PROTECTED;\r |
1419 | }\r | |
1420 | \r | |
1421 | ErasePolarity = FvDevice->ErasePolarity;\r | |
1422 | \r | |
1423 | //\r | |
1424 | // Loop for all files\r | |
1425 | //\r | |
1426 | NumDelete = 0;\r | |
1427 | for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r | |
23491d5c SZ |
1428 | \r |
1429 | if ((FileData[Index1].BufferSize + sizeof (EFI_FFS_FILE_HEADER) > 0x00FFFFFF) && !FvDevice->IsFfs3Fv) {\r | |
1430 | //\r | |
1431 | // Found a file needs a FFS3 formatted file to store it, but it is in a non-FFS3 formatted FV.\r | |
1432 | //\r | |
1433 | DEBUG ((EFI_D_ERROR, "FFS3 formatted file can't be written in a non-FFS3 formatted FV.\n"));\r | |
1434 | return EFI_INVALID_PARAMETER;\r | |
1435 | }\r | |
1436 | \r | |
c2df8e13 | 1437 | if (FileData[Index1].BufferSize == 0) {\r |
1438 | //\r | |
1439 | // Here we will delete this file\r | |
1440 | //\r | |
1441 | Status = This->ReadFile (\r | |
1442 | This,\r | |
1443 | FileData[Index1].NameGuid,\r | |
1444 | NULL,\r | |
1445 | &Size,\r | |
1446 | &FileType,\r | |
1447 | &FileAttributes,\r | |
1448 | &AuthenticationStatus\r | |
1449 | );\r | |
1450 | if (!EFI_ERROR (Status)) {\r | |
1451 | NumDelete++;\r | |
1452 | } else {\r | |
1453 | return Status;\r | |
1454 | }\r | |
1455 | }\r | |
1456 | \r | |
1457 | if (FileData[Index1].Type == EFI_FV_FILETYPE_FFS_PAD) {\r | |
1458 | //\r | |
0a6f4824 LG |
1459 | // According to PI spec, on EFI_FV_FILETYPE_FFS_PAD:\r |
1460 | // "Standard firmware file system services will not return the handle of any pad files,\r | |
c2df8e13 | 1461 | // nor will they permit explicit creation of such files."\r |
1462 | //\r | |
1463 | return EFI_INVALID_PARAMETER;\r | |
1464 | }\r | |
1465 | }\r | |
1466 | \r | |
1467 | if ((NumDelete != NumberOfFiles) && (NumDelete != 0)) {\r | |
1468 | //\r | |
1469 | // A delete was request with a multiple file write\r | |
1470 | //\r | |
1471 | return EFI_INVALID_PARAMETER;\r | |
1472 | }\r | |
1473 | \r | |
1474 | if (NumDelete == NumberOfFiles) {\r | |
1475 | for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r | |
1476 | //\r | |
1477 | // Delete Files\r | |
1478 | //\r | |
1479 | Status = FvDeleteFile (FvDevice, FileData[Index1].NameGuid);\r | |
1480 | if (EFI_ERROR (Status)) {\r | |
1481 | return Status;\r | |
1482 | }\r | |
1483 | }\r | |
1484 | \r | |
1485 | return EFI_SUCCESS;\r | |
1486 | }\r | |
1487 | \r | |
1488 | for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r | |
1489 | Status = This->ReadFile (\r | |
1490 | This,\r | |
1491 | FileData[Index1].NameGuid,\r | |
1492 | NULL,\r | |
1493 | &Size,\r | |
1494 | &FileType,\r | |
1495 | &FileAttributes,\r | |
1496 | &AuthenticationStatus\r | |
1497 | );\r | |
1498 | if (!EFI_ERROR (Status)) {\r | |
1499 | CreateNewFile[Index1] = FALSE;\r | |
1500 | } else if (Status == EFI_NOT_FOUND) {\r | |
1501 | CreateNewFile[Index1] = TRUE;\r | |
1502 | } else {\r | |
1503 | return Status;\r | |
1504 | }\r | |
1505 | //\r | |
1506 | // Checking alignment\r | |
1507 | //\r | |
1508 | if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) {\r | |
1509 | UINT8 FFSAlignmentValue;\r | |
1510 | UINT8 FvAlignmentValue;\r | |
1511 | \r | |
1512 | FFSAlignmentValue = (UINT8) (FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT);\r | |
1513 | FvAlignmentValue = (UINT8) (((UINT32) (FvAttributes & EFI_FV2_ALIGNMENT)) >> 16);\r | |
1514 | \r | |
1515 | if (FFSAlignmentValue > FvAlignmentValue) {\r | |
1516 | return EFI_INVALID_PARAMETER;\r | |
1517 | }\r | |
1518 | }\r | |
1519 | }\r | |
1520 | \r | |
1521 | if ((WritePolicy != EFI_FV_RELIABLE_WRITE) && (WritePolicy != EFI_FV_UNRELIABLE_WRITE)) {\r | |
1522 | return EFI_INVALID_PARAMETER;\r | |
1523 | }\r | |
1524 | //\r | |
1525 | // Checking the reliable write is supported by FV\r | |
1526 | //\r | |
1527 | \r | |
1528 | if ((WritePolicy == EFI_FV_RELIABLE_WRITE) && (NumberOfFiles > 1)) {\r | |
1529 | //\r | |
1530 | // Only for multiple files, reliable write is meaningful\r | |
1531 | //\r | |
1532 | Status = FvCreateMultipleFiles (\r | |
1533 | FvDevice,\r | |
1534 | NumberOfFiles,\r | |
1535 | FileData,\r | |
1536 | CreateNewFile\r | |
1537 | );\r | |
1538 | \r | |
1539 | return Status;\r | |
1540 | }\r | |
1541 | \r | |
1542 | for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r | |
1543 | //\r | |
70d3fe9d | 1544 | // Making Buffersize QWORD boundary, and add file tail.\r |
c2df8e13 | 1545 | //\r |
23491d5c SZ |
1546 | HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r |
1547 | ActualSize = FileData[Index1].BufferSize + HeaderSize;\r | |
1548 | if (ActualSize > 0x00FFFFFF) {\r | |
1549 | HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r | |
1550 | ActualSize = FileData[Index1].BufferSize + HeaderSize;\r | |
1551 | }\r | |
c2df8e13 | 1552 | BufferSize = ActualSize;\r |
1553 | \r | |
1554 | while ((BufferSize & 0x07) != 0) {\r | |
1555 | BufferSize++;\r | |
1556 | }\r | |
1557 | \r | |
1558 | FileBuffer = AllocateZeroPool (BufferSize);\r | |
1559 | if (FileBuffer == NULL) {\r | |
1560 | return Status;\r | |
1561 | }\r | |
1562 | //\r | |
1563 | // Copy File Data into FileBuffer\r | |
1564 | //\r | |
1565 | CopyMem (\r | |
23491d5c | 1566 | FileBuffer + HeaderSize,\r |
c2df8e13 | 1567 | FileData[Index1].Buffer,\r |
1568 | FileData[Index1].BufferSize\r | |
1569 | );\r | |
1570 | \r | |
1571 | if (ErasePolarity == 1) {\r | |
1572 | //\r | |
1573 | // Fill the file header and padding byte with Erase Byte\r | |
1574 | //\r | |
23491d5c | 1575 | for (Index2 = 0; Index2 < HeaderSize; Index2++) {\r |
c2df8e13 | 1576 | FileBuffer[Index2] = (UINT8)~FileBuffer[Index2];\r |
1577 | }\r | |
1578 | \r | |
1579 | for (Index2 = ActualSize; Index2 < BufferSize; Index2++) {\r | |
1580 | FileBuffer[Index2] = (UINT8)~FileBuffer[Index2];\r | |
1581 | }\r | |
1582 | }\r | |
1583 | \r | |
1584 | if (CreateNewFile[Index1]) {\r | |
1585 | Status = FvCreateNewFile (\r | |
1586 | FvDevice,\r | |
1587 | FileBuffer,\r | |
1588 | BufferSize,\r | |
1589 | ActualSize,\r | |
1590 | FileData[Index1].NameGuid,\r | |
1591 | FileData[Index1].Type,\r | |
1592 | FileData[Index1].FileAttributes\r | |
1593 | );\r | |
1594 | } else {\r | |
1595 | Status = FvUpdateFile (\r | |
1596 | FvDevice,\r | |
1597 | FileBuffer,\r | |
1598 | BufferSize,\r | |
1599 | ActualSize,\r | |
1600 | FileData[Index1].NameGuid,\r | |
1601 | FileData[Index1].Type,\r | |
1602 | FileData[Index1].FileAttributes\r | |
1603 | );\r | |
1604 | }\r | |
1605 | \r | |
1606 | FreePool (FileBuffer);\r | |
1607 | \r | |
1608 | if (EFI_ERROR (Status)) {\r | |
1609 | return Status;\r | |
1610 | }\r | |
1611 | }\r | |
1612 | \r | |
1613 | return EFI_SUCCESS;\r | |
1614 | }\r |