]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c
IntelFrameworkModulePkg AcpiS3SaveDxe: Remove ASSERT, add lock and remove RT for...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / Acpi / AcpiS3SaveDxe / AcpiVariableThunkPlatform.c
CommitLineData
13d4af68 1/** @file\r
2 This is an implementation of the AcpiVariable platform field for ECP platform.\r
3\r
ef4defca 4Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
13d4af68 5\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions\r
8of the BSD License which accompanies this distribution. The\r
9full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15==\r
16\r
17typedef struct {\r
18 EFI_PHYSICAL_ADDRESS AcpiReservedMemoryBase; <<===\r
19 UINT32 AcpiReservedMemorySize; <<===\r
20 EFI_PHYSICAL_ADDRESS S3ReservedLowMemoryBase;\r
21 EFI_PHYSICAL_ADDRESS AcpiBootScriptTable;\r
22 EFI_PHYSICAL_ADDRESS RuntimeScriptTableBase;\r
23 EFI_PHYSICAL_ADDRESS AcpiFacsTable;\r
24 UINT64 SystemMemoryLength; <<===\r
25 ACPI_CPU_DATA_COMPATIBILITY AcpiCpuData;\r
26 EFI_PHYSICAL_ADDRESS VideoOpromAddress;\r
27 UINT32 VideoOpromSize;\r
28 EFI_PHYSICAL_ADDRESS S3DebugBufferAddress; \r
29 EFI_PHYSICAL_ADDRESS S3ResumeNvsEntryPoint; \r
30} ACPI_VARIABLE_SET_COMPATIBILITY;\r
31\r
32**/\r
33\r
34#include <FrameworkDxe.h>\r
35#include <Library/BaseLib.h>\r
36#include <Library/BaseMemoryLib.h>\r
37#include <Library/UefiBootServicesTableLib.h>\r
38#include <Library/UefiRuntimeServicesTableLib.h>\r
39#include <Library/HobLib.h>\r
40#include <Library/PcdLib.h>\r
41#include <Library/DebugLib.h>\r
ef4defca 42#include <Library/UefiLib.h>\r
13d4af68 43#include <Protocol/FrameworkMpService.h>\r
ef4defca 44#include <Protocol/VariableLock.h>\r
13d4af68 45#include <Guid/AcpiVariableCompatibility.h>\r
46#include <Guid/AcpiS3Context.h>\r
47\r
48GLOBAL_REMOVE_IF_UNREFERENCED\r
49ACPI_VARIABLE_SET_COMPATIBILITY *mAcpiVariableSetCompatibility = NULL;\r
50\r
51/**\r
091249f4 52 Allocate memory below 4G memory address.\r
13d4af68 53\r
091249f4 54 This function allocates memory below 4G memory address.\r
13d4af68 55\r
091249f4 56 @param MemoryType Memory type of memory to allocate.\r
13d4af68 57 @param Size Size of memory to allocate.\r
58 \r
59 @return Allocated address for output.\r
60\r
61**/\r
62VOID*\r
091249f4 63AllocateMemoryBelow4G (\r
73f0127f
SZ
64 IN EFI_MEMORY_TYPE MemoryType,\r
65 IN UINTN Size\r
13d4af68 66 );\r
67\r
68/**\r
69 Hook point for AcpiVariableThunkPlatform for S3Ready.\r
70\r
71 @param AcpiS3Context ACPI s3 context\r
72**/\r
73VOID\r
74S3ReadyThunkPlatform (\r
75 IN ACPI_S3_CONTEXT *AcpiS3Context\r
76 )\r
77{\r
78 EFI_PHYSICAL_ADDRESS AcpiMemoryBase;\r
79 UINT32 AcpiMemorySize;\r
80 EFI_PEI_HOB_POINTERS Hob;\r
81 UINT64 MemoryLength;\r
82\r
83 DEBUG ((EFI_D_INFO, "S3ReadyThunkPlatform\n"));\r
84\r
ef4defca
SZ
85 if (mAcpiVariableSetCompatibility == NULL) {\r
86 return;\r
87 }\r
88\r
13d4af68 89 //\r
90 // Allocate ACPI reserved memory under 4G\r
91 //\r
091249f4 92 AcpiMemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, PcdGet32 (PcdS3AcpiReservedMemorySize));\r
13d4af68 93 ASSERT (AcpiMemoryBase != 0);\r
94 AcpiMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);\r
95\r
96 //\r
97 // Calculate the system memory length by memory hobs\r
98 //\r
99 MemoryLength = 0x100000;\r
100 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
101 ASSERT (Hob.Raw != NULL);\r
102 while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {\r
103 if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
104 //\r
105 // Skip the memory region below 1MB\r
106 //\r
107 if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {\r
108 MemoryLength += Hob.ResourceDescriptor->ResourceLength;\r
109 }\r
110 }\r
111 Hob.Raw = GET_NEXT_HOB (Hob);\r
112 Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r
113 }\r
114\r
115 mAcpiVariableSetCompatibility->AcpiReservedMemoryBase = AcpiMemoryBase;\r
116 mAcpiVariableSetCompatibility->AcpiReservedMemorySize = AcpiMemorySize;\r
117 mAcpiVariableSetCompatibility->SystemMemoryLength = MemoryLength;\r
118\r
119 DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemoryBase is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemoryBase));\r
120 DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemorySize is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemorySize));\r
121 DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: SystemMemoryLength is 0x%8x\n", mAcpiVariableSetCompatibility->SystemMemoryLength));\r
122\r
123 return ;\r
124}\r
125\r
ef4defca
SZ
126/**\r
127 Register callback function upon VariableLockProtocol\r
128 to lock ACPI_GLOBAL_VARIABLE variable to avoid malicious code to update it.\r
129\r
130 @param[in] Event Event whose notification function is being invoked.\r
131 @param[in] Context Pointer to the notification function's context.\r
132**/\r
133VOID\r
134EFIAPI\r
135VariableLockAcpiGlobalVariable (\r
136 IN EFI_EVENT Event,\r
137 IN VOID *Context\r
138 )\r
139{\r
140 EFI_STATUS Status;\r
141 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
142 //\r
143 // Mark ACPI_GLOBAL_VARIABLE variable to read-only if the Variable Lock protocol exists\r
144 //\r
145 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
146 if (!EFI_ERROR (Status)) {\r
147 Status = VariableLock->RequestToLock (VariableLock, ACPI_GLOBAL_VARIABLE, &gEfiAcpiVariableCompatiblityGuid);\r
148 ASSERT_EFI_ERROR (Status);\r
149 }\r
150}\r
151\r
13d4af68 152/**\r
153 Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save.\r
154**/\r
155VOID\r
156InstallAcpiS3SaveThunk (\r
157 VOID\r
158 )\r
159{\r
160 EFI_STATUS Status;\r
161 FRAMEWORK_EFI_MP_SERVICES_PROTOCOL *FrameworkMpService;\r
162 UINTN VarSize;\r
ef4defca 163 VOID *Registration;\r
13d4af68 164\r
165 Status = gBS->LocateProtocol (\r
166 &gFrameworkEfiMpServiceProtocolGuid,\r
167 NULL,\r
168 (VOID**) &FrameworkMpService\r
169 );\r
170 if (!EFI_ERROR (Status)) {\r
171 //\r
172 // On ECP platform, if framework CPU drivers are in use, The compatible version of ACPI variable set \r
173 // should be produced by CPU driver. \r
174 //\r
175 VarSize = sizeof (mAcpiVariableSetCompatibility);\r
176 Status = gRT->GetVariable (\r
177 ACPI_GLOBAL_VARIABLE,\r
178 &gEfiAcpiVariableCompatiblityGuid,\r
179 NULL,\r
180 &VarSize,\r
181 &mAcpiVariableSetCompatibility\r
182 );\r
ef4defca
SZ
183 if (EFI_ERROR (Status) || (VarSize != sizeof (mAcpiVariableSetCompatibility))) {\r
184 DEBUG ((EFI_D_ERROR, "FATAL ERROR: AcpiVariableSetCompatibility was not saved by CPU driver correctly. OS S3 may fail!\n"));\r
185 mAcpiVariableSetCompatibility = NULL;\r
186 }\r
13d4af68 187 } else {\r
188 //\r
189 // Allocate/initialize the compatible version of Acpi Variable Set since Framework chipset/platform \r
ef4defca
SZ
190 // driver need this variable. ACPI_GLOBAL_VARIABLE variable is not used in runtime phase,\r
191 // so RT attribute is not needed for it.\r
13d4af68 192 //\r
091249f4 193 mAcpiVariableSetCompatibility = AllocateMemoryBelow4G (EfiACPIMemoryNVS, sizeof(ACPI_VARIABLE_SET_COMPATIBILITY));\r
13d4af68 194 Status = gRT->SetVariable (\r
195 ACPI_GLOBAL_VARIABLE,\r
196 &gEfiAcpiVariableCompatiblityGuid,\r
ef4defca 197 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
13d4af68 198 sizeof(mAcpiVariableSetCompatibility),\r
199 &mAcpiVariableSetCompatibility\r
200 );\r
ef4defca
SZ
201 if (!EFI_ERROR (Status)) {\r
202 //\r
203 // Register callback function upon VariableLockProtocol\r
204 // to lock ACPI_GLOBAL_VARIABLE variable to avoid malicious code to update it.\r
205 //\r
206 EfiCreateProtocolNotifyEvent (\r
207 &gEdkiiVariableLockProtocolGuid,\r
208 TPL_CALLBACK,\r
209 VariableLockAcpiGlobalVariable,\r
210 NULL,\r
211 &Registration\r
212 );\r
213 } else {\r
214 DEBUG ((EFI_D_ERROR, "FATAL ERROR: AcpiVariableSetCompatibility cannot be saved: %r. OS S3 may fail!\n", Status));\r
215 gBS->FreePages (\r
216 (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiVariableSetCompatibility,\r
217 EFI_SIZE_TO_PAGES (sizeof (ACPI_VARIABLE_SET_COMPATIBILITY))\r
218 );\r
219 mAcpiVariableSetCompatibility = NULL;\r
220 }\r
13d4af68 221 }\r
222\r
223 DEBUG((EFI_D_INFO, "AcpiVariableSetCompatibility is 0x%8x\n", mAcpiVariableSetCompatibility));\r
224}\r