]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkPlatformPkg/Platform/SpiFvbServices/FwBlockService.c
MdeModulePkg/Ps2MouseDxe: Use a different FILE_GUID
[mirror_edk2.git] / QuarkPlatformPkg / Platform / SpiFvbServices / FwBlockService.c
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 }