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