]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / EmuVariableFvbRuntimeDxe / Fvb.c
1 /** @file
2 Firmware Block Services to support emulating non-volatile variables
3 by pretending that a memory buffer is storage for the NV variables.
4
5 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "PiDxe.h"
11 #include <Guid/EventGroup.h>
12 #include <Guid/SystemNvDataGuid.h>
13 #include <Guid/VariableFormat.h>
14
15 #include <Protocol/FirmwareVolumeBlock.h>
16 #include <Protocol/DevicePath.h>
17
18 #include <Library/UefiLib.h>
19 #include <Library/UefiDriverEntryPoint.h>
20 #include <Library/BaseLib.h>
21 #include <Library/UefiRuntimeLib.h>
22 #include <Library/DebugLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/UefiBootServicesTableLib.h>
26 #include <Library/DevicePathLib.h>
27 #include <Library/PcdLib.h>
28 #include <Library/PlatformFvbLib.h>
29 #include "Fvb.h"
30
31 #define EFI_AUTHENTICATED_VARIABLE_GUID \
32 { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }
33
34 //
35 // Virtual Address Change Event
36 //
37 // This is needed for runtime variable access.
38 //
39 EFI_EVENT mEmuVarsFvbAddrChangeEvent = NULL;
40
41 //
42 // This is the single instance supported by this driver. It
43 // supports the FVB and Device Path protocols.
44 //
45 EFI_FW_VOL_BLOCK_DEVICE mEmuVarsFvb = {
46 FVB_DEVICE_SIGNATURE,
47 { // DevicePath
48 {
49 {
50 HARDWARE_DEVICE_PATH,
51 HW_MEMMAP_DP,
52 {
53 sizeof (MEMMAP_DEVICE_PATH),
54 0
55 }
56 },
57 EfiMemoryMappedIO,
58 0,
59 0,
60 },
61 {
62 END_DEVICE_PATH_TYPE,
63 END_ENTIRE_DEVICE_PATH_SUBTYPE,
64 {
65 sizeof (EFI_DEVICE_PATH_PROTOCOL),
66 0
67 }
68 }
69 },
70 NULL, // BufferPtr
71 EMU_FVB_BLOCK_SIZE, // BlockSize
72 EMU_FVB_SIZE, // Size
73 { // FwVolBlockInstance
74 FvbProtocolGetAttributes,
75 FvbProtocolSetAttributes,
76 FvbProtocolGetPhysicalAddress,
77 FvbProtocolGetBlockSize,
78 FvbProtocolRead,
79 FvbProtocolWrite,
80 FvbProtocolEraseBlocks,
81 NULL
82 },
83 };
84
85 /**
86 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
87
88 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
89 It converts pointer to new virtual address.
90
91 @param Event Event whose notification function is being invoked.
92 @param Context Pointer to the notification function's context.
93
94 **/
95 VOID
96 EFIAPI
97 FvbVirtualAddressChangeEvent (
98 IN EFI_EVENT Event,
99 IN VOID *Context
100 )
101 {
102 EfiConvertPointer (0x0, &mEmuVarsFvb.BufferPtr);
103 }
104
105 //
106 // FVB protocol APIs
107 //
108
109 /**
110 The GetPhysicalAddress() function retrieves the base address of
111 a memory-mapped firmware volume. This function should be called
112 only for memory-mapped firmware volumes.
113
114 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
115
116 @param Address Pointer to a caller-allocated
117 EFI_PHYSICAL_ADDRESS that, on successful
118 return from GetPhysicalAddress(), contains the
119 base address of the firmware volume.
120
121 @retval EFI_SUCCESS The firmware volume base address is returned.
122
123 @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
124
125 **/
126 EFI_STATUS
127 EFIAPI
128 FvbProtocolGetPhysicalAddress (
129 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
130 OUT EFI_PHYSICAL_ADDRESS *Address
131 )
132 {
133 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
134
135 FvbDevice = FVB_DEVICE_FROM_THIS (This);
136
137 *Address = (EFI_PHYSICAL_ADDRESS)(UINTN)FvbDevice->BufferPtr;
138
139 return EFI_SUCCESS;
140 }
141
142 /**
143 The GetBlockSize() function retrieves the size of the requested
144 block. It also returns the number of additional blocks with
145 the identical size. The GetBlockSize() function is used to
146 retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
147
148
149 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
150
151 @param Lba Indicates the block for which to return the size.
152
153 @param BlockSize Pointer to a caller-allocated UINTN in which
154 the size of the block is returned.
155
156 @param NumberOfBlocks Pointer to a caller-allocated UINTN in
157 which the number of consecutive blocks,
158 starting with Lba, is returned. All
159 blocks in this range have a size of
160 BlockSize.
161
162
163 @retval EFI_SUCCESS The firmware volume base address is returned.
164
165 @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
166
167 **/
168 EFI_STATUS
169 EFIAPI
170 FvbProtocolGetBlockSize (
171 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
172 IN EFI_LBA Lba,
173 OUT UINTN *BlockSize,
174 OUT UINTN *NumberOfBlocks
175 )
176 {
177 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
178
179 if (Lba >= EMU_FVB_NUM_TOTAL_BLOCKS) {
180 return EFI_INVALID_PARAMETER;
181 }
182
183 FvbDevice = FVB_DEVICE_FROM_THIS (This);
184
185 *BlockSize = FvbDevice->BlockSize;
186 *NumberOfBlocks = (UINTN)(EMU_FVB_NUM_TOTAL_BLOCKS - Lba);
187
188 return EFI_SUCCESS;
189 }
190
191 /**
192 The GetAttributes() function retrieves the attributes and
193 current settings of the block. Status Codes Returned
194
195 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
196
197 @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the
198 attributes and current settings are
199 returned. Type EFI_FVB_ATTRIBUTES_2 is defined
200 in EFI_FIRMWARE_VOLUME_HEADER.
201
202 @retval EFI_SUCCESS The firmware volume attributes were
203 returned.
204
205 **/
206 EFI_STATUS
207 EFIAPI
208 FvbProtocolGetAttributes (
209 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
210 OUT EFI_FVB_ATTRIBUTES_2 *Attributes
211 )
212 {
213 *Attributes =
214 (EFI_FVB_ATTRIBUTES_2)(
215 EFI_FVB2_READ_ENABLED_CAP |
216 EFI_FVB2_READ_STATUS |
217 EFI_FVB2_WRITE_ENABLED_CAP |
218 EFI_FVB2_WRITE_STATUS |
219 EFI_FVB2_ERASE_POLARITY
220 );
221
222 return EFI_SUCCESS;
223 }
224
225 /**
226 The SetAttributes() function sets configurable firmware volume
227 attributes and returns the new settings of the firmware volume.
228
229 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
230
231 @param Attributes On input, Attributes is a pointer to
232 EFI_FVB_ATTRIBUTES_2 that contains the
233 desired firmware volume settings. On
234 successful return, it contains the new
235 settings of the firmware volume. Type
236 EFI_FVB_ATTRIBUTES_2 is defined in
237 EFI_FIRMWARE_VOLUME_HEADER.
238
239 @retval EFI_SUCCESS The firmware volume attributes were returned.
240
241 @retval EFI_INVALID_PARAMETER The attributes requested are in
242 conflict with the capabilities
243 as declared in the firmware
244 volume header.
245
246 **/
247 EFI_STATUS
248 EFIAPI
249 FvbProtocolSetAttributes (
250 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
251 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
252 )
253 {
254 return EFI_ACCESS_DENIED;
255 }
256
257 /**
258 Erases and initializes a firmware volume block.
259
260 The EraseBlocks() function erases one or more blocks as denoted
261 by the variable argument list. The entire parameter list of
262 blocks must be verified before erasing any blocks. If a block is
263 requested that does not exist within the associated firmware
264 volume (it has a larger index than the last block of the
265 firmware volume), the EraseBlocks() function must return the
266 status code EFI_INVALID_PARAMETER without modifying the contents
267 of the firmware volume. Implementations should be mindful that
268 the firmware volume might be in the WriteDisabled state. If it
269 is in this state, the EraseBlocks() function must return the
270 status code EFI_ACCESS_DENIED without modifying the contents of
271 the firmware volume. All calls to EraseBlocks() must be fully
272 flushed to the hardware before the EraseBlocks() service
273 returns.
274
275 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
276 instance.
277
278 @param ... The variable argument list is a list of tuples.
279 Each tuple describes a range of LBAs to erase
280 and consists of the following:
281 - An EFI_LBA that indicates the starting LBA
282 - A UINTN that indicates the number of blocks to
283 erase
284
285 The list is terminated with an
286 EFI_LBA_LIST_TERMINATOR. For example, the
287 following indicates that two ranges of blocks
288 (5-7 and 10-11) are to be erased: EraseBlocks
289 (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
290
291 @retval EFI_SUCCESS The erase request was successfully
292 completed.
293
294 @retval EFI_ACCESS_DENIED The firmware volume is in the
295 WriteDisabled state.
296 @retval EFI_DEVICE_ERROR The block device is not functioning
297 correctly and could not be written.
298 The firmware device may have been
299 partially erased.
300 @retval EFI_INVALID_PARAMETER One or more of the LBAs listed
301 in the variable argument list do
302 not exist in the firmware volume.
303
304 **/
305 EFI_STATUS
306 EFIAPI
307 FvbProtocolEraseBlocks (
308 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
309 ...
310 )
311 {
312 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
313 VA_LIST Args;
314 EFI_LBA StartingLba;
315 UINTN NumOfLba;
316 UINT8 *ErasePtr;
317 UINTN EraseSize;
318
319 FvbDevice = FVB_DEVICE_FROM_THIS (This);
320
321 //
322 // Check input parameters
323 //
324 VA_START (Args, This);
325 do {
326 StartingLba = VA_ARG (Args, EFI_LBA);
327 if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
328 break;
329 }
330
331 NumOfLba = VA_ARG (Args, UINTN);
332
333 if ((StartingLba > EMU_FVB_NUM_TOTAL_BLOCKS) ||
334 (NumOfLba > EMU_FVB_NUM_TOTAL_BLOCKS - StartingLba))
335 {
336 VA_END (Args);
337 return EFI_INVALID_PARAMETER;
338 }
339 } while (1);
340
341 VA_END (Args);
342
343 //
344 // Erase blocks
345 //
346 VA_START (Args, This);
347 do {
348 StartingLba = VA_ARG (Args, EFI_LBA);
349 if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
350 break;
351 }
352
353 NumOfLba = VA_ARG (Args, UINTN);
354
355 ErasePtr = FvbDevice->BufferPtr;
356 ErasePtr += (UINTN)StartingLba * FvbDevice->BlockSize;
357 EraseSize = NumOfLba * FvbDevice->BlockSize;
358
359 SetMem (ErasePtr, EraseSize, ERASED_UINT8);
360 } while (1);
361
362 VA_END (Args);
363
364 //
365 // Call platform hook
366 //
367 VA_START (Args, This);
368 PlatformFvbBlocksErased (This, Args);
369 VA_END (Args);
370
371 return EFI_SUCCESS;
372 }
373
374 /**
375 Writes the specified number of bytes from the input buffer to the block.
376
377 The Write() function writes the specified number of bytes from
378 the provided buffer to the specified block and offset. If the
379 firmware volume is sticky write, the caller must ensure that
380 all the bits of the specified range to write are in the
381 EFI_FVB_ERASE_POLARITY state before calling the Write()
382 function, or else the result will be unpredictable. This
383 unpredictability arises because, for a sticky-write firmware
384 volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
385 state but cannot flip it back again. In general, before
386 calling the Write() function, the caller should call the
387 EraseBlocks() function first to erase the specified block to
388 write. A block erase cycle will transition bits from the
389 (NOT)EFI_FVB_ERASE_POLARITY state back to the
390 EFI_FVB_ERASE_POLARITY state. Implementations should be
391 mindful that the firmware volume might be in the WriteDisabled
392 state. If it is in this state, the Write() function must
393 return the status code EFI_ACCESS_DENIED without modifying the
394 contents of the firmware volume. The Write() function must
395 also prevent spanning block boundaries. If a write is
396 requested that spans a block boundary, the write must store up
397 to the boundary but not beyond. The output parameter NumBytes
398 must be set to correctly indicate the number of bytes actually
399 written. The caller must be aware that a write may be
400 partially completed. All writes, partial or otherwise, must be
401 fully flushed to the hardware before the Write() service
402 returns.
403
404 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
405
406 @param Lba The starting logical block index to write to.
407
408 @param Offset Offset into the block at which to begin writing.
409
410 @param NumBytes Pointer to a UINTN. At entry, *NumBytes
411 contains the total size of the buffer. At
412 exit, *NumBytes contains the total number of
413 bytes actually written.
414
415 @param Buffer Pointer to a caller-allocated buffer that
416 contains the source for the write.
417
418 @retval EFI_SUCCESS The firmware volume was written successfully.
419
420 @retval EFI_BAD_BUFFER_SIZE The write was attempted across an
421 LBA boundary. On output, NumBytes
422 contains the total number of bytes
423 actually written.
424
425 @retval EFI_ACCESS_DENIED The firmware volume is in the
426 WriteDisabled state.
427
428 @retval EFI_DEVICE_ERROR The block device is malfunctioning
429 and could not be written.
430
431
432 **/
433 EFI_STATUS
434 EFIAPI
435 FvbProtocolWrite (
436 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
437 IN EFI_LBA Lba,
438 IN UINTN Offset,
439 IN OUT UINTN *NumBytes,
440 IN UINT8 *Buffer
441 )
442 {
443 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
444 UINT8 *FvbDataPtr;
445 EFI_STATUS Status;
446
447 FvbDevice = FVB_DEVICE_FROM_THIS (This);
448
449 if ((Lba >= EMU_FVB_NUM_TOTAL_BLOCKS) ||
450 (Offset > FvbDevice->BlockSize))
451 {
452 return EFI_INVALID_PARAMETER;
453 }
454
455 Status = EFI_SUCCESS;
456 if (*NumBytes > FvbDevice->BlockSize - Offset) {
457 *NumBytes = FvbDevice->BlockSize - Offset;
458 Status = EFI_BAD_BUFFER_SIZE;
459 }
460
461 FvbDataPtr = FvbDevice->BufferPtr;
462 FvbDataPtr += (UINTN)Lba * FvbDevice->BlockSize;
463 FvbDataPtr += Offset;
464
465 CopyMem (FvbDataPtr, Buffer, *NumBytes);
466 PlatformFvbDataWritten (This, Lba, Offset, *NumBytes, Buffer);
467 return Status;
468 }
469
470 /**
471 Reads the specified number of bytes into a buffer from the specified block.
472
473 The Read() function reads the requested number of bytes from the
474 requested block and stores them in the provided buffer.
475 Implementations should be mindful that the firmware volume
476 might be in the ReadDisabled state. If it is in this state,
477 the Read() function must return the status code
478 EFI_ACCESS_DENIED without modifying the contents of the
479 buffer. The Read() function must also prevent spanning block
480 boundaries. If a read is requested that would span a block
481 boundary, the read must read up to the boundary but not
482 beyond. The output parameter NumBytes must be set to correctly
483 indicate the number of bytes actually read. The caller must be
484 aware that a read may be partially completed.
485
486 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
487
488 @param Lba The starting logical block index
489 from which to read.
490
491 @param Offset Offset into the block at which to begin reading.
492
493 @param NumBytes Pointer to a UINTN. At entry, *NumBytes
494 contains the total size of the buffer. At
495 exit, *NumBytes contains the total number of
496 bytes read.
497
498 @param Buffer Pointer to a caller-allocated buffer that will
499 be used to hold the data that is read.
500
501 @retval EFI_SUCCESS The firmware volume was read successfully
502 and contents are in Buffer.
503
504 @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA
505 boundary. On output, NumBytes
506 contains the total number of bytes
507 returned in Buffer.
508
509 @retval EFI_ACCESS_DENIED The firmware volume is in the
510 ReadDisabled state.
511
512 @retval EFI_DEVICE_ERROR The block device is not
513 functioning correctly and could
514 not be read.
515
516 **/
517 EFI_STATUS
518 EFIAPI
519 FvbProtocolRead (
520 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
521 IN EFI_LBA Lba,
522 IN UINTN Offset,
523 IN OUT UINTN *NumBytes,
524 IN OUT UINT8 *Buffer
525 )
526 {
527 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
528 UINT8 *FvbDataPtr;
529 EFI_STATUS Status;
530
531 FvbDevice = FVB_DEVICE_FROM_THIS (This);
532
533 if ((Lba >= EMU_FVB_NUM_TOTAL_BLOCKS) ||
534 (Offset > FvbDevice->BlockSize))
535 {
536 return EFI_INVALID_PARAMETER;
537 }
538
539 Status = EFI_SUCCESS;
540 if (*NumBytes > FvbDevice->BlockSize - Offset) {
541 *NumBytes = FvbDevice->BlockSize - Offset;
542 Status = EFI_BAD_BUFFER_SIZE;
543 }
544
545 FvbDataPtr = FvbDevice->BufferPtr;
546 FvbDataPtr += (UINTN)Lba * FvbDevice->BlockSize;
547 FvbDataPtr += Offset;
548
549 CopyMem (Buffer, FvbDataPtr, *NumBytes);
550 PlatformFvbDataRead (This, Lba, Offset, *NumBytes, Buffer);
551 return Status;
552 }
553
554 /**
555 Check the integrity of firmware volume header.
556
557 @param[in] FwVolHeader - A pointer to a firmware volume header
558
559 @retval EFI_SUCCESS - The firmware volume is consistent
560 @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
561
562 **/
563 EFI_STATUS
564 ValidateFvHeader (
565 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
566 )
567 {
568 UINT16 Checksum;
569
570 //
571 // Verify the header revision, header signature, length
572 // Length of FvBlock cannot be 2**64-1
573 // HeaderLength cannot be an odd number
574 //
575 if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
576 (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
577 (FwVolHeader->FvLength != EMU_FVB_SIZE) ||
578 (FwVolHeader->HeaderLength != EMU_FV_HEADER_LENGTH)
579 )
580 {
581 DEBUG ((DEBUG_INFO, "EMU Variable FVB: Basic FV headers were invalid\n"));
582 return EFI_NOT_FOUND;
583 }
584
585 //
586 // Verify the header checksum
587 //
588 Checksum = CalculateSum16 ((VOID *)FwVolHeader, FwVolHeader->HeaderLength);
589
590 if (Checksum != 0) {
591 DEBUG ((DEBUG_INFO, "EMU Variable FVB: FV checksum was invalid\n"));
592 return EFI_NOT_FOUND;
593 }
594
595 return EFI_SUCCESS;
596 }
597
598 /**
599 Initializes the FV Header and Variable Store Header
600 to support variable operations.
601
602 @param[in] Ptr - Location to initialize the headers
603
604 **/
605 VOID
606 InitializeFvAndVariableStoreHeaders (
607 IN VOID *Ptr
608 )
609 {
610 //
611 // Templates for authenticated variable FV header
612 //
613 STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndAuthenticatedVarTemplate = {
614 { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;
615 // UINT8 ZeroVector[16];
616 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
617
618 // EFI_GUID FileSystemGuid;
619 EFI_SYSTEM_NV_DATA_FV_GUID,
620
621 // UINT64 FvLength;
622 EMU_FVB_SIZE,
623
624 // UINT32 Signature;
625 EFI_FVH_SIGNATURE,
626
627 // EFI_FVB_ATTRIBUTES_2 Attributes;
628 0x4feff,
629
630 // UINT16 HeaderLength;
631 EMU_FV_HEADER_LENGTH,
632
633 // UINT16 Checksum;
634 0,
635
636 // UINT16 ExtHeaderOffset;
637 0,
638
639 // UINT8 Reserved[1];
640 { 0 },
641
642 // UINT8 Revision;
643 EFI_FVH_REVISION,
644
645 // EFI_FV_BLOCK_MAP_ENTRY BlockMap[1];
646 {
647 {
648 EMU_FVB_NUM_TOTAL_BLOCKS, // UINT32 NumBlocks;
649 EMU_FVB_BLOCK_SIZE // UINT32 Length;
650 }
651 }
652 },
653 // EFI_FV_BLOCK_MAP_ENTRY EndBlockMap;
654 { 0, 0 }, // End of block map
655 { // VARIABLE_STORE_HEADER VarHdr;
656 // EFI_GUID Signature; // need authenticated variables for secure boot
657 EFI_AUTHENTICATED_VARIABLE_GUID,
658
659 // UINT32 Size;
660 (
661 FixedPcdGet32 (PcdFlashNvStorageVariableSize) -
662 OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr)
663 ),
664
665 // UINT8 Format;
666 VARIABLE_STORE_FORMATTED,
667
668 // UINT8 State;
669 VARIABLE_STORE_HEALTHY,
670
671 // UINT16 Reserved;
672 0,
673
674 // UINT32 Reserved1;
675 0
676 }
677 };
678
679 EFI_FIRMWARE_VOLUME_HEADER *Fv;
680
681 //
682 // Copy the template structure into the location
683 //
684 CopyMem (
685 Ptr,
686 &FvAndAuthenticatedVarTemplate,
687 sizeof FvAndAuthenticatedVarTemplate
688 );
689
690 //
691 // Update the checksum for the FV header
692 //
693 Fv = (EFI_FIRMWARE_VOLUME_HEADER *)Ptr;
694 Fv->Checksum = CalculateCheckSum16 (Ptr, Fv->HeaderLength);
695 }
696
697 /**
698 Main entry point.
699
700 @param[in] ImageHandle The firmware allocated handle for the EFI image.
701 @param[in] SystemTable A pointer to the EFI System Table.
702
703 @retval EFI_SUCCESS Successfully initialized.
704
705 **/
706 EFI_STATUS
707 EFIAPI
708 FvbInitialize (
709 IN EFI_HANDLE ImageHandle,
710 IN EFI_SYSTEM_TABLE *SystemTable
711 )
712 {
713 EFI_STATUS Status;
714 VOID *Ptr;
715 VOID *SubPtr;
716 BOOLEAN Initialize;
717 EFI_HANDLE Handle;
718 EFI_PHYSICAL_ADDRESS Address;
719 RETURN_STATUS PcdStatus;
720
721 DEBUG ((DEBUG_INFO, "EMU Variable FVB Started\n"));
722
723 //
724 // Verify that the PCD's are set correctly.
725 //
726 ASSERT (
727 FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) %
728 EMU_FVB_BLOCK_SIZE == 0
729 );
730 if (
731 (PcdGet32 (PcdFlashNvStorageVariableSize) +
732 PcdGet32 (PcdFlashNvStorageFtwWorkingSize)
733 ) >
734 EMU_FVB_NUM_SPARE_BLOCKS * EMU_FVB_BLOCK_SIZE
735 )
736 {
737 DEBUG ((DEBUG_ERROR, "EMU Variable invalid PCD sizes\n"));
738 return EFI_INVALID_PARAMETER;
739 }
740
741 if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {
742 DEBUG ((
743 DEBUG_INFO,
744 "Disabling EMU Variable FVB since "
745 "flash variables appear to be supported.\n"
746 ));
747 return EFI_ABORTED;
748 }
749
750 //
751 // By default we will initialize the FV contents. But, if
752 // PcdEmuVariableNvStoreReserved is non-zero, then we will
753 // use this location for our buffer.
754 //
755 // If this location does not have a proper FV header, then
756 // we will initialize it.
757 //
758 Initialize = TRUE;
759 if (PcdGet64 (PcdEmuVariableNvStoreReserved) != 0) {
760 Ptr = (VOID *)(UINTN)PcdGet64 (PcdEmuVariableNvStoreReserved);
761 DEBUG ((
762 DEBUG_INFO,
763 "EMU Variable FVB: Using pre-reserved block at %p\n",
764 Ptr
765 ));
766 Status = ValidateFvHeader (Ptr);
767 if (!EFI_ERROR (Status)) {
768 DEBUG ((DEBUG_INFO, "EMU Variable FVB: Found valid pre-existing FV\n"));
769 Initialize = FALSE;
770 }
771 } else {
772 Ptr = AllocateRuntimePages (EFI_SIZE_TO_PAGES (EMU_FVB_SIZE));
773 }
774
775 mEmuVarsFvb.BufferPtr = Ptr;
776
777 //
778 // Initialize the main FV header and variable store header
779 //
780 if (Initialize) {
781 SetMem (Ptr, EMU_FVB_SIZE, ERASED_UINT8);
782 InitializeFvAndVariableStoreHeaders (Ptr);
783 }
784
785 PcdStatus = PcdSet64S (PcdFlashNvStorageVariableBase64, (UINTN)Ptr);
786 ASSERT_RETURN_ERROR (PcdStatus);
787
788 //
789 // Initialize the Fault Tolerant Write data area
790 //
791 SubPtr = (VOID *)((UINT8 *)Ptr + PcdGet32 (PcdFlashNvStorageVariableSize));
792 PcdStatus = PcdSet64S (
793 PcdFlashNvStorageFtwWorkingBase64,
794 (UINTN)SubPtr
795 );
796 ASSERT_RETURN_ERROR (PcdStatus);
797
798 //
799 // Initialize the Fault Tolerant Write spare block
800 //
801 SubPtr = (VOID *)((UINT8 *)Ptr +
802 EMU_FVB_NUM_SPARE_BLOCKS * EMU_FVB_BLOCK_SIZE);
803 PcdStatus = PcdSet64S (
804 PcdFlashNvStorageFtwSpareBase64,
805 (UINTN)SubPtr
806 );
807 ASSERT_RETURN_ERROR (PcdStatus);
808
809 //
810 // Setup FVB device path
811 //
812 Address = (EFI_PHYSICAL_ADDRESS)(UINTN)Ptr;
813 mEmuVarsFvb.DevicePath.MemMapDevPath.StartingAddress = Address;
814 mEmuVarsFvb.DevicePath.MemMapDevPath.EndingAddress = Address + EMU_FVB_SIZE - 1;
815
816 //
817 // Install the protocols
818 //
819 DEBUG ((DEBUG_INFO, "Installing FVB for EMU Variable support\n"));
820 Handle = 0;
821 Status = gBS->InstallMultipleProtocolInterfaces (
822 &Handle,
823 &gEfiFirmwareVolumeBlock2ProtocolGuid,
824 &mEmuVarsFvb.FwVolBlockInstance,
825 &gEfiDevicePathProtocolGuid,
826 &mEmuVarsFvb.DevicePath,
827 NULL
828 );
829 ASSERT_EFI_ERROR (Status);
830
831 //
832 // Register for the virtual address change event
833 //
834 Status = gBS->CreateEventEx (
835 EVT_NOTIFY_SIGNAL,
836 TPL_NOTIFY,
837 FvbVirtualAddressChangeEvent,
838 NULL,
839 &gEfiEventVirtualAddressChangeGuid,
840 &mEmuVarsFvbAddrChangeEvent
841 );
842 ASSERT_EFI_ERROR (Status);
843
844 return EFI_SUCCESS;
845 }