Home | History | Annotate | Download | only in DxeIpl
      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