Home | History | Annotate | Download | only in CbSupportPei
      1 /** @file
      2   This PEIM will parse coreboot table in memory and report resource information into pei core.
      3   This file contains the main entrypoint of the PEIM.
      4 
      5 Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 #include "CbSupportPei.h"
     16 
     17 #define LEGACY_8259_MASK_REGISTER_MASTER  0x21
     18 #define LEGACY_8259_MASK_REGISTER_SLAVE   0xA1
     19 
     20 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
     21   { EfiACPIReclaimMemory,   FixedPcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory) },
     22   { EfiACPIMemoryNVS,       FixedPcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS) },
     23   { EfiReservedMemoryType,  FixedPcdGet32 (PcdMemoryTypeEfiReservedMemoryType) },
     24   { EfiRuntimeServicesData, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesData) },
     25   { EfiRuntimeServicesCode, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode) },
     26   { EfiMaxMemoryType,       0     }
     27 };
     28 
     29 EFI_PEI_PPI_DESCRIPTOR   mPpiBootMode[] = {
     30   {
     31     EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
     32     &gEfiPeiMasterBootModePpiGuid,
     33     NULL
     34   }
     35 };
     36 
     37 /**
     38   Create memory mapped io resource hob.
     39 
     40   @param  MmioBase    Base address of the memory mapped io range
     41   @param  MmioSize    Length of the memory mapped io range
     42 
     43 **/
     44 VOID
     45 BuildMemoryMappedIoRangeHob (
     46   EFI_PHYSICAL_ADDRESS        MmioBase,
     47   UINT64                      MmioSize
     48   )
     49 {
     50   BuildResourceDescriptorHob (
     51     EFI_RESOURCE_MEMORY_MAPPED_IO,
     52     (EFI_RESOURCE_ATTRIBUTE_PRESENT    |
     53     EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
     54     EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
     55     EFI_RESOURCE_ATTRIBUTE_TESTED),
     56     MmioBase,
     57     MmioSize
     58     );
     59 
     60   BuildMemoryAllocationHob (
     61     MmioBase,
     62     MmioSize,
     63     EfiMemoryMappedIO
     64     );
     65 }
     66 
     67 /**
     68   Check the integrity of firmware volume header
     69 
     70   @param[in]  FwVolHeader   A pointer to a firmware volume header
     71 
     72   @retval     TRUE          The firmware volume is consistent
     73   @retval     FALSE         The firmware volume has corrupted.
     74 
     75 **/
     76 STATIC
     77 BOOLEAN
     78 IsFvHeaderValid (
     79   IN EFI_FIRMWARE_VOLUME_HEADER    *FwVolHeader
     80   )
     81 {
     82   UINT16 Checksum;
     83 
     84   // Skip nv storage fv
     85   if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) {
     86     return FALSE;
     87   }
     88 
     89   if ( (FwVolHeader->Revision != EFI_FVH_REVISION)   ||
     90      (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
     91      (FwVolHeader->FvLength == ((UINTN) -1))       ||
     92      ((FwVolHeader->HeaderLength & 0x01 ) !=0) )  {
     93     return FALSE;
     94   }
     95 
     96   Checksum = CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength);
     97   if (Checksum != 0) {
     98     DEBUG (( DEBUG_ERROR,
     99               "ERROR - Invalid Firmware Volume Header Checksum, change 0x%04x to 0x%04x\r\n",
    100               FwVolHeader->Checksum,
    101               (UINT16)( Checksum + FwVolHeader->Checksum )));
    102     return FALSE;
    103   }
    104 
    105   return TRUE;
    106 }
    107 
    108 /**
    109   Install FvInfo PPI and create fv hobs for remained fvs
    110 
    111 **/
    112 VOID
    113 CbPeiReportRemainedFvs (
    114   VOID
    115   )
    116 {
    117   UINT8*  TempPtr;
    118   UINT8*  EndPtr;
    119 
    120   TempPtr = (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase);
    121   EndPtr = (UINT8* )(UINTN) (PcdGet32 (PcdPayloadFdMemBase) + PcdGet32 (PcdPayloadFdMemSize));
    122 
    123   for (;TempPtr < EndPtr;) {
    124     if (IsFvHeaderValid ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)) {
    125       if (TempPtr != (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase))  {
    126         // Skip the PEI FV
    127         DEBUG((EFI_D_ERROR, "Found one valid fv : 0x%lx.\n", TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength));
    128 
    129         PeiServicesInstallFvInfoPpi (
    130           NULL,
    131           (VOID *) (UINTN) TempPtr,
    132           (UINT32) (UINTN) ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength,
    133           NULL,
    134           NULL
    135           );
    136         BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN) TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength);
    137       }
    138     }
    139     TempPtr += ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength;
    140   }
    141 }
    142 
    143 /**
    144   Based on memory base, size and type, build resource descripter HOB.
    145 
    146   @param  Base    Memory base address.
    147   @param  Size    Memory size.
    148   @param  Type    Memory type.
    149   @param  Param   A pointer to CB_MEM_INFO.
    150 
    151   @retval EFI_SUCCESS if it completed successfully.
    152 **/
    153 EFI_STATUS
    154 CbMemInfoCallback (
    155   UINT64                  Base,
    156   UINT64                  Size,
    157   UINT32                  Type,
    158   VOID                    *Param
    159   )
    160 {
    161   CB_MEM_INFO             *MemInfo;
    162   UINTN                   Attribue;
    163 
    164   Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT |
    165              EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
    166              EFI_RESOURCE_ATTRIBUTE_TESTED |
    167              EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
    168              EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
    169              EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
    170              EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;
    171 
    172   if ((Base  < 0x100000) && ((Base + Size) > 0x100000)) {
    173          Size -= (0x100000 - Base);
    174          Base  = 0x100000;
    175   }
    176 
    177   MemInfo = (CB_MEM_INFO *)Param;
    178   if (Base >= 0x100000) {
    179     if (Type == CB_MEM_RAM) {
    180       if (Base < 0x100000000ULL) {
    181         MemInfo->UsableLowMemTop = (UINT32)(Base + Size);
    182       } else {
    183         Attribue &= ~EFI_RESOURCE_ATTRIBUTE_TESTED;
    184       }
    185       BuildResourceDescriptorHob (
    186         EFI_RESOURCE_SYSTEM_MEMORY,
    187         Attribue,
    188         (EFI_PHYSICAL_ADDRESS)Base,
    189         Size
    190         );
    191     } else if (Type == CB_MEM_TABLE) {
    192       BuildResourceDescriptorHob (
    193         EFI_RESOURCE_MEMORY_RESERVED,
    194         Attribue,
    195         (EFI_PHYSICAL_ADDRESS)Base,
    196         Size
    197         );
    198       MemInfo->SystemLowMemTop = ((UINT32)(Base + Size) + 0x0FFFFFFF) & 0xF0000000;
    199     } else if (Type == CB_MEM_RESERVED) {
    200       if ((MemInfo->SystemLowMemTop == 0) || (Base < MemInfo->SystemLowMemTop)) {
    201         BuildResourceDescriptorHob (
    202           EFI_RESOURCE_MEMORY_RESERVED,
    203           Attribue,
    204           (EFI_PHYSICAL_ADDRESS)Base,
    205           Size
    206           );
    207       }
    208     }
    209   }
    210 
    211   return EFI_SUCCESS;
    212 }
    213 
    214 /**
    215   This is the entrypoint of PEIM
    216 
    217   @param  FileHandle  Handle of the file being invoked.
    218   @param  PeiServices Describes the list of possible PEI Services.
    219 
    220   @retval EFI_SUCCESS if it completed successfully.
    221 **/
    222 EFI_STATUS
    223 EFIAPI
    224 CbPeiEntryPoint (
    225   IN       EFI_PEI_FILE_HANDLE  FileHandle,
    226   IN CONST EFI_PEI_SERVICES     **PeiServices
    227   )
    228 {
    229   EFI_STATUS           Status;
    230   UINT64               LowMemorySize;
    231   UINT64               PeiMemSize = SIZE_64MB;   // 64 MB
    232   EFI_PHYSICAL_ADDRESS PeiMemBase = 0;
    233   UINT32               RegEax;
    234   UINT8                PhysicalAddressBits;
    235   VOID*                pCbHeader;
    236   VOID*                pAcpiTable;
    237   UINT32               AcpiTableSize;
    238   VOID*                pSmbiosTable;
    239   UINT32               SmbiosTableSize;
    240   SYSTEM_TABLE_INFO*   pSystemTableInfo;
    241   FRAME_BUFFER_INFO    FbInfo;
    242   FRAME_BUFFER_INFO*   pFbInfo;
    243   ACPI_BOARD_INFO*     pAcpiBoardInfo;
    244   UINTN                PmCtrlRegBase, PmTimerRegBase, ResetRegAddress, ResetValue;
    245   UINTN                PmEvtBase;
    246   UINTN                PmGpeEnBase;
    247   CB_MEM_INFO          CbMemInfo;
    248 
    249   //
    250   // Report lower 640KB of RAM. Attribute EFI_RESOURCE_ATTRIBUTE_TESTED
    251   // is intentionally omitted to prevent erasing of the coreboot header
    252   // record before it is processed by CbParseMemoryInfo.
    253   //
    254   BuildResourceDescriptorHob (
    255     EFI_RESOURCE_SYSTEM_MEMORY,
    256     (
    257     EFI_RESOURCE_ATTRIBUTE_PRESENT |
    258     EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
    259     EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
    260     EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
    261     EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
    262     EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
    263     ),
    264     (EFI_PHYSICAL_ADDRESS)(0),
    265     (UINT64)(0xA0000)
    266     );
    267 
    268 
    269   BuildResourceDescriptorHob (
    270     EFI_RESOURCE_MEMORY_RESERVED,
    271     (
    272     EFI_RESOURCE_ATTRIBUTE_PRESENT |
    273     EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
    274     EFI_RESOURCE_ATTRIBUTE_TESTED |
    275     EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
    276     EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
    277     EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
    278     EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
    279     ),
    280     (EFI_PHYSICAL_ADDRESS)(0xA0000),
    281     (UINT64)(0x60000)
    282     );
    283 
    284   ZeroMem (&CbMemInfo, sizeof(CbMemInfo));
    285   Status = CbParseMemoryInfo (CbMemInfoCallback, (VOID *)&CbMemInfo);
    286   if (EFI_ERROR(Status)) {
    287     return Status;
    288   }
    289 
    290   LowMemorySize = CbMemInfo.UsableLowMemTop;
    291   DEBUG ((EFI_D_INFO, "Low memory 0x%lx\n", LowMemorySize));
    292   DEBUG ((EFI_D_INFO, "SystemLowMemTop 0x%x\n", CbMemInfo.SystemLowMemTop));
    293 
    294   //
    295   // Should be 64k aligned
    296   //
    297   PeiMemBase = (LowMemorySize - PeiMemSize) & (~(BASE_64KB - 1));
    298 
    299   DEBUG((EFI_D_ERROR, "PeiMemBase: 0x%lx.\n", PeiMemBase));
    300   DEBUG((EFI_D_ERROR, "PeiMemSize: 0x%lx.\n", PeiMemSize));
    301 
    302   Status = PeiServicesInstallPeiMemory (
    303          PeiMemBase,
    304          PeiMemSize
    305          );
    306   ASSERT_EFI_ERROR (Status);
    307 
    308   //
    309   // Set cache on the physical memory
    310   //
    311   MtrrSetMemoryAttribute (BASE_1MB, LowMemorySize - BASE_1MB, CacheWriteBack);
    312   MtrrSetMemoryAttribute (0, 0xA0000, CacheWriteBack);
    313 
    314   //
    315   // Create Memory Type Information HOB
    316   //
    317   BuildGuidDataHob (
    318     &gEfiMemoryTypeInformationGuid,
    319     mDefaultMemoryTypeInformation,
    320     sizeof(mDefaultMemoryTypeInformation)
    321     );
    322 
    323   //
    324   // Create Fv hob
    325   //
    326   CbPeiReportRemainedFvs ();
    327 
    328   BuildMemoryAllocationHob (
    329     PcdGet32 (PcdPayloadFdMemBase),
    330     PcdGet32 (PcdPayloadFdMemSize),
    331     EfiBootServicesData
    332     );
    333 
    334   //
    335   // Build CPU memory space and IO space hob
    336   //
    337   AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
    338   if (RegEax >= 0x80000008) {
    339     AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
    340     PhysicalAddressBits = (UINT8) RegEax;
    341   } else {
    342     PhysicalAddressBits  = 36;
    343   }
    344   //
    345   // Create a CPU hand-off information
    346   //
    347   BuildCpuHob (PhysicalAddressBits, 16);
    348 
    349   //
    350   // Report Local APIC range
    351   //
    352   BuildMemoryMappedIoRangeHob (0xFEC80000, SIZE_512KB);
    353 
    354   //
    355   // Boot mode
    356   //
    357   Status = PeiServicesSetBootMode (BOOT_WITH_FULL_CONFIGURATION);
    358   ASSERT_EFI_ERROR (Status);
    359 
    360   Status = PeiServicesInstallPpi (mPpiBootMode);
    361   ASSERT_EFI_ERROR (Status);
    362 
    363    //
    364   // Set pcd to save the upper coreboot header in case the dxecore will
    365   // erase 0~4k memory
    366   //
    367   pCbHeader = NULL;
    368   if ((CbParseGetCbHeader (1, &pCbHeader) == RETURN_SUCCESS)
    369     && ((UINTN)pCbHeader > BASE_4KB)) {
    370     DEBUG((EFI_D_ERROR, "Actual Coreboot header: %p.\n", pCbHeader));
    371     Status = PcdSet32S (PcdCbHeaderPointer, (UINT32)(UINTN)pCbHeader);
    372     ASSERT_EFI_ERROR (Status);
    373   }
    374 
    375   //
    376   // Create guid hob for system tables like acpi table and smbios table
    377   //
    378   pAcpiTable = NULL;
    379   AcpiTableSize = 0;
    380   pSmbiosTable = NULL;
    381   SmbiosTableSize = 0;
    382   Status = CbParseAcpiTable (&pAcpiTable, &AcpiTableSize);
    383   if (EFI_ERROR (Status)) {
    384     // ACPI table is oblidgible
    385     DEBUG ((EFI_D_ERROR, "Failed to find the required acpi table\n"));
    386     ASSERT (FALSE);
    387   }
    388   CbParseSmbiosTable (&pSmbiosTable, &SmbiosTableSize);
    389 
    390   pSystemTableInfo = NULL;
    391   pSystemTableInfo = BuildGuidHob (&gUefiSystemTableInfoGuid, sizeof (SYSTEM_TABLE_INFO));
    392   ASSERT (pSystemTableInfo != NULL);
    393   pSystemTableInfo->AcpiTableBase = (UINT64) (UINTN)pAcpiTable;
    394   pSystemTableInfo->AcpiTableSize = AcpiTableSize;
    395   pSystemTableInfo->SmbiosTableBase = (UINT64) (UINTN)pSmbiosTable;
    396   pSystemTableInfo->SmbiosTableSize = SmbiosTableSize;
    397   DEBUG ((EFI_D_ERROR, "Detected Acpi Table at 0x%lx, length 0x%x\n", pSystemTableInfo->AcpiTableBase, pSystemTableInfo->AcpiTableSize));
    398   DEBUG ((EFI_D_ERROR, "Detected Smbios Table at 0x%lx, length 0x%x\n", pSystemTableInfo->SmbiosTableBase, pSystemTableInfo->SmbiosTableSize));
    399   DEBUG ((EFI_D_ERROR, "Create system table info guid hob\n"));
    400 
    401   //
    402   // Create guid hob for acpi board information
    403   //
    404   Status = CbParseFadtInfo (&PmCtrlRegBase, &PmTimerRegBase, &ResetRegAddress, &ResetValue, &PmEvtBase, &PmGpeEnBase);
    405   ASSERT_EFI_ERROR (Status);
    406   pAcpiBoardInfo = NULL;
    407   pAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO));
    408   ASSERT (pAcpiBoardInfo != NULL);
    409   pAcpiBoardInfo->PmCtrlRegBase = (UINT64)PmCtrlRegBase;
    410   pAcpiBoardInfo->PmTimerRegBase = (UINT64)PmTimerRegBase;
    411   pAcpiBoardInfo->ResetRegAddress = (UINT64)ResetRegAddress;
    412   pAcpiBoardInfo->ResetValue = (UINT8)ResetValue;
    413   pAcpiBoardInfo->PmEvtBase = (UINT64)PmEvtBase;
    414   pAcpiBoardInfo->PmGpeEnBase = (UINT64)PmGpeEnBase;
    415   DEBUG ((EFI_D_ERROR, "Create acpi board info guid hob\n"));
    416 
    417   //
    418   // Create guid hob for frame buffer information
    419   //
    420   ZeroMem (&FbInfo, sizeof (FRAME_BUFFER_INFO));
    421   Status = CbParseFbInfo (&FbInfo);
    422   if (!EFI_ERROR (Status)) {
    423     pFbInfo = BuildGuidHob (&gUefiFrameBufferInfoGuid, sizeof (FRAME_BUFFER_INFO));
    424     ASSERT (pSystemTableInfo != NULL);
    425     CopyMem (pFbInfo, &FbInfo, sizeof (FRAME_BUFFER_INFO));
    426     DEBUG ((EFI_D_ERROR, "Create frame buffer info guid hob\n"));
    427   }
    428 
    429   //
    430   // Parse platform specific information from coreboot.
    431   //
    432   Status = CbParsePlatformInfo ();
    433   if (EFI_ERROR (Status)) {
    434     DEBUG ((EFI_D_ERROR, "Error when parsing platform info, Status = %r\n", Status));
    435     return Status;
    436   }
    437 
    438   //
    439   // Mask off all legacy 8259 interrupt sources
    440   //
    441   IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
    442   IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE,  0xFF);
    443 
    444   return EFI_SUCCESS;
    445 }
    446 
    447