/** Submits the I/O and memory resource requirements for the specified PCI root bridge. This function is used to submit all the I/O and memory resources that are required by the specified PCI root bridge. The input parameter Configuration is used to specify the following: - The various types of resources that are required - The associated lengths in terms of ACPI 2.0 resource descriptor format @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted. @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor. @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted. @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. @retval EFI_INVALID_PARAMETER Configuration is NULL. @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor. @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are not supported by this PCI root bridge. This error will happen if the caller did not combine resources according to Attributes that were returned by GetAllocAttributes(). @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid. @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge. @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge. **/ EFI_STATUS EFIAPI SubmitResources( IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, IN EFI_HANDLE RootBridgeHandle, IN VOID *Configuration ) { LIST_ENTRY *List; PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; UINT8 *Temp; EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; UINT64 AddrLen; UINT64 Alignment; // // Check the input parameter: Configuration // if (Configuration == NULL) { return EFI_INVALID_PARAMETER; } HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); List = HostBridgeInstance->Head.ForwardLink; Temp = (UINT8 *)Configuration; while ( *Temp == 0x8A) { Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ; } if (*Temp != 0x79) { return EFI_INVALID_PARAMETER; } Temp = (UINT8 *)Configuration; while (List != &HostBridgeInstance->Head) { RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); if (RootBridgeHandle == RootBridgeInstance->Handle) { while ( *Temp == 0x8A) { Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ; // // Check Address Length // if (Ptr->AddrLen > 0xffffffff) { return EFI_INVALID_PARAMETER; } // // Check address range alignment // if (Ptr->AddrRangeMax >= 0xffffffff || Ptr->AddrRangeMax != (GetPowerOfTwo64 (Ptr->AddrRangeMax + 1) - 1)) { return EFI_INVALID_PARAMETER; } switch (Ptr->ResType) { case 0: // // Check invalid Address Sapce Granularity // if (Ptr->AddrSpaceGranularity != 32) { return EFI_INVALID_PARAMETER; } // // check the memory resource request is supported by PCI root bridge // if (RootBridgeInstance->RootBridgeAttrib == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM && Ptr->SpecificFlag == 0x06) { return EFI_INVALID_PARAMETER; } AddrLen = Ptr->AddrLen; Alignment = Ptr->AddrRangeMax; if (Ptr->AddrSpaceGranularity == 32) { if (Ptr->SpecificFlag == 0x06) { // // Apply from GCD // RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted; } else { RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen; RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment; RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested; HostBridgeInstance->ResourceSubmited = TRUE; } } if (Ptr->AddrSpaceGranularity == 64) { if (Ptr->SpecificFlag == 0x06) { RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted; } else { RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted; } } break; case 1: AddrLen = (UINTN) Ptr->AddrLen; Alignment = (UINTN) Ptr->AddrRangeMax; RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen; RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment; RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested; HostBridgeInstance->ResourceSubmited = TRUE; break; default: break; }; Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ; } return EFI_SUCCESS; } List = List->ForwardLink; } return EFI_INVALID_PARAMETER; }
/** This function will be called when MRC is done. @param PeiServices General purpose services available to every PEIM. @param NotifyDescriptor Information about the notify event.. @param Ppi The notify context. @retval EFI_SUCCESS If the function completed successfully. **/ EFI_STATUS EFIAPI MemoryDiscoveredPpiNotifyCallback ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status; EFI_BOOT_MODE BootMode; UINT64 MemoryLength; UINT64 MemoryLengthUc; UINT64 MaxMemoryLength; UINT64 MemOverflow; EFI_SMRAM_DESCRIPTOR *SmramDescriptor; UINTN NumSmramRegions; UINT64 EnlargedMemoryLength; UINT32 RmuMainBaseAddress; UINTN Index; MTRR_SETTINGS MtrrSetting; UINT32 RegData32; EFI_PHYSICAL_ADDRESS NewBuffer; UINT8 CpuAddressWidth; EFI_CPUID_REGISTER FeatureInfo; DEBUG ((EFI_D_INFO, "Platform PEIM Memory Callback\n")); NumSmramRegions = 0; SmramDescriptor = NULL; RmuMainBaseAddress = 0; PERF_START (NULL, "SetCache", NULL, 0); InfoPostInstallMemory (&RmuMainBaseAddress, &SmramDescriptor, &NumSmramRegions); ASSERT (SmramDescriptor != NULL); ASSERT (RmuMainBaseAddress != 0); MemoryLength = ((UINT64) RmuMainBaseAddress) + 0x10000; EnlargedMemoryLength = MemoryLength; if (NumSmramRegions > 0) { // // Find the TSEG // for (Index = 0; Index < NumSmramRegions; Index ++) { if ((SmramDescriptor[Index].PhysicalStart) == EnlargedMemoryLength) { if (SmramDescriptor[Index].RegionState & EFI_CACHEABLE) { // // Enlarge memory length to include TSEG size // EnlargedMemoryLength += (SmramDescriptor[Index].PhysicalSize); } } } } // // Check if a UC region is present // MaxMemoryLength = EnlargedMemoryLength; // Round up to nearest 256MB MemOverflow = (MemoryLength & 0x0fffffff); if (MemOverflow != 0) { MaxMemoryLength = MemoryLength + (0x10000000 - MemOverflow); } Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS)); (**PeiServices).CopyMem ((VOID *)&MtrrSetting.Fixed,(VOID *)&mFixedMtrrTable, sizeof(MTRR_FIXED_SETTINGS) ); // // Cache the flash area to improve the boot performance in PEI phase // MtrrSetting.Variables.Mtrr[0].Base = (QUARK_BOOTROM_BASE_ADDRESS | CacheWriteBack); MtrrSetting.Variables.Mtrr[0].Mask = (((~(QUARK_BOOTROM_SIZE_BYTES - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED); MtrrSetting.Variables.Mtrr[1].Base = CacheWriteBack; MtrrSetting.Variables.Mtrr[1].Mask = ((~(MaxMemoryLength - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; Index = 2; while (MaxMemoryLength != MemoryLength) { MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength); //Status = MtrrSetMemoryAttribute (MaxMemoryLength - MemoryLengthUc, MemoryLengthUc, CacheUncacheable); //ASSERT_EFI_ERROR (Status); MtrrSetting.Variables.Mtrr[Index].Base = ((MaxMemoryLength - MemoryLengthUc) & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheUncacheable; MtrrSetting.Variables.Mtrr[Index].Mask= ((~(MemoryLengthUc - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; MaxMemoryLength -= MemoryLengthUc; Index++; } AsmInvd (); MtrrSetting.MtrrDefType = MTRR_LIB_CACHE_MTRR_ENABLED | MTRR_LIB_CACHE_FIXED_MTRR_ENABLED; MtrrSetAllMtrrs(&MtrrSetting); PERF_END (NULL, "SetCache", NULL, 0); // // Install PeiReset for PeiResetSystem service // Status = PeiServicesInstallPpi (&mPpiList[0]); ASSERT_EFI_ERROR (Status); // // Do QNC initialization after MRC // PeiQNCPostMemInit (); Status = PeiServicesInstallPpi (&mPpiStall[0]); ASSERT_EFI_ERROR (Status); // // Set E000/F000 Routing // RegData32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC); RegData32 |= (BIT2|BIT1); QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, RegData32); if (BootMode == BOOT_IN_RECOVERY_MODE) { PeiServicesInstallFvInfoPpi ( NULL, (VOID *) (UINTN) PcdGet32 (PcdFlashFvRecovery2Base), PcdGet32 (PcdFlashFvRecovery2Size), NULL, NULL ); Status = PeimInitializeRecovery (PeiServices); ASSERT_EFI_ERROR (Status); } else if (BootMode == BOOT_ON_S3_RESUME) { return EFI_SUCCESS; } else { // // Allocate the memory so that it gets preserved into DXE // Status = PeiServicesAllocatePages ( EfiBootServicesData, EFI_SIZE_TO_PAGES (PcdGet32 (PcdFvSecurityHeaderSize) + PcdGet32 (PcdFlashFvMainSize)), &NewBuffer ); // // Copy the compressed main Firmware Volume to memory for faster processing later // CopyMem ((VOID *) (UINTN) NewBuffer, (VOID *) (UINTN) (PcdGet32 (PcdFlashFvMainBase) - PcdGet32 (PcdFvSecurityHeaderSize)), (PcdGet32 (PcdFvSecurityHeaderSize) +PcdGet32 (PcdFlashFvMainSize))); PeiServicesInstallFvInfoPpi ( NULL, (VOID *) (UINTN) (NewBuffer + PcdGet32 (PcdFvSecurityHeaderSize)), PcdGet32 (PcdFlashFvMainSize), NULL, NULL ); } // // Build flash HOB, it's going to be used by GCD and E820 building // Map full SPI flash decode range (regardless of smaller SPI flash parts installed) // BuildResourceDescriptorHob ( EFI_RESOURCE_FIRMWARE_DEVICE, (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), (SIZE_4GB - SIZE_8MB), SIZE_8MB ); // // Create a CPU hand-off information // CpuAddressWidth = 32; AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &FeatureInfo.RegEax, NULL, NULL, NULL); if (FeatureInfo.RegEax >= EFI_CPUID_VIR_PHY_ADDRESS_SIZE) { AsmCpuid (EFI_CPUID_VIR_PHY_ADDRESS_SIZE, &FeatureInfo.RegEax, NULL, NULL, NULL); CpuAddressWidth = (UINT8) (FeatureInfo.RegEax & 0xFF); } DEBUG ((EFI_D_INFO, "CpuAddressWidth: %d\n", CpuAddressWidth)); BuildCpuHob (CpuAddressWidth, 16); ASSERT_EFI_ERROR (Status); return Status; }
EFI_STATUS EFIAPI SetPeiCacheMode ( IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; PEI_CACHE_PPI *CachePpi; EFI_BOOT_MODE BootMode; UINT64 MemoryLength; UINT64 MemOverflow; UINT64 MemoryLengthUc; UINT64 MaxMemoryLength; UINT64 LowMemoryLength; UINT64 HighMemoryLength; UINT8 Index; MTRR_SETTINGS MtrrSetting; UINT64 ValidMtrrAddressMask; // // Load Cache PPI // Status = (**PeiServices).LocatePpi ( PeiServices, &gPeiCachePpiGuid, // GUID 0, // Instance NULL, // EFI_PEI_PPI_DESCRIPTOR (void **)&CachePpi // PPI ); if (!EFI_ERROR(Status)) { // // Clear the CAR Settings (Default Cache Type => UC) // DEBUG ((EFI_D_INFO, "Reset cache attribute and disable CAR. \n")); CachePpi->ResetCache( (EFI_PEI_SERVICES**)PeiServices, CachePpi ); } // // Variable initialization // LowMemoryLength = 0; HighMemoryLength = 0; MemoryLengthUc = 0; Status = (*PeiServices)->GetBootMode ( PeiServices, &BootMode ); ValidMtrrAddressMask = InitializeAddressMtrrMask (); // // Determine memory usage // GetMemorySize ( PeiServices, &LowMemoryLength, &HighMemoryLength ); LowMemoryLength = (EFI_PHYSICAL_ADDRESS)MmPci32( 0, 0, 2, 0, 0x70); LowMemoryLength &= 0xFFF00000ULL; MaxMemoryLength = LowMemoryLength; // // Round up to nearest 256MB with high memory and 64MB w/o high memory // if (HighMemoryLength != 0 ) { MemOverflow = (LowMemoryLength & 0x0fffffff); if (MemOverflow != 0) { MaxMemoryLength = LowMemoryLength + (0x10000000 - MemOverflow); } } else { MemOverflow = (LowMemoryLength & 0x03ffffff); if (MemOverflow != 0) { MaxMemoryLength = LowMemoryLength + (0x4000000 - MemOverflow); } } ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS)); for (Index = 0; Index < 2; Index++) { MtrrSetting.Fixed.Mtrr[Index]=0x0606060606060606; } for (Index = 2; Index < 11; Index++) { MtrrSetting.Fixed.Mtrr[Index]=0x0505050505050505; } // // Cache the flash area to improve the boot performance in PEI phase // Index = 0; ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Base)->Uint64 = FixedPcdGet32 (PcdFlashAreaBaseAddress); ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Base)->Bits.Type = CacheWriteProtected; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Mask)->Uint64 = (~((UINT64)(FixedPcdGet32 (PcdFlashAreaSize) - 1))) & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Mask)->Bits.V = 1; Index ++; MemOverflow =0; while (MaxMemoryLength > MemOverflow){ MemoryLength = MaxMemoryLength - MemOverflow; MemoryLength = GetPowerOfTwo64 (MemoryLength); ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = MemOverflow & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheWriteBack; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLength - 1)) & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1; MemOverflow += MemoryLength; Index++; } MemoryLength = LowMemoryLength; while (MaxMemoryLength != MemoryLength) { MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength); ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = (MaxMemoryLength - MemoryLengthUc) & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheUncacheable; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLengthUc - 1)) & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1; MaxMemoryLength -= MemoryLengthUc; Index++; } MemOverflow =0x100000000; while (HighMemoryLength > 0) { MemoryLength = HighMemoryLength; MemoryLength = GetPowerOfTwo64 (MemoryLength); if (MemoryLength > MemOverflow){ MemoryLength = MemOverflow; } ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = MemOverflow & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheWriteBack; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLength - 1)) & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1; MemOverflow += MemoryLength; HighMemoryLength -= MemoryLength; Index++; } for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) { if (MtrrSetting.Variables.Mtrr[Index].Base == 0){ break; } DEBUG ((EFI_D_INFO, "Base=%lx, Mask=%lx\n",MtrrSetting.Variables.Mtrr[Index].Base ,MtrrSetting.Variables.Mtrr[Index].Mask)); } // // set FE/E bits for IA32_MTRR_DEF_TYPE // MtrrSetting.MtrrDefType |= 3 <<10; MtrrSetAllMtrrs(&MtrrSetting); // // Dump MTRR Setting // MtrrDebugPrintAllMtrrs (); return EFI_SUCCESS; }