1 /** @file 2 3 Copyright (c) 2013-2016 Intel Corporation. 4 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 14 **/ 15 16 #include "FwBlockService.h" 17 18 ESAL_FWB_GLOBAL *mFvbModuleGlobal; 19 20 EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = { 21 FVB_DEVICE_SIGNATURE, // Signature 22 // 23 // FV_DEVICE_PATH FvDevicePath 24 // 25 { 26 { 27 { 28 HARDWARE_DEVICE_PATH, 29 HW_MEMMAP_DP, 30 { 31 (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), 32 (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) 33 } 34 }, 35 EfiMemoryMappedIO, 36 (EFI_PHYSICAL_ADDRESS) 0, 37 (EFI_PHYSICAL_ADDRESS) 0 38 }, 39 { 40 END_DEVICE_PATH_TYPE, 41 END_ENTIRE_DEVICE_PATH_SUBTYPE, 42 { 43 END_DEVICE_PATH_LENGTH, 44 0 45 } 46 } 47 }, 48 // 49 // UEFI_FV_DEVICE_PATH UefiFvDevicePath 50 // 51 { 52 { 53 { 54 MEDIA_DEVICE_PATH, 55 MEDIA_PIWG_FW_VOL_DP, 56 { 57 (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), 58 (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) 59 } 60 }, 61 { 0 } 62 }, 63 { 64 END_DEVICE_PATH_TYPE, 65 END_ENTIRE_DEVICE_PATH_SUBTYPE, 66 { 67 END_DEVICE_PATH_LENGTH, 68 0 69 } 70 } 71 }, 72 0, // Instance 73 // 74 // EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance 75 // 76 { 77 FvbProtocolGetAttributes, 78 FvbProtocolSetAttributes, 79 FvbProtocolGetPhysicalAddress, 80 FvbProtocolGetBlockSize, 81 FvbProtocolRead, 82 FvbProtocolWrite, 83 FvbProtocolEraseBlocks, 84 NULL 85 } 86 }; 87 88 UINT32 mInSmmMode = 0; 89 EFI_SMM_SYSTEM_TABLE2* mSmst = NULL; 90 91 VOID 92 PublishFlashDeviceInfo ( 93 IN SPI_INIT_TABLE *Found 94 ) 95 /*++ 96 97 Routine Description: 98 99 Publish info on found flash device to other drivers via PcdSpiFlashDeviceSize. 100 101 Arguments: 102 Found - Pointer to entry in mSpiInitTable for found flash part. 103 104 Returns: 105 None 106 107 --*/ 108 { 109 EFI_STATUS Status; 110 111 // 112 // Publish Byte Size of found flash device. 113 // 114 Status = PcdSet32S (PcdSpiFlashDeviceSize, (UINT32)(Found->BiosStartOffset + Found->BiosSize)); 115 ASSERT_EFI_ERROR (Status); 116 } 117 118 VOID 119 FvbVirtualddressChangeEvent ( 120 IN EFI_EVENT Event, 121 IN VOID *Context 122 ) 123 /*++ 124 125 Routine Description: 126 127 Fixup internal data so that EFI and SAL can be call in virtual mode. 128 Call the passed in Child Notify event and convert the mFvbModuleGlobal 129 date items to there virtual address. 130 131 mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] - Physical copy of instance data 132 mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] - Virtual pointer to common 133 instance data. 134 135 Arguments: 136 137 (Standard EFI notify event - EFI_EVENT_NOTIFY) 138 139 Returns: 140 141 None 142 143 --*/ 144 { 145 EFI_FW_VOL_INSTANCE *FwhInstance; 146 UINTN Index; 147 148 gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]); 149 150 // 151 // Convert the base address of all the instances 152 // 153 Index = 0; 154 FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; 155 while (Index < mFvbModuleGlobal->NumFv) { 156 157 gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]); 158 // 159 // SpiWrite and SpiErase always use Physical Address instead of 160 // Virtual Address, even in Runtime. So we need not convert pointer 161 // for FvWriteBase[FVB_VIRTUAL] 162 // 163 // EfiConvertPointer (0, (VOID **) &FwhInstance->FvWriteBase[FVB_VIRTUAL]); 164 // 165 FwhInstance = (EFI_FW_VOL_INSTANCE *) 166 ( 167 (UINTN) ((UINT8 *) FwhInstance) + FwhInstance->VolumeHeader.HeaderLength + 168 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) 169 ); 170 Index++; 171 } 172 173 gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]); 174 // 175 // Convert SPI_PROTOCOL instance for runtime 176 // 177 gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->SpiProtocol); 178 gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal); 179 } 180 181 VOID 182 FvbMemWrite8 ( 183 IN UINT64 Dest, 184 IN UINT8 Byte 185 ) 186 { 187 MmioWrite8 ((UINTN)Dest, Byte); 188 189 return ; 190 } 191 192 EFI_STATUS 193 GetFvbInstance ( 194 IN UINTN Instance, 195 IN ESAL_FWB_GLOBAL *Global, 196 OUT EFI_FW_VOL_INSTANCE **FwhInstance, 197 IN BOOLEAN Virtual 198 ) 199 /*++ 200 201 Routine Description: 202 Retrieves the physical address of a memory mapped FV 203 204 Arguments: 205 Instance - The FV instance whose base address is going to be 206 returned 207 Global - Pointer to ESAL_FWB_GLOBAL that contains all 208 instance data 209 FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure 210 Virtual - Whether CPU is in virtual or physical mode 211 212 Returns: 213 EFI_SUCCESS - Successfully returns 214 EFI_INVALID_PARAMETER - Instance not found 215 216 --*/ 217 { 218 EFI_FW_VOL_INSTANCE *FwhRecord; 219 220 if (Instance >= Global->NumFv) { 221 return EFI_INVALID_PARAMETER; 222 } 223 // 224 // Find the right instance of the FVB private data 225 // 226 FwhRecord = Global->FvInstance[Virtual]; 227 while (Instance > 0) { 228 FwhRecord = (EFI_FW_VOL_INSTANCE *) 229 ( 230 (UINTN) ((UINT8 *) FwhRecord) + FwhRecord->VolumeHeader.HeaderLength + 231 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) 232 ); 233 Instance--; 234 } 235 236 *FwhInstance = FwhRecord; 237 238 return EFI_SUCCESS; 239 } 240 241 EFI_STATUS 242 FvbGetPhysicalAddress ( 243 IN UINTN Instance, 244 OUT EFI_PHYSICAL_ADDRESS *Address, 245 IN ESAL_FWB_GLOBAL *Global, 246 IN BOOLEAN Virtual 247 ) 248 /*++ 249 250 Routine Description: 251 Retrieves the physical address of a memory mapped FV 252 253 Arguments: 254 Instance - The FV instance whose base address is going to be 255 returned 256 Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS 257 that on successful return, contains the base address 258 of the firmware volume. 259 Global - Pointer to ESAL_FWB_GLOBAL that contains all 260 instance data 261 Virtual - Whether CPU is in virtual or physical mode 262 263 Returns: 264 EFI_SUCCESS - Successfully returns 265 EFI_INVALID_PARAMETER - Instance not found 266 267 --*/ 268 { 269 EFI_FW_VOL_INSTANCE *FwhInstance; 270 EFI_STATUS Status; 271 272 FwhInstance = NULL; 273 274 // 275 // Find the right instance of the FVB private data 276 // 277 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 278 ASSERT_EFI_ERROR (Status); 279 *Address = FwhInstance->FvBase[Virtual]; 280 281 return EFI_SUCCESS; 282 } 283 284 EFI_STATUS 285 FvbGetVolumeAttributes ( 286 IN UINTN Instance, 287 OUT EFI_FVB_ATTRIBUTES_2 *Attributes, 288 IN ESAL_FWB_GLOBAL *Global, 289 IN BOOLEAN Virtual 290 ) 291 /*++ 292 293 Routine Description: 294 Retrieves attributes, insures positive polarity of attribute bits, returns 295 resulting attributes in output parameter 296 297 Arguments: 298 Instance - The FV instance whose attributes is going to be 299 returned 300 Attributes - Output buffer which contains attributes 301 Global - Pointer to ESAL_FWB_GLOBAL that contains all 302 instance data 303 Virtual - Whether CPU is in virtual or physical mode 304 305 Returns: 306 EFI_SUCCESS - Successfully returns 307 EFI_INVALID_PARAMETER - Instance not found 308 309 --*/ 310 { 311 EFI_FW_VOL_INSTANCE *FwhInstance; 312 EFI_STATUS Status; 313 314 FwhInstance = NULL; 315 316 // 317 // Find the right instance of the FVB private data 318 // 319 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 320 ASSERT_EFI_ERROR (Status); 321 *Attributes = FwhInstance->VolumeHeader.Attributes; 322 323 return EFI_SUCCESS; 324 } 325 326 EFI_STATUS 327 FvbGetLbaAddress ( 328 IN UINTN Instance, 329 IN EFI_LBA Lba, 330 OUT UINTN *LbaAddress, 331 OUT UINTN *LbaWriteAddress, 332 OUT UINTN *LbaLength, 333 OUT UINTN *NumOfBlocks, 334 IN ESAL_FWB_GLOBAL *Global, 335 IN BOOLEAN Virtual 336 ) 337 /*++ 338 339 Routine Description: 340 Retrieves the starting address of an LBA in an FV 341 342 Arguments: 343 Instance - The FV instance which the Lba belongs to 344 Lba - The logical block address 345 LbaAddress - On output, contains the physical starting address 346 of the Lba 347 LbaWriteAddress - On output, contains the physical starting address 348 of the Lba for writing 349 LbaLength - On output, contains the length of the block 350 NumOfBlocks - A pointer to a caller allocated UINTN in which the 351 number of consecutive blocks starting with Lba is 352 returned. All blocks in this range have a size of 353 BlockSize 354 Global - Pointer to ESAL_FWB_GLOBAL that contains all 355 instance data 356 Virtual - Whether CPU is in virtual or physical mode 357 358 Returns: 359 EFI_SUCCESS - Successfully returns 360 EFI_INVALID_PARAMETER - Instance not found 361 362 --*/ 363 { 364 UINT32 NumBlocks; 365 UINT32 BlockLength; 366 UINTN Offset; 367 EFI_LBA StartLba; 368 EFI_LBA NextLba; 369 EFI_FW_VOL_INSTANCE *FwhInstance; 370 EFI_FV_BLOCK_MAP_ENTRY *BlockMap; 371 EFI_STATUS Status; 372 373 FwhInstance = NULL; 374 375 // 376 // Find the right instance of the FVB private data 377 // 378 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 379 ASSERT_EFI_ERROR (Status); 380 381 StartLba = 0; 382 Offset = 0; 383 BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]); 384 385 // 386 // Parse the blockmap of the FV to find which map entry the Lba belongs to 387 // 388 while (TRUE) { 389 NumBlocks = BlockMap->NumBlocks; 390 BlockLength = BlockMap->Length; 391 392 if ((NumBlocks == 0) || (BlockLength == 0)) { 393 return EFI_INVALID_PARAMETER; 394 } 395 396 NextLba = StartLba + NumBlocks; 397 398 // 399 // The map entry found 400 // 401 if (Lba >= StartLba && Lba < NextLba) { 402 Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength); 403 if (LbaAddress) { 404 *LbaAddress = FwhInstance->FvBase[Virtual] + Offset; 405 } 406 407 if (LbaWriteAddress) { 408 *LbaWriteAddress = FwhInstance->FvWriteBase[Virtual] + Offset; 409 } 410 411 if (LbaLength) { 412 *LbaLength = BlockLength; 413 } 414 415 if (NumOfBlocks) { 416 *NumOfBlocks = (UINTN) (NextLba - Lba); 417 } 418 419 return EFI_SUCCESS; 420 } 421 422 StartLba = NextLba; 423 Offset = Offset + NumBlocks * BlockLength; 424 BlockMap++; 425 } 426 } 427 428 EFI_STATUS 429 FvbReadBlock ( 430 IN UINTN Instance, 431 IN EFI_LBA Lba, 432 IN UINTN BlockOffset, 433 IN OUT UINTN *NumBytes, 434 IN UINT8 *Buffer, 435 IN ESAL_FWB_GLOBAL *Global, 436 IN BOOLEAN Virtual 437 ) 438 /*++ 439 440 Routine Description: 441 Reads specified number of bytes into a buffer from the specified block 442 443 Arguments: 444 Instance - The FV instance to be read from 445 Lba - The logical block address to be read from 446 BlockOffset - Offset into the block at which to begin reading 447 NumBytes - Pointer that on input contains the total size of 448 the buffer. On output, it contains the total number 449 of bytes read 450 Buffer - Pointer to a caller allocated buffer that will be 451 used to hold the data read 452 Global - Pointer to ESAL_FWB_GLOBAL that contains all 453 instance data 454 Virtual - Whether CPU is in virtual or physical mode 455 456 Returns: 457 EFI_SUCCESS - The firmware volume was read successfully and 458 contents are in Buffer 459 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, 460 NumBytes contains the total number of bytes returned 461 in Buffer 462 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state 463 EFI_DEVICE_ERROR - The block device is not functioning correctly and 464 could not be read 465 EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL 466 467 --*/ 468 { 469 EFI_FVB_ATTRIBUTES_2 Attributes; 470 UINTN LbaAddress; 471 UINTN LbaLength; 472 EFI_STATUS Status; 473 474 // 475 // Check for invalid conditions 476 // 477 if ((NumBytes == NULL) || (Buffer == NULL)) { 478 return EFI_INVALID_PARAMETER; 479 } 480 481 if (*NumBytes == 0) { 482 return EFI_INVALID_PARAMETER; 483 } 484 485 Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, NULL, &LbaLength, NULL, Global, Virtual); 486 if (EFI_ERROR (Status)) { 487 return Status; 488 } 489 // 490 // Check if the FV is read enabled 491 // 492 FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 493 494 if ((Attributes & EFI_FVB2_READ_STATUS) == 0) { 495 return EFI_ACCESS_DENIED; 496 } 497 // 498 // Perform boundary checks and adjust NumBytes 499 // 500 if (BlockOffset > LbaLength) { 501 return EFI_INVALID_PARAMETER; 502 } 503 504 if (LbaLength < (*NumBytes + BlockOffset)) { 505 *NumBytes = (UINT32) (LbaLength - BlockOffset); 506 Status = EFI_BAD_BUFFER_SIZE; 507 } 508 509 MmioReadBuffer8 (LbaAddress + BlockOffset, (UINTN) *NumBytes, Buffer); 510 511 return Status; 512 } 513 514 EFI_STATUS 515 FlashFdWrite ( 516 IN UINTN WriteAddress, 517 IN UINTN Address, 518 IN OUT UINTN *NumBytes, 519 IN UINT8 *Buffer, 520 IN UINTN LbaLength 521 ) 522 /*++ 523 524 Routine Description: 525 Writes specified number of bytes from the input buffer to the address 526 527 Arguments: 528 529 Returns: 530 531 --*/ 532 { 533 EFI_STATUS Status; 534 535 Status = EFI_SUCCESS; 536 537 // 538 // TODO: Suggested that this code be "critical section" 539 // 540 WriteAddress -= ( PcdGet32 (PcdFlashAreaBaseAddress) ); 541 if (mInSmmMode == 0) { // !(EfiInManagementInterrupt ())) { 542 Status = mFvbModuleGlobal->SpiProtocol->Execute ( 543 mFvbModuleGlobal->SpiProtocol, 544 SPI_OPCODE_WRITE_INDEX, // OpcodeIndex 545 0, // PrefixOpcodeIndex 546 TRUE, // DataCycle 547 TRUE, // Atomic 548 TRUE, // ShiftOut 549 WriteAddress, // Address 550 (UINT32) (*NumBytes), // Data Number 551 Buffer, 552 EnumSpiRegionBios 553 ); 554 555 } else { 556 Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 557 mFvbModuleGlobal->SmmSpiProtocol, 558 SPI_OPCODE_WRITE_INDEX, // OpcodeIndex 559 0, // PrefixOpcodeIndex 560 TRUE, // DataCycle 561 TRUE, // Atomic 562 TRUE, // ShiftOut 563 WriteAddress, // Address 564 (UINT32) (*NumBytes), // Data Number 565 Buffer, 566 EnumSpiRegionBios 567 ); 568 } 569 570 AsmWbinvd (); 571 572 return Status; 573 } 574 575 EFI_STATUS 576 FlashFdErase ( 577 IN UINTN WriteAddress, 578 IN UINTN Address, 579 IN UINTN LbaLength 580 ) 581 /*++ 582 583 Routine Description: 584 Erase a certain block from address LbaWriteAddress 585 586 Arguments: 587 588 Returns: 589 590 --*/ 591 { 592 EFI_STATUS Status; 593 594 WriteAddress -= (PcdGet32 (PcdFlashAreaBaseAddress)); 595 if (mInSmmMode == 0 ) { // !(EfiInManagementInterrupt ())) { 596 Status = mFvbModuleGlobal->SpiProtocol->Execute ( 597 mFvbModuleGlobal->SpiProtocol, 598 SPI_OPCODE_ERASE_INDEX, // OpcodeIndex 599 0, // PrefixOpcodeIndex 600 FALSE, // DataCycle 601 TRUE, // Atomic 602 FALSE, // ShiftOut 603 WriteAddress, // Address 604 0, // Data Number 605 NULL, 606 EnumSpiRegionBios // SPI_REGION_TYPE 607 ); 608 } else { 609 Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 610 mFvbModuleGlobal->SmmSpiProtocol, 611 SPI_OPCODE_ERASE_INDEX, // OpcodeIndex 612 0, // PrefixOpcodeIndex 613 FALSE, // DataCycle 614 TRUE, // Atomic 615 FALSE, // ShiftOut 616 WriteAddress, // Address 617 0, // Data Number 618 NULL, 619 EnumSpiRegionBios // SPI_REGION_TYPE 620 ); 621 } 622 623 AsmWbinvd (); 624 625 return Status; 626 } 627 628 EFI_STATUS 629 FvbWriteBlock ( 630 IN UINTN Instance, 631 IN EFI_LBA Lba, 632 IN UINTN BlockOffset, 633 IN OUT UINTN *NumBytes, 634 IN UINT8 *Buffer, 635 IN ESAL_FWB_GLOBAL *Global, 636 IN BOOLEAN Virtual 637 ) 638 /*++ 639 640 Routine Description: 641 Writes specified number of bytes from the input buffer to the block 642 643 Arguments: 644 Instance - The FV instance to be written to 645 Lba - The starting logical block index to write to 646 BlockOffset - Offset into the block at which to begin writing 647 NumBytes - Pointer that on input contains the total size of 648 the buffer. On output, it contains the total number 649 of bytes actually written 650 Buffer - Pointer to a caller allocated buffer that contains 651 the source for the write 652 Global - Pointer to ESAL_FWB_GLOBAL that contains all 653 instance data 654 Virtual - Whether CPU is in virtual or physical mode 655 656 Returns: 657 EFI_SUCCESS - The firmware volume was written successfully 658 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, 659 NumBytes contains the total number of bytes 660 actually written 661 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 662 EFI_DEVICE_ERROR - The block device is not functioning correctly and 663 could not be written 664 EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL 665 666 --*/ 667 { 668 EFI_FVB_ATTRIBUTES_2 Attributes; 669 UINTN LbaAddress; 670 UINTN LbaWriteAddress; 671 UINTN LbaLength; 672 EFI_FW_VOL_INSTANCE *FwhInstance; 673 EFI_STATUS Status; 674 EFI_STATUS ReturnStatus; 675 676 FwhInstance = NULL; 677 678 // 679 // Find the right instance of the FVB private data 680 // 681 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 682 ASSERT_EFI_ERROR (Status); 683 684 // 685 // Writes are enabled in the init routine itself 686 // 687 if (!FwhInstance->WriteEnabled) { 688 return EFI_ACCESS_DENIED; 689 } 690 // 691 // Check for invalid conditions 692 // 693 if ((NumBytes == NULL) || (Buffer == NULL)) { 694 return EFI_INVALID_PARAMETER; 695 } 696 697 if (*NumBytes == 0) { 698 return EFI_INVALID_PARAMETER; 699 } 700 701 Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual); 702 if (EFI_ERROR (Status)) { 703 return Status; 704 } 705 // 706 // Check if the FV is write enabled 707 // 708 FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 709 710 if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { 711 return EFI_ACCESS_DENIED; 712 } 713 // 714 // Perform boundary checks and adjust NumBytes 715 // 716 if (BlockOffset > LbaLength) { 717 return EFI_INVALID_PARAMETER; 718 } 719 720 if (LbaLength < (*NumBytes + BlockOffset)) { 721 *NumBytes = (UINT32) (LbaLength - BlockOffset); 722 Status = EFI_BAD_BUFFER_SIZE; 723 } 724 725 ReturnStatus = FlashFdWrite ( 726 LbaWriteAddress + BlockOffset, 727 LbaAddress, 728 NumBytes, 729 Buffer, 730 LbaLength 731 ); 732 if (EFI_ERROR (ReturnStatus)) { 733 return ReturnStatus; 734 } 735 736 return Status; 737 } 738 739 EFI_STATUS 740 FvbEraseBlock ( 741 IN UINTN Instance, 742 IN EFI_LBA Lba, 743 IN ESAL_FWB_GLOBAL *Global, 744 IN BOOLEAN Virtual 745 ) 746 /*++ 747 748 Routine Description: 749 Erases and initializes a firmware volume block 750 751 Arguments: 752 Instance - The FV instance to be erased 753 Lba - The logical block index to be erased 754 Global - Pointer to ESAL_FWB_GLOBAL that contains all 755 instance data 756 Virtual - Whether CPU is in virtual or physical mode 757 758 Returns: 759 EFI_SUCCESS - The erase request was successfully completed 760 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 761 EFI_DEVICE_ERROR - The block device is not functioning correctly and 762 could not be written. Firmware device may have been 763 partially erased 764 EFI_INVALID_PARAMETER - Instance not found 765 766 --*/ 767 { 768 769 EFI_FVB_ATTRIBUTES_2 Attributes; 770 UINTN LbaAddress; 771 UINTN LbaWriteAddress; 772 EFI_FW_VOL_INSTANCE *FwhInstance; 773 UINTN LbaLength; 774 EFI_STATUS Status; 775 UINTN SectorNum; 776 UINTN Index; 777 778 FwhInstance = NULL; 779 780 // 781 // Find the right instance of the FVB private data 782 // 783 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 784 ASSERT_EFI_ERROR (Status); 785 786 // 787 // Writes are enabled in the init routine itself 788 // 789 if (!FwhInstance->WriteEnabled) { 790 return EFI_ACCESS_DENIED; 791 } 792 // 793 // Check if the FV is write enabled 794 // 795 FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 796 797 if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { 798 return EFI_ACCESS_DENIED; 799 } 800 // 801 // Get the starting address of the block for erase. For debug reasons, 802 // LbaWriteAddress may not be the same as LbaAddress. 803 // 804 Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual); 805 if (EFI_ERROR (Status)) { 806 return Status; 807 } 808 809 SectorNum = LbaLength / SPI_ERASE_SECTOR_SIZE; 810 for (Index = 0; Index < SectorNum; Index++){ 811 Status = FlashFdErase ( 812 LbaWriteAddress + Index * SPI_ERASE_SECTOR_SIZE, 813 LbaAddress, 814 SPI_ERASE_SECTOR_SIZE 815 ); 816 if (Status != EFI_SUCCESS){ 817 break; 818 } 819 } 820 821 return Status; 822 } 823 824 EFI_STATUS 825 FvbEraseCustomBlockRange ( 826 IN UINTN Instance, 827 IN EFI_LBA StartLba, 828 IN UINTN OffsetStartLba, 829 IN EFI_LBA LastLba, 830 IN UINTN OffsetLastLba, 831 IN ESAL_FWB_GLOBAL *Global, 832 IN BOOLEAN Virtual 833 ) 834 /*++ 835 836 Routine Description: 837 Erases and initializes a specified range of a firmware volume 838 839 Arguments: 840 Instance - The FV instance to be erased 841 StartLba - The starting logical block index to be erased 842 OffsetStartLba - Offset into the starting block at which to 843 begin erasing 844 LastLba - The last logical block index to be erased 845 OffsetStartLba - Offset into the last block at which to end erasing 846 Global - Pointer to ESAL_FWB_GLOBAL that contains all 847 instance data 848 Virtual - Whether CPU is in virtual or physical mode 849 850 Returns: 851 EFI_SUCCESS - The firmware volume was erased successfully 852 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 853 EFI_DEVICE_ERROR - The block device is not functioning correctly and 854 could not be written. Firmware device may have been 855 partially erased 856 EFI_INVALID_PARAMETER - Instance not found 857 858 --*/ 859 { 860 EFI_LBA Index; 861 UINTN LbaSize; 862 UINTN ScratchLbaSizeData; 863 864 // 865 // First LBA. 866 // 867 FvbGetLbaAddress (Instance, StartLba, NULL, NULL, &LbaSize, NULL, Global, Virtual); 868 869 // 870 // Use the scratch space as the intermediate buffer to transfer data 871 // Back up the first LBA in scratch space. 872 // 873 FvbReadBlock (Instance, StartLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual); 874 875 // 876 // erase now 877 // 878 FvbEraseBlock (Instance, StartLba, Global, Virtual); 879 ScratchLbaSizeData = OffsetStartLba; 880 881 // 882 // write the data back to the first block 883 // 884 if (ScratchLbaSizeData > 0) { 885 FvbWriteBlock (Instance, StartLba, 0, &ScratchLbaSizeData, Global->FvbScratchSpace[Virtual], Global, Virtual); 886 } 887 // 888 // Middle LBAs 889 // 890 if (LastLba > (StartLba + 1)) { 891 for (Index = (StartLba + 1); Index <= (LastLba - 1); Index++) { 892 FvbEraseBlock (Instance, Index, Global, Virtual); 893 } 894 } 895 // 896 // Last LBAs, the same as first LBAs 897 // 898 if (LastLba > StartLba) { 899 FvbGetLbaAddress (Instance, LastLba, NULL, NULL, &LbaSize, NULL, Global, Virtual); 900 FvbReadBlock (Instance, LastLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual); 901 FvbEraseBlock (Instance, LastLba, Global, Virtual); 902 } 903 904 ScratchLbaSizeData = LbaSize - (OffsetStartLba + 1); 905 906 return FvbWriteBlock ( 907 Instance, 908 LastLba, 909 (OffsetLastLba + 1), 910 &ScratchLbaSizeData, 911 Global->FvbScratchSpace[Virtual], 912 Global, 913 Virtual 914 ); 915 } 916 917 EFI_STATUS 918 FvbSetVolumeAttributes ( 919 IN UINTN Instance, 920 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes, 921 IN ESAL_FWB_GLOBAL *Global, 922 IN BOOLEAN Virtual 923 ) 924 /*++ 925 926 Routine Description: 927 Modifies the current settings of the firmware volume according to the 928 input parameter, and returns the new setting of the volume 929 930 Arguments: 931 Instance - The FV instance whose attributes is going to be 932 modified 933 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2 934 containing the desired firmware volume settings. 935 On successful return, it contains the new settings 936 of the firmware volume 937 Global - Pointer to ESAL_FWB_GLOBAL that contains all 938 instance data 939 Virtual - Whether CPU is in virtual or physical mode 940 941 Returns: 942 EFI_SUCCESS - Successfully returns 943 EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified 944 EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are 945 in conflict with the capabilities as declared in the 946 firmware volume header 947 948 --*/ 949 { 950 EFI_FW_VOL_INSTANCE *FwhInstance; 951 EFI_FVB_ATTRIBUTES_2 OldAttributes; 952 EFI_FVB_ATTRIBUTES_2 *AttribPtr; 953 UINT32 Capabilities; 954 UINT32 OldStatus; 955 UINT32 NewStatus; 956 EFI_STATUS Status; 957 958 FwhInstance = NULL; 959 960 // 961 // Find the right instance of the FVB private data 962 // 963 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 964 ASSERT_EFI_ERROR (Status); 965 966 AttribPtr = (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes); 967 OldAttributes = *AttribPtr; 968 Capabilities = OldAttributes & EFI_FVB2_CAPABILITIES; 969 OldStatus = OldAttributes & EFI_FVB2_STATUS; 970 NewStatus = *Attributes & EFI_FVB2_STATUS; 971 972 // 973 // If firmware volume is locked, no status bit can be updated 974 // 975 if (OldAttributes & EFI_FVB2_LOCK_STATUS) { 976 if (OldStatus ^ NewStatus) { 977 return EFI_ACCESS_DENIED; 978 } 979 } 980 // 981 // Test read disable 982 // 983 if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) { 984 if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) { 985 return EFI_INVALID_PARAMETER; 986 } 987 } 988 // 989 // Test read enable 990 // 991 if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) { 992 if (NewStatus & EFI_FVB2_READ_STATUS) { 993 return EFI_INVALID_PARAMETER; 994 } 995 } 996 // 997 // Test write disable 998 // 999 if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) { 1000 if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) { 1001 return EFI_INVALID_PARAMETER; 1002 } 1003 } 1004 // 1005 // Test write enable 1006 // 1007 if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) { 1008 if (NewStatus & EFI_FVB2_WRITE_STATUS) { 1009 return EFI_INVALID_PARAMETER; 1010 } 1011 } 1012 // 1013 // Test lock 1014 // 1015 if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) { 1016 if (NewStatus & EFI_FVB2_LOCK_STATUS) { 1017 return EFI_INVALID_PARAMETER; 1018 } 1019 } 1020 1021 *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); 1022 *AttribPtr = (*AttribPtr) | NewStatus; 1023 *Attributes = *AttribPtr; 1024 1025 return EFI_SUCCESS; 1026 } 1027 // 1028 // FVB protocol APIs 1029 // 1030 EFI_STATUS 1031 EFIAPI 1032 FvbProtocolGetPhysicalAddress ( 1033 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1034 OUT EFI_PHYSICAL_ADDRESS *Address 1035 ) 1036 /*++ 1037 1038 Routine Description: 1039 1040 Retrieves the physical address of the device. 1041 1042 Arguments: 1043 1044 This - Calling context 1045 Address - Output buffer containing the address. 1046 1047 Returns: 1048 1049 Returns: 1050 EFI_SUCCESS - Successfully returns 1051 1052 --*/ 1053 { 1054 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1055 1056 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1057 1058 return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ()); 1059 } 1060 1061 EFI_STATUS 1062 FvbProtocolGetBlockSize ( 1063 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1064 IN EFI_LBA Lba, 1065 OUT UINTN *BlockSize, 1066 OUT UINTN *NumOfBlocks 1067 ) 1068 /*++ 1069 1070 Routine Description: 1071 Retrieve the size of a logical block 1072 1073 Arguments: 1074 This - Calling context 1075 Lba - Indicates which block to return the size for. 1076 BlockSize - A pointer to a caller allocated UINTN in which 1077 the size of the block is returned 1078 NumOfBlocks - a pointer to a caller allocated UINTN in which the 1079 number of consecutive blocks starting with Lba is 1080 returned. All blocks in this range have a size of 1081 BlockSize 1082 1083 Returns: 1084 EFI_SUCCESS - The firmware volume was read successfully and 1085 contents are in Buffer 1086 1087 --*/ 1088 { 1089 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1090 1091 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1092 1093 return FvbGetLbaAddress ( 1094 FvbDevice->Instance, 1095 Lba, 1096 NULL, 1097 NULL, 1098 BlockSize, 1099 NumOfBlocks, 1100 mFvbModuleGlobal, 1101 EfiGoneVirtual () 1102 ); 1103 } 1104 1105 EFI_STATUS 1106 EFIAPI 1107 FvbProtocolGetAttributes ( 1108 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1109 OUT EFI_FVB_ATTRIBUTES_2 *Attributes 1110 ) 1111 /*++ 1112 1113 Routine Description: 1114 Retrieves Volume attributes. No polarity translations are done. 1115 1116 Arguments: 1117 This - Calling context 1118 Attributes - output buffer which contains attributes 1119 1120 Returns: 1121 EFI_SUCCESS - Successfully returns 1122 1123 --*/ 1124 { 1125 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1126 1127 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1128 1129 return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); 1130 } 1131 1132 EFI_STATUS 1133 EFIAPI 1134 FvbProtocolSetAttributes ( 1135 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1136 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes 1137 ) 1138 /*++ 1139 1140 Routine Description: 1141 Sets Volume attributes. No polarity translations are done. 1142 1143 Arguments: 1144 This - Calling context 1145 Attributes - output buffer which contains attributes 1146 1147 Returns: 1148 EFI_SUCCESS - Successfully returns 1149 1150 --*/ 1151 { 1152 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1153 1154 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1155 1156 return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); 1157 } 1158 1159 EFI_STATUS 1160 EFIAPI 1161 FvbProtocolEraseBlocks ( 1162 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1163 ... 1164 ) 1165 /*++ 1166 1167 Routine Description: 1168 1169 The EraseBlock() function erases one or more blocks as denoted by the 1170 variable argument list. The entire parameter list of blocks must be verified 1171 prior to erasing any blocks. If a block is requested that does not exist 1172 within the associated firmware volume (it has a larger index than the last 1173 block of the firmware volume), the EraseBlock() function must return 1174 EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. 1175 1176 Arguments: 1177 This - Calling context 1178 ... - Starting LBA followed by Number of Lba to erase. 1179 a -1 to terminate the list. 1180 1181 Returns: 1182 EFI_SUCCESS - The erase request was successfully completed 1183 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 1184 EFI_DEVICE_ERROR - The block device is not functioning correctly and 1185 could not be written. Firmware device may have been 1186 partially erased 1187 1188 --*/ 1189 { 1190 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1191 EFI_FW_VOL_INSTANCE *FwhInstance; 1192 UINTN NumOfBlocks; 1193 VA_LIST args; 1194 EFI_LBA StartingLba; 1195 UINTN NumOfLba; 1196 EFI_STATUS Status; 1197 1198 FwhInstance = NULL; 1199 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1200 1201 Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ()); 1202 ASSERT_EFI_ERROR (Status); 1203 1204 NumOfBlocks = FwhInstance->NumOfBlocks; 1205 1206 VA_START (args, This); 1207 1208 do { 1209 StartingLba = VA_ARG (args, EFI_LBA); 1210 if (StartingLba == EFI_LBA_LIST_TERMINATOR) { 1211 break; 1212 } 1213 1214 NumOfLba = VA_ARG (args, UINT32); 1215 1216 // 1217 // Check input parameters 1218 // 1219 if (NumOfLba == 0) { 1220 VA_END (args); 1221 return EFI_INVALID_PARAMETER; 1222 } 1223 1224 if ((StartingLba + NumOfLba) > NumOfBlocks) { 1225 return EFI_INVALID_PARAMETER; 1226 } 1227 } while (TRUE); 1228 1229 VA_END (args); 1230 1231 VA_START (args, This); 1232 do { 1233 StartingLba = VA_ARG (args, EFI_LBA); 1234 if (StartingLba == EFI_LBA_LIST_TERMINATOR) { 1235 break; 1236 } 1237 1238 NumOfLba = VA_ARG (args, UINT32); 1239 1240 while (NumOfLba > 0) { 1241 Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ()); 1242 if (EFI_ERROR (Status)) { 1243 VA_END (args); 1244 return Status; 1245 } 1246 1247 StartingLba++; 1248 NumOfLba--; 1249 } 1250 1251 } while (TRUE); 1252 1253 VA_END (args); 1254 1255 return EFI_SUCCESS; 1256 } 1257 1258 EFI_STATUS 1259 EFIAPI 1260 FvbProtocolWrite ( 1261 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1262 IN EFI_LBA Lba, 1263 IN UINTN Offset, 1264 IN OUT UINTN *NumBytes, 1265 IN UINT8 *Buffer 1266 ) 1267 /*++ 1268 1269 Routine Description: 1270 1271 Writes data beginning at Lba:Offset from FV. The write terminates either 1272 when *NumBytes of data have been written, or when a block boundary is 1273 reached. *NumBytes is updated to reflect the actual number of bytes 1274 written. The write opertion does not include erase. This routine will 1275 attempt to write only the specified bytes. If the writes do not stick, 1276 it will return an error. 1277 1278 Arguments: 1279 This - Calling context 1280 Lba - Block in which to begin write 1281 Offset - Offset in the block at which to begin write 1282 NumBytes - On input, indicates the requested write size. On 1283 output, indicates the actual number of bytes written 1284 Buffer - Buffer containing source data for the write. 1285 1286 Returns: 1287 EFI_SUCCESS - The firmware volume was written successfully 1288 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, 1289 NumBytes contains the total number of bytes 1290 actually written 1291 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 1292 EFI_DEVICE_ERROR - The block device is not functioning correctly and 1293 could not be written 1294 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL 1295 1296 --*/ 1297 { 1298 1299 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1300 1301 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1302 1303 return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); 1304 } 1305 1306 EFI_STATUS 1307 EFIAPI 1308 FvbProtocolRead ( 1309 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1310 IN EFI_LBA Lba, 1311 IN UINTN Offset, 1312 IN OUT UINTN *NumBytes, 1313 IN UINT8 *Buffer 1314 ) 1315 /*++ 1316 1317 Routine Description: 1318 1319 Reads data beginning at Lba:Offset from FV. The Read terminates either 1320 when *NumBytes of data have been read, or when a block boundary is 1321 reached. *NumBytes is updated to reflect the actual number of bytes 1322 written. The write opertion does not include erase. This routine will 1323 attempt to write only the specified bytes. If the writes do not stick, 1324 it will return an error. 1325 1326 Arguments: 1327 This - Calling context 1328 Lba - Block in which to begin Read 1329 Offset - Offset in the block at which to begin Read 1330 NumBytes - On input, indicates the requested write size. On 1331 output, indicates the actual number of bytes Read 1332 Buffer - Buffer containing source data for the Read. 1333 1334 Returns: 1335 EFI_SUCCESS - The firmware volume was read successfully and 1336 contents are in Buffer 1337 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, 1338 NumBytes contains the total number of bytes returned 1339 in Buffer 1340 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state 1341 EFI_DEVICE_ERROR - The block device is not functioning correctly and 1342 could not be read 1343 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL 1344 1345 --*/ 1346 { 1347 1348 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1349 EFI_STATUS Status; 1350 1351 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1352 Status = FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); 1353 1354 return Status; 1355 } 1356 1357 EFI_STATUS 1358 ValidateFvHeader ( 1359 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader 1360 ) 1361 /*++ 1362 1363 Routine Description: 1364 Check the integrity of firmware volume header 1365 1366 Arguments: 1367 FwVolHeader - A pointer to a firmware volume header 1368 1369 Returns: 1370 EFI_SUCCESS - The firmware volume is consistent 1371 EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an FV 1372 1373 --*/ 1374 { 1375 UINT16 *Ptr; 1376 UINT16 HeaderLength; 1377 UINT16 Checksum; 1378 1379 // 1380 // Verify the header revision, header signature, length 1381 // Length of FvBlock cannot be 2**64-1 1382 // HeaderLength cannot be an odd number 1383 // 1384 #ifndef R864_BUILD 1385 if (((FwVolHeader->Revision != EFI_FVH_REVISION) && (FwVolHeader->Revision != EFI_FVH_REVISION)) || 1386 #else 1387 if ((FwVolHeader->Revision != EFI_FVH_REVISION) || 1388 #endif 1389 (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || 1390 (FwVolHeader->FvLength == ((UINTN) -1)) || 1391 ((FwVolHeader->HeaderLength & 0x01) != 0) 1392 ) { 1393 return EFI_NOT_FOUND; 1394 } 1395 // 1396 // Verify the header checksum 1397 // 1398 HeaderLength = (UINT16) (FwVolHeader->HeaderLength / 2); 1399 Ptr = (UINT16 *) FwVolHeader; 1400 Checksum = 0; 1401 while (HeaderLength > 0) { 1402 Checksum = Checksum + (*Ptr); 1403 Ptr++; 1404 HeaderLength--; 1405 } 1406 1407 if (Checksum != 0) { 1408 return EFI_NOT_FOUND; 1409 } 1410 1411 return EFI_SUCCESS; 1412 } 1413 1414 EFI_STATUS 1415 GetFvbHeader ( 1416 VOID **HobList, 1417 OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader, 1418 OUT EFI_PHYSICAL_ADDRESS *BaseAddress, 1419 OUT BOOLEAN *WriteBack 1420 ) 1421 { 1422 EFI_STATUS Status; 1423 1424 Status = EFI_SUCCESS; 1425 *WriteBack = FALSE; 1426 1427 if (*FwVolHeader == NULL) { 1428 *BaseAddress = PcdGet32 (PcdFlashFvRecoveryBase); 1429 } else if (*FwVolHeader == (VOID *)(UINTN)PcdGet32 (PcdFlashFvRecoveryBase)) { 1430 *BaseAddress = PcdGet32 (PcdFlashFvMainBase); 1431 } else if (*FwVolHeader == (VOID *)(UINTN)PcdGet32 (PcdFlashFvMainBase)) { 1432 *BaseAddress = PcdGet32 (PcdFlashNvStorageVariableBase); 1433 } else { 1434 return EFI_NOT_FOUND; 1435 } 1436 1437 DEBUG((EFI_D_INFO, "Fvb base : %08x\n",*BaseAddress)); 1438 1439 *FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (*BaseAddress); 1440 Status = ValidateFvHeader (*FwVolHeader); 1441 if (EFI_ERROR (Status)) { 1442 // 1443 // Get FvbInfo 1444 // 1445 *WriteBack = TRUE; 1446 1447 Status = GetFvbInfo (*BaseAddress, FwVolHeader); 1448 DEBUG(( DEBUG_ERROR, "Through GetFvbInfo: %08x!\n",*BaseAddress)); 1449 1450 ASSERT_EFI_ERROR (Status); 1451 } 1452 1453 return EFI_SUCCESS; 1454 } 1455 1456 1457 EFI_STATUS 1458 SmmSpiInit ( 1459 VOID 1460 ) 1461 { 1462 UINT8 SpiStatus; 1463 UINT8 FlashIndex; 1464 UINT8 FlashID[3]; 1465 EFI_STATUS Status; 1466 1467 // 1468 // Obtain a handle for ICH SPI Protocol 1469 // 1470 ASSERT(mSmst != NULL); 1471 if (mFvbModuleGlobal->SmmSpiProtocol == NULL){ 1472 Status = mSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SmmSpiProtocol); 1473 ASSERT_EFI_ERROR(Status); 1474 } 1475 // 1476 // attempt to identify flash part and initialize spi table 1477 // 1478 for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) { 1479 Status = mFvbModuleGlobal->SmmSpiProtocol->Init ( 1480 mFvbModuleGlobal->SmmSpiProtocol, 1481 &(mSpiInitTable[FlashIndex]) 1482 ); 1483 if (!EFI_ERROR (Status)) { 1484 // 1485 // read vendor/device IDs to check if flash device is supported 1486 // 1487 Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 1488 mFvbModuleGlobal->SmmSpiProtocol, 1489 SPI_OPCODE_JEDEC_ID_INDEX, 1490 SPI_WREN_INDEX, 1491 TRUE, 1492 FALSE, 1493 FALSE, 1494 0, 1495 3, 1496 FlashID, 1497 EnumSpiRegionAll 1498 ); 1499 if (!EFI_ERROR (Status)) { 1500 if (((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1501 (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1)) || 1502 ((FlashID[0] == SPI_AT26DF321_ID1) && 1503 (FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1504 (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0))) { 1505 // 1506 // Supported SPI device found 1507 // 1508 DEBUG ( 1509 ((EFI_D_INFO), 1510 "Smm Mode: Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1511 FlashID[0], 1512 FlashID[1], 1513 FlashID[2]) 1514 ); 1515 break; 1516 } 1517 } 1518 } 1519 } 1520 1521 if (FlashIndex >= EnumSpiFlashMax) { 1522 Status = EFI_UNSUPPORTED; 1523 DEBUG ( 1524 (EFI_D_ERROR, 1525 "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1526 FlashID[0], 1527 FlashID[1], 1528 FlashID[2]) 1529 ); 1530 ASSERT_EFI_ERROR (Status); 1531 } 1532 1533 SpiStatus = 0; 1534 Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 1535 mFvbModuleGlobal->SmmSpiProtocol, 1536 SPI_OPCODE_WRITE_S_INDEX, // OpcodeIndex 1537 1, // PrefixOpcodeIndex 1538 TRUE, // DataCycle 1539 TRUE, // Atomic 1540 TRUE, // ShiftOut 1541 0, // Address 1542 1, // Data Number 1543 &SpiStatus, 1544 EnumSpiRegionAll // SPI_REGION_TYPE 1545 ); 1546 return Status; 1547 } 1548 1549 EFI_STATUS 1550 SmmSpiNotificationFunction ( 1551 IN CONST EFI_GUID *Protocol, 1552 IN VOID *Interface, 1553 IN EFI_HANDLE Handle 1554 ) 1555 { 1556 return SmmSpiInit(); 1557 } 1558 1559 1560 VOID 1561 EFIAPI 1562 GetFullDriverPath ( 1563 IN EFI_HANDLE ImageHandle, 1564 IN EFI_SYSTEM_TABLE *SystemTable, 1565 OUT EFI_DEVICE_PATH_PROTOCOL **CompleteFilePath 1566 ) 1567 /*++ 1568 1569 Routine Description: 1570 1571 Function is used to get the full device path for this driver. 1572 1573 Arguments: 1574 1575 ImageHandle - The loaded image handle of this driver. 1576 SystemTable - The pointer of system table. 1577 CompleteFilePath - The pointer of returned full file path 1578 1579 Returns: 1580 1581 none 1582 1583 --*/ 1584 { 1585 EFI_STATUS Status; 1586 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; 1587 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; 1588 1589 1590 Status = gBS->HandleProtocol ( 1591 ImageHandle, 1592 &gEfiLoadedImageProtocolGuid, 1593 (VOID **) &LoadedImage 1594 ); 1595 ASSERT_EFI_ERROR (Status); 1596 1597 Status = gBS->HandleProtocol ( 1598 LoadedImage->DeviceHandle, 1599 &gEfiDevicePathProtocolGuid, 1600 (VOID *) &ImageDevicePath 1601 ); 1602 ASSERT_EFI_ERROR (Status); 1603 1604 *CompleteFilePath = AppendDevicePath ( 1605 ImageDevicePath, 1606 LoadedImage->FilePath 1607 ); 1608 1609 return ; 1610 } 1611 1612 1613 1614 EFI_STATUS 1615 FvbInitialize ( 1616 IN EFI_HANDLE ImageHandle, 1617 IN EFI_SYSTEM_TABLE *SystemTable 1618 ) 1619 /*++ 1620 1621 Routine Description: 1622 This function does common initialization for FVB services 1623 1624 Arguments: 1625 1626 Returns: 1627 1628 --*/ 1629 { 1630 EFI_STATUS Status; 1631 EFI_FW_VOL_INSTANCE *FwhInstance; 1632 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; 1633 EFI_FIRMWARE_VOLUME_HEADER *TempFwVolHeader; 1634 VOID *HobList; 1635 VOID *FirmwareVolumeHobList; 1636 UINT32 BufferSize; 1637 EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; 1638 BOOLEAN WriteEnabled; 1639 BOOLEAN WriteLocked; 1640 EFI_HANDLE FwbHandle; 1641 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1642 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; 1643 EFI_DEVICE_PATH_PROTOCOL *FwbDevicePath; 1644 EFI_DEVICE_PATH_PROTOCOL *TempFwbDevicePath; 1645 UINT32 MaxLbaSize; 1646 EFI_PHYSICAL_ADDRESS BaseAddress; 1647 BOOLEAN WriteBack; 1648 UINTN NumOfBlocks; 1649 UINTN HeaderLength; 1650 UINT8 SpiStatus; 1651 UINT8 FlashIndex; 1652 UINT8 FlashID[3]; 1653 EFI_DEVICE_PATH_PROTOCOL *CompleteFilePath; 1654 UINT8 PrefixOpcodeIndex; 1655 BOOLEAN InSmm; 1656 EFI_SMM_BASE2_PROTOCOL *mSmmBase2; 1657 EFI_HANDLE Handle; 1658 1659 VOID *Registration; 1660 EFI_EVENT Event; 1661 1662 CompleteFilePath = NULL; 1663 GetFullDriverPath (ImageHandle, SystemTable, &CompleteFilePath); 1664 1665 Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList); 1666 1667 // 1668 // No FV HOBs found 1669 // 1670 ASSERT_EFI_ERROR (Status); 1671 1672 1673 // 1674 // Allocate runtime services data for global variable, which contains 1675 // the private data of all firmware volume block instances 1676 // 1677 mFvbModuleGlobal = (ESAL_FWB_GLOBAL *)AllocateRuntimeZeroPool(sizeof (ESAL_FWB_GLOBAL )); 1678 ASSERT(mFvbModuleGlobal); 1679 mSmmBase2 = NULL; 1680 Status = gBS->LocateProtocol ( 1681 &gEfiSmmBase2ProtocolGuid, 1682 NULL, 1683 (VOID **) &mSmmBase2 1684 ); 1685 1686 if (mSmmBase2 == NULL) { 1687 InSmm = FALSE; 1688 } else { 1689 mSmmBase2->InSmm (mSmmBase2, &InSmm); 1690 mSmmBase2->GetSmstLocation (mSmmBase2, &mSmst); 1691 1692 } 1693 1694 if (!InSmm) { 1695 mInSmmMode = 0; 1696 // 1697 // Obtain a handle for ICH SPI Protocol 1698 // 1699 Status = gBS->LocateProtocol (&gEfiSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SpiProtocol); 1700 ASSERT_EFI_ERROR (Status); 1701 1702 // 1703 // attempt to identify flash part and initialize spi table 1704 // 1705 for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) { 1706 Status = mFvbModuleGlobal->SpiProtocol->Init ( 1707 mFvbModuleGlobal->SpiProtocol, 1708 &(mSpiInitTable[FlashIndex]) 1709 ); 1710 if (!EFI_ERROR (Status)) { 1711 // 1712 // read vendor/device IDs to check if flash device is supported 1713 // 1714 Status = mFvbModuleGlobal->SpiProtocol->Execute ( 1715 mFvbModuleGlobal->SpiProtocol, 1716 SPI_OPCODE_JEDEC_ID_INDEX, 1717 SPI_WREN_INDEX, 1718 TRUE, 1719 FALSE, 1720 FALSE, 1721 0, 1722 3, 1723 FlashID, 1724 EnumSpiRegionAll 1725 ); 1726 if (!EFI_ERROR (Status)) { 1727 if (((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1728 (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1)) || 1729 ((FlashID[0] == SPI_AT26DF321_ID1) && 1730 (FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1731 (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0))) { 1732 // 1733 // Supported SPI device found 1734 // 1735 DEBUG ( 1736 ((EFI_D_INFO), 1737 "Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1738 FlashID[0], 1739 FlashID[1], 1740 FlashID[2]) 1741 ); 1742 1743 PublishFlashDeviceInfo (&mSpiInitTable[FlashIndex]); 1744 break; 1745 } 1746 } 1747 } 1748 } 1749 1750 if (FlashIndex >= EnumSpiFlashMax) { 1751 Status = EFI_UNSUPPORTED; 1752 DEBUG ( 1753 (DEBUG_ERROR, 1754 "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1755 FlashID[0], 1756 FlashID[1], 1757 FlashID[2]) 1758 ); 1759 ASSERT_EFI_ERROR (Status); 1760 } 1761 1762 // 1763 // Unlock all regions by writing to status register 1764 // This could be SPI device specific, need to follow the datasheet 1765 // To write to Write Status Register the Spi PrefixOpcode needs to be: 1766 // 0 for Atmel parts 1767 // 0 for Intel parts 1768 // 0 for Macronix parts 1769 // 0 for Winbond parts 1770 // 1 for SST parts 1771 SpiStatus = 0; 1772 if (FlashID[0] == SPI_SST25VF016B_ID1) { 1773 PrefixOpcodeIndex = 1; 1774 } else { 1775 PrefixOpcodeIndex = 0; 1776 } 1777 Status = mFvbModuleGlobal->SpiProtocol->Execute ( 1778 mFvbModuleGlobal->SpiProtocol, 1779 SPI_OPCODE_WRITE_S_INDEX, // OpcodeIndex 1780 PrefixOpcodeIndex, // PrefixOpcodeIndex 1781 TRUE, // DataCycle 1782 TRUE, // Atomic 1783 TRUE, // ShiftOut 1784 0, // Address 1785 1, // Data Number 1786 &SpiStatus, 1787 EnumSpiRegionAll // SPI_REGION_TYPE 1788 ); 1789 1790 1791 } else { 1792 mInSmmMode = 1; 1793 1794 Status = mSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SmmSpiProtocol); 1795 if (EFI_ERROR(Status)) { 1796 Registration = NULL; 1797 Status = mSmst->SmmRegisterProtocolNotify ( 1798 &gEfiSmmSpiProtocolGuid, 1799 SmmSpiNotificationFunction, 1800 &Registration 1801 ); 1802 } else { 1803 Status = SmmSpiInit(); 1804 } 1805 1806 } 1807 1808 // 1809 // Calculate the total size for all firmware volume block instances 1810 // 1811 BufferSize = 0; 1812 FirmwareVolumeHobList = HobList; 1813 FwVolHeader = NULL; 1814 do { 1815 Status = GetFvbHeader (&FirmwareVolumeHobList, &FwVolHeader, &BaseAddress, &WriteBack); 1816 if (EFI_ERROR (Status)) { 1817 break; 1818 } 1819 1820 if (FwVolHeader) { 1821 BufferSize += (FwVolHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)); 1822 } 1823 } while (TRUE); 1824 1825 // 1826 // Only need to allocate once. There is only one copy of physical memory for 1827 // the private data of each FV instance. But in virtual mode or in physical 1828 // mode, the address of the the physical memory may be different. 1829 // 1830 mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] = (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize); 1831 ASSERT(mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]); 1832 // 1833 // Make a virtual copy of the FvInstance pointer. 1834 // 1835 FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; 1836 mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance; 1837 1838 mFvbModuleGlobal->NumFv = 0; 1839 FirmwareVolumeHobList = HobList; 1840 TempFwVolHeader = NULL; 1841 1842 MaxLbaSize = 0; 1843 1844 // 1845 // Fill in the private data of each firmware volume block instance 1846 // 1847 // Foreach Fv HOB in the FirmwareVolumeHobList, loop 1848 // 1849 do { 1850 Status = GetFvbHeader (&FirmwareVolumeHobList, &TempFwVolHeader, &BaseAddress, &WriteBack); 1851 if (EFI_ERROR (Status)) { 1852 break; 1853 } 1854 FwVolHeader = TempFwVolHeader; 1855 1856 if (!FwVolHeader) { 1857 continue; 1858 } 1859 1860 1861 CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength); 1862 FwVolHeader = &(FwhInstance->VolumeHeader); 1863 1864 FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress; 1865 FwhInstance->FvBase[FVB_VIRTUAL] = (UINTN) BaseAddress; 1866 1867 // 1868 // FwhInstance->FvWriteBase may not be the same as FwhInstance->FvBase 1869 // 1870 FwhInstance->FvWriteBase[FVB_PHYSICAL] = (UINTN) BaseAddress; 1871 WriteEnabled = TRUE; 1872 1873 // 1874 // Every pointer should have a virtual copy. 1875 // 1876 FwhInstance->FvWriteBase[FVB_VIRTUAL] = FwhInstance->FvWriteBase[FVB_PHYSICAL]; 1877 1878 FwhInstance->WriteEnabled = WriteEnabled; 1879 EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL); 1880 1881 NumOfBlocks = 0; 1882 WriteLocked = FALSE; 1883 1884 if (WriteEnabled) { 1885 for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { 1886 // 1887 // Get the maximum size of a block. The size will be used to allocate 1888 // buffer for Scratch space, the intermediate buffer for FVB extension 1889 // protocol 1890 // 1891 if (MaxLbaSize < PtrBlockMapEntry->Length) { 1892 MaxLbaSize = PtrBlockMapEntry->Length; 1893 } 1894 1895 NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks; 1896 } 1897 // 1898 // Write back a healthy FV header 1899 // 1900 if (WriteBack && (!WriteLocked)) { 1901 1902 Status = FlashFdErase ( 1903 (UINTN) FwhInstance->FvWriteBase[0], 1904 (UINTN) BaseAddress, 1905 FwVolHeader->BlockMap->Length 1906 ); 1907 1908 HeaderLength = (UINTN) FwVolHeader->HeaderLength; 1909 Status = FlashFdWrite ( 1910 (UINTN) FwhInstance->FvWriteBase[0], 1911 (UINTN) BaseAddress, 1912 &HeaderLength, 1913 (UINT8 *) FwVolHeader, 1914 FwVolHeader->BlockMap->Length 1915 ); 1916 1917 } 1918 } 1919 // 1920 // The total number of blocks in the FV. 1921 // 1922 FwhInstance->NumOfBlocks = NumOfBlocks; 1923 1924 // 1925 // If the FV is write locked, set the appropriate attributes 1926 // 1927 if (WriteLocked) { 1928 // 1929 // write disabled 1930 // 1931 FwhInstance->VolumeHeader.Attributes &= ~EFI_FVB2_WRITE_STATUS; 1932 // 1933 // lock enabled 1934 // 1935 FwhInstance->VolumeHeader.Attributes |= EFI_FVB2_LOCK_STATUS; 1936 } 1937 1938 // 1939 // Allocate and initialize FVB Device in a runtime data buffer 1940 // 1941 FvbDevice = AllocateRuntimeCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFvbDeviceTemplate); 1942 ASSERT (FvbDevice); 1943 1944 FvbDevice->Instance = mFvbModuleGlobal->NumFv; 1945 mFvbModuleGlobal->NumFv++; 1946 1947 // 1948 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH 1949 // 1950 if (FwVolHeader->ExtHeaderOffset == 0) { 1951 FvbDevice->FvDevicePath.MemMapDevPath.StartingAddress = BaseAddress; 1952 FvbDevice->FvDevicePath.MemMapDevPath.EndingAddress = BaseAddress + (FwVolHeader->FvLength - 1); 1953 FwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&FvbDevice->FvDevicePath; 1954 } else { 1955 CopyGuid ( 1956 &FvbDevice->UefiFvDevicePath.FvDevPath.FvName, 1957 (EFI_GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset) 1958 ); 1959 FwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&FvbDevice->UefiFvDevicePath; 1960 } 1961 1962 if (!InSmm) { 1963 // 1964 // Find a handle with a matching device path that has supports FW Block protocol 1965 // 1966 TempFwbDevicePath = FwbDevicePath; 1967 Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle); 1968 if (EFI_ERROR (Status)) { 1969 // 1970 // LocateDevicePath fails so install a new interface and device path 1971 // 1972 FwbHandle = NULL; 1973 Status = gBS->InstallMultipleProtocolInterfaces ( 1974 &FwbHandle, 1975 &gEfiFirmwareVolumeBlockProtocolGuid, 1976 &FvbDevice->FwVolBlockInstance, 1977 &gEfiDevicePathProtocolGuid, 1978 FwbDevicePath, 1979 NULL 1980 ); 1981 ASSERT_EFI_ERROR (Status); 1982 } else if (EfiIsDevicePathEnd (TempFwbDevicePath)) { 1983 // 1984 // Device already exists, so reinstall the FVB protocol 1985 // 1986 Status = gBS->HandleProtocol ( 1987 FwbHandle, 1988 &gEfiFirmwareVolumeBlockProtocolGuid, 1989 (VOID **) &OldFwbInterface 1990 ); 1991 ASSERT_EFI_ERROR (Status); 1992 1993 Status = gBS->ReinstallProtocolInterface ( 1994 FwbHandle, 1995 &gEfiFirmwareVolumeBlockProtocolGuid, 1996 OldFwbInterface, 1997 &FvbDevice->FwVolBlockInstance 1998 ); 1999 ASSERT_EFI_ERROR (Status); 2000 2001 } else { 2002 // 2003 // There was a FVB protocol on an End Device Path node 2004 // 2005 ASSERT (FALSE); 2006 } 2007 } else { 2008 FwbHandle = NULL; 2009 Status = mSmst->SmmInstallProtocolInterface ( 2010 &FwbHandle, 2011 &gEfiSmmFirmwareVolumeBlockProtocolGuid, 2012 EFI_NATIVE_INTERFACE, 2013 &FvbDevice->FwVolBlockInstance 2014 ); 2015 ASSERT_EFI_ERROR (Status); 2016 } 2017 2018 FwhInstance = (EFI_FW_VOL_INSTANCE *) 2019 ( 2020 (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + 2021 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) 2022 ); 2023 } while (TRUE); 2024 2025 // 2026 // Allocate for scratch space, an intermediate buffer for FVB extention 2027 // 2028 2029 mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL] = AllocateRuntimeZeroPool (MaxLbaSize); 2030 2031 ASSERT (mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]); 2032 2033 mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL] = mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]; 2034 2035 if (!InSmm) { 2036 Status = gBS->CreateEventEx ( 2037 EVT_NOTIFY_SIGNAL, 2038 TPL_NOTIFY, 2039 FvbVirtualddressChangeEvent, 2040 NULL, 2041 &gEfiEventVirtualAddressChangeGuid, 2042 &Event 2043 ); 2044 ASSERT_EFI_ERROR (Status); 2045 } else { 2046 // 2047 // Inform other platform drivers that SPI device discovered and 2048 // SPI interface ready for use. 2049 // 2050 Handle = NULL; 2051 Status = gBS->InstallProtocolInterface ( 2052 &Handle, 2053 &gEfiSmmSpiReadyProtocolGuid, 2054 EFI_NATIVE_INTERFACE, 2055 NULL 2056 ); 2057 } 2058 return EFI_SUCCESS; 2059 } 2060