]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiVariableThunkPlatform.c
IntelFrameworkModulePkg: Clean up source files
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / Acpi / AcpiS3SaveDxe / AcpiVariableThunkPlatform.c
... / ...
CommitLineData
1/** @file\r
2 This is an implementation of the AcpiVariable platform field for ECP platform.\r
3\r
4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
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
42#include <Library/UefiLib.h>\r
43#include <Protocol/FrameworkMpService.h>\r
44#include <Protocol/VariableLock.h>\r
45#include <Guid/AcpiVariableCompatibility.h>\r
46\r
47GLOBAL_REMOVE_IF_UNREFERENCED\r
48ACPI_VARIABLE_SET_COMPATIBILITY *mAcpiVariableSetCompatibility = NULL;\r
49\r
50/**\r
51 Allocate memory below 4G memory address.\r
52\r
53 This function allocates memory below 4G memory address.\r
54\r
55 @param MemoryType Memory type of memory to allocate.\r
56 @param Size Size of memory to allocate.\r
57\r
58 @return Allocated address for output.\r
59\r
60**/\r
61VOID*\r
62AllocateMemoryBelow4G (\r
63 IN EFI_MEMORY_TYPE MemoryType,\r
64 IN UINTN Size\r
65 );\r
66\r
67/**\r
68 Hook point for AcpiVariableThunkPlatform for S3Ready.\r
69\r
70**/\r
71VOID\r
72S3ReadyThunkPlatform (\r
73 VOID\r
74 )\r
75{\r
76 EFI_PHYSICAL_ADDRESS AcpiMemoryBase;\r
77 UINT32 AcpiMemorySize;\r
78 EFI_PEI_HOB_POINTERS Hob;\r
79 UINT64 MemoryLength;\r
80\r
81 DEBUG ((EFI_D_INFO, "S3ReadyThunkPlatform\n"));\r
82\r
83 if (mAcpiVariableSetCompatibility == NULL) {\r
84 return;\r
85 }\r
86\r
87 //\r
88 // Allocate ACPI reserved memory under 4G\r
89 //\r
90 AcpiMemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, PcdGet32 (PcdS3AcpiReservedMemorySize));\r
91 ASSERT (AcpiMemoryBase != 0);\r
92 AcpiMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);\r
93\r
94 //\r
95 // Calculate the system memory length by memory hobs\r
96 //\r
97 MemoryLength = 0x100000;\r
98 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
99 ASSERT (Hob.Raw != NULL);\r
100 while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {\r
101 if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
102 //\r
103 // Skip the memory region below 1MB\r
104 //\r
105 if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {\r
106 MemoryLength += Hob.ResourceDescriptor->ResourceLength;\r
107 }\r
108 }\r
109 Hob.Raw = GET_NEXT_HOB (Hob);\r
110 Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r
111 }\r
112\r
113 mAcpiVariableSetCompatibility->AcpiReservedMemoryBase = AcpiMemoryBase;\r
114 mAcpiVariableSetCompatibility->AcpiReservedMemorySize = AcpiMemorySize;\r
115 mAcpiVariableSetCompatibility->SystemMemoryLength = MemoryLength;\r
116\r
117 DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemoryBase is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemoryBase));\r
118 DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemorySize is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemorySize));\r
119 DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: SystemMemoryLength is 0x%8x\n", mAcpiVariableSetCompatibility->SystemMemoryLength));\r
120\r
121 return ;\r
122}\r
123\r
124/**\r
125 Register callback function upon VariableLockProtocol\r
126 to lock ACPI_GLOBAL_VARIABLE variable to avoid malicious code to update it.\r
127\r
128 @param[in] Event Event whose notification function is being invoked.\r
129 @param[in] Context Pointer to the notification function's context.\r
130**/\r
131VOID\r
132EFIAPI\r
133VariableLockAcpiGlobalVariable (\r
134 IN EFI_EVENT Event,\r
135 IN VOID *Context\r
136 )\r
137{\r
138 EFI_STATUS Status;\r
139 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
140 //\r
141 // Mark ACPI_GLOBAL_VARIABLE variable to read-only if the Variable Lock protocol exists\r
142 //\r
143 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
144 if (!EFI_ERROR (Status)) {\r
145 Status = VariableLock->RequestToLock (VariableLock, ACPI_GLOBAL_VARIABLE, &gEfiAcpiVariableCompatiblityGuid);\r
146 ASSERT_EFI_ERROR (Status);\r
147 }\r
148}\r
149\r
150/**\r
151 Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save.\r
152**/\r
153VOID\r
154InstallAcpiS3SaveThunk (\r
155 VOID\r
156 )\r
157{\r
158 EFI_STATUS Status;\r
159 FRAMEWORK_EFI_MP_SERVICES_PROTOCOL *FrameworkMpService;\r
160 UINTN VarSize;\r
161 VOID *Registration;\r
162\r
163 Status = gBS->LocateProtocol (\r
164 &gFrameworkEfiMpServiceProtocolGuid,\r
165 NULL,\r
166 (VOID**) &FrameworkMpService\r
167 );\r
168 if (!EFI_ERROR (Status)) {\r
169 //\r
170 // On ECP platform, if framework CPU drivers are in use, The compatible version of ACPI variable set\r
171 // should be produced by CPU driver.\r
172 //\r
173 VarSize = sizeof (mAcpiVariableSetCompatibility);\r
174 Status = gRT->GetVariable (\r
175 ACPI_GLOBAL_VARIABLE,\r
176 &gEfiAcpiVariableCompatiblityGuid,\r
177 NULL,\r
178 &VarSize,\r
179 &mAcpiVariableSetCompatibility\r
180 );\r
181 if (EFI_ERROR (Status) || (VarSize != sizeof (mAcpiVariableSetCompatibility))) {\r
182 DEBUG ((EFI_D_ERROR, "FATAL ERROR: AcpiVariableSetCompatibility was not saved by CPU driver correctly. OS S3 may fail!\n"));\r
183 mAcpiVariableSetCompatibility = NULL;\r
184 }\r
185 } else {\r
186 //\r
187 // Allocate/initialize the compatible version of Acpi Variable Set since Framework chipset/platform\r
188 // driver need this variable. ACPI_GLOBAL_VARIABLE variable is not used in runtime phase,\r
189 // so RT attribute is not needed for it.\r
190 //\r
191 mAcpiVariableSetCompatibility = AllocateMemoryBelow4G (EfiACPIMemoryNVS, sizeof(ACPI_VARIABLE_SET_COMPATIBILITY));\r
192 Status = gRT->SetVariable (\r
193 ACPI_GLOBAL_VARIABLE,\r
194 &gEfiAcpiVariableCompatiblityGuid,\r
195 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
196 sizeof(mAcpiVariableSetCompatibility),\r
197 &mAcpiVariableSetCompatibility\r
198 );\r
199 if (!EFI_ERROR (Status)) {\r
200 //\r
201 // Register callback function upon VariableLockProtocol\r
202 // to lock ACPI_GLOBAL_VARIABLE variable to avoid malicious code to update it.\r
203 //\r
204 EfiCreateProtocolNotifyEvent (\r
205 &gEdkiiVariableLockProtocolGuid,\r
206 TPL_CALLBACK,\r
207 VariableLockAcpiGlobalVariable,\r
208 NULL,\r
209 &Registration\r
210 );\r
211 } else {\r
212 DEBUG ((EFI_D_ERROR, "FATAL ERROR: AcpiVariableSetCompatibility cannot be saved: %r. OS S3 may fail!\n", Status));\r
213 gBS->FreePages (\r
214 (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiVariableSetCompatibility,\r
215 EFI_SIZE_TO_PAGES (sizeof (ACPI_VARIABLE_SET_COMPATIBILITY))\r
216 );\r
217 mAcpiVariableSetCompatibility = NULL;\r
218 }\r
219 }\r
220\r
221 DEBUG((EFI_D_INFO, "AcpiVariableSetCompatibility is 0x%8x\n", mAcpiVariableSetCompatibility));\r
222}\r