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