]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c
QuarkPlatformPkg/PlatformHelperLib: Move PCAL functions for PEI use
[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
177 ASSERT_EFI_ERROR (SpiProtocol != NULL);\r
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
328/**\r
329 Erase and Write to platform flash.\r
330\r
331 Routine accesses one flash block at a time, each access consists\r
332 of an erase followed by a write of FLASH_BLOCK_SIZE. One or both\r
333 of DoErase & DoWrite params must be TRUE.\r
334\r
335 Limitations:-\r
336 CpuWriteAddress must be aligned to FLASH_BLOCK_SIZE.\r
337 DataSize must be a multiple of FLASH_BLOCK_SIZE.\r
338\r
339 @param Smst If != NULL then InSmm and use to locate\r
340 SpiProtocol.\r
341 @param CpuWriteAddress Address in CPU memory map of flash region.\r
342 @param Data The buffer containing the data to be written.\r
343 @param DataSize Amount of data to write.\r
344 @param DoErase Earse each block.\r
345 @param DoWrite Write to each block.\r
346\r
347 @retval EFI_SUCCESS Operation successful.\r
348 @retval EFI_NOT_READY Required resources not setup.\r
349 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
350 @retval Others Unexpected error happened.\r
351\r
352**/\r
353EFI_STATUS\r
354EFIAPI\r
355PlatformFlashEraseWrite (\r
356 IN VOID *Smst,\r
357 IN UINTN CpuWriteAddress,\r
358 IN UINT8 *Data,\r
359 IN UINTN DataSize,\r
360 IN BOOLEAN DoErase,\r
361 IN BOOLEAN DoWrite\r
362 )\r
363{\r
364 EFI_STATUS Status;\r
365 UINT64 CpuBaseAddress;\r
366 SPI_INIT_INFO *SpiInfo;\r
367 UINT8 *WriteBuf;\r
368 UINTN Index;\r
369 UINTN SpiWriteAddress;\r
370 EFI_SPI_PROTOCOL *SpiProtocol;\r
371\r
372 if (!DoErase && !DoWrite) {\r
373 return EFI_INVALID_PARAMETER;\r
374 }\r
375 if (DoWrite && Data == NULL) {\r
376 return EFI_INVALID_PARAMETER;\r
377 }\r
378 if ((CpuWriteAddress % FLASH_BLOCK_SIZE) != 0) {\r
379 return EFI_INVALID_PARAMETER;\r
380 }\r
381 if ((DataSize % FLASH_BLOCK_SIZE) != 0) {\r
382 return EFI_INVALID_PARAMETER;\r
383 }\r
384 SpiProtocol = LocateSpiProtocol ((EFI_SMM_SYSTEM_TABLE2 *)Smst);\r
385 if (SpiProtocol == NULL) {\r
386 return EFI_NOT_READY;\r
387 }\r
388\r
389 //\r
390 // Find info to allow usage of SpiProtocol->Execute.\r
391 //\r
392 Status = SpiProtocol->Info (\r
393 SpiProtocol,\r
394 &SpiInfo\r
395 );\r
396 if (EFI_ERROR(Status)) {\r
397 return Status;\r
398 }\r
399 ASSERT (SpiInfo->InitTable != NULL);\r
400 ASSERT (SpiInfo->EraseOpcodeIndex < SPI_NUM_OPCODE);\r
401 ASSERT (SpiInfo->ProgramOpcodeIndex < SPI_NUM_OPCODE);\r
402\r
403 CpuBaseAddress = PcdGet32 (PcdFlashAreaBaseAddress) - (UINT32)SpiInfo->InitTable->BiosStartOffset;\r
404 ASSERT(CpuBaseAddress >= (SIZE_4GB - SIZE_8MB));\r
405 if (CpuWriteAddress < CpuBaseAddress) {\r
406 return (EFI_INVALID_PARAMETER);\r
407 }\r
408\r
409 SpiWriteAddress = CpuWriteAddress - ((UINTN) CpuBaseAddress);\r
410 WriteBuf = Data;\r
411 DEBUG (\r
412 (EFI_D_INFO, "PlatformFlashWrite:SpiWriteAddress=%08x EraseIndex=%d WriteIndex=%d\n",\r
413 SpiWriteAddress,\r
414 (UINTN) SpiInfo->EraseOpcodeIndex,\r
415 (UINTN) SpiInfo->ProgramOpcodeIndex\r
416 ));\r
417 for (Index =0; Index < DataSize / FLASH_BLOCK_SIZE; Index++) {\r
418 if (DoErase) {\r
419 DEBUG (\r
420 (EFI_D_INFO, "PlatformFlashWrite:Erase[%04x] SpiWriteAddress=%08x\n",\r
421 Index,\r
422 SpiWriteAddress\r
423 ));\r
424 Status = SpiProtocol->Execute (\r
425 SpiProtocol,\r
426 SpiInfo->EraseOpcodeIndex,// OpcodeIndex\r
427 0, // PrefixOpcodeIndex\r
428 FALSE, // DataCycle\r
429 TRUE, // Atomic\r
430 FALSE, // ShiftOut\r
431 SpiWriteAddress, // Address\r
432 0, // Data Number\r
433 NULL,\r
434 EnumSpiRegionAll // SPI_REGION_TYPE\r
435 );\r
436 if (EFI_ERROR(Status)) {\r
437 return Status;\r
438 }\r
439 }\r
440\r
441 if (DoWrite) {\r
442 DEBUG (\r
443 (EFI_D_INFO, "PlatformFlashWrite:Write[%04x] SpiWriteAddress=%08x\n",\r
444 Index,\r
445 SpiWriteAddress\r
446 ));\r
447 Status = SpiProtocol->Execute (\r
448 SpiProtocol,\r
449 SpiInfo->ProgramOpcodeIndex, // OpcodeIndex\r
450 0, // PrefixOpcodeIndex\r
451 TRUE, // DataCycle\r
452 TRUE, // Atomic\r
453 TRUE, // ShiftOut\r
454 SpiWriteAddress, // Address\r
455 FLASH_BLOCK_SIZE, // Data Number\r
456 WriteBuf,\r
457 EnumSpiRegionAll\r
458 );\r
459 if (EFI_ERROR(Status)) {\r
460 return Status;\r
461 }\r
462 WriteBuf+=FLASH_BLOCK_SIZE;\r
463 }\r
464 SpiWriteAddress+=FLASH_BLOCK_SIZE;\r
465 }\r
466 return EFI_SUCCESS;\r
467}\r
468\r
469/** Check if System booted with recovery Boot Stage1 image.\r
470\r
471 @retval TRUE If system booted with recovery Boot Stage1 image.\r
472 @retval FALSE If system booted with normal stage1 image.\r
473\r
474**/\r
475BOOLEAN\r
476EFIAPI\r
477PlatformIsBootWithRecoveryStage1 (\r
478 VOID\r
479 )\r
480{\r
481 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
482 return FALSE;\r
483}\r
484\r