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