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