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