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