]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.c
Add Missing invocations to VA_END() for VA_START().
[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 - 2012, 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 VA_END (args);
383 }
384
385 return EFI_SUCCESS;
386 }
387
388
389 /**
390 Writes the specified number of bytes from the input buffer to the block.
391
392 The Write() function writes the specified number of bytes from
393 the provided buffer to the specified block and offset. If the
394 firmware volume is sticky write, the caller must ensure that
395 all the bits of the specified range to write are in the
396 EFI_FVB_ERASE_POLARITY state before calling the Write()
397 function, or else the result will be unpredictable. This
398 unpredictability arises because, for a sticky-write firmware
399 volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
400 state but cannot flip it back again. In general, before
401 calling the Write() function, the caller should call the
402 EraseBlocks() function first to erase the specified block to
403 write. A block erase cycle will transition bits from the
404 (NOT)EFI_FVB_ERASE_POLARITY state back to the
405 EFI_FVB_ERASE_POLARITY state. Implementations should be
406 mindful that the firmware volume might be in the WriteDisabled
407 state. If it is in this state, the Write() function must
408 return the status code EFI_ACCESS_DENIED without modifying the
409 contents of the firmware volume. The Write() function must
410 also prevent spanning block boundaries. If a write is
411 requested that spans a block boundary, the write must store up
412 to the boundary but not beyond. The output parameter NumBytes
413 must be set to correctly indicate the number of bytes actually
414 written. The caller must be aware that a write may be
415 partially completed. All writes, partial or otherwise, must be
416 fully flushed to the hardware before the Write() service
417 returns.
418
419 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
420
421 @param Lba The starting logical block index to write to.
422
423 @param Offset Offset into the block at which to begin writing.
424
425 @param NumBytes Pointer to a UINTN. At entry, *NumBytes
426 contains the total size of the buffer. At
427 exit, *NumBytes contains the total number of
428 bytes actually written.
429
430 @param Buffer Pointer to a caller-allocated buffer that
431 contains the source for the write.
432
433 @retval EFI_SUCCESS The firmware volume was written successfully.
434
435 @retval EFI_BAD_BUFFER_SIZE The write was attempted across an
436 LBA boundary. On output, NumBytes
437 contains the total number of bytes
438 actually written.
439
440 @retval EFI_ACCESS_DENIED The firmware volume is in the
441 WriteDisabled state.
442
443 @retval EFI_DEVICE_ERROR The block device is malfunctioning
444 and could not be written.
445
446
447 **/
448 EFI_STATUS
449 EFIAPI
450 FvbProtocolWrite (
451 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
452 IN EFI_LBA Lba,
453 IN UINTN Offset,
454 IN OUT UINTN *NumBytes,
455 IN UINT8 *Buffer
456 )
457 {
458
459 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
460 UINT8 *FvbDataPtr;
461
462 FvbDevice = FVB_DEVICE_FROM_THIS (This);
463
464 if ((Lba > 1) || (Offset > FvbDevice->BlockSize)) {
465 return EFI_INVALID_PARAMETER;
466 }
467
468 if ((Offset + *NumBytes) > FvbDevice->BlockSize) {
469 *NumBytes = FvbDevice->BlockSize - Offset;
470 }
471
472 FvbDataPtr =
473 (UINT8*) FvbDevice->BufferPtr +
474 MultU64x32 (Lba, (UINT32) FvbDevice->BlockSize) +
475 Offset;
476
477 if (*NumBytes > 0) {
478 CopyMem (FvbDataPtr, Buffer, *NumBytes);
479 PlatformFvbDataWritten (This, Lba, Offset, *NumBytes, Buffer);
480 }
481
482 return EFI_SUCCESS;
483 }
484
485
486 /**
487 Reads the specified number of bytes into a buffer from the specified block.
488
489 The Read() function reads the requested number of bytes from the
490 requested block and stores them in the provided buffer.
491 Implementations should be mindful that the firmware volume
492 might be in the ReadDisabled state. If it is in this state,
493 the Read() function must return the status code
494 EFI_ACCESS_DENIED without modifying the contents of the
495 buffer. The Read() function must also prevent spanning block
496 boundaries. If a read is requested that would span a block
497 boundary, the read must read up to the boundary but not
498 beyond. The output parameter NumBytes must be set to correctly
499 indicate the number of bytes actually read. The caller must be
500 aware that a read may be partially completed.
501
502 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
503
504 @param Lba The starting logical block index
505 from which to read.
506
507 @param Offset Offset into the block at which to begin reading.
508
509 @param NumBytes Pointer to a UINTN. At entry, *NumBytes
510 contains the total size of the buffer. At
511 exit, *NumBytes contains the total number of
512 bytes read.
513
514 @param Buffer Pointer to a caller-allocated buffer that will
515 be used to hold the data that is read.
516
517 @retval EFI_SUCCESS The firmware volume was read successfully
518 and contents are in Buffer.
519
520 @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA
521 boundary. On output, NumBytes
522 contains the total number of bytes
523 returned in Buffer.
524
525 @retval EFI_ACCESS_DENIED The firmware volume is in the
526 ReadDisabled state.
527
528 @retval EFI_DEVICE_ERROR The block device is not
529 functioning correctly and could
530 not be read.
531
532 **/
533 EFI_STATUS
534 EFIAPI
535 FvbProtocolRead (
536 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
537 IN EFI_LBA Lba,
538 IN UINTN Offset,
539 IN OUT UINTN *NumBytes,
540 IN OUT UINT8 *Buffer
541 )
542 {
543 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
544 UINT8 *FvbDataPtr;
545
546 FvbDevice = FVB_DEVICE_FROM_THIS (This);
547
548 if ((Lba > 1) || (Offset > FvbDevice->BlockSize)) {
549 return EFI_INVALID_PARAMETER;
550 }
551
552 if ((Offset + *NumBytes) > FvbDevice->BlockSize) {
553 *NumBytes = FvbDevice->BlockSize - Offset;
554 }
555
556 FvbDataPtr =
557 (UINT8*) FvbDevice->BufferPtr +
558 MultU64x32 (Lba, (UINT32) FvbDevice->BlockSize) +
559 Offset;
560
561 if (*NumBytes > 0) {
562 CopyMem (Buffer, FvbDataPtr, *NumBytes);
563 PlatformFvbDataRead (This, Lba, Offset, *NumBytes, Buffer);
564 }
565
566 return EFI_SUCCESS;
567 }
568
569
570 /**
571 Check the integrity of firmware volume header.
572
573 @param[in] FwVolHeader - A pointer to a firmware volume header
574
575 @retval EFI_SUCCESS - The firmware volume is consistent
576 @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
577
578 **/
579 EFI_STATUS
580 ValidateFvHeader (
581 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
582 )
583 {
584 UINT16 Checksum;
585
586 //
587 // Verify the header revision, header signature, length
588 // Length of FvBlock cannot be 2**64-1
589 // HeaderLength cannot be an odd number
590 //
591 if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
592 (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
593 (FwVolHeader->FvLength != EMU_FVB_SIZE) ||
594 (FwVolHeader->HeaderLength != EMU_FV_HEADER_LENGTH)
595 ) {
596 DEBUG ((EFI_D_INFO, "EMU Variable FVB: Basic FV headers were invalid\n"));
597 return EFI_NOT_FOUND;
598 }
599 //
600 // Verify the header checksum
601 //
602 Checksum = CalculateSum16((VOID*) FwVolHeader, FwVolHeader->HeaderLength);
603
604 if (Checksum != 0) {
605 DEBUG ((EFI_D_INFO, "EMU Variable FVB: FV checksum was invalid\n"));
606 return EFI_NOT_FOUND;
607 }
608
609 return EFI_SUCCESS;
610 }
611
612
613 /**
614 Initializes the FV Header and Variable Store Header
615 to support variable operations.
616
617 @param[in] Ptr - Location to initialize the headers
618
619 **/
620 VOID
621 InitializeFvAndVariableStoreHeaders (
622 IN VOID *Ptr
623 )
624 {
625 STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndVarTemplate = {
626 { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;
627 // UINT8 ZeroVector[16];
628 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
629
630 // EFI_GUID FileSystemGuid;
631 EFI_SYSTEM_NV_DATA_FV_GUID,
632
633 // UINT64 FvLength;
634 EMU_FVB_SIZE,
635
636 // UINT32 Signature;
637 EFI_FVH_SIGNATURE,
638
639 // EFI_FVB_ATTRIBUTES_2 Attributes;
640 0x4feff,
641
642 // UINT16 HeaderLength;
643 EMU_FV_HEADER_LENGTH,
644
645 // UINT16 Checksum;
646 0,
647
648 // UINT16 ExtHeaderOffset;
649 0,
650
651 // UINT8 Reserved[1];
652 0,
653
654 // UINT8 Revision;
655 EFI_FVH_REVISION,
656
657 // EFI_FV_BLOCK_MAP_ENTRY BlockMap[1];
658 { 2, // UINT32 NumBlocks;
659 EMU_FVB_BLOCK_SIZE // UINT32 Length;
660 }
661 },
662 // EFI_FV_BLOCK_MAP_ENTRY EndBlockMap;
663 { 0, 0 }, // End of block map
664 { // VARIABLE_STORE_HEADER VarHdr;
665 // EFI_GUID Signature;
666 EFI_VARIABLE_GUID,
667
668 // UINT32 Size;
669 (
670 FixedPcdGet32 (PcdVariableStoreSize) -
671 OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr)
672 ),
673
674 // UINT8 Format;
675 VARIABLE_STORE_FORMATTED,
676
677 // UINT8 State;
678 VARIABLE_STORE_HEALTHY,
679
680 // UINT16 Reserved;
681 0,
682
683 // UINT32 Reserved1;
684 0
685 }
686 };
687 EFI_FIRMWARE_VOLUME_HEADER *Fv;
688
689 //
690 // Copy the template structure into the location
691 //
692 CopyMem (Ptr, (VOID*)&FvAndVarTemplate, sizeof (FvAndVarTemplate));
693
694 //
695 // Update the checksum for the FV header
696 //
697 Fv = (EFI_FIRMWARE_VOLUME_HEADER*) Ptr;
698 Fv->Checksum = CalculateCheckSum16 (Ptr, Fv->HeaderLength);
699 }
700
701
702 /**
703 Initializes the Fault Tolerant Write data structure
704
705 This data structure is used by the Fault Tolerant Write driver.
706
707 @param[in] Buffer - Location for the FTW data structure
708
709 **/
710 VOID
711 InitializeFtwState (
712 IN VOID *Buffer
713 )
714 {
715 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *Hdr;
716 UINT32 TempCrc;
717 STATIC EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER DefaultFtw = {
718 EFI_SYSTEM_NV_DATA_FV_GUID, // EFI_GUID Signature;
719 ERASED_UINT32, // UINT32 Crc;
720 ERASED_BIT, // UINT8 WorkingBlockValid : 1;
721 ERASED_BIT, // UINT8 WorkingBlockInvalid : 1;
722 0, // UINT8 Reserved : 6;
723 { 0, 0, 0 }, // UINT8 Reserved3[3];
724 FTW_WRITE_QUEUE_SIZE // UINT64 WriteQueueSize;
725 };
726
727 CopyMem (Buffer, (VOID*) &DefaultFtw, sizeof (DefaultFtw));
728
729 Hdr = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER*) Buffer;
730
731 //
732 // Calculate checksum.
733 //
734 // The Crc, WorkingBlockValid and WorkingBlockInvalid bits should
735 // be set to the erased state before computing the checksum.
736 //
737 gBS->CalculateCrc32 (Buffer, sizeof (DefaultFtw), &TempCrc);
738 Hdr->Crc = TempCrc;
739
740 //
741 // Mark as valid.
742 //
743 Hdr->WorkingBlockValid = NOT_ERASED_BIT;
744 }
745
746
747 /**
748 Main entry point.
749
750 @param[in] ImageHandle The firmware allocated handle for the EFI image.
751 @param[in] SystemTable A pointer to the EFI System Table.
752
753 @retval EFI_SUCCESS Successfully initialized.
754
755 **/
756 EFI_STATUS
757 EFIAPI
758 FvbInitialize (
759 IN EFI_HANDLE ImageHandle,
760 IN EFI_SYSTEM_TABLE *SystemTable
761 )
762 {
763 EFI_STATUS Status;
764 VOID *Ptr;
765 VOID *SubPtr;
766 BOOLEAN Initialize;
767 EFI_HANDLE Handle;
768 EFI_PHYSICAL_ADDRESS Address;
769
770 DEBUG ((EFI_D_INFO, "EMU Variable FVB Started\n"));
771
772 //
773 // Verify that the PCD's are set correctly.
774 //
775 if (
776 (PcdGet32 (PcdVariableStoreSize) +
777 PcdGet32 (PcdFlashNvStorageFtwWorkingSize)
778 ) >
779 EMU_FVB_BLOCK_SIZE
780 ) {
781 DEBUG ((EFI_D_ERROR, "EMU Variable invalid PCD sizes\n"));
782 return EFI_INVALID_PARAMETER;
783 }
784
785 //
786 // By default we will initialize the FV contents. But, if
787 // PcdEmuVariableNvStoreReserved is non-zero, then we will
788 // use this location for our buffer.
789 //
790 // If this location does not have a proper FV header, then
791 // we will initialize it.
792 //
793 Initialize = TRUE;
794 if (PcdGet64 (PcdEmuVariableNvStoreReserved) != 0) {
795 Ptr = (VOID*)(UINTN) PcdGet64 (PcdEmuVariableNvStoreReserved);
796 DEBUG ((
797 EFI_D_INFO,
798 "EMU Variable FVB: Using pre-reserved block at %p\n",
799 Ptr
800 ));
801 Status = ValidateFvHeader (Ptr);
802 if (!EFI_ERROR (Status)) {
803 DEBUG ((EFI_D_INFO, "EMU Variable FVB: Found valid pre-existing FV\n"));
804 Initialize = FALSE;
805 }
806 } else {
807 Ptr = AllocateAlignedRuntimePages (
808 EFI_SIZE_TO_PAGES (EMU_FVB_SIZE),
809 SIZE_64KB
810 );
811 }
812
813 mEmuVarsFvb.BufferPtr = Ptr;
814
815 //
816 // Initialize the main FV header and variable store header
817 //
818 if (Initialize) {
819 SetMem (Ptr, EMU_FVB_SIZE, ERASED_UINT8);
820 InitializeFvAndVariableStoreHeaders (Ptr);
821 }
822 PcdSet64 (PcdFlashNvStorageVariableBase64, (UINT32)(UINTN) Ptr);
823
824 //
825 // Initialize the Fault Tolerant Write data area
826 //
827 SubPtr = (VOID*) ((UINT8*) Ptr + PcdGet32 (PcdVariableStoreSize));
828 if (Initialize) {
829 InitializeFtwState (SubPtr);
830 }
831 PcdSet32 (PcdFlashNvStorageFtwWorkingBase, (UINT32)(UINTN) SubPtr);
832
833 //
834 // Initialize the Fault Tolerant Write spare block
835 //
836 SubPtr = (VOID*) ((UINT8*) Ptr + EMU_FVB_BLOCK_SIZE);
837 PcdSet32 (PcdFlashNvStorageFtwSpareBase, (UINT32)(UINTN) SubPtr);
838
839 //
840 // Setup FVB device path
841 //
842 Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Ptr;
843 mEmuVarsFvb.DevicePath.MemMapDevPath.StartingAddress = Address;
844 mEmuVarsFvb.DevicePath.MemMapDevPath.EndingAddress = Address + EMU_FVB_SIZE - 1;
845
846 //
847 // Install the protocols
848 //
849 DEBUG ((EFI_D_INFO, "Installing FVB for EMU Variable support\n"));
850 Handle = 0;
851 Status = gBS->InstallMultipleProtocolInterfaces (
852 &Handle,
853 &gEfiFirmwareVolumeBlock2ProtocolGuid,
854 &mEmuVarsFvb.FwVolBlockInstance,
855 &gEfiDevicePathProtocolGuid,
856 &mEmuVarsFvb.DevicePath,
857 NULL
858 );
859 ASSERT_EFI_ERROR (Status);
860
861 //
862 // Register for the virtual address change event
863 //
864 Status = gBS->CreateEventEx (
865 EVT_NOTIFY_SIGNAL,
866 TPL_NOTIFY,
867 FvbVirtualAddressChangeEvent,
868 NULL,
869 &gEfiEventVirtualAddressChangeGuid,
870 &mEmuVarsFvbAddrChangeEvent
871 );
872 ASSERT_EFI_ERROR (Status);
873
874 return EFI_SUCCESS;
875 }
876
877