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   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
FvbVirtualAddressChangeEvent(IN EFI_EVENT Event,IN VOID * Context)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
FvbProtocolGetPhysicalAddress(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,OUT EFI_PHYSICAL_ADDRESS * Address)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
FvbProtocolGetBlockSize(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,IN EFI_LBA Lba,OUT UINTN * BlockSize,OUT UINTN * NumberOfBlocks)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
FvbProtocolGetAttributes(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,OUT EFI_FVB_ATTRIBUTES_2 * Attributes)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
FvbProtocolSetAttributes(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,IN OUT EFI_FVB_ATTRIBUTES_2 * Attributes)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
FvbProtocolEraseBlocks(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,...)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
FvbProtocolWrite(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,IN EFI_LBA Lba,IN UINTN Offset,IN OUT UINTN * NumBytes,IN UINT8 * Buffer)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
FvbProtocolRead(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,IN EFI_LBA Lba,IN UINTN Offset,IN OUT UINTN * NumBytes,IN OUT UINT8 * Buffer)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
ValidateFvHeader(IN EFI_FIRMWARE_VOLUME_HEADER * FwVolHeader)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
InitializeFvAndVariableStoreHeaders(IN VOID * Ptr)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       {
665         {
666           2, // UINT32 NumBlocks;
667           EMU_FVB_BLOCK_SIZE  // UINT32 Length;
668         }
669       }
670     },
671     // EFI_FV_BLOCK_MAP_ENTRY     EndBlockMap;
672     { 0, 0 }, // End of block map
673     { // VARIABLE_STORE_HEADER      VarHdr;
674       // EFI_GUID  Signature;
675       EFI_VARIABLE_GUID,
676 
677       // UINT32  Size;
678       (
679         FixedPcdGet32 (PcdVariableStoreSize) -
680         OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr)
681       ),
682 
683       // UINT8   Format;
684       VARIABLE_STORE_FORMATTED,
685 
686       // UINT8   State;
687       VARIABLE_STORE_HEALTHY,
688 
689       // UINT16  Reserved;
690       0,
691 
692       // UINT32  Reserved1;
693       0
694     }
695   };
696 
697   //
698   // Templates for authenticated variable FV header
699   //
700   STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndAuthenticatedVarTemplate = {
701     { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;
702       // UINT8                     ZeroVector[16];
703       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
704 
705       // EFI_GUID                  FileSystemGuid;
706       EFI_SYSTEM_NV_DATA_FV_GUID,
707 
708       // UINT64                    FvLength;
709       EMU_FVB_SIZE,
710 
711       // UINT32                    Signature;
712       EFI_FVH_SIGNATURE,
713 
714       // EFI_FVB_ATTRIBUTES_2      Attributes;
715       0x4feff,
716 
717       // UINT16                    HeaderLength;
718       EMU_FV_HEADER_LENGTH,
719 
720       // UINT16                    Checksum;
721       0,
722 
723       // UINT16                    ExtHeaderOffset;
724       0,
725 
726       // UINT8                     Reserved[1];
727       {0},
728 
729       // UINT8                     Revision;
730       EFI_FVH_REVISION,
731 
732       // EFI_FV_BLOCK_MAP_ENTRY    BlockMap[1];
733       {
734         {
735           2, // UINT32 NumBlocks;
736           EMU_FVB_BLOCK_SIZE  // UINT32 Length;
737         }
738       }
739     },
740     // EFI_FV_BLOCK_MAP_ENTRY     EndBlockMap;
741     { 0, 0 }, // End of block map
742     { // VARIABLE_STORE_HEADER      VarHdr;
743         // EFI_GUID  Signature;     // need authenticated variables for secure boot
744         EFI_AUTHENTICATED_VARIABLE_GUID,
745 
746       // UINT32  Size;
747       (
748         FixedPcdGet32 (PcdVariableStoreSize) -
749         OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr)
750       ),
751 
752       // UINT8   Format;
753       VARIABLE_STORE_FORMATTED,
754 
755       // UINT8   State;
756       VARIABLE_STORE_HEALTHY,
757 
758       // UINT16  Reserved;
759       0,
760 
761       // UINT32  Reserved1;
762       0
763     }
764   };
765 
766   EFI_FIRMWARE_VOLUME_HEADER  *Fv;
767 
768   //
769   // Copy the template structure into the location
770   //
771   if (FeaturePcdGet (PcdSecureBootEnable) == FALSE) {
772     CopyMem (Ptr, (VOID*)&FvAndVarTemplate, sizeof (FvAndVarTemplate));
773   } else {
774     CopyMem (Ptr, (VOID*)&FvAndAuthenticatedVarTemplate, sizeof (FvAndAuthenticatedVarTemplate));
775   }
776 
777   //
778   // Update the checksum for the FV header
779   //
780   Fv = (EFI_FIRMWARE_VOLUME_HEADER*) Ptr;
781   Fv->Checksum = CalculateCheckSum16 (Ptr, Fv->HeaderLength);
782 }
783 
784 /**
785   Main entry point.
786 
787   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
788   @param[in] SystemTable    A pointer to the EFI System Table.
789 
790   @retval EFI_SUCCESS       Successfully initialized.
791 
792 **/
793 EFI_STATUS
794 EFIAPI
FvbInitialize(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)795 FvbInitialize (
796   IN EFI_HANDLE         ImageHandle,
797   IN EFI_SYSTEM_TABLE   *SystemTable
798   )
799 {
800   EFI_STATUS                          Status;
801   VOID                                *Ptr;
802   VOID                                *SubPtr;
803   BOOLEAN                             Initialize;
804   EFI_HANDLE                          Handle;
805   EFI_PHYSICAL_ADDRESS                Address;
806 
807   DEBUG ((EFI_D_INFO, "EMU Variable FVB Started\n"));
808 
809   //
810   // Verify that the PCD's are set correctly.
811   //
812   if (
813        (PcdGet32 (PcdVariableStoreSize) +
814         PcdGet32 (PcdFlashNvStorageFtwWorkingSize)
815        ) >
816        EMU_FVB_BLOCK_SIZE
817      ) {
818     DEBUG ((EFI_D_ERROR, "EMU Variable invalid PCD sizes\n"));
819     return EFI_INVALID_PARAMETER;
820   }
821 
822   if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {
823     DEBUG ((EFI_D_INFO, "Disabling EMU Variable FVB since "
824                         "flash variables appear to be supported.\n"));
825     return EFI_ABORTED;
826   }
827 
828   //
829   // By default we will initialize the FV contents.  But, if
830   // PcdEmuVariableNvStoreReserved is non-zero, then we will
831   // use this location for our buffer.
832   //
833   // If this location does not have a proper FV header, then
834   // we will initialize it.
835   //
836   Initialize = TRUE;
837   if (PcdGet64 (PcdEmuVariableNvStoreReserved) != 0) {
838     Ptr = (VOID*)(UINTN) PcdGet64 (PcdEmuVariableNvStoreReserved);
839     DEBUG ((
840       EFI_D_INFO,
841       "EMU Variable FVB: Using pre-reserved block at %p\n",
842       Ptr
843       ));
844     Status = ValidateFvHeader (Ptr);
845     if (!EFI_ERROR (Status)) {
846       DEBUG ((EFI_D_INFO, "EMU Variable FVB: Found valid pre-existing FV\n"));
847       Initialize = FALSE;
848     }
849   } else {
850     Ptr = AllocateAlignedRuntimePages (
851             EFI_SIZE_TO_PAGES (EMU_FVB_SIZE),
852             SIZE_64KB
853             );
854   }
855 
856   mEmuVarsFvb.BufferPtr = Ptr;
857 
858   //
859   // Initialize the main FV header and variable store header
860   //
861   if (Initialize) {
862     SetMem (Ptr, EMU_FVB_SIZE, ERASED_UINT8);
863     InitializeFvAndVariableStoreHeaders (Ptr);
864   }
865   PcdSet64 (PcdFlashNvStorageVariableBase64, (UINT32)(UINTN) Ptr);
866 
867   //
868   // Initialize the Fault Tolerant Write data area
869   //
870   SubPtr = (VOID*) ((UINT8*) Ptr + PcdGet32 (PcdVariableStoreSize));
871   PcdSet32 (PcdFlashNvStorageFtwWorkingBase, (UINT32)(UINTN) SubPtr);
872 
873   //
874   // Initialize the Fault Tolerant Write spare block
875   //
876   SubPtr = (VOID*) ((UINT8*) Ptr + EMU_FVB_BLOCK_SIZE);
877   PcdSet32 (PcdFlashNvStorageFtwSpareBase, (UINT32)(UINTN) SubPtr);
878 
879   //
880   // Setup FVB device path
881   //
882   Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Ptr;
883   mEmuVarsFvb.DevicePath.MemMapDevPath.StartingAddress = Address;
884   mEmuVarsFvb.DevicePath.MemMapDevPath.EndingAddress = Address + EMU_FVB_SIZE - 1;
885 
886   //
887   // Install the protocols
888   //
889   DEBUG ((EFI_D_INFO, "Installing FVB for EMU Variable support\n"));
890   Handle = 0;
891   Status = gBS->InstallMultipleProtocolInterfaces (
892                   &Handle,
893                   &gEfiFirmwareVolumeBlock2ProtocolGuid,
894                   &mEmuVarsFvb.FwVolBlockInstance,
895                   &gEfiDevicePathProtocolGuid,
896                   &mEmuVarsFvb.DevicePath,
897                   NULL
898                   );
899   ASSERT_EFI_ERROR (Status);
900 
901   //
902   // Register for the virtual address change event
903   //
904   Status = gBS->CreateEventEx (
905                   EVT_NOTIFY_SIGNAL,
906                   TPL_NOTIFY,
907                   FvbVirtualAddressChangeEvent,
908                   NULL,
909                   &gEfiEventVirtualAddressChangeGuid,
910                   &mEmuVarsFvbAddrChangeEvent
911                   );
912   ASSERT_EFI_ERROR (Status);
913 
914   return EFI_SUCCESS;
915 }
916 
917 
918