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