]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c
Merge branch 'master' of https://github.com/tianocore/edk2
[mirror_edk2.git] / QuarkPlatformPkg / Library / PlatformHelperLib / PlatformHelperDxe.c
CommitLineData
b303605e
MK
1/** @file\r
2Implementation of helper routines for DXE environment.\r
3\r
b1169100 4Copyright (c) 2013 - 2016 Intel Corporation.\r
b303605e
MK
5\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include <PiDxe.h>\r
17\r
18#include <Library/UefiBootServicesTableLib.h>\r
19#include <Library/S3BootScriptLib.h>\r
20#include <Library/DxeServicesLib.h>\r
21#include <Library/UefiRuntimeServicesTableLib.h>\r
b303605e
MK
22#include <Protocol/SmmBase2.h>\r
23#include <Protocol/Spi.h>\r
24#include <Protocol/VariableLock.h>\r
25\r
26#include <Guid/MemoryConfigData.h>\r
27#include <Guid/QuarkVariableLock.h>\r
28\r
29#include "CommonHeader.h"\r
30\r
31#define FLASH_BLOCK_SIZE SIZE_4KB\r
32\r
33//\r
34// Global variables.\r
35//\r
36EFI_SPI_PROTOCOL *mPlatHelpSpiProtocolRef = NULL;\r
37\r
38//\r
39// Routines defined in other source modules of this component.\r
40//\r
41\r
42//\r
43// Routines local to this component.\r
44//\r
45\r
46//\r
47// Routines shared with other souce modules in this component.\r
48//\r
49\r
b303605e
MK
50EFI_SPI_PROTOCOL *\r
51LocateSpiProtocol (\r
52 IN EFI_SMM_SYSTEM_TABLE2 *Smst\r
53 )\r
54{\r
55 if (mPlatHelpSpiProtocolRef == NULL) {\r
56 if (Smst != NULL) {\r
57 Smst->SmmLocateProtocol (\r
58 &gEfiSmmSpiProtocolGuid,\r
59 NULL,\r
60 (VOID **) &mPlatHelpSpiProtocolRef\r
61 );\r
62 } else {\r
63 gBS->LocateProtocol (\r
64 &gEfiSpiProtocolGuid,\r
65 NULL,\r
66 (VOID **) &mPlatHelpSpiProtocolRef\r
67 );\r
68 }\r
69 ASSERT (mPlatHelpSpiProtocolRef != NULL);\r
70 }\r
71 return mPlatHelpSpiProtocolRef;\r
72}\r
73\r
74//\r
75// Routines exported by this source module.\r
76//\r
77\r
78/**\r
79 Find pointer to RAW data in Firmware volume file.\r
80\r
81 @param FvNameGuid Firmware volume to search. If == NULL search all.\r
82 @param FileNameGuid Firmware volume file to search for.\r
83 @param SectionData Pointer to RAW data section of found file.\r
84 @param SectionDataSize Pointer to UNITN to get size of RAW data.\r
85\r
86 @retval EFI_SUCCESS Raw Data found.\r
87 @retval EFI_INVALID_PARAMETER FileNameGuid == NULL.\r
88 @retval EFI_NOT_FOUND Firmware volume file not found.\r
89 @retval EFI_UNSUPPORTED Unsupported in current enviroment (PEI or DXE).\r
90\r
91**/\r
92EFI_STATUS\r
93EFIAPI\r
94PlatformFindFvFileRawDataSection (\r
95 IN CONST EFI_GUID *FvNameGuid OPTIONAL,\r
96 IN CONST EFI_GUID *FileNameGuid,\r
97 OUT VOID **SectionData,\r
98 OUT UINTN *SectionDataSize\r
99 )\r
100{\r
101 if (FileNameGuid == NULL || SectionData == NULL || SectionDataSize == NULL) {\r
102 return EFI_INVALID_PARAMETER;\r
103 }\r
104 if (FvNameGuid != NULL) {\r
105 return EFI_UNSUPPORTED; // Searching in specific FV unsupported in DXE.\r
106 }\r
107\r
108 return GetSectionFromAnyFv (FileNameGuid, EFI_SECTION_RAW, 0, SectionData, SectionDataSize);\r
109}\r
110\r
111/**\r
112 Find free spi protect register and write to it to protect a flash region.\r
113\r
114 @param DirectValue Value to directly write to register.\r
115 if DirectValue == 0 the use Base & Length below.\r
116 @param BaseAddress Base address of region in Flash Memory Map.\r
117 @param Length Length of region to protect.\r
118\r
119 @retval EFI_SUCCESS Free spi protect register found & written.\r
120 @retval EFI_NOT_FOUND Free Spi protect register not found.\r
121 @retval EFI_DEVICE_ERROR Unable to write to spi protect register.\r
122**/\r
123EFI_STATUS\r
124EFIAPI\r
125PlatformWriteFirstFreeSpiProtect (\r
126 IN CONST UINT32 DirectValue,\r
127 IN CONST UINT32 BaseAddress,\r
128 IN CONST UINT32 Length\r
129 )\r
130{\r
131 UINT32 FreeOffset;\r
132 UINT32 PchRootComplexBar;\r
133 EFI_STATUS Status;\r
134\r
135 PchRootComplexBar = QNC_RCRB_BASE;\r
136\r
137 Status = WriteFirstFreeSpiProtect (\r
138 PchRootComplexBar,\r
139 DirectValue,\r
140 BaseAddress,\r
141 Length,\r
142 &FreeOffset\r
143 );\r
144\r
145 if (!EFI_ERROR (Status)) {\r
146 S3BootScriptSaveMemWrite (\r
147 S3BootScriptWidthUint32,\r
148 (UINTN) (PchRootComplexBar + FreeOffset),\r
149 1,\r
150 (VOID *) (UINTN) (PchRootComplexBar + FreeOffset)\r
151 );\r
152 }\r
153\r
154 return Status;\r
155}\r
156\r
157/**\r
158 Lock legacy SPI static configuration information.\r
159\r
160 Function will assert if unable to lock config.\r
161\r
162**/\r
163VOID\r
164EFIAPI\r
165PlatformFlashLockConfig (\r
166 VOID\r
167 )\r
168{\r
169 EFI_STATUS Status;\r
170 EFI_SPI_PROTOCOL *SpiProtocol;\r
171\r
172 //\r
173 // Enable lock of legacy SPI static configuration information.\r
174 //\r
175\r
176 SpiProtocol = LocateSpiProtocol (NULL); // This routine will not be called in SMM.\r
74e00be5 177 ASSERT (SpiProtocol != NULL);\r
b303605e
MK
178 if (SpiProtocol != NULL) {\r
179 Status = SpiProtocol->Lock (SpiProtocol);\r
180\r
181 if (!EFI_ERROR (Status)) {\r
182 DEBUG ((EFI_D_INFO, "Platform: Spi Config Locked Down\n"));\r
183 } else if (Status == EFI_ACCESS_DENIED) {\r
184 DEBUG ((EFI_D_INFO, "Platform: Spi Config already locked down\n"));\r
185 } else {\r
186 ASSERT_EFI_ERROR (Status);\r
187 }\r
188 }\r
189}\r
190\r
191/**\r
192 Platform Variable Lock.\r
193\r
194 @retval EFI_SUCCESS Platform Variable Lock successful.\r
195 @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and\r
196 Registration.\r
197\r
198**/\r
199VOID\r
200EFIAPI\r
201PlatformVariableLock (\r
202 )\r
203{\r
204 EFI_STATUS Status;\r
205 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol;\r
206\r
207 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);\r
208 ASSERT_EFI_ERROR (Status);\r
209\r
210 Status = VariableLockProtocol->RequestToLock (\r
211 VariableLockProtocol,\r
212 QUARK_VARIABLE_LOCK_NAME,\r
213 &gQuarkVariableLockGuid\r
214 );\r
215 ASSERT_EFI_ERROR (Status);\r
216\r
217 // Memory Config Data shouldn't be writable when Quark Variable Lock is enabled.\r
218 Status = VariableLockProtocol->RequestToLock (\r
219 VariableLockProtocol,\r
220 EFI_MEMORY_CONFIG_DATA_NAME,\r
221 &gEfiMemoryConfigDataGuid\r
222 );\r
223 ASSERT_EFI_ERROR (Status);\r
224}\r
225\r
226/**\r
227 Lock regions and config of SPI flash given the policy for this platform.\r
228\r
229 Function will assert if unable to lock regions or config.\r
230\r
231 @param PreBootPolicy If TRUE do Pre Boot Flash Lock Policy.\r
232\r
233**/\r
234VOID\r
235EFIAPI\r
236PlatformFlashLockPolicy (\r
237 IN CONST BOOLEAN PreBootPolicy\r
238 )\r
239{\r
240 EFI_STATUS Status;\r
241 UINT64 CpuAddressNvStorage;\r
242 UINT64 CpuAddressFlashDevice;\r
243 UINT64 SpiAddress;\r
244 EFI_BOOT_MODE BootMode;\r
245 UINTN SpiFlashDeviceSize;\r
246\r
247 BootMode = GetBootModeHob ();\r
248\r
249 SpiFlashDeviceSize = (UINTN) PcdGet32 (PcdSpiFlashDeviceSize);\r
250 CpuAddressFlashDevice = SIZE_4GB - SpiFlashDeviceSize;\r
251 DEBUG (\r
252 (EFI_D_INFO,\r
253 "Platform:FlashDeviceSize = 0x%08x Bytes\n",\r
254 SpiFlashDeviceSize)\r
255 );\r
256\r
257 //\r
258 // If not in update or recovery mode, lock stuff down\r
259 //\r
260 if ((BootMode != BOOT_IN_RECOVERY_MODE) && (BootMode != BOOT_ON_FLASH_UPDATE)) {\r
261\r
262 //\r
263 // Lock regions\r
264 //\r
265 CpuAddressNvStorage = (UINT64) PcdGet32 (PcdFlashNvStorageVariableBase);\r
266\r
267 //\r
268 // Lock from start of flash device up to Smi writable flash storage areas.\r
269 //\r
270 SpiAddress = 0;\r
271 if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress, (UINT32) (CpuAddressNvStorage - CpuAddressFlashDevice))) {\r
272 DEBUG (\r
273 (EFI_D_INFO,\r
274 "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",\r
275 (UINTN) SpiAddress, (UINTN)(CpuAddressNvStorage - CpuAddressFlashDevice))\r
276 );\r
277 Status = PlatformWriteFirstFreeSpiProtect (\r
278 0,\r
279 (UINT32) SpiAddress,\r
280 (UINT32) (CpuAddressNvStorage - CpuAddressFlashDevice)\r
281 );\r
282\r
283 ASSERT_EFI_ERROR (Status);\r
284 }\r
285 //\r
286 // Move Spi Address to after Smi writable flash storage areas.\r
287 //\r
288 SpiAddress = CpuAddressNvStorage - CpuAddressFlashDevice;\r
289 SpiAddress += ((UINT64) PcdGet32 (PcdFlashNvStorageVariableSize));\r
290\r
291 //\r
292 // Lock from end of OEM area to end of flash part.\r
293 //\r
294 if (!PlatformIsSpiRangeProtected ((UINT32) SpiAddress, SpiFlashDeviceSize - ((UINT32) SpiAddress))) {\r
295 DEBUG (\r
296 (EFI_D_INFO,\r
297 "Platform: Protect Region Base:Len 0x%08x:0x%08x\n",\r
298 (UINTN) SpiAddress,\r
299 (UINTN) (SpiFlashDeviceSize - ((UINT32) SpiAddress)))\r
300 );\r
301 ASSERT (SpiAddress < ((UINT64) SpiFlashDeviceSize));\r
302 Status = PlatformWriteFirstFreeSpiProtect (\r
303 0,\r
304 (UINT32) SpiAddress,\r
305 SpiFlashDeviceSize - ((UINT32) SpiAddress)\r
306 );\r
307\r
308 ASSERT_EFI_ERROR (Status);\r
309 }\r
310 }\r
311\r
312 //\r
313 // Always Lock flash config registers if about to boot a boot option\r
314 // else lock depending on boot mode.\r
315 //\r
316 if (PreBootPolicy || (BootMode != BOOT_ON_FLASH_UPDATE)) {\r
317 PlatformFlashLockConfig ();\r
318 }\r
319\r
320 //\r
321 // Enable Quark Variable lock if PreBootPolicy.\r
322 //\r
323 if (PreBootPolicy) {\r
324 PlatformVariableLock ();\r
325 }\r
326}\r
327\r
b303605e
MK
328/** Check if System booted with recovery Boot Stage1 image.\r
329\r
330 @retval TRUE If system booted with recovery Boot Stage1 image.\r
331 @retval FALSE If system booted with normal stage1 image.\r
332\r
333**/\r
334BOOLEAN\r
335EFIAPI\r
336PlatformIsBootWithRecoveryStage1 (\r
337 VOID\r
338 )\r
339{\r
340 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
341 return FALSE;\r
342}\r
343\r