hc
2024-03-25 edb30157bad0c0001c32b854271ace01d3b9a16a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/** @file
 
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
 
**/
 
#include <PiPei.h>
#include <Library/PeiServicesTablePointerLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/HobVariableLib.h>
#include <Library/HobLib.h>
#include <Ppi/MemoryDiscovered.h>
#include "Variable.h"
#include "Fce.h"
 
extern EFI_PEI_NOTIFY_DESCRIPTOR mMemoryNotifyList;
 
/**
  This function finds the matched default data and create GUID hob for it. 
  
  @param StoreId  Specifies the type of defaults to retrieve.
  @param SkuId    Specifies the platform board of defaults to retrieve.
 
  @retval EFI_SUCCESS           The matched default data is found.
  @retval EFI_NOT_FOUND         The matched default data is not found.
  @retval EFI_OUT_OF_RESOURCES  No enough resource to create HOB.
 
**/
EFI_STATUS
EFIAPI
CreateDefaultVariableHob (
  IN UINT16  StoreId,
  IN UINT16  SkuId
  )
{
  UINTN                      FvInstance;
  EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
  EFI_FFS_FILE_HEADER        *FfsHeader;
  UINT32                     FileSize;
  EFI_COMMON_SECTION_HEADER  *Section;
  UINT32                     SectionLength;
  EFI_STATUS                 Status;
  BOOLEAN                    DefaultSettingIsFound;
  DEFAULT_DATA               *DefaultData;
  DEFAULT_INFO               *DefaultInfo;
  VARIABLE_STORE_HEADER      *VarStoreHeader;
  VARIABLE_STORE_HEADER      *VarStoreHeaderHob;
  UINT8                      *VarHobPtr;
  UINT8                      *VarPtr;
  UINT32                     VarDataOffset;
  UINT32                     VarHobDataOffset;
  EFI_BOOT_MODE              BootMode;
  BOOLEAN                    IsFirstSection;
  DATA_DELTA                 *DataDelta;
  UINTN                      DataDeltaSize;
  UINTN                      Index;
  CONST EFI_PEI_SERVICES     **PeiServices;
 
  //
  // Get PeiService pointer
  //
  PeiServices = GetPeiServicesTablePointer ();
 
  //
  // Find the FFS file that stores all default data.
  //
  DefaultSettingIsFound = FALSE;
  FvInstance            = 0;
  FfsHeader             = NULL;
  while (((*PeiServices)->FfsFindNextVolume (PeiServices, FvInstance, (VOID **) &FvHeader) == EFI_SUCCESS) &&
         (!DefaultSettingIsFound)) {
    FfsHeader = NULL;
    while ((*PeiServices)->FfsFindNextFile (PeiServices, EFI_FV_FILETYPE_FREEFORM, FvHeader, (VOID **) &FfsHeader) == EFI_SUCCESS) {
      if (CompareGuid ((EFI_GUID *) FfsHeader, &gDefaultDataOptSizeFileGuid)) {
        DefaultSettingIsFound = TRUE;
        break;
      }
    }
    FvInstance ++;
  }
 
  //
  // FFS file is not found.
  //
  if (!DefaultSettingIsFound) {
    return EFI_NOT_FOUND;
  }
 
  //
  // Find the matched default data for the input default ID and plat ID.
  //
  DefaultSettingIsFound = FALSE;
  VarStoreHeaderHob     = NULL;
  VarHobPtr      = NULL;
  DataDelta      = NULL;
  DataDeltaSize  = 0;
  IsFirstSection = TRUE;
  VarStoreHeader = NULL;
  Section  = (EFI_COMMON_SECTION_HEADER *)(FfsHeader + 1);
  FileSize = *(UINT32 *)(FfsHeader->Size) & 0x00FFFFFF;
  while (((UINTN) Section < (UINTN) FfsHeader + FileSize) && !DefaultSettingIsFound) {
    DefaultData = (DEFAULT_DATA *) (Section + 1);
    DefaultInfo   = &(DefaultData->DefaultInfo[0]);
    SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
 
    if (IsFirstSection) {
      //
      // Create HOB to store default data so that Variable driver can use it.
      // Allocate more data for header alignment.
      //
      VarStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) DefaultData + DefaultData->HeaderSize);
      VarStoreHeaderHob = (VARIABLE_STORE_HEADER *) BuildGuidHob (&VarStoreHeader->Signature, VarStoreHeader->Size + HEADER_ALIGNMENT - 1);
      if (VarStoreHeaderHob == NULL) {
        //
        // No enough hob resource.
        //
        return EFI_OUT_OF_RESOURCES;
      }
 
      //
      // Copy variable storage header.
      //
      CopyMem (VarStoreHeaderHob, VarStoreHeader, sizeof (VARIABLE_STORE_HEADER));
      //
      // Copy variable data.
      //
      VarPtr           = (UINT8 *) HEADER_ALIGN ((UINTN) (VarStoreHeader + 1));
      VarDataOffset    = (UINT32) ((UINTN) VarPtr - (UINTN) VarStoreHeader);
      VarHobPtr        = (UINT8 *) HEADER_ALIGN ((UINTN) (VarStoreHeaderHob + 1));
      VarHobDataOffset = (UINT32) ((UINTN) VarHobPtr - (UINTN) VarStoreHeaderHob);
      CopyMem (VarHobPtr, VarPtr, VarStoreHeader->Size - VarDataOffset);
      //
      // Update variable size.
      //
      VarStoreHeaderHob->Size = VarStoreHeader->Size - VarDataOffset + VarHobDataOffset;
 
      //
      // Update Delta Data
      //
      VarHobPtr = (UINT8 *) VarStoreHeaderHob - VarDataOffset + VarHobDataOffset;
    } else {
      //
      // Apply delta setting
      //
      DataDelta     = (DATA_DELTA *) ((UINT8 *) DefaultData + DefaultData->HeaderSize);
      DataDeltaSize = SectionLength - sizeof (EFI_COMMON_SECTION_HEADER) - DefaultData->HeaderSize;
      for (Index = 0; Index < DataDeltaSize / sizeof (DATA_DELTA); Index ++) {
        *((UINT8 *) VarHobPtr + DataDelta[Index].Offset) = DataDelta[Index].Value;
      }
    }
 
    //
    // Find the matched DefaultId and BoardId
    //
    while ((UINTN) DefaultInfo < (UINTN) DefaultData + DefaultData->HeaderSize) {
      if (DefaultInfo->DefaultId == StoreId && DefaultInfo->BoardId == SkuId) {
        DefaultSettingIsFound = TRUE;
        break;
      }
      DefaultInfo ++;
    }
    //
    // Size is 24 bits wide so mask upper 8 bits. 
    // SectionLength is adjusted it is 4 byte aligned.
    // Go to the next section
    //
    SectionLength = (SectionLength + 3) & (~3);
    ASSERT (SectionLength != 0);
    Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
    IsFirstSection = FALSE;
  }
  //
  // Matched default data is not found.
  //
  if (!DefaultSettingIsFound) {
    //
    // Change created HOB type to be unused.
    //
    if (VarStoreHeaderHob != NULL) {
      ((EFI_HOB_GUID_TYPE *)((UINT8 *) VarStoreHeaderHob - sizeof (EFI_HOB_GUID_TYPE)))->Header.HobType = EFI_HOB_TYPE_UNUSED;
    }
    return EFI_NOT_FOUND;
  }
 
  //
  // On recovery boot mode, emulation variable driver will be used.
  // But, Emulation variable only knows normal variable data format. 
  // So, if the default variable data format is authenticated, it needs to be converted to normal data.
  //
  Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode);
  if (BootMode == BOOT_IN_RECOVERY_MODE && 
      CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) {
    Status = (**PeiServices).NotifyPpi (PeiServices, &mMemoryNotifyList);
    ASSERT_EFI_ERROR (Status);
  }
 
  return EFI_SUCCESS;
}