1 /** @file 2 3 Copyright (c) 2013-2015 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 UINTN NumBytes; 594 595 NumBytes = LbaLength; 596 597 WriteAddress -= (PcdGet32 (PcdFlashAreaBaseAddress)); 598 if (mInSmmMode == 0 ) { // !(EfiInManagementInterrupt ())) { 599 Status = mFvbModuleGlobal->SpiProtocol->Execute ( 600 mFvbModuleGlobal->SpiProtocol, 601 SPI_OPCODE_ERASE_INDEX, // OpcodeIndex 602 0, // PrefixOpcodeIndex 603 FALSE, // DataCycle 604 TRUE, // Atomic 605 FALSE, // ShiftOut 606 WriteAddress, // Address 607 0, // Data Number 608 NULL, 609 EnumSpiRegionBios // SPI_REGION_TYPE 610 ); 611 } else { 612 Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 613 mFvbModuleGlobal->SmmSpiProtocol, 614 SPI_OPCODE_ERASE_INDEX, // OpcodeIndex 615 0, // PrefixOpcodeIndex 616 FALSE, // DataCycle 617 TRUE, // Atomic 618 FALSE, // ShiftOut 619 WriteAddress, // Address 620 0, // Data Number 621 NULL, 622 EnumSpiRegionBios // SPI_REGION_TYPE 623 ); 624 } 625 626 AsmWbinvd (); 627 628 return Status; 629 } 630 631 EFI_STATUS 632 FvbWriteBlock ( 633 IN UINTN Instance, 634 IN EFI_LBA Lba, 635 IN UINTN BlockOffset, 636 IN OUT UINTN *NumBytes, 637 IN UINT8 *Buffer, 638 IN ESAL_FWB_GLOBAL *Global, 639 IN BOOLEAN Virtual 640 ) 641 /*++ 642 643 Routine Description: 644 Writes specified number of bytes from the input buffer to the block 645 646 Arguments: 647 Instance - The FV instance to be written to 648 Lba - The starting logical block index to write to 649 BlockOffset - Offset into the block at which to begin writing 650 NumBytes - Pointer that on input contains the total size of 651 the buffer. On output, it contains the total number 652 of bytes actually written 653 Buffer - Pointer to a caller allocated buffer that contains 654 the source for the write 655 Global - Pointer to ESAL_FWB_GLOBAL that contains all 656 instance data 657 Virtual - Whether CPU is in virtual or physical mode 658 659 Returns: 660 EFI_SUCCESS - The firmware volume was written successfully 661 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, 662 NumBytes contains the total number of bytes 663 actually written 664 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 665 EFI_DEVICE_ERROR - The block device is not functioning correctly and 666 could not be written 667 EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL 668 669 --*/ 670 { 671 EFI_FVB_ATTRIBUTES_2 Attributes; 672 UINTN LbaAddress; 673 UINTN LbaWriteAddress; 674 UINTN LbaLength; 675 EFI_FW_VOL_INSTANCE *FwhInstance; 676 EFI_STATUS Status; 677 EFI_STATUS ReturnStatus; 678 679 FwhInstance = NULL; 680 681 // 682 // Find the right instance of the FVB private data 683 // 684 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 685 ASSERT_EFI_ERROR (Status); 686 687 // 688 // Writes are enabled in the init routine itself 689 // 690 if (!FwhInstance->WriteEnabled) { 691 return EFI_ACCESS_DENIED; 692 } 693 // 694 // Check for invalid conditions 695 // 696 if ((NumBytes == NULL) || (Buffer == NULL)) { 697 return EFI_INVALID_PARAMETER; 698 } 699 700 if (*NumBytes == 0) { 701 return EFI_INVALID_PARAMETER; 702 } 703 704 Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual); 705 if (EFI_ERROR (Status)) { 706 return Status; 707 } 708 // 709 // Check if the FV is write enabled 710 // 711 FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 712 713 if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { 714 return EFI_ACCESS_DENIED; 715 } 716 // 717 // Perform boundary checks and adjust NumBytes 718 // 719 if (BlockOffset > LbaLength) { 720 return EFI_INVALID_PARAMETER; 721 } 722 723 if (LbaLength < (*NumBytes + BlockOffset)) { 724 *NumBytes = (UINT32) (LbaLength - BlockOffset); 725 Status = EFI_BAD_BUFFER_SIZE; 726 } 727 728 ReturnStatus = FlashFdWrite ( 729 LbaWriteAddress + BlockOffset, 730 LbaAddress, 731 NumBytes, 732 Buffer, 733 LbaLength 734 ); 735 if (EFI_ERROR (ReturnStatus)) { 736 return ReturnStatus; 737 } 738 739 return Status; 740 } 741 742 EFI_STATUS 743 FvbEraseBlock ( 744 IN UINTN Instance, 745 IN EFI_LBA Lba, 746 IN ESAL_FWB_GLOBAL *Global, 747 IN BOOLEAN Virtual 748 ) 749 /*++ 750 751 Routine Description: 752 Erases and initializes a firmware volume block 753 754 Arguments: 755 Instance - The FV instance to be erased 756 Lba - The logical block index to be erased 757 Global - Pointer to ESAL_FWB_GLOBAL that contains all 758 instance data 759 Virtual - Whether CPU is in virtual or physical mode 760 761 Returns: 762 EFI_SUCCESS - The erase request was successfully completed 763 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 764 EFI_DEVICE_ERROR - The block device is not functioning correctly and 765 could not be written. Firmware device may have been 766 partially erased 767 EFI_INVALID_PARAMETER - Instance not found 768 769 --*/ 770 { 771 772 EFI_FVB_ATTRIBUTES_2 Attributes; 773 UINTN LbaAddress; 774 UINTN LbaWriteAddress; 775 EFI_FW_VOL_INSTANCE *FwhInstance; 776 UINTN LbaLength; 777 EFI_STATUS Status; 778 UINTN SectorNum; 779 UINTN Index; 780 781 FwhInstance = NULL; 782 783 // 784 // Find the right instance of the FVB private data 785 // 786 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 787 ASSERT_EFI_ERROR (Status); 788 789 // 790 // Writes are enabled in the init routine itself 791 // 792 if (!FwhInstance->WriteEnabled) { 793 return EFI_ACCESS_DENIED; 794 } 795 // 796 // Check if the FV is write enabled 797 // 798 FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 799 800 if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { 801 return EFI_ACCESS_DENIED; 802 } 803 // 804 // Get the starting address of the block for erase. For debug reasons, 805 // LbaWriteAddress may not be the same as LbaAddress. 806 // 807 Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual); 808 if (EFI_ERROR (Status)) { 809 return Status; 810 } 811 812 SectorNum = LbaLength / SPI_ERASE_SECTOR_SIZE; 813 for (Index = 0; Index < SectorNum; Index++){ 814 Status = FlashFdErase ( 815 LbaWriteAddress + Index * SPI_ERASE_SECTOR_SIZE, 816 LbaAddress, 817 SPI_ERASE_SECTOR_SIZE 818 ); 819 if (Status != EFI_SUCCESS){ 820 break; 821 } 822 } 823 824 return Status; 825 } 826 827 EFI_STATUS 828 FvbEraseCustomBlockRange ( 829 IN UINTN Instance, 830 IN EFI_LBA StartLba, 831 IN UINTN OffsetStartLba, 832 IN EFI_LBA LastLba, 833 IN UINTN OffsetLastLba, 834 IN ESAL_FWB_GLOBAL *Global, 835 IN BOOLEAN Virtual 836 ) 837 /*++ 838 839 Routine Description: 840 Erases and initializes a specified range of a firmware volume 841 842 Arguments: 843 Instance - The FV instance to be erased 844 StartLba - The starting logical block index to be erased 845 OffsetStartLba - Offset into the starting block at which to 846 begin erasing 847 LastLba - The last logical block index to be erased 848 OffsetStartLba - Offset into the last block at which to end erasing 849 Global - Pointer to ESAL_FWB_GLOBAL that contains all 850 instance data 851 Virtual - Whether CPU is in virtual or physical mode 852 853 Returns: 854 EFI_SUCCESS - The firmware volume was erased successfully 855 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 856 EFI_DEVICE_ERROR - The block device is not functioning correctly and 857 could not be written. Firmware device may have been 858 partially erased 859 EFI_INVALID_PARAMETER - Instance not found 860 861 --*/ 862 { 863 EFI_LBA Index; 864 UINTN LbaSize; 865 UINTN ScratchLbaSizeData; 866 867 // 868 // First LBA. 869 // 870 FvbGetLbaAddress (Instance, StartLba, NULL, NULL, &LbaSize, NULL, Global, Virtual); 871 872 // 873 // Use the scratch space as the intermediate buffer to transfer data 874 // Back up the first LBA in scratch space. 875 // 876 FvbReadBlock (Instance, StartLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual); 877 878 // 879 // erase now 880 // 881 FvbEraseBlock (Instance, StartLba, Global, Virtual); 882 ScratchLbaSizeData = OffsetStartLba; 883 884 // 885 // write the data back to the first block 886 // 887 if (ScratchLbaSizeData > 0) { 888 FvbWriteBlock (Instance, StartLba, 0, &ScratchLbaSizeData, Global->FvbScratchSpace[Virtual], Global, Virtual); 889 } 890 // 891 // Middle LBAs 892 // 893 if (LastLba > (StartLba + 1)) { 894 for (Index = (StartLba + 1); Index <= (LastLba - 1); Index++) { 895 FvbEraseBlock (Instance, Index, Global, Virtual); 896 } 897 } 898 // 899 // Last LBAs, the same as first LBAs 900 // 901 if (LastLba > StartLba) { 902 FvbGetLbaAddress (Instance, LastLba, NULL, NULL, &LbaSize, NULL, Global, Virtual); 903 FvbReadBlock (Instance, LastLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual); 904 FvbEraseBlock (Instance, LastLba, Global, Virtual); 905 } 906 907 ScratchLbaSizeData = LbaSize - (OffsetStartLba + 1); 908 909 return FvbWriteBlock ( 910 Instance, 911 LastLba, 912 (OffsetLastLba + 1), 913 &ScratchLbaSizeData, 914 Global->FvbScratchSpace[Virtual], 915 Global, 916 Virtual 917 ); 918 } 919 920 EFI_STATUS 921 FvbSetVolumeAttributes ( 922 IN UINTN Instance, 923 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes, 924 IN ESAL_FWB_GLOBAL *Global, 925 IN BOOLEAN Virtual 926 ) 927 /*++ 928 929 Routine Description: 930 Modifies the current settings of the firmware volume according to the 931 input parameter, and returns the new setting of the volume 932 933 Arguments: 934 Instance - The FV instance whose attributes is going to be 935 modified 936 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2 937 containing the desired firmware volume settings. 938 On successful return, it contains the new settings 939 of the firmware volume 940 Global - Pointer to ESAL_FWB_GLOBAL that contains all 941 instance data 942 Virtual - Whether CPU is in virtual or physical mode 943 944 Returns: 945 EFI_SUCCESS - Successfully returns 946 EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified 947 EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are 948 in conflict with the capabilities as declared in the 949 firmware volume header 950 951 --*/ 952 { 953 EFI_FW_VOL_INSTANCE *FwhInstance; 954 EFI_FVB_ATTRIBUTES_2 OldAttributes; 955 EFI_FVB_ATTRIBUTES_2 *AttribPtr; 956 UINT32 Capabilities; 957 UINT32 OldStatus; 958 UINT32 NewStatus; 959 EFI_STATUS Status; 960 961 FwhInstance = NULL; 962 963 // 964 // Find the right instance of the FVB private data 965 // 966 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 967 ASSERT_EFI_ERROR (Status); 968 969 AttribPtr = (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes); 970 OldAttributes = *AttribPtr; 971 Capabilities = OldAttributes & EFI_FVB2_CAPABILITIES; 972 OldStatus = OldAttributes & EFI_FVB2_STATUS; 973 NewStatus = *Attributes & EFI_FVB2_STATUS; 974 975 // 976 // If firmware volume is locked, no status bit can be updated 977 // 978 if (OldAttributes & EFI_FVB2_LOCK_STATUS) { 979 if (OldStatus ^ NewStatus) { 980 return EFI_ACCESS_DENIED; 981 } 982 } 983 // 984 // Test read disable 985 // 986 if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) { 987 if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) { 988 return EFI_INVALID_PARAMETER; 989 } 990 } 991 // 992 // Test read enable 993 // 994 if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) { 995 if (NewStatus & EFI_FVB2_READ_STATUS) { 996 return EFI_INVALID_PARAMETER; 997 } 998 } 999 // 1000 // Test write disable 1001 // 1002 if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) { 1003 if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) { 1004 return EFI_INVALID_PARAMETER; 1005 } 1006 } 1007 // 1008 // Test write enable 1009 // 1010 if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) { 1011 if (NewStatus & EFI_FVB2_WRITE_STATUS) { 1012 return EFI_INVALID_PARAMETER; 1013 } 1014 } 1015 // 1016 // Test lock 1017 // 1018 if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) { 1019 if (NewStatus & EFI_FVB2_LOCK_STATUS) { 1020 return EFI_INVALID_PARAMETER; 1021 } 1022 } 1023 1024 *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); 1025 *AttribPtr = (*AttribPtr) | NewStatus; 1026 *Attributes = *AttribPtr; 1027 1028 return EFI_SUCCESS; 1029 } 1030 // 1031 // FVB protocol APIs 1032 // 1033 EFI_STATUS 1034 EFIAPI 1035 FvbProtocolGetPhysicalAddress ( 1036 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1037 OUT EFI_PHYSICAL_ADDRESS *Address 1038 ) 1039 /*++ 1040 1041 Routine Description: 1042 1043 Retrieves the physical address of the device. 1044 1045 Arguments: 1046 1047 This - Calling context 1048 Address - Output buffer containing the address. 1049 1050 Returns: 1051 1052 Returns: 1053 EFI_SUCCESS - Successfully returns 1054 1055 --*/ 1056 { 1057 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1058 1059 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1060 1061 return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ()); 1062 } 1063 1064 EFI_STATUS 1065 FvbProtocolGetBlockSize ( 1066 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1067 IN EFI_LBA Lba, 1068 OUT UINTN *BlockSize, 1069 OUT UINTN *NumOfBlocks 1070 ) 1071 /*++ 1072 1073 Routine Description: 1074 Retrieve the size of a logical block 1075 1076 Arguments: 1077 This - Calling context 1078 Lba - Indicates which block to return the size for. 1079 BlockSize - A pointer to a caller allocated UINTN in which 1080 the size of the block is returned 1081 NumOfBlocks - a pointer to a caller allocated UINTN in which the 1082 number of consecutive blocks starting with Lba is 1083 returned. All blocks in this range have a size of 1084 BlockSize 1085 1086 Returns: 1087 EFI_SUCCESS - The firmware volume was read successfully and 1088 contents are in Buffer 1089 1090 --*/ 1091 { 1092 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1093 1094 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1095 1096 return FvbGetLbaAddress ( 1097 FvbDevice->Instance, 1098 Lba, 1099 NULL, 1100 NULL, 1101 BlockSize, 1102 NumOfBlocks, 1103 mFvbModuleGlobal, 1104 EfiGoneVirtual () 1105 ); 1106 } 1107 1108 EFI_STATUS 1109 EFIAPI 1110 FvbProtocolGetAttributes ( 1111 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1112 OUT EFI_FVB_ATTRIBUTES_2 *Attributes 1113 ) 1114 /*++ 1115 1116 Routine Description: 1117 Retrieves Volume attributes. No polarity translations are done. 1118 1119 Arguments: 1120 This - Calling context 1121 Attributes - output buffer which contains attributes 1122 1123 Returns: 1124 EFI_SUCCESS - Successfully returns 1125 1126 --*/ 1127 { 1128 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1129 1130 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1131 1132 return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); 1133 } 1134 1135 EFI_STATUS 1136 EFIAPI 1137 FvbProtocolSetAttributes ( 1138 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1139 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes 1140 ) 1141 /*++ 1142 1143 Routine Description: 1144 Sets Volume attributes. No polarity translations are done. 1145 1146 Arguments: 1147 This - Calling context 1148 Attributes - output buffer which contains attributes 1149 1150 Returns: 1151 EFI_SUCCESS - Successfully returns 1152 1153 --*/ 1154 { 1155 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1156 1157 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1158 1159 return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); 1160 } 1161 1162 EFI_STATUS 1163 EFIAPI 1164 FvbProtocolEraseBlocks ( 1165 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1166 ... 1167 ) 1168 /*++ 1169 1170 Routine Description: 1171 1172 The EraseBlock() function erases one or more blocks as denoted by the 1173 variable argument list. The entire parameter list of blocks must be verified 1174 prior to erasing any blocks. If a block is requested that does not exist 1175 within the associated firmware volume (it has a larger index than the last 1176 block of the firmware volume), the EraseBlock() function must return 1177 EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. 1178 1179 Arguments: 1180 This - Calling context 1181 ... - Starting LBA followed by Number of Lba to erase. 1182 a -1 to terminate the list. 1183 1184 Returns: 1185 EFI_SUCCESS - The erase request was successfully completed 1186 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 1187 EFI_DEVICE_ERROR - The block device is not functioning correctly and 1188 could not be written. Firmware device may have been 1189 partially erased 1190 1191 --*/ 1192 { 1193 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1194 EFI_FW_VOL_INSTANCE *FwhInstance; 1195 UINTN NumOfBlocks; 1196 VA_LIST args; 1197 EFI_LBA StartingLba; 1198 UINTN NumOfLba; 1199 EFI_STATUS Status; 1200 1201 FwhInstance = NULL; 1202 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1203 1204 Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ()); 1205 ASSERT_EFI_ERROR (Status); 1206 1207 NumOfBlocks = FwhInstance->NumOfBlocks; 1208 1209 VA_START (args, This); 1210 1211 do { 1212 StartingLba = VA_ARG (args, EFI_LBA); 1213 if (StartingLba == EFI_LBA_LIST_TERMINATOR) { 1214 break; 1215 } 1216 1217 NumOfLba = VA_ARG (args, UINT32); 1218 1219 // 1220 // Check input parameters 1221 // 1222 if (NumOfLba == 0) { 1223 VA_END (args); 1224 return EFI_INVALID_PARAMETER; 1225 } 1226 1227 if ((StartingLba + NumOfLba) > NumOfBlocks) { 1228 return EFI_INVALID_PARAMETER; 1229 } 1230 } while (TRUE); 1231 1232 VA_END (args); 1233 1234 VA_START (args, This); 1235 do { 1236 StartingLba = VA_ARG (args, EFI_LBA); 1237 if (StartingLba == EFI_LBA_LIST_TERMINATOR) { 1238 break; 1239 } 1240 1241 NumOfLba = VA_ARG (args, UINT32); 1242 1243 while (NumOfLba > 0) { 1244 Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ()); 1245 if (EFI_ERROR (Status)) { 1246 VA_END (args); 1247 return Status; 1248 } 1249 1250 StartingLba++; 1251 NumOfLba--; 1252 } 1253 1254 } while (TRUE); 1255 1256 VA_END (args); 1257 1258 return EFI_SUCCESS; 1259 } 1260 1261 EFI_STATUS 1262 EFIAPI 1263 FvbProtocolWrite ( 1264 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1265 IN EFI_LBA Lba, 1266 IN UINTN Offset, 1267 IN OUT UINTN *NumBytes, 1268 IN UINT8 *Buffer 1269 ) 1270 /*++ 1271 1272 Routine Description: 1273 1274 Writes data beginning at Lba:Offset from FV. The write terminates either 1275 when *NumBytes of data have been written, or when a block boundary is 1276 reached. *NumBytes is updated to reflect the actual number of bytes 1277 written. The write opertion does not include erase. This routine will 1278 attempt to write only the specified bytes. If the writes do not stick, 1279 it will return an error. 1280 1281 Arguments: 1282 This - Calling context 1283 Lba - Block in which to begin write 1284 Offset - Offset in the block at which to begin write 1285 NumBytes - On input, indicates the requested write size. On 1286 output, indicates the actual number of bytes written 1287 Buffer - Buffer containing source data for the write. 1288 1289 Returns: 1290 EFI_SUCCESS - The firmware volume was written successfully 1291 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, 1292 NumBytes contains the total number of bytes 1293 actually written 1294 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 1295 EFI_DEVICE_ERROR - The block device is not functioning correctly and 1296 could not be written 1297 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL 1298 1299 --*/ 1300 { 1301 1302 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1303 1304 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1305 1306 return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); 1307 } 1308 1309 EFI_STATUS 1310 EFIAPI 1311 FvbProtocolRead ( 1312 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1313 IN EFI_LBA Lba, 1314 IN UINTN Offset, 1315 IN OUT UINTN *NumBytes, 1316 IN UINT8 *Buffer 1317 ) 1318 /*++ 1319 1320 Routine Description: 1321 1322 Reads data beginning at Lba:Offset from FV. The Read terminates either 1323 when *NumBytes of data have been read, or when a block boundary is 1324 reached. *NumBytes is updated to reflect the actual number of bytes 1325 written. The write opertion does not include erase. This routine will 1326 attempt to write only the specified bytes. If the writes do not stick, 1327 it will return an error. 1328 1329 Arguments: 1330 This - Calling context 1331 Lba - Block in which to begin Read 1332 Offset - Offset in the block at which to begin Read 1333 NumBytes - On input, indicates the requested write size. On 1334 output, indicates the actual number of bytes Read 1335 Buffer - Buffer containing source data for the Read. 1336 1337 Returns: 1338 EFI_SUCCESS - The firmware volume was read successfully and 1339 contents are in Buffer 1340 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, 1341 NumBytes contains the total number of bytes returned 1342 in Buffer 1343 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state 1344 EFI_DEVICE_ERROR - The block device is not functioning correctly and 1345 could not be read 1346 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL 1347 1348 --*/ 1349 { 1350 1351 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1352 EFI_STATUS Status; 1353 1354 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1355 Status = FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); 1356 1357 return Status; 1358 } 1359 1360 EFI_STATUS 1361 ValidateFvHeader ( 1362 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader 1363 ) 1364 /*++ 1365 1366 Routine Description: 1367 Check the integrity of firmware volume header 1368 1369 Arguments: 1370 FwVolHeader - A pointer to a firmware volume header 1371 1372 Returns: 1373 EFI_SUCCESS - The firmware volume is consistent 1374 EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an FV 1375 1376 --*/ 1377 { 1378 UINT16 *Ptr; 1379 UINT16 HeaderLength; 1380 UINT16 Checksum; 1381 1382 // 1383 // Verify the header revision, header signature, length 1384 // Length of FvBlock cannot be 2**64-1 1385 // HeaderLength cannot be an odd number 1386 // 1387 #ifndef R864_BUILD 1388 if (((FwVolHeader->Revision != EFI_FVH_REVISION) && (FwVolHeader->Revision != EFI_FVH_REVISION)) || 1389 #else 1390 if ((FwVolHeader->Revision != EFI_FVH_REVISION) || 1391 #endif 1392 (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || 1393 (FwVolHeader->FvLength == ((UINTN) -1)) || 1394 ((FwVolHeader->HeaderLength & 0x01) != 0) 1395 ) { 1396 return EFI_NOT_FOUND; 1397 } 1398 // 1399 // Verify the header checksum 1400 // 1401 HeaderLength = (UINT16) (FwVolHeader->HeaderLength / 2); 1402 Ptr = (UINT16 *) FwVolHeader; 1403 Checksum = 0; 1404 while (HeaderLength > 0) { 1405 Checksum = Checksum + (*Ptr); 1406 Ptr++; 1407 HeaderLength--; 1408 } 1409 1410 if (Checksum != 0) { 1411 return EFI_NOT_FOUND; 1412 } 1413 1414 return EFI_SUCCESS; 1415 } 1416 1417 EFI_STATUS 1418 GetFvbHeader ( 1419 VOID **HobList, 1420 OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader, 1421 OUT EFI_PHYSICAL_ADDRESS *BaseAddress, 1422 OUT BOOLEAN *WriteBack 1423 ) 1424 { 1425 EFI_STATUS Status; 1426 1427 Status = EFI_SUCCESS; 1428 *WriteBack = FALSE; 1429 1430 if (*FwVolHeader == NULL) { 1431 *BaseAddress = PcdGet32 (PcdFlashFvRecoveryBase); 1432 } else if (*FwVolHeader == (VOID *)(UINTN)PcdGet32 (PcdFlashFvRecoveryBase)) { 1433 *BaseAddress = PcdGet32 (PcdFlashFvMainBase); 1434 } else if (*FwVolHeader == (VOID *)(UINTN)PcdGet32 (PcdFlashFvMainBase)) { 1435 *BaseAddress = PcdGet32 (PcdFlashNvStorageVariableBase); 1436 } else { 1437 return EFI_NOT_FOUND; 1438 } 1439 1440 DEBUG((EFI_D_INFO, "Fvb base : %08x\n",*BaseAddress)); 1441 1442 *FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (*BaseAddress); 1443 Status = ValidateFvHeader (*FwVolHeader); 1444 if (EFI_ERROR (Status)) { 1445 // 1446 // Get FvbInfo 1447 // 1448 *WriteBack = TRUE; 1449 1450 Status = GetFvbInfo (*BaseAddress, FwVolHeader); 1451 DEBUG(( DEBUG_ERROR, "Through GetFvbInfo: %08x!\n",*BaseAddress)); 1452 1453 ASSERT_EFI_ERROR (Status); 1454 } 1455 1456 return EFI_SUCCESS; 1457 } 1458 1459 1460 EFI_STATUS 1461 SmmSpiInit ( 1462 VOID 1463 ) 1464 { 1465 UINT8 SpiStatus; 1466 UINT8 FlashIndex; 1467 UINT8 FlashID[3]; 1468 EFI_STATUS Status; 1469 1470 // 1471 // Obtain a handle for ICH SPI Protocol 1472 // 1473 ASSERT(mSmst != NULL); 1474 if (mFvbModuleGlobal->SmmSpiProtocol == NULL){ 1475 Status = mSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SmmSpiProtocol); 1476 ASSERT_EFI_ERROR(Status); 1477 } 1478 // 1479 // attempt to identify flash part and initialize spi table 1480 // 1481 for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) { 1482 Status = mFvbModuleGlobal->SmmSpiProtocol->Init ( 1483 mFvbModuleGlobal->SmmSpiProtocol, 1484 &(mSpiInitTable[FlashIndex]) 1485 ); 1486 if (!EFI_ERROR (Status)) { 1487 // 1488 // read vendor/device IDs to check if flash device is supported 1489 // 1490 Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 1491 mFvbModuleGlobal->SmmSpiProtocol, 1492 SPI_OPCODE_JEDEC_ID_INDEX, 1493 SPI_WREN_INDEX, 1494 TRUE, 1495 FALSE, 1496 FALSE, 1497 0, 1498 3, 1499 FlashID, 1500 EnumSpiRegionAll 1501 ); 1502 if (!EFI_ERROR (Status)) { 1503 if (((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1504 (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1)) || 1505 ((FlashID[0] == SPI_AT26DF321_ID1) && 1506 (FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1507 (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0))) { 1508 // 1509 // Supported SPI device found 1510 // 1511 DEBUG ( 1512 ((EFI_D_INFO), 1513 "Smm Mode: Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1514 FlashID[0], 1515 FlashID[1], 1516 FlashID[2]) 1517 ); 1518 break; 1519 } 1520 } 1521 } 1522 } 1523 1524 if (FlashIndex >= EnumSpiFlashMax) { 1525 Status = EFI_UNSUPPORTED; 1526 DEBUG ( 1527 (EFI_D_ERROR, 1528 "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1529 FlashID[0], 1530 FlashID[1], 1531 FlashID[2]) 1532 ); 1533 ASSERT_EFI_ERROR (Status); 1534 } 1535 1536 SpiStatus = 0; 1537 Status = mFvbModuleGlobal->SmmSpiProtocol->Execute ( 1538 mFvbModuleGlobal->SmmSpiProtocol, 1539 SPI_OPCODE_WRITE_S_INDEX, // OpcodeIndex 1540 1, // PrefixOpcodeIndex 1541 TRUE, // DataCycle 1542 TRUE, // Atomic 1543 TRUE, // ShiftOut 1544 0, // Address 1545 1, // Data Number 1546 &SpiStatus, 1547 EnumSpiRegionAll // SPI_REGION_TYPE 1548 ); 1549 return Status; 1550 } 1551 1552 EFI_STATUS 1553 SmmSpiNotificationFunction ( 1554 IN CONST EFI_GUID *Protocol, 1555 IN VOID *Interface, 1556 IN EFI_HANDLE Handle 1557 ) 1558 { 1559 return SmmSpiInit(); 1560 } 1561 1562 1563 VOID 1564 EFIAPI 1565 GetFullDriverPath ( 1566 IN EFI_HANDLE ImageHandle, 1567 IN EFI_SYSTEM_TABLE *SystemTable, 1568 OUT EFI_DEVICE_PATH_PROTOCOL **CompleteFilePath 1569 ) 1570 /*++ 1571 1572 Routine Description: 1573 1574 Function is used to get the full device path for this driver. 1575 1576 Arguments: 1577 1578 ImageHandle - The loaded image handle of this driver. 1579 SystemTable - The pointer of system table. 1580 CompleteFilePath - The pointer of returned full file path 1581 1582 Returns: 1583 1584 none 1585 1586 --*/ 1587 { 1588 EFI_STATUS Status; 1589 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; 1590 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; 1591 1592 1593 Status = gBS->HandleProtocol ( 1594 ImageHandle, 1595 &gEfiLoadedImageProtocolGuid, 1596 (VOID **) &LoadedImage 1597 ); 1598 ASSERT_EFI_ERROR (Status); 1599 1600 Status = gBS->HandleProtocol ( 1601 LoadedImage->DeviceHandle, 1602 &gEfiDevicePathProtocolGuid, 1603 (VOID *) &ImageDevicePath 1604 ); 1605 ASSERT_EFI_ERROR (Status); 1606 1607 *CompleteFilePath = AppendDevicePath ( 1608 ImageDevicePath, 1609 LoadedImage->FilePath 1610 ); 1611 1612 return ; 1613 } 1614 1615 1616 1617 EFI_STATUS 1618 FvbInitialize ( 1619 IN EFI_HANDLE ImageHandle, 1620 IN EFI_SYSTEM_TABLE *SystemTable 1621 ) 1622 /*++ 1623 1624 Routine Description: 1625 This function does common initialization for FVB services 1626 1627 Arguments: 1628 1629 Returns: 1630 1631 --*/ 1632 { 1633 EFI_STATUS Status; 1634 EFI_FW_VOL_INSTANCE *FwhInstance; 1635 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; 1636 EFI_FIRMWARE_VOLUME_HEADER *TempFwVolHeader; 1637 VOID *HobList; 1638 VOID *FirmwareVolumeHobList; 1639 UINT32 BufferSize; 1640 EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; 1641 UINTN LbaAddress; 1642 BOOLEAN WriteEnabled; 1643 BOOLEAN WriteLocked; 1644 EFI_HANDLE FwbHandle; 1645 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1646 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; 1647 EFI_DEVICE_PATH_PROTOCOL *FwbDevicePath; 1648 EFI_DEVICE_PATH_PROTOCOL *TempFwbDevicePath; 1649 UINT32 MaxLbaSize; 1650 EFI_PHYSICAL_ADDRESS BaseAddress; 1651 BOOLEAN WriteBack; 1652 UINTN NumOfBlocks; 1653 UINTN HeaderLength; 1654 UINT8 SpiStatus; 1655 UINT8 FlashIndex; 1656 UINT8 FlashID[3]; 1657 EFI_DEVICE_PATH_PROTOCOL *CompleteFilePath; 1658 UINT8 PrefixOpcodeIndex; 1659 BOOLEAN InSmm; 1660 EFI_SMM_BASE2_PROTOCOL *mSmmBase2; 1661 EFI_HANDLE Handle; 1662 1663 VOID *Registration; 1664 EFI_EVENT Event; 1665 1666 CompleteFilePath = NULL; 1667 GetFullDriverPath (ImageHandle, SystemTable, &CompleteFilePath); 1668 1669 Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList); 1670 1671 // 1672 // No FV HOBs found 1673 // 1674 ASSERT_EFI_ERROR (Status); 1675 1676 1677 // 1678 // Allocate runtime services data for global variable, which contains 1679 // the private data of all firmware volume block instances 1680 // 1681 mFvbModuleGlobal = (ESAL_FWB_GLOBAL *)AllocateRuntimeZeroPool(sizeof (ESAL_FWB_GLOBAL )); 1682 ASSERT(mFvbModuleGlobal); 1683 mSmmBase2 = NULL; 1684 Status = gBS->LocateProtocol ( 1685 &gEfiSmmBase2ProtocolGuid, 1686 NULL, 1687 (VOID **) &mSmmBase2 1688 ); 1689 1690 if (mSmmBase2 == NULL) { 1691 InSmm = FALSE; 1692 } else { 1693 mSmmBase2->InSmm (mSmmBase2, &InSmm); 1694 mSmmBase2->GetSmstLocation (mSmmBase2, &mSmst); 1695 1696 } 1697 1698 if (!InSmm) { 1699 mInSmmMode = 0; 1700 // 1701 // Obtain a handle for ICH SPI Protocol 1702 // 1703 Status = gBS->LocateProtocol (&gEfiSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SpiProtocol); 1704 ASSERT_EFI_ERROR (Status); 1705 1706 // 1707 // attempt to identify flash part and initialize spi table 1708 // 1709 for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) { 1710 Status = mFvbModuleGlobal->SpiProtocol->Init ( 1711 mFvbModuleGlobal->SpiProtocol, 1712 &(mSpiInitTable[FlashIndex]) 1713 ); 1714 if (!EFI_ERROR (Status)) { 1715 // 1716 // read vendor/device IDs to check if flash device is supported 1717 // 1718 Status = mFvbModuleGlobal->SpiProtocol->Execute ( 1719 mFvbModuleGlobal->SpiProtocol, 1720 SPI_OPCODE_JEDEC_ID_INDEX, 1721 SPI_WREN_INDEX, 1722 TRUE, 1723 FALSE, 1724 FALSE, 1725 0, 1726 3, 1727 FlashID, 1728 EnumSpiRegionAll 1729 ); 1730 if (!EFI_ERROR (Status)) { 1731 if (((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1732 (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1)) || 1733 ((FlashID[0] == SPI_AT26DF321_ID1) && 1734 (FlashID[0] == mSpiInitTable[FlashIndex].VendorId) && 1735 (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0))) { 1736 // 1737 // Supported SPI device found 1738 // 1739 DEBUG ( 1740 ((EFI_D_INFO), 1741 "Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1742 FlashID[0], 1743 FlashID[1], 1744 FlashID[2]) 1745 ); 1746 1747 PublishFlashDeviceInfo (&mSpiInitTable[FlashIndex]); 1748 break; 1749 } 1750 } 1751 } 1752 } 1753 1754 if (FlashIndex >= EnumSpiFlashMax) { 1755 Status = EFI_UNSUPPORTED; 1756 DEBUG ( 1757 (DEBUG_ERROR, 1758 "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n", 1759 FlashID[0], 1760 FlashID[1], 1761 FlashID[2]) 1762 ); 1763 ASSERT_EFI_ERROR (Status); 1764 } 1765 1766 // 1767 // Unlock all regions by writing to status register 1768 // This could be SPI device specific, need to follow the datasheet 1769 // To write to Write Status Register the Spi PrefixOpcode needs to be: 1770 // 0 for Atmel parts 1771 // 0 for Intel parts 1772 // 0 for Macronix parts 1773 // 0 for Winbond parts 1774 // 1 for SST parts 1775 SpiStatus = 0; 1776 if (FlashID[0] == SPI_SST25VF016B_ID1) { 1777 PrefixOpcodeIndex = 1; 1778 } else { 1779 PrefixOpcodeIndex = 0; 1780 } 1781 Status = mFvbModuleGlobal->SpiProtocol->Execute ( 1782 mFvbModuleGlobal->SpiProtocol, 1783 SPI_OPCODE_WRITE_S_INDEX, // OpcodeIndex 1784 PrefixOpcodeIndex, // PrefixOpcodeIndex 1785 TRUE, // DataCycle 1786 TRUE, // Atomic 1787 TRUE, // ShiftOut 1788 0, // Address 1789 1, // Data Number 1790 &SpiStatus, 1791 EnumSpiRegionAll // SPI_REGION_TYPE 1792 ); 1793 1794 1795 } else { 1796 mInSmmMode = 1; 1797 1798 Status = mSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, (VOID **) &mFvbModuleGlobal->SmmSpiProtocol); 1799 if (EFI_ERROR(Status)) { 1800 Registration = NULL; 1801 Status = mSmst->SmmRegisterProtocolNotify ( 1802 &gEfiSmmSpiProtocolGuid, 1803 SmmSpiNotificationFunction, 1804 &Registration 1805 ); 1806 } else { 1807 Status = SmmSpiInit(); 1808 } 1809 1810 } 1811 1812 // 1813 // Calculate the total size for all firmware volume block instances 1814 // 1815 BufferSize = 0; 1816 FirmwareVolumeHobList = HobList; 1817 FwVolHeader = NULL; 1818 do { 1819 Status = GetFvbHeader (&FirmwareVolumeHobList, &FwVolHeader, &BaseAddress, &WriteBack); 1820 if (EFI_ERROR (Status)) { 1821 break; 1822 } 1823 1824 if (FwVolHeader) { 1825 BufferSize += (FwVolHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)); 1826 } 1827 } while (TRUE); 1828 1829 // 1830 // Only need to allocate once. There is only one copy of physical memory for 1831 // the private data of each FV instance. But in virtual mode or in physical 1832 // mode, the address of the the physical memory may be different. 1833 // 1834 mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] = (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize); 1835 ASSERT(mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]); 1836 // 1837 // Make a virtual copy of the FvInstance pointer. 1838 // 1839 FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; 1840 mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance; 1841 1842 mFvbModuleGlobal->NumFv = 0; 1843 FirmwareVolumeHobList = HobList; 1844 TempFwVolHeader = NULL; 1845 1846 MaxLbaSize = 0; 1847 1848 // 1849 // Fill in the private data of each firmware volume block instance 1850 // 1851 // Foreach Fv HOB in the FirmwareVolumeHobList, loop 1852 // 1853 do { 1854 Status = GetFvbHeader (&FirmwareVolumeHobList, &TempFwVolHeader, &BaseAddress, &WriteBack); 1855 if (EFI_ERROR (Status)) { 1856 break; 1857 } 1858 FwVolHeader = TempFwVolHeader; 1859 1860 if (!FwVolHeader) { 1861 continue; 1862 } 1863 1864 1865 CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength); 1866 FwVolHeader = &(FwhInstance->VolumeHeader); 1867 1868 FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress; 1869 FwhInstance->FvBase[FVB_VIRTUAL] = (UINTN) BaseAddress; 1870 1871 // 1872 // FwhInstance->FvWriteBase may not be the same as FwhInstance->FvBase 1873 // 1874 FwhInstance->FvWriteBase[FVB_PHYSICAL] = (UINTN) BaseAddress; 1875 WriteEnabled = TRUE; 1876 1877 // 1878 // Every pointer should have a virtual copy. 1879 // 1880 FwhInstance->FvWriteBase[FVB_VIRTUAL] = FwhInstance->FvWriteBase[FVB_PHYSICAL]; 1881 1882 FwhInstance->WriteEnabled = WriteEnabled; 1883 EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL); 1884 1885 LbaAddress = (UINTN) FwhInstance->FvWriteBase[0]; 1886 NumOfBlocks = 0; 1887 WriteLocked = FALSE; 1888 1889 if (WriteEnabled) { 1890 for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { 1891 // 1892 // Get the maximum size of a block. The size will be used to allocate 1893 // buffer for Scratch space, the intermediate buffer for FVB extension 1894 // protocol 1895 // 1896 if (MaxLbaSize < PtrBlockMapEntry->Length) { 1897 MaxLbaSize = PtrBlockMapEntry->Length; 1898 } 1899 1900 NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks; 1901 } 1902 // 1903 // Write back a healthy FV header 1904 // 1905 if (WriteBack && (!WriteLocked)) { 1906 1907 Status = FlashFdErase ( 1908 (UINTN) FwhInstance->FvWriteBase[0], 1909 (UINTN) BaseAddress, 1910 FwVolHeader->BlockMap->Length 1911 ); 1912 1913 HeaderLength = (UINTN) FwVolHeader->HeaderLength; 1914 Status = FlashFdWrite ( 1915 (UINTN) FwhInstance->FvWriteBase[0], 1916 (UINTN) BaseAddress, 1917 &HeaderLength, 1918 (UINT8 *) FwVolHeader, 1919 FwVolHeader->BlockMap->Length 1920 ); 1921 1922 } 1923 } 1924 // 1925 // The total number of blocks in the FV. 1926 // 1927 FwhInstance->NumOfBlocks = NumOfBlocks; 1928 1929 // 1930 // If the FV is write locked, set the appropriate attributes 1931 // 1932 if (WriteLocked) { 1933 // 1934 // write disabled 1935 // 1936 FwhInstance->VolumeHeader.Attributes &= ~EFI_FVB2_WRITE_STATUS; 1937 // 1938 // lock enabled 1939 // 1940 FwhInstance->VolumeHeader.Attributes |= EFI_FVB2_LOCK_STATUS; 1941 } 1942 1943 // 1944 // Allocate and initialize FVB Device in a runtime data buffer 1945 // 1946 FvbDevice = AllocateRuntimeCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFvbDeviceTemplate); 1947 ASSERT (FvbDevice); 1948 1949 FvbDevice->Instance = mFvbModuleGlobal->NumFv; 1950 mFvbModuleGlobal->NumFv++; 1951 1952 // 1953 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH 1954 // 1955 if (FwVolHeader->ExtHeaderOffset == 0) { 1956 FvbDevice->FvDevicePath.MemMapDevPath.StartingAddress = BaseAddress; 1957 FvbDevice->FvDevicePath.MemMapDevPath.EndingAddress = BaseAddress + (FwVolHeader->FvLength - 1); 1958 FwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&FvbDevice->FvDevicePath; 1959 } else { 1960 CopyGuid ( 1961 &FvbDevice->UefiFvDevicePath.FvDevPath.FvName, 1962 (EFI_GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset) 1963 ); 1964 FwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&FvbDevice->UefiFvDevicePath; 1965 } 1966 1967 if (!InSmm) { 1968 // 1969 // Find a handle with a matching device path that has supports FW Block protocol 1970 // 1971 TempFwbDevicePath = FwbDevicePath; 1972 Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle); 1973 if (EFI_ERROR (Status)) { 1974 // 1975 // LocateDevicePath fails so install a new interface and device path 1976 // 1977 FwbHandle = NULL; 1978 Status = gBS->InstallMultipleProtocolInterfaces ( 1979 &FwbHandle, 1980 &gEfiFirmwareVolumeBlockProtocolGuid, 1981 &FvbDevice->FwVolBlockInstance, 1982 &gEfiDevicePathProtocolGuid, 1983 FwbDevicePath, 1984 NULL 1985 ); 1986 ASSERT_EFI_ERROR (Status); 1987 } else if (EfiIsDevicePathEnd (TempFwbDevicePath)) { 1988 // 1989 // Device already exists, so reinstall the FVB protocol 1990 // 1991 Status = gBS->HandleProtocol ( 1992 FwbHandle, 1993 &gEfiFirmwareVolumeBlockProtocolGuid, 1994 (VOID **) &OldFwbInterface 1995 ); 1996 ASSERT_EFI_ERROR (Status); 1997 1998 Status = gBS->ReinstallProtocolInterface ( 1999 FwbHandle, 2000 &gEfiFirmwareVolumeBlockProtocolGuid, 2001 OldFwbInterface, 2002 &FvbDevice->FwVolBlockInstance 2003 ); 2004 ASSERT_EFI_ERROR (Status); 2005 2006 } else { 2007 // 2008 // There was a FVB protocol on an End Device Path node 2009 // 2010 ASSERT (FALSE); 2011 } 2012 } else { 2013 FwbHandle = NULL; 2014 Status = mSmst->SmmInstallProtocolInterface ( 2015 &FwbHandle, 2016 &gEfiSmmFirmwareVolumeBlockProtocolGuid, 2017 EFI_NATIVE_INTERFACE, 2018 &FvbDevice->FwVolBlockInstance 2019 ); 2020 ASSERT_EFI_ERROR (Status); 2021 } 2022 2023 FwhInstance = (EFI_FW_VOL_INSTANCE *) 2024 ( 2025 (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + 2026 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) 2027 ); 2028 } while (TRUE); 2029 2030 // 2031 // Allocate for scratch space, an intermediate buffer for FVB extention 2032 // 2033 2034 mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL] = AllocateRuntimeZeroPool (MaxLbaSize); 2035 2036 ASSERT (mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]); 2037 2038 mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL] = mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]; 2039 2040 if (!InSmm) { 2041 Status = gBS->CreateEventEx ( 2042 EVT_NOTIFY_SIGNAL, 2043 TPL_NOTIFY, 2044 FvbVirtualddressChangeEvent, 2045 NULL, 2046 &gEfiEventVirtualAddressChangeGuid, 2047 &Event 2048 ); 2049 ASSERT_EFI_ERROR (Status); 2050 } else { 2051 // 2052 // Inform other platform drivers that SPI device discovered and 2053 // SPI interface ready for use. 2054 // 2055 Handle = NULL; 2056 Status = gBS->InstallProtocolInterface ( 2057 &Handle, 2058 &gEfiSmmSpiReadyProtocolGuid, 2059 EFI_NATIVE_INTERFACE, 2060 NULL 2061 ); 2062 } 2063 return EFI_SUCCESS; 2064 } 2065