1 /**@file 2 3 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 14 FWBlockService.c 15 16 Abstract: 17 18 Revision History 19 20 **/ 21 22 // 23 // The package level header files this module uses 24 // 25 #include <PiDxe.h> 26 #include <WinNtDxe.h> 27 // 28 // The protocols, PPI and GUID defintions for this module 29 // 30 #include <Guid/EventGroup.h> 31 #include <Protocol/FirmwareVolumeBlock.h> 32 #include <Protocol/DevicePath.h> 33 // 34 // The Library classes this module consumes 35 // 36 #include <Library/UefiLib.h> 37 #include <Library/UefiDriverEntryPoint.h> 38 #include <Library/BaseLib.h> 39 #include <Library/DxeServicesTableLib.h> 40 #include <Library/UefiRuntimeLib.h> 41 #include <Library/DebugLib.h> 42 #include <Library/HobLib.h> 43 #include <Library/BaseMemoryLib.h> 44 #include <Library/MemoryAllocationLib.h> 45 #include <Library/UefiBootServicesTableLib.h> 46 #include <Library/DevicePathLib.h> 47 48 #include "FWBlockService.h" 49 50 #define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS) 51 52 ESAL_FWB_GLOBAL *mFvbModuleGlobal; 53 54 FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = { 55 { 56 { 57 HARDWARE_DEVICE_PATH, 58 HW_MEMMAP_DP, 59 { 60 (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), 61 (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) 62 } 63 }, 64 EfiMemoryMappedIO, 65 (EFI_PHYSICAL_ADDRESS) 0, 66 (EFI_PHYSICAL_ADDRESS) 0, 67 }, 68 { 69 END_DEVICE_PATH_TYPE, 70 END_ENTIRE_DEVICE_PATH_SUBTYPE, 71 { 72 END_DEVICE_PATH_LENGTH, 73 0 74 } 75 } 76 }; 77 78 FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = { 79 { 80 { 81 MEDIA_DEVICE_PATH, 82 MEDIA_PIWG_FW_VOL_DP, 83 { 84 (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), 85 (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) 86 } 87 }, 88 { 0 } 89 }, 90 { 91 END_DEVICE_PATH_TYPE, 92 END_ENTIRE_DEVICE_PATH_SUBTYPE, 93 { 94 END_DEVICE_PATH_LENGTH, 95 0 96 } 97 } 98 }; 99 100 EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = { 101 FVB_DEVICE_SIGNATURE, 102 NULL, 103 0, 104 { 105 FvbProtocolGetAttributes, 106 FvbProtocolSetAttributes, 107 FvbProtocolGetPhysicalAddress, 108 FvbProtocolGetBlockSize, 109 FvbProtocolRead, 110 FvbProtocolWrite, 111 FvbProtocolEraseBlocks, 112 NULL 113 } 114 }; 115 116 117 118 VOID 119 EFIAPI 120 FvbVirtualddressChangeEvent ( 121 IN EFI_EVENT Event, 122 IN VOID *Context 123 ) 124 /*++ 125 126 Routine Description: 127 128 Fixup internal data so that EFI and SAL can be call in virtual mode. 129 Call the passed in Child Notify event and convert the mFvbModuleGlobal 130 date items to there virtual address. 131 132 mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] - Physical copy of instance data 133 mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] - Virtual pointer to common 134 instance data. 135 136 Arguments: 137 138 (Standard EFI notify event - EFI_EVENT_NOTIFY) 139 140 Returns: 141 142 None 143 144 --*/ 145 { 146 EFI_FW_VOL_INSTANCE *FwhInstance; 147 UINTN Index; 148 149 EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]); 150 151 // 152 // Convert the base address of all the instances 153 // 154 Index = 0; 155 FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; 156 while (Index < mFvbModuleGlobal->NumFv) { 157 EfiConvertPointer (0x0, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]); 158 FwhInstance = (EFI_FW_VOL_INSTANCE *) 159 ( 160 (UINTN) ((UINT8 *) FwhInstance) + FwhInstance->VolumeHeader.HeaderLength + 161 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) 162 ); 163 Index++; 164 } 165 166 EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]); 167 EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal); 168 } 169 170 EFI_STATUS 171 GetFvbInstance ( 172 IN UINTN Instance, 173 IN ESAL_FWB_GLOBAL *Global, 174 OUT EFI_FW_VOL_INSTANCE **FwhInstance, 175 IN BOOLEAN Virtual 176 ) 177 /*++ 178 179 Routine Description: 180 Retrieves the physical address of a memory mapped FV 181 182 Arguments: 183 Instance - The FV instance whose base address is going to be 184 returned 185 Global - Pointer to ESAL_FWB_GLOBAL that contains all 186 instance data 187 FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure 188 Virtual - Whether CPU is in virtual or physical mode 189 190 Returns: 191 EFI_SUCCESS - Successfully returns 192 EFI_INVALID_PARAMETER - Instance not found 193 194 --*/ 195 { 196 EFI_FW_VOL_INSTANCE *FwhRecord; 197 198 if (Instance >= Global->NumFv) { 199 return EFI_INVALID_PARAMETER; 200 } 201 // 202 // Find the right instance of the FVB private data 203 // 204 FwhRecord = Global->FvInstance[Virtual]; 205 while (Instance > 0) { 206 FwhRecord = (EFI_FW_VOL_INSTANCE *) 207 ( 208 (UINTN) ((UINT8 *) FwhRecord) + FwhRecord->VolumeHeader.HeaderLength + 209 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) 210 ); 211 Instance--; 212 } 213 214 *FwhInstance = FwhRecord; 215 216 return EFI_SUCCESS; 217 } 218 219 EFI_STATUS 220 FvbGetPhysicalAddress ( 221 IN UINTN Instance, 222 OUT EFI_PHYSICAL_ADDRESS *Address, 223 IN ESAL_FWB_GLOBAL *Global, 224 IN BOOLEAN Virtual 225 ) 226 /*++ 227 228 Routine Description: 229 Retrieves the physical address of a memory mapped FV 230 231 Arguments: 232 Instance - The FV instance whose base address is going to be 233 returned 234 Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS 235 that on successful return, contains the base address 236 of the firmware volume. 237 Global - Pointer to ESAL_FWB_GLOBAL that contains all 238 instance data 239 Virtual - Whether CPU is in virtual or physical mode 240 241 Returns: 242 EFI_SUCCESS - Successfully returns 243 EFI_INVALID_PARAMETER - Instance not found 244 245 --*/ 246 { 247 EFI_FW_VOL_INSTANCE *FwhInstance; 248 EFI_STATUS Status; 249 250 // 251 // Find the right instance of the FVB private data 252 // 253 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 254 ASSERT_EFI_ERROR (Status); 255 *Address = FwhInstance->FvBase[Virtual]; 256 257 return EFI_SUCCESS; 258 } 259 260 EFI_STATUS 261 FvbGetVolumeAttributes ( 262 IN UINTN Instance, 263 OUT EFI_FVB_ATTRIBUTES_2 *Attributes, 264 IN ESAL_FWB_GLOBAL *Global, 265 IN BOOLEAN Virtual 266 ) 267 /*++ 268 269 Routine Description: 270 Retrieves attributes, insures positive polarity of attribute bits, returns 271 resulting attributes in output parameter 272 273 Arguments: 274 Instance - The FV instance whose attributes is going to be 275 returned 276 Attributes - Output buffer which contains attributes 277 Global - Pointer to ESAL_FWB_GLOBAL that contains all 278 instance data 279 Virtual - Whether CPU is in virtual or physical mode 280 281 Returns: 282 EFI_SUCCESS - Successfully returns 283 EFI_INVALID_PARAMETER - Instance not found 284 285 --*/ 286 { 287 EFI_FW_VOL_INSTANCE *FwhInstance; 288 EFI_STATUS Status; 289 290 // 291 // Find the right instance of the FVB private data 292 // 293 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 294 ASSERT_EFI_ERROR (Status); 295 *Attributes = FwhInstance->VolumeHeader.Attributes; 296 297 return EFI_SUCCESS; 298 } 299 300 EFI_STATUS 301 FvbGetLbaAddress ( 302 IN UINTN Instance, 303 IN EFI_LBA Lba, 304 OUT UINTN *LbaAddress, 305 OUT UINTN *LbaLength, 306 OUT UINTN *NumOfBlocks, 307 IN ESAL_FWB_GLOBAL *Global, 308 IN BOOLEAN Virtual 309 ) 310 /*++ 311 312 Routine Description: 313 Retrieves the starting address of an LBA in an FV 314 315 Arguments: 316 Instance - The FV instance which the Lba belongs to 317 Lba - The logical block address 318 LbaAddress - On output, contains the physical starting address 319 of the Lba 320 LbaLength - On output, contains the length of the block 321 NumOfBlocks - A pointer to a caller allocated UINTN in which the 322 number of consecutive blocks starting with Lba is 323 returned. All blocks in this range have a size of 324 BlockSize 325 Global - Pointer to ESAL_FWB_GLOBAL that contains all 326 instance data 327 Virtual - Whether CPU is in virtual or physical mode 328 329 Returns: 330 EFI_SUCCESS - Successfully returns 331 EFI_INVALID_PARAMETER - Instance not found 332 333 --*/ 334 { 335 UINT32 NumBlocks; 336 UINT32 BlockLength; 337 UINTN Offset; 338 EFI_LBA StartLba; 339 EFI_LBA NextLba; 340 EFI_FW_VOL_INSTANCE *FwhInstance; 341 EFI_FV_BLOCK_MAP_ENTRY *BlockMap; 342 EFI_STATUS Status; 343 344 // 345 // Find the right instance of the FVB private data 346 // 347 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 348 ASSERT_EFI_ERROR (Status); 349 350 StartLba = 0; 351 Offset = 0; 352 BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]); 353 354 // 355 // Parse the blockmap of the FV to find which map entry the Lba belongs to 356 // 357 while (TRUE) { 358 NumBlocks = BlockMap->NumBlocks; 359 BlockLength = BlockMap->Length; 360 361 if (NumBlocks == 0 || BlockLength == 0) { 362 return EFI_INVALID_PARAMETER; 363 } 364 365 NextLba = StartLba + NumBlocks; 366 367 // 368 // The map entry found 369 // 370 if (Lba >= StartLba && Lba < NextLba) { 371 Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength); 372 if (LbaAddress != NULL) { 373 *LbaAddress = FwhInstance->FvBase[Virtual] + Offset; 374 } 375 376 if (LbaLength != NULL) { 377 *LbaLength = BlockLength; 378 } 379 380 if (NumOfBlocks != NULL) { 381 *NumOfBlocks = (UINTN) (NextLba - Lba); 382 } 383 384 return EFI_SUCCESS; 385 } 386 387 StartLba = NextLba; 388 Offset = Offset + NumBlocks * BlockLength; 389 BlockMap++; 390 } 391 } 392 393 EFI_STATUS 394 FvbReadBlock ( 395 IN UINTN Instance, 396 IN EFI_LBA Lba, 397 IN UINTN BlockOffset, 398 IN OUT UINTN *NumBytes, 399 IN UINT8 *Buffer, 400 IN ESAL_FWB_GLOBAL *Global, 401 IN BOOLEAN Virtual 402 ) 403 /*++ 404 405 Routine Description: 406 Reads specified number of bytes into a buffer from the specified block 407 408 Arguments: 409 Instance - The FV instance to be read from 410 Lba - The logical block address to be read from 411 BlockOffset - Offset into the block at which to begin reading 412 NumBytes - Pointer that on input contains the total size of 413 the buffer. On output, it contains the total number 414 of bytes read 415 Buffer - Pointer to a caller allocated buffer that will be 416 used to hold the data read 417 Global - Pointer to ESAL_FWB_GLOBAL that contains all 418 instance data 419 Virtual - Whether CPU is in virtual or physical mode 420 421 Returns: 422 EFI_SUCCESS - The firmware volume was read successfully and 423 contents are in Buffer 424 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, 425 NumBytes contains the total number of bytes returned 426 in Buffer 427 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state 428 EFI_DEVICE_ERROR - The block device is not functioning correctly and 429 could not be read 430 EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL 431 432 --*/ 433 { 434 EFI_FVB_ATTRIBUTES_2 Attributes; 435 UINTN LbaAddress; 436 UINTN LbaLength; 437 EFI_STATUS Status; 438 439 // 440 // Check for invalid conditions 441 // 442 if ((NumBytes == NULL) || (Buffer == NULL)) { 443 return EFI_INVALID_PARAMETER; 444 } 445 446 if (*NumBytes == 0) { 447 return EFI_INVALID_PARAMETER; 448 } 449 450 Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual); 451 if (EFI_ERROR (Status)) { 452 return Status; 453 } 454 // 455 // Check if the FV is read enabled 456 // 457 FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 458 459 if ((Attributes & EFI_FVB2_READ_STATUS) == 0) { 460 return EFI_ACCESS_DENIED; 461 } 462 // 463 // Perform boundary checks and adjust NumBytes 464 // 465 if (BlockOffset > LbaLength) { 466 return EFI_INVALID_PARAMETER; 467 } 468 469 if (LbaLength < (*NumBytes + BlockOffset)) { 470 *NumBytes = (UINT32) (LbaLength - BlockOffset); 471 Status = EFI_BAD_BUFFER_SIZE; 472 } 473 474 CopyMem (Buffer, (UINT8 *) (LbaAddress + BlockOffset), (UINTN) (*NumBytes)); 475 476 return Status; 477 } 478 479 EFI_STATUS 480 FvbWriteBlock ( 481 IN UINTN Instance, 482 IN EFI_LBA Lba, 483 IN UINTN BlockOffset, 484 IN OUT UINTN *NumBytes, 485 IN UINT8 *Buffer, 486 IN ESAL_FWB_GLOBAL *Global, 487 IN BOOLEAN Virtual 488 ) 489 /*++ 490 491 Routine Description: 492 Writes specified number of bytes from the input buffer to the block 493 494 Arguments: 495 Instance - The FV instance to be written to 496 Lba - The starting logical block index to write to 497 BlockOffset - Offset into the block at which to begin writing 498 NumBytes - Pointer that on input contains the total size of 499 the buffer. On output, it contains the total number 500 of bytes actually written 501 Buffer - Pointer to a caller allocated buffer that contains 502 the source for the write 503 Global - Pointer to ESAL_FWB_GLOBAL that contains all 504 instance data 505 Virtual - Whether CPU is in virtual or physical mode 506 507 Returns: 508 EFI_SUCCESS - The firmware volume was written successfully 509 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, 510 NumBytes contains the total number of bytes 511 actually written 512 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 513 EFI_DEVICE_ERROR - The block device is not functioning correctly and 514 could not be written 515 EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL 516 517 --*/ 518 { 519 EFI_FVB_ATTRIBUTES_2 Attributes; 520 UINTN LbaAddress; 521 UINTN LbaLength; 522 EFI_STATUS Status; 523 524 // 525 // Check for invalid conditions 526 // 527 if ((NumBytes == NULL) || (Buffer == NULL)) { 528 return EFI_INVALID_PARAMETER; 529 } 530 531 if (*NumBytes == 0) { 532 return EFI_INVALID_PARAMETER; 533 } 534 535 Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual); 536 if (EFI_ERROR (Status)) { 537 return Status; 538 } 539 // 540 // Check if the FV is write enabled 541 // 542 FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 543 544 if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { 545 return EFI_ACCESS_DENIED; 546 } 547 // 548 // Perform boundary checks and adjust NumBytes 549 // 550 if (BlockOffset > LbaLength) { 551 return EFI_INVALID_PARAMETER; 552 } 553 554 if (LbaLength < (*NumBytes + BlockOffset)) { 555 *NumBytes = (UINT32) (LbaLength - BlockOffset); 556 Status = EFI_BAD_BUFFER_SIZE; 557 } 558 // 559 // Write data 560 // 561 CopyMem ((UINT8 *) (LbaAddress + BlockOffset), Buffer, (UINTN) (*NumBytes)); 562 563 return Status; 564 } 565 566 EFI_STATUS 567 FvbEraseBlock ( 568 IN UINTN Instance, 569 IN EFI_LBA Lba, 570 IN ESAL_FWB_GLOBAL *Global, 571 IN BOOLEAN Virtual 572 ) 573 /*++ 574 575 Routine Description: 576 Erases and initializes a firmware volume block 577 578 Arguments: 579 Instance - The FV instance to be erased 580 Lba - The logical block index to be erased 581 Global - Pointer to ESAL_FWB_GLOBAL that contains all 582 instance data 583 Virtual - Whether CPU is in virtual or physical mode 584 585 Returns: 586 EFI_SUCCESS - The erase request was successfully completed 587 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 588 EFI_DEVICE_ERROR - The block device is not functioning correctly and 589 could not be written. Firmware device may have been 590 partially erased 591 EFI_INVALID_PARAMETER - Instance not found 592 593 --*/ 594 { 595 596 EFI_FVB_ATTRIBUTES_2 Attributes; 597 UINTN LbaAddress; 598 UINTN LbaLength; 599 EFI_STATUS Status; 600 UINT8 Data; 601 602 // 603 // Check if the FV is write enabled 604 // 605 FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); 606 607 if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { 608 return EFI_ACCESS_DENIED; 609 } 610 // 611 // Get the starting address of the block for erase. 612 // 613 Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual); 614 615 if (EFI_ERROR (Status)) { 616 return Status; 617 } 618 619 if ((Attributes & EFI_FVB2_ERASE_POLARITY) != 0) { 620 Data = 0xFF; 621 } else { 622 Data = 0x0; 623 } 624 625 SetMem ((UINT8 *) LbaAddress, LbaLength, Data); 626 627 return EFI_SUCCESS; 628 } 629 630 EFI_STATUS 631 FvbSetVolumeAttributes ( 632 IN UINTN Instance, 633 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes, 634 IN ESAL_FWB_GLOBAL *Global, 635 IN BOOLEAN Virtual 636 ) 637 /*++ 638 639 Routine Description: 640 Modifies the current settings of the firmware volume according to the 641 input parameter, and returns the new setting of the volume 642 643 Arguments: 644 Instance - The FV instance whose attributes is going to be 645 modified 646 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2 647 containing the desired firmware volume settings. 648 On successful return, it contains the new settings 649 of the firmware volume 650 Global - Pointer to ESAL_FWB_GLOBAL that contains all 651 instance data 652 Virtual - Whether CPU is in virtual or physical mode 653 654 Returns: 655 EFI_SUCCESS - Successfully returns 656 EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified 657 EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are 658 in conflict with the capabilities as declared in the 659 firmware volume header 660 661 --*/ 662 { 663 EFI_FW_VOL_INSTANCE *FwhInstance; 664 EFI_FVB_ATTRIBUTES_2 OldAttributes; 665 EFI_FVB_ATTRIBUTES_2 *AttribPtr; 666 UINT32 Capabilities; 667 UINT32 OldStatus; 668 UINT32 NewStatus; 669 EFI_STATUS Status; 670 EFI_FVB_ATTRIBUTES_2 UnchangedAttributes; 671 672 // 673 // Find the right instance of the FVB private data 674 // 675 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); 676 ASSERT_EFI_ERROR (Status); 677 678 AttribPtr = (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes); 679 OldAttributes = *AttribPtr; 680 Capabilities = OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \ 681 EFI_FVB2_READ_ENABLED_CAP | \ 682 EFI_FVB2_WRITE_DISABLED_CAP | \ 683 EFI_FVB2_WRITE_ENABLED_CAP | \ 684 EFI_FVB2_LOCK_CAP \ 685 ); 686 OldStatus = OldAttributes & EFI_FVB2_STATUS; 687 NewStatus = *Attributes & EFI_FVB2_STATUS; 688 689 UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \ 690 EFI_FVB2_READ_ENABLED_CAP | \ 691 EFI_FVB2_WRITE_DISABLED_CAP | \ 692 EFI_FVB2_WRITE_ENABLED_CAP | \ 693 EFI_FVB2_LOCK_CAP | \ 694 EFI_FVB2_STICKY_WRITE | \ 695 EFI_FVB2_MEMORY_MAPPED | \ 696 EFI_FVB2_ERASE_POLARITY | \ 697 EFI_FVB2_READ_LOCK_CAP | \ 698 EFI_FVB2_WRITE_LOCK_CAP | \ 699 EFI_FVB2_ALIGNMENT; 700 701 // 702 // Some attributes of FV is read only can *not* be set 703 // 704 if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttributes)) { 705 return EFI_INVALID_PARAMETER; 706 } 707 // 708 // If firmware volume is locked, no status bit can be updated 709 // 710 if (OldAttributes & EFI_FVB2_LOCK_STATUS) { 711 if (OldStatus ^ NewStatus) { 712 return EFI_ACCESS_DENIED; 713 } 714 } 715 // 716 // Test read disable 717 // 718 if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) { 719 if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) { 720 return EFI_INVALID_PARAMETER; 721 } 722 } 723 // 724 // Test read enable 725 // 726 if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) { 727 if (NewStatus & EFI_FVB2_READ_STATUS) { 728 return EFI_INVALID_PARAMETER; 729 } 730 } 731 // 732 // Test write disable 733 // 734 if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) { 735 if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) { 736 return EFI_INVALID_PARAMETER; 737 } 738 } 739 // 740 // Test write enable 741 // 742 if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) { 743 if (NewStatus & EFI_FVB2_WRITE_STATUS) { 744 return EFI_INVALID_PARAMETER; 745 } 746 } 747 // 748 // Test lock 749 // 750 if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) { 751 if (NewStatus & EFI_FVB2_LOCK_STATUS) { 752 return EFI_INVALID_PARAMETER; 753 } 754 } 755 756 *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); 757 *AttribPtr = (*AttribPtr) | NewStatus; 758 *Attributes = *AttribPtr; 759 760 return EFI_SUCCESS; 761 } 762 // 763 // FVB protocol APIs 764 // 765 EFI_STATUS 766 EFIAPI 767 FvbProtocolGetPhysicalAddress ( 768 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 769 OUT EFI_PHYSICAL_ADDRESS *Address 770 ) 771 /*++ 772 773 Routine Description: 774 775 Retrieves the physical address of the device. 776 777 Arguments: 778 779 This - Calling context 780 Address - Output buffer containing the address. 781 782 Returns: 783 784 Returns: 785 EFI_SUCCESS - Successfully returns 786 787 --*/ 788 { 789 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 790 791 FvbDevice = FVB_DEVICE_FROM_THIS (This); 792 793 return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ()); 794 } 795 796 EFI_STATUS 797 EFIAPI 798 FvbProtocolGetBlockSize ( 799 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 800 IN CONST EFI_LBA Lba, 801 OUT UINTN *BlockSize, 802 OUT UINTN *NumOfBlocks 803 ) 804 /*++ 805 806 Routine Description: 807 Retrieve the size of a logical block 808 809 Arguments: 810 This - Calling context 811 Lba - Indicates which block to return the size for. 812 BlockSize - A pointer to a caller allocated UINTN in which 813 the size of the block is returned 814 NumOfBlocks - a pointer to a caller allocated UINTN in which the 815 number of consecutive blocks starting with Lba is 816 returned. All blocks in this range have a size of 817 BlockSize 818 819 Returns: 820 EFI_SUCCESS - The firmware volume was read successfully and 821 contents are in Buffer 822 823 --*/ 824 { 825 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 826 827 FvbDevice = FVB_DEVICE_FROM_THIS (This); 828 829 return FvbGetLbaAddress ( 830 FvbDevice->Instance, 831 Lba, 832 NULL, 833 BlockSize, 834 NumOfBlocks, 835 mFvbModuleGlobal, 836 EfiGoneVirtual () 837 ); 838 } 839 840 EFI_STATUS 841 EFIAPI 842 FvbProtocolGetAttributes ( 843 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 844 OUT EFI_FVB_ATTRIBUTES_2 *Attributes 845 ) 846 /*++ 847 848 Routine Description: 849 Retrieves Volume attributes. No polarity translations are done. 850 851 Arguments: 852 This - Calling context 853 Attributes - output buffer which contains attributes 854 855 Returns: 856 EFI_SUCCESS - Successfully returns 857 858 --*/ 859 { 860 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 861 862 FvbDevice = FVB_DEVICE_FROM_THIS (This); 863 864 return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); 865 } 866 867 EFI_STATUS 868 EFIAPI 869 FvbProtocolSetAttributes ( 870 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 871 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes 872 ) 873 /*++ 874 875 Routine Description: 876 Sets Volume attributes. No polarity translations are done. 877 878 Arguments: 879 This - Calling context 880 Attributes - output buffer which contains attributes 881 882 Returns: 883 EFI_SUCCESS - Successfully returns 884 885 --*/ 886 { 887 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 888 889 FvbDevice = FVB_DEVICE_FROM_THIS (This); 890 891 return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); 892 } 893 894 EFI_STATUS 895 EFIAPI 896 FvbProtocolEraseBlocks ( 897 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 898 ... 899 ) 900 /*++ 901 902 Routine Description: 903 904 The EraseBlock() function erases one or more blocks as denoted by the 905 variable argument list. The entire parameter list of blocks must be verified 906 prior to erasing any blocks. If a block is requested that does not exist 907 within the associated firmware volume (it has a larger index than the last 908 block of the firmware volume), the EraseBlock() function must return 909 EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. 910 911 Arguments: 912 This - Calling context 913 ... - Starting LBA followed by Number of Lba to erase. 914 a -1 to terminate the list. 915 916 Returns: 917 EFI_SUCCESS - The erase request was successfully completed 918 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 919 EFI_DEVICE_ERROR - The block device is not functioning correctly and 920 could not be written. Firmware device may have been 921 partially erased 922 923 --*/ 924 { 925 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 926 EFI_FW_VOL_INSTANCE *FwhInstance; 927 UINTN NumOfBlocks; 928 VA_LIST args; 929 EFI_LBA StartingLba; 930 UINTN NumOfLba; 931 EFI_STATUS Status; 932 933 FvbDevice = FVB_DEVICE_FROM_THIS (This); 934 935 Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ()); 936 ASSERT_EFI_ERROR (Status); 937 938 NumOfBlocks = FwhInstance->NumOfBlocks; 939 940 VA_START (args, This); 941 942 do { 943 StartingLba = VA_ARG (args, EFI_LBA); 944 if (StartingLba == EFI_LBA_LIST_TERMINATOR) { 945 break; 946 } 947 948 NumOfLba = VA_ARG (args, UINT32); 949 950 // 951 // Check input parameters 952 // 953 if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) { 954 VA_END (args); 955 return EFI_INVALID_PARAMETER; 956 } 957 } while (1); 958 959 VA_END (args); 960 961 VA_START (args, This); 962 do { 963 StartingLba = VA_ARG (args, EFI_LBA); 964 if (StartingLba == EFI_LBA_LIST_TERMINATOR) { 965 break; 966 } 967 968 NumOfLba = VA_ARG (args, UINT32); 969 970 while (NumOfLba > 0) { 971 Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ()); 972 if (EFI_ERROR (Status)) { 973 VA_END (args); 974 return Status; 975 } 976 977 StartingLba++; 978 NumOfLba--; 979 } 980 981 } while (1); 982 983 VA_END (args); 984 985 return EFI_SUCCESS; 986 } 987 988 EFI_STATUS 989 EFIAPI 990 FvbProtocolWrite ( 991 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 992 IN EFI_LBA Lba, 993 IN UINTN Offset, 994 IN OUT UINTN *NumBytes, 995 IN UINT8 *Buffer 996 ) 997 /*++ 998 999 Routine Description: 1000 1001 Writes data beginning at Lba:Offset from FV. The write terminates either 1002 when *NumBytes of data have been written, or when a block boundary is 1003 reached. *NumBytes is updated to reflect the actual number of bytes 1004 written. The write opertion does not include erase. This routine will 1005 attempt to write only the specified bytes. If the writes do not stick, 1006 it will return an error. 1007 1008 Arguments: 1009 This - Calling context 1010 Lba - Block in which to begin write 1011 Offset - Offset in the block at which to begin write 1012 NumBytes - On input, indicates the requested write size. On 1013 output, indicates the actual number of bytes written 1014 Buffer - Buffer containing source data for the write. 1015 1016 Returns: 1017 EFI_SUCCESS - The firmware volume was written successfully 1018 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, 1019 NumBytes contains the total number of bytes 1020 actually written 1021 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state 1022 EFI_DEVICE_ERROR - The block device is not functioning correctly and 1023 could not be written 1024 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL 1025 1026 --*/ 1027 { 1028 1029 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1030 1031 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1032 1033 return FvbWriteBlock (FvbDevice->Instance, (EFI_LBA)Lba, (UINTN)Offset, NumBytes, (UINT8 *)Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); 1034 } 1035 1036 EFI_STATUS 1037 EFIAPI 1038 FvbProtocolRead ( 1039 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, 1040 IN CONST EFI_LBA Lba, 1041 IN CONST UINTN Offset, 1042 IN OUT UINTN *NumBytes, 1043 IN UINT8 *Buffer 1044 ) 1045 /*++ 1046 1047 Routine Description: 1048 1049 Reads data beginning at Lba:Offset from FV. The Read terminates either 1050 when *NumBytes of data have been read, or when a block boundary is 1051 reached. *NumBytes is updated to reflect the actual number of bytes 1052 written. The write opertion does not include erase. This routine will 1053 attempt to write only the specified bytes. If the writes do not stick, 1054 it will return an error. 1055 1056 Arguments: 1057 This - Calling context 1058 Lba - Block in which to begin Read 1059 Offset - Offset in the block at which to begin Read 1060 NumBytes - On input, indicates the requested write size. On 1061 output, indicates the actual number of bytes Read 1062 Buffer - Buffer containing source data for the Read. 1063 1064 Returns: 1065 EFI_SUCCESS - The firmware volume was read successfully and 1066 contents are in Buffer 1067 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, 1068 NumBytes contains the total number of bytes returned 1069 in Buffer 1070 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state 1071 EFI_DEVICE_ERROR - The block device is not functioning correctly and 1072 could not be read 1073 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL 1074 1075 --*/ 1076 { 1077 1078 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1079 1080 FvbDevice = FVB_DEVICE_FROM_THIS (This); 1081 1082 return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); 1083 } 1084 1085 EFI_STATUS 1086 ValidateFvHeader ( 1087 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader 1088 ) 1089 /*++ 1090 1091 Routine Description: 1092 Check the integrity of firmware volume header 1093 1094 Arguments: 1095 FwVolHeader - A pointer to a firmware volume header 1096 1097 Returns: 1098 EFI_SUCCESS - The firmware volume is consistent 1099 EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an FV 1100 1101 --*/ 1102 { 1103 // 1104 // Verify the header revision, header signature, length 1105 // Length of FvBlock cannot be 2**64-1 1106 // HeaderLength cannot be an odd number 1107 // 1108 if ((FwVolHeader->Revision != EFI_FVH_REVISION) || 1109 (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || 1110 (FwVolHeader->FvLength == ((UINTN) -1)) || 1111 ((FwVolHeader->HeaderLength & 0x01) != 0) 1112 ) { 1113 return EFI_NOT_FOUND; 1114 } 1115 1116 // 1117 // Verify the header checksum 1118 // 1119 if (CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength) != 0) { 1120 return EFI_NOT_FOUND; 1121 } 1122 1123 return EFI_SUCCESS; 1124 } 1125 1126 EFI_STATUS 1127 EFIAPI 1128 FvbInitialize ( 1129 IN EFI_HANDLE ImageHandle, 1130 IN EFI_SYSTEM_TABLE *SystemTable 1131 ) 1132 /*++ 1133 1134 Routine Description: 1135 This function does common initialization for FVB services 1136 1137 Arguments: 1138 1139 Returns: 1140 1141 --*/ 1142 { 1143 EFI_STATUS Status; 1144 EFI_FW_VOL_INSTANCE *FwhInstance; 1145 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; 1146 EFI_DXE_SERVICES *DxeServices; 1147 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; 1148 UINT32 BufferSize; 1149 EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; 1150 EFI_HANDLE FwbHandle; 1151 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; 1152 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; 1153 UINT32 MaxLbaSize; 1154 EFI_PHYSICAL_ADDRESS BaseAddress; 1155 UINT64 Length; 1156 UINTN NumOfBlocks; 1157 EFI_PEI_HOB_POINTERS FvHob; 1158 1159 // 1160 // Get the DXE services table 1161 // 1162 DxeServices = gDS; 1163 1164 // 1165 // Allocate runtime services data for global variable, which contains 1166 // the private data of all firmware volume block instances 1167 // 1168 mFvbModuleGlobal = AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL)); 1169 ASSERT (mFvbModuleGlobal != NULL); 1170 1171 // 1172 // Calculate the total size for all firmware volume block instances 1173 // 1174 BufferSize = 0; 1175 1176 FvHob.Raw = GetHobList (); 1177 while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) { 1178 BaseAddress = FvHob.FirmwareVolume->BaseAddress; 1179 Length = FvHob.FirmwareVolume->Length; 1180 // 1181 // Check if it is a "real" flash 1182 // 1183 Status = DxeServices->GetMemorySpaceDescriptor ( 1184 BaseAddress, 1185 &Descriptor 1186 ); 1187 if (EFI_ERROR (Status)) { 1188 break; 1189 } 1190 1191 if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) { 1192 FvHob.Raw = GET_NEXT_HOB (FvHob); 1193 continue; 1194 } 1195 1196 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; 1197 Status = ValidateFvHeader (FwVolHeader); 1198 if (EFI_ERROR (Status)) { 1199 // 1200 // Get FvbInfo 1201 // 1202 Status = GetFvbInfo (Length, &FwVolHeader); 1203 if (EFI_ERROR (Status)) { 1204 FvHob.Raw = GET_NEXT_HOB (FvHob); 1205 continue; 1206 } 1207 } 1208 1209 BufferSize += (sizeof (EFI_FW_VOL_INSTANCE) + FwVolHeader->HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER)); 1210 FvHob.Raw = GET_NEXT_HOB (FvHob); 1211 } 1212 1213 // 1214 // Only need to allocate once. There is only one copy of physical memory for 1215 // the private data of each FV instance. But in virtual mode or in physical 1216 // mode, the address of the the physical memory may be different. 1217 // 1218 mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] = AllocateRuntimePool (BufferSize); 1219 ASSERT (mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] != NULL); 1220 1221 // 1222 // Make a virtual copy of the FvInstance pointer. 1223 // 1224 FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; 1225 mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance; 1226 1227 mFvbModuleGlobal->NumFv = 0; 1228 MaxLbaSize = 0; 1229 1230 FvHob.Raw = GetHobList (); 1231 while (NULL != (FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw))) { 1232 BaseAddress = FvHob.FirmwareVolume->BaseAddress; 1233 Length = FvHob.FirmwareVolume->Length; 1234 // 1235 // Check if it is a "real" flash 1236 // 1237 Status = DxeServices->GetMemorySpaceDescriptor ( 1238 BaseAddress, 1239 &Descriptor 1240 ); 1241 if (EFI_ERROR (Status)) { 1242 break; 1243 } 1244 1245 if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) { 1246 FvHob.Raw = GET_NEXT_HOB (FvHob); 1247 continue; 1248 } 1249 1250 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; 1251 Status = ValidateFvHeader (FwVolHeader); 1252 if (EFI_ERROR (Status)) { 1253 // 1254 // Get FvbInfo to provide in FwhInstance. 1255 // 1256 Status = GetFvbInfo (Length, &FwVolHeader); 1257 if (EFI_ERROR (Status)) { 1258 FvHob.Raw = GET_NEXT_HOB (FvHob); 1259 continue; 1260 } 1261 // 1262 // Write healthy FV header back. 1263 // 1264 CopyMem ( 1265 (VOID *) (UINTN) BaseAddress, 1266 (VOID *) FwVolHeader, 1267 FwVolHeader->HeaderLength 1268 ); 1269 } 1270 1271 FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress; 1272 FwhInstance->FvBase[FVB_VIRTUAL] = (UINTN) BaseAddress; 1273 1274 CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength); 1275 FwVolHeader = &(FwhInstance->VolumeHeader); 1276 EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL); 1277 1278 NumOfBlocks = 0; 1279 1280 for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { 1281 // 1282 // Get the maximum size of a block. 1283 // 1284 if (MaxLbaSize < PtrBlockMapEntry->Length) { 1285 MaxLbaSize = PtrBlockMapEntry->Length; 1286 } 1287 1288 NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks; 1289 } 1290 // 1291 // The total number of blocks in the FV. 1292 // 1293 FwhInstance->NumOfBlocks = NumOfBlocks; 1294 1295 // 1296 // Add a FVB Protocol Instance 1297 // 1298 FvbDevice = AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE)); 1299 ASSERT (FvbDevice != NULL); 1300 1301 CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE)); 1302 1303 FvbDevice->Instance = mFvbModuleGlobal->NumFv; 1304 mFvbModuleGlobal->NumFv++; 1305 1306 1307 // 1308 // Set up the devicepath 1309 // 1310 if (FwVolHeader->ExtHeaderOffset == 0) { 1311 // 1312 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH 1313 // 1314 FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate); 1315 ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.StartingAddress = BaseAddress; 1316 ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.EndingAddress = BaseAddress + FwVolHeader->FvLength - 1; 1317 } else { 1318 FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate); 1319 CopyGuid ( 1320 &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName, 1321 (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset) 1322 ); 1323 } 1324 // 1325 // Find a handle with a matching device path that has supports FW Block protocol 1326 // 1327 Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &FvbDevice->DevicePath, &FwbHandle); 1328 if (EFI_ERROR (Status)) { 1329 // 1330 // LocateDevicePath fails so install a new interface and device path 1331 // 1332 FwbHandle = NULL; 1333 Status = gBS->InstallMultipleProtocolInterfaces ( 1334 &FwbHandle, 1335 &gEfiFirmwareVolumeBlockProtocolGuid, 1336 &FvbDevice->FwVolBlockInstance, 1337 &gEfiDevicePathProtocolGuid, 1338 FvbDevice->DevicePath, 1339 NULL 1340 ); 1341 ASSERT_EFI_ERROR (Status); 1342 } else if (IsDevicePathEnd (FvbDevice->DevicePath)) { 1343 // 1344 // Device allready exists, so reinstall the FVB protocol 1345 // 1346 Status = gBS->HandleProtocol ( 1347 FwbHandle, 1348 &gEfiFirmwareVolumeBlockProtocolGuid, 1349 (VOID**)&OldFwbInterface 1350 ); 1351 ASSERT_EFI_ERROR (Status); 1352 1353 Status = gBS->ReinstallProtocolInterface ( 1354 FwbHandle, 1355 &gEfiFirmwareVolumeBlockProtocolGuid, 1356 OldFwbInterface, 1357 &FvbDevice->FwVolBlockInstance 1358 ); 1359 ASSERT_EFI_ERROR (Status); 1360 1361 } else { 1362 // 1363 // There was a FVB protocol on an End Device Path node 1364 // 1365 ASSERT (FALSE); 1366 } 1367 1368 FwhInstance = (EFI_FW_VOL_INSTANCE *) 1369 ( 1370 (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + 1371 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) 1372 ); 1373 1374 FvHob.Raw = GET_NEXT_HOB (FvHob); 1375 } 1376 1377 return EFI_SUCCESS; 1378 } 1379