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//
45EFI_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//
51EFI_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**/
102VOID
103EFIAPI
104FvbVirtualAddressChangeEvent (
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**/
134EFI_STATUS
135EFIAPI
136FvbProtocolGetPhysicalAddress (
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**/
177EFI_STATUS
178EFIAPI
179FvbProtocolGetBlockSize (
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**/
216EFI_STATUS
217EFIAPI
218FvbProtocolGetAttributes (
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**/
258EFI_STATUS
259EFIAPI
260FvbProtocolSetAttributes (
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**/
317EFI_STATUS
318EFIAPI
319FvbProtocolEraseBlocks (
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**/
451EFI_STATUS
452EFIAPI
453FvbProtocolWrite (
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**/
536EFI_STATUS
537EFIAPI
538FvbProtocolRead (
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**/
582EFI_STATUS
583ValidateFvHeader (
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**/
623VOID
624InitializeFvAndVariableStoreHeaders (
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**/
793EFI_STATUS
794EFIAPI
795FvbInitialize (
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