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