1 /** @file 2 3 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 LegacyTable.c 14 15 Abstract: 16 17 Revision History: 18 19 **/ 20 21 #include "DxeIpl.h" 22 #include "HobGeneration.h" 23 #include "Debug.h" 24 25 #define MPS_PTR SIGNATURE_32('_','M','P','_') 26 #define SMBIOS_PTR SIGNATURE_32('_','S','M','_') 27 28 #define EBDA_BASE_ADDRESS 0x40E 29 30 VOID * 31 FindAcpiRsdPtr ( 32 VOID 33 ) 34 { 35 UINTN Address; 36 UINTN Index; 37 38 // 39 // First Seach 0x0e0000 - 0x0fffff for RSD Ptr 40 // 41 for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) { 42 if (*(UINT64 *)(Address) == EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) { 43 return (VOID *)Address; 44 } 45 } 46 47 // 48 // Search EBDA 49 // 50 51 Address = (*(UINT16 *)(UINTN)(EBDA_BASE_ADDRESS)) << 4; 52 for (Index = 0; Index < 0x400 ; Index += 16) { 53 if (*(UINT64 *)(Address + Index) == EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) { 54 return (VOID *)Address; 55 } 56 } 57 return NULL; 58 } 59 60 VOID * 61 FindSMBIOSPtr ( 62 VOID 63 ) 64 { 65 UINTN Address; 66 67 // 68 // First Seach 0x0f0000 - 0x0fffff for SMBIOS Ptr 69 // 70 for (Address = 0xf0000; Address < 0xfffff; Address += 0x10) { 71 if (*(UINT32 *)(Address) == SMBIOS_PTR) { 72 return (VOID *)Address; 73 } 74 } 75 return NULL; 76 } 77 78 VOID * 79 FindMPSPtr ( 80 VOID 81 ) 82 { 83 UINTN Address; 84 UINTN Index; 85 86 // 87 // First Seach 0x0e0000 - 0x0fffff for MPS Ptr 88 // 89 for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) { 90 if (*(UINT32 *)(Address) == MPS_PTR) { 91 return (VOID *)Address; 92 } 93 } 94 95 // 96 // Search EBDA 97 // 98 99 Address = (*(UINT16 *)(UINTN)(EBDA_BASE_ADDRESS)) << 4; 100 for (Index = 0; Index < 0x400 ; Index += 16) { 101 if (*(UINT32 *)(Address + Index) == MPS_PTR) { 102 return (VOID *)Address; 103 } 104 } 105 return NULL; 106 } 107 108 #pragma pack(1) 109 110 typedef struct { 111 EFI_ACPI_DESCRIPTION_HEADER Header; 112 UINT32 Entry; 113 } RSDT_TABLE; 114 115 typedef struct { 116 EFI_ACPI_DESCRIPTION_HEADER Header; 117 UINT64 Entry; 118 } XSDT_TABLE; 119 120 #pragma pack() 121 122 VOID 123 ScanTableInRSDT ( 124 RSDT_TABLE *Rsdt, 125 UINT32 Signature, 126 EFI_ACPI_DESCRIPTION_HEADER **FoundTable 127 ) 128 { 129 UINTN Index; 130 UINT32 EntryCount; 131 UINT32 *EntryPtr; 132 EFI_ACPI_DESCRIPTION_HEADER *Table; 133 134 *FoundTable = NULL; 135 136 EntryCount = (Rsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32); 137 138 EntryPtr = &Rsdt->Entry; 139 for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) { 140 Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(*EntryPtr)); 141 if (Table->Signature == Signature) { 142 *FoundTable = Table; 143 break; 144 } 145 } 146 147 return; 148 } 149 150 VOID 151 ScanTableInXSDT ( 152 XSDT_TABLE *Xsdt, 153 UINT32 Signature, 154 EFI_ACPI_DESCRIPTION_HEADER **FoundTable 155 ) 156 { 157 UINTN Index; 158 UINT32 EntryCount; 159 UINT64 EntryPtr; 160 UINTN BasePtr; 161 EFI_ACPI_DESCRIPTION_HEADER *Table; 162 163 *FoundTable = NULL; 164 165 EntryCount = (Xsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64); 166 167 BasePtr = (UINTN)(&(Xsdt->Entry)); 168 for (Index = 0; Index < EntryCount; Index ++) { 169 CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64)); 170 Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(EntryPtr)); 171 if (Table->Signature == Signature) { 172 *FoundTable = Table; 173 break; 174 } 175 } 176 177 return; 178 } 179 180 VOID * 181 FindAcpiPtr ( 182 IN HOB_TEMPLATE *Hob, 183 UINT32 Signature 184 ) 185 { 186 EFI_ACPI_DESCRIPTION_HEADER *AcpiTable; 187 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; 188 RSDT_TABLE *Rsdt; 189 XSDT_TABLE *Xsdt; 190 191 AcpiTable = NULL; 192 193 // 194 // Check ACPI2.0 table 195 // 196 if ((int)Hob->Acpi20.Table != -1) { 197 Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)Hob->Acpi20.Table; 198 Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress; 199 Xsdt = NULL; 200 if ((Rsdp->Revision >= 2) && (Rsdp->XsdtAddress < (UINT64)(UINTN)-1)) { 201 Xsdt = (XSDT_TABLE *)(UINTN)Rsdp->XsdtAddress; 202 } 203 // 204 // Check Xsdt 205 // 206 if (Xsdt != NULL) { 207 ScanTableInXSDT (Xsdt, Signature, &AcpiTable); 208 } 209 // 210 // Check Rsdt 211 // 212 if ((AcpiTable == NULL) && (Rsdt != NULL)) { 213 ScanTableInRSDT (Rsdt, Signature, &AcpiTable); 214 } 215 } 216 217 // 218 // Check ACPI1.0 table 219 // 220 if ((AcpiTable == NULL) && ((int)Hob->Acpi.Table != -1)) { 221 Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)Hob->Acpi.Table; 222 Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress; 223 // 224 // Check Rsdt 225 // 226 if (Rsdt != NULL) { 227 ScanTableInRSDT (Rsdt, Signature, &AcpiTable); 228 } 229 } 230 231 return AcpiTable; 232 } 233 234 #pragma pack(1) 235 typedef struct { 236 UINT64 BaseAddress; 237 UINT16 PciSegmentGroupNumber; 238 UINT8 StartBusNumber; 239 UINT8 EndBusNumber; 240 UINT32 Reserved; 241 } MCFG_STRUCTURE; 242 #pragma pack() 243 244 VOID 245 PrepareMcfgTable ( 246 IN HOB_TEMPLATE *Hob 247 ) 248 { 249 EFI_ACPI_DESCRIPTION_HEADER *McfgTable; 250 MCFG_STRUCTURE *Mcfg; 251 UINTN McfgCount; 252 UINTN Index; 253 254 McfgTable = FindAcpiPtr (Hob, EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE); 255 if (McfgTable == NULL) { 256 return ; 257 } 258 259 Mcfg = (MCFG_STRUCTURE *)((UINTN)McfgTable + sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)); 260 McfgCount = (McfgTable->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER) - sizeof(UINT64)) / sizeof(MCFG_STRUCTURE); 261 262 // 263 // Fill PciExpress info on Hob 264 // Note: Only for 1st segment 265 // 266 for (Index = 0; Index < McfgCount; Index++) { 267 if (Mcfg[Index].PciSegmentGroupNumber == 0) { 268 Hob->PciExpress.PciExpressBaseAddressInfo.PciExpressBaseAddress = Mcfg[Index].BaseAddress; 269 break; 270 } 271 } 272 273 return ; 274 } 275 276 VOID 277 PrepareFadtTable ( 278 IN HOB_TEMPLATE *Hob 279 ) 280 { 281 EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; 282 EFI_ACPI_DESCRIPTION *AcpiDescription; 283 284 Fadt = FindAcpiPtr (Hob, EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE); 285 if (Fadt == NULL) { 286 return ; 287 } 288 289 AcpiDescription = &Hob->AcpiInfo.AcpiDescription; 290 // 291 // Fill AcpiDescription according to FADT 292 // Currently, only for PM_TMR 293 // 294 AcpiDescription->PM_TMR_LEN = Fadt->PmTmrLen; 295 AcpiDescription->TMR_VAL_EXT = (UINT8)((Fadt->Flags & 0x100) != 0); 296 297 // 298 // For fields not included in ACPI 1.0 spec, we get the value based on table length 299 // 300 if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, XPmTmrBlk) + sizeof (Fadt->XPmTmrBlk)) { 301 CopyMem ( 302 &AcpiDescription->PM_TMR_BLK, 303 &Fadt->XPmTmrBlk, 304 sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE) 305 ); 306 } 307 if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, ResetValue) + sizeof (Fadt->ResetValue)) { 308 CopyMem ( 309 &AcpiDescription->RESET_REG, 310 &Fadt->ResetReg, 311 sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE) 312 ); 313 AcpiDescription->RESET_VALUE = Fadt->ResetValue; 314 } 315 316 if (AcpiDescription->PM_TMR_BLK.Address == 0) { 317 AcpiDescription->PM_TMR_BLK.Address = Fadt->PmTmrBlk; 318 AcpiDescription->PM_TMR_BLK.AddressSpaceId = EFI_ACPI_3_0_SYSTEM_IO; 319 } 320 321 // 322 // It's possible that the PM_TMR_BLK.RegisterBitWidth is always 32, 323 // we need to set the correct RegisterBitWidth value according to the TMR_VAL_EXT 324 // A zero indicates TMR_VAL is implemented as a 24-bit value. 325 // A one indicates TMR_VAL is implemented as a 32-bit value 326 // 327 AcpiDescription->PM_TMR_BLK.RegisterBitWidth = (UINT8) ((AcpiDescription->TMR_VAL_EXT == 0) ? 24 : 32); 328 329 330 return ; 331 } 332 333 VOID 334 PrepareHobLegacyTable ( 335 IN HOB_TEMPLATE *Hob 336 ) 337 { 338 CHAR8 PrintBuffer[256]; 339 340 Hob->Acpi.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiRsdPtr (); 341 AsciiSPrint (PrintBuffer, 256, "\nAcpiTable=0x%x ", (UINT32)(UINTN)Hob->Acpi.Table); 342 PrintString (PrintBuffer); 343 Hob->Acpi20.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiRsdPtr (); 344 Hob->Smbios.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindSMBIOSPtr (); 345 AsciiSPrint (PrintBuffer, 256, "SMBIOS Table=0x%x ", (UINT32)(UINTN)Hob->Smbios.Table); 346 PrintString (PrintBuffer); 347 Hob->Mps.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindMPSPtr (); 348 AsciiSPrint (PrintBuffer, 256, "MPS Table=0x%x\n", (UINT32)(UINTN)Hob->Mps.Table); 349 PrintString (PrintBuffer); 350 351 PrepareMcfgTable (Hob); 352 353 PrepareFadtTable (Hob); 354 355 return ; 356 } 357 358