UINT64 Power2MaxMemory ( IN UINT64 MemoryLength ) /*++ Routine Description: TODO: Add function description Arguments: MemoryLength - TODO: add argument description Returns: TODO: add return values --*/ { UINT64 Result; if (RShiftU64 (MemoryLength, 32)) { Result = LShiftU64 ((UINT64) SetPower2 ((UINT32) RShiftU64 (MemoryLength, 32)), 32); } else { Result = (UINT64) SetPower2 ((UINT32) MemoryLength); } return Result; }
/** Configure RootPort for downstream PCIe NAND devices. @param[in] RpBase - PCIe configuration space address of this RootPort @param[in] BusNumber - Bus number @param[in] MemoryBase - Memory base address @param[in] MemoryLength - Memory size **/ VOID ConfigureRootPortForPcieNand ( IN UINTN RpBase, IN UINTN BusNumber, IN UINT32 MemoryBase, IN UINT32 MemoryLength ) { UINT32 MemoryLimit; DEBUG ((DEBUG_INFO, "ConfigureRootPortForPcieNand, BusNumber: %x, MemoryBase: %x, MemoryLength: %x\n", BusNumber, MemoryBase, MemoryLength)); if (MemoryLength == 0) { MemoryLimit = MemoryBase; } else { MemoryLimit = MemoryBase + MemoryLength + 0xFFFFF; // 1M } /// /// Configue PCIE configuration space for RootPort /// PciWrite8 (RpBase + NVME_PCIE_BNUM + 1, (UINT8) BusNumber); // Secondary Bus Number registers PciWrite8 (RpBase + NVME_PCIE_BNUM + 2, (UINT8) BusNumber); // Subordinate Bus Number registers PciWrite8 (RpBase + NVME_PCIE_IOBL, 0xFF); // I/O Base registers PciWrite8 (RpBase + NVME_PCIE_IOBL + 1, 0x00); // I/O Limit registers PciWrite16 (RpBase + NVME_PCIE_MBL, (UINT16) RShiftU64 ((UINTN)MemoryBase, 16)); // Memory Base register PciWrite16 (RpBase + NVME_PCIE_MBL + 2, (UINT16) RShiftU64 ((UINTN)MemoryLimit, 16)); // Memory Limit register PciWrite16 (RpBase + NVME_PCIE_PMBL, 0xFFFF); // Prefetchable Memory Base registers PciWrite16 (RpBase + NVME_PCIE_PMBL + 2, 0x0000); // Prefetchable Memory Limit registers PciWrite32 (RpBase + NVME_PCIE_PMBU32, 0xFFFFFFFF); // Prefetchable Memory Upper Base registers PciWrite32 (RpBase + NVME_PCIE_PMLU32, 0x00000000); // Prefetchable Memory Upper Limit registers }
/** Set memory cache ability. @param PageTable PageTable Address @param Address Memory Address to change cache ability @param Cacheability Cache ability to set **/ VOID SetCacheability ( IN UINT64 *PageTable, IN UINTN Address, IN UINT8 Cacheability ) { UINTN PTIndex; VOID *NewPageTableAddress; UINT64 *NewPageTable; UINTN Index; ASSERT ((Address & EFI_PAGE_MASK) == 0); if (sizeof (UINTN) == sizeof (UINT64)) { PTIndex = (UINTN)RShiftU64 (Address, 39) & 0x1ff; ASSERT (PageTable[PTIndex] & IA32_PG_P); PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & gPhyMask); } PTIndex = (UINTN)RShiftU64 (Address, 30) & 0x1ff; ASSERT (PageTable[PTIndex] & IA32_PG_P); PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & gPhyMask); // // A perfect implementation should check the original cacheability with the // one being set, and break a 2M page entry into pieces only when they // disagreed. // PTIndex = (UINTN)RShiftU64 (Address, 21) & 0x1ff; if ((PageTable[PTIndex] & IA32_PG_PS) != 0) { // // Allocate a page from SMRAM // NewPageTableAddress = AllocatePages (1); ASSERT (NewPageTableAddress != NULL); NewPageTable = (UINT64 *)NewPageTableAddress; for (Index = 0; Index < 0x200; Index++) { NewPageTable[Index] = PageTable[PTIndex]; if ((NewPageTable[Index] & IA32_PG_PAT_2M) != 0) { NewPageTable[Index] &= ~((UINT64)IA32_PG_PAT_2M); NewPageTable[Index] |= (UINT64)IA32_PG_PAT_4K; } NewPageTable[Index] |= (UINT64)(Index << EFI_PAGE_SHIFT); } PageTable[PTIndex] = ((UINTN)NewPageTableAddress & gPhyMask) | IA32_PG_P; } ASSERT (PageTable[PTIndex] & IA32_PG_P); PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & gPhyMask); PTIndex = (UINTN)RShiftU64 (Address, 12) & 0x1ff; ASSERT (PageTable[PTIndex] & IA32_PG_P); PageTable[PTIndex] &= ~((UINT64)((IA32_PG_PAT_4K | IA32_PG_CD | IA32_PG_WT))); PageTable[PTIndex] |= (UINT64)Cacheability; }
EFI_STATUS EFIAPI PostPmInitCallBack ( IN EFI_EVENT Event, IN VOID *Context ) { UINT64 OriginalGTTMMADR; UINT32 LoGTBaseAddress; UINT32 HiGTBaseAddress; // // Enable Bus Master, I/O and Memory access on 0:2:0 // PciOr8 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_CMD), (BIT2 | BIT1)); // // only 32bit read/write is legal for device 0:2:0 // OriginalGTTMMADR = (UINT64) PciRead32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR)); OriginalGTTMMADR = LShiftU64 ((UINT64) PciRead32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR + 4)), 32) | (OriginalGTTMMADR); // // 64bit GTTMADR does not work for S3 save script table since it is executed in PEIM phase // Program temporarily 32bits GTTMMADR for POST and S3 resume // LoGTBaseAddress = (UINT32) (GTTMMADR & 0xFFFFFFFF); HiGTBaseAddress = (UINT32) RShiftU64 ((GTTMMADR & 0xFFFFFFFF00000000), 32); S3PciWrite32(PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR), LoGTBaseAddress); S3PciWrite32(PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR+4), HiGTBaseAddress); // // Restore original GTTMMADR // LoGTBaseAddress = (UINT32) (OriginalGTTMMADR & 0xFFFFFFFF); HiGTBaseAddress = (UINT32) RShiftU64 ((OriginalGTTMMADR & 0xFFFFFFFF00000000), 32); S3PciWrite32(PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR), LoGTBaseAddress); S3PciWrite32(PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_GTTMMADR+4), HiGTBaseAddress); // // Lock the following registers, GGC, BDSM, BGSM // PciOr32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_MGGC_OFFSET), LockBit); PciOr32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_BSM_OFFSET), LockBit); PciOr32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0,IGD_R_BGSM), LockBit); gBS->CloseEvent (Event); // // Return final status // return EFI_SUCCESS; }
EFI_RUNTIMESERVICE EFI_STATUS EFIAPI MonotonicCounterDriverGetNextHighMonotonicCount ( OUT UINT32 *HighCount ) /*++ Routine Description: Arguments: Returns: --*/ { EFI_STATUS Status; EFI_TPL OldTpl; // // Check input parameters // if (HighCount == NULL) { return EFI_INVALID_PARAMETER; } if (!mEfiAtRuntime) { // // Use a lock if called before ExitBootServices() // OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1; mEfiMtc = LShiftU64 (*HighCount, 32); gBS->RestoreTPL (OldTpl); } else { *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1; mEfiMtc = LShiftU64 (*HighCount, 32); } // // Update the NvRam store to match the new high part // Status = gRT->SetVariable ( mEfiMtcName, &mEfiMtcGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof (UINT32), HighCount ); return Status; }
/** This is the standard EFI driver point that detects whether there is a MemoryConfigurationData Variable and, if so, reports memory configuration info to the DataHub. @param ImageHandle Handle for the image of this driver @param SystemTable Pointer to the EFI System Table @return EFI_SUCCESS if the data is successfully reported @return EFI_NOT_FOUND if the HOB list could not be located. **/ EFI_STATUS LogMemorySmbiosRecord ( VOID ) { EFI_STATUS Status; UINT64 TotalMemorySize; UINT8 NumSlots; SMBIOS_TABLE_TYPE19 *Type19Record; EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle; EFI_SMBIOS_PROTOCOL *Smbios; CHAR16 *MemString; Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios); ASSERT_EFI_ERROR (Status); NumSlots = 1; // // Process Memory String in form size!size ... // So 64!64 is 128 MB // MemString = (CHAR16 *)PcdGetPtr (PcdEmuMemorySize); for (TotalMemorySize = 0; *MemString != '\0';) { TotalMemorySize += StrDecimalToUint64 (MemString); while (*MemString != '\0') { if (*MemString == '!') { MemString++; break; } MemString++; } } // // Convert Total Memory Size to based on KiloByte // TotalMemorySize = LShiftU64 (TotalMemorySize, 20); // // Generate Memory Array Mapped Address info // Type19Record = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE19) + 2); Type19Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS; Type19Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE19); Type19Record->Hdr.Handle = 0; Type19Record->StartingAddress = 0; Type19Record->EndingAddress = (UINT32)RShiftU64(TotalMemorySize, 10) - 1; Type19Record->MemoryArrayHandle = 0; Type19Record->PartitionWidth = (UINT8)(NumSlots); // // Generate Memory Array Mapped Address info (TYPE 19) // Status = AddSmbiosRecord (Smbios, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type19Record); FreePool(Type19Record); ASSERT_EFI_ERROR (Status); return Status; }
/** This function initialize host VMCS. **/ VOID InitHostVmcs ( UINTN Index ) { UINT64 Data64; UINTN Size; // // VMCS size // Data64 = AsmReadMsr64 (IA32_VMX_BASIC_MSR_INDEX); Size = (UINTN)(RShiftU64 (Data64, 32) & 0xFFFF); // // Allocate // mHostContextCommon.HostContextPerCpu[Index].Vmcs = (UINT64)(UINTN)AllocatePages (FRM_SIZE_TO_PAGES(Size)); // // Set RevisionIdentifier // *(UINT32 *)(UINTN)mHostContextCommon.HostContextPerCpu[Index].Vmcs = (UINT32)Data64; return ; }
/** Converts a size, in bytes, to a number of EFI_PAGESs. NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only. @param Size A size in bytes. @return The number of EFI_PAGESs associated with the number of bytes specified by Size. **/ STATIC UINT64 EfiSizeToPages ( IN UINT64 Size ) { return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0); }
EFI_STATUS EFIAPI Stall ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_STALL_PPI *This, IN UINTN Microseconds ) { UINTN Ticks; UINTN Counts; UINT32 CurrentTick; UINT32 OriginalTick; UINT32 RemainingTick; if (Microseconds == 0) { return EFI_SUCCESS; } OriginalTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR); OriginalTick &= (V_PCH_ACPI_PM1_TMR_MAX_VAL - 1); CurrentTick = OriginalTick; // // The timer frequency is 3.579545MHz, so 1 ms corresponds to 3.58 clocks // Ticks = Microseconds * 358 / 100 + OriginalTick + 1; // // The loops needed for timer overflow // Counts = (UINTN)RShiftU64((UINT64)Ticks, 24); // // Remaining clocks within one loop // RemainingTick = Ticks & 0xFFFFFF; // // Do not intend to use TMROF_STS bit of register PM1_STS, because this add extra // one I/O operation, and may generate SMI // while (Counts != 0) { CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL; if (CurrentTick <= OriginalTick) { Counts--; } OriginalTick = CurrentTick; } while ((RemainingTick > CurrentTick) && (OriginalTick <= CurrentTick)) { OriginalTick = CurrentTick; CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL; } return EFI_SUCCESS; }
/** Convert FV attrbiutes to FV2 attributes. @param Fv2Attributes FV2 attributes. @return FV attributes. **/ FRAMEWORK_EFI_FV_ATTRIBUTES Fv2AttributesToFvAttributes ( IN EFI_FV_ATTRIBUTES Fv2Attributes ) { // // Clear those filed that is not defined in Framework FV spec and Alignment conversion. // return (Fv2Attributes & 0x1ff) | ((UINTN) EFI_FV_ALIGNMENT_2 << RShiftU64((Fv2Attributes & EFI_FV2_ALIGNMENT), 16)); }
/** Get the PCI-E Address from a PCI address format 0x0000ssbbddffrrr where ss is SEGMENT, bb is BUS, dd is DEVICE, ff is FUNCTION and rrr is REGISTER (extension format for PCI-E). @param[in] InputAddress PCI address format on input. @param[out]PciEAddress PCI-E address extention format. **/ VOID EFIAPI GetPciEAddressFromInputAddress ( IN UINT64 InputAddress, OUT UINT64 *PciEAddress ) { *PciEAddress = RShiftU64(InputAddress & ~(UINT64) 0xFFF, 4); *PciEAddress += LShiftU64((UINT16) InputAddress & 0x0FFF, 32); }
/** Calculate the maximum value which is a power of 2, but less the MemoryLength. @param MemoryLength The number to pass in. @return The maximum value which is align to power of 2 and less the MemoryLength **/ UINT64 Power2MaxMemory ( IN UINT64 MemoryLength ) { UINT64 Result; if (RShiftU64 (MemoryLength, 32) != 0) { Result = LShiftU64 ( (UINT64) GetPowerOfTwo32 ( (UINT32) RShiftU64 (MemoryLength, 32) ), 32 ); } else { Result = (UINT64) GetPowerOfTwo32 ((UINT32) MemoryLength); } return Result; }
/** Internal worker function to call the Metronome Architectural Protocol for the number of ticks specified by the UINT64 Counter value. WaitForTick() service of the Metronome Architectural Protocol uses a UINT32 for the number of ticks to wait, so this function loops when Counter is larger than 0xffffffff. @param Counter Number of ticks to wait. **/ VOID CoreInternalWaitForTick ( IN UINT64 Counter ) { while (RShiftU64 (Counter, 32) > 0) { gMetronome->WaitForTick (gMetronome, 0xffffffff); Counter -= 0xffffffff; } gMetronome->WaitForTick (gMetronome, (UINT32)Counter); }
/** Get microcode update signature of currently loaded microcode update. @return Microcode signature. **/ UINT32 GetCurrentMicrocodeSignature ( VOID ) { UINT64 Signature; AsmWriteMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID, 0); AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL); Signature = AsmReadMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID); return (UINT32) RShiftU64 (Signature, 32); }
/** Returns a bit field from a 64-bit value. Returns the bitfield specified by the StartBit and the EndBit from Operand. If 64-bit operations are not supported, then ASSERT(). If StartBit is greater than 63, then ASSERT(). If EndBit is greater than 63, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. Range 0..63. @param EndBit The ordinal of the most significant bit in the bit field. Range 0..63. @return The bit field read. **/ UINT64 EFIAPI BitFieldRead64 ( IN UINT64 Operand, IN UINTN StartBit, IN UINTN EndBit ) { ASSERT (EndBit < sizeof (Operand) * 8); ASSERT (StartBit <= EndBit); return RShiftU64 (Operand & ~LShiftU64 ((UINT64)-2, EndBit), StartBit); }
/** WRITE_DMA_EXT command @param CardData Pointer to CARD_DATA. @param LBA The starting logical block address to read from on the device. @param Buffer A pointer to the destination buffer for the data. The caller is responsible for either having implicit or explicit ownership of the buffer. @param SectorCount Size in 512 bytes unit. @retval EFI_SUCCESS Success @retval EFI_DEVICE_ERROR Hardware Error @retval EFI_INVALID_PARAMETER Parameter is error @retval EFI_NO_MEDIA No media @retval EFI_MEDIA_CHANGED Media Change @retval EFI_BAD_BUFFER_SIZE Buffer size is bad **/ EFI_STATUS WriteDMAExt ( IN CARD_DATA *CardData, IN EFI_LBA LBA, IN UINT8 *Buffer, IN UINT16 SectorCount ) { EFI_STATUS Status; ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE)); // //The host only supports nIEN = 0 // CardData->TaskFile.Command_Status = WRITE_DMA_EXT; CardData->TaskFile.SectorCount = (UINT8)SectorCount; CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8); CardData->TaskFile.LBALow = (UINT8)LBA; CardData->TaskFile.LBAMid = (UINT8)RShiftU64(LBA, 8); CardData->TaskFile.LBAHigh = (UINT8)RShiftU64(LBA, 16); CardData->TaskFile.LBALow_Exp = (UINT8)RShiftU64(LBA, 24); CardData->TaskFile.LBAMid_Exp = (UINT8)RShiftU64(LBA, 32); CardData->TaskFile.LBAHigh_Exp = (UINT8)RShiftU64(LBA, 40); Status = SendATACommand ( CardData, &CardData->TaskFile, TRUE, Buffer, SectorCount ); return Status; }
VOID SetEncodedSizeOfBuf( UINT64 EncodedSize, UINT8* EncodedData ) { INT32 Index; EncodedData[LZMA_PROPS_SIZE] = EncodedSize & 0xFF; for (Index = LZMA_PROPS_SIZE + 1; Index <= LZMA_PROPS_SIZE + 7; Index++) { EncodedSize = RShiftU64(EncodedSize, 8); EncodedData[Index] = EncodedSize & 0xFF; } }
EFI_STATUS EFIAPI GetNextHighMonotonicCount ( OUT UINT32 *HighCount ) { if (HighCount == NULL) { return EFI_INVALID_PARAMETER; } gCurrentMonotonicCount += 0x0000000100000000ULL; *HighCount = (UINT32)RShiftU64 (gCurrentMonotonicCount, 32) & 0xFFFFFFFF; return EFI_SUCCESS; }
/** Returns the bit position of the lowest bit set in a 64-bit value. This function computes the bit position of the lowest bit set in the 64-bit value specified by Operand. If Operand is zero, then -1 is returned. Otherwise, a value between 0 and 63 is returned. @param Operand The 64-bit operand to evaluate. @retval 0..63 The lowest bit set in Operand was found. @retval -1 Operand is zero. **/ INTN EFIAPI LowBitSet64 ( IN UINT64 Operand ) { INTN BitIndex; if (Operand == 0) { return -1; } for (BitIndex = 0; (Operand & 1) == 0; BitIndex++, Operand = RShiftU64 (Operand, 1)); return BitIndex; }
/** Saves a PCI configuration value to the boot script. This internal worker function saves a PCI configuration value in the S3 script to be replayed on S3 resume. If the saving process fails, then ASSERT(). @param Width The width of PCI configuration. @param Address Address that encodes the PCI Bus, Device, Function and Register. @param Buffer The buffer containing value. **/ VOID InternalSavePciSegmentWriteValueToBootScript ( IN S3_BOOT_SCRIPT_LIB_WIDTH Width, IN UINT64 Address, IN VOID *Buffer ) { RETURN_STATUS Status; Status = S3BootScriptSavePciCfg2Write ( Width, RShiftU64 ((Address), 32) & 0xffff, PCI_SEGMENT_LIB_ADDRESS_TO_S3_BOOT_SCRIPT_PCI_ADDRESS (Address), 1, Buffer ); ASSERT_RETURN_ERROR (Status); }
/** Get bit value in bitmap table for the given address. @param[in] Address The address to retrieve for. @return 1 or 0. **/ UINTN EFIAPI GetGuardMapBit ( IN EFI_PHYSICAL_ADDRESS Address ) { UINT64 *GuardMap; FindGuardedMemoryMap (Address, FALSE, &GuardMap); if (GuardMap != NULL) { if (RShiftU64 (*GuardMap, GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address)) & 1) { return 1; } } return 0; }
STATIC EFI_STATUS EFIAPI Virtio10SetGuestFeatures ( IN VIRTIO_DEVICE_PROTOCOL *This, IN UINT64 Features ) { VIRTIO_1_0_DEV *Dev; UINT32 Selector; UINT32 Features32[2]; Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); Features32[0] = (UINT32)Features; Features32[1] = (UINT32)RShiftU64 (Features, 32); for (Selector = 0; Selector < 2; ++Selector) { EFI_STATUS Status; // // Select the low or high half of the features. // Status = Virtio10Transfer (Dev->PciIo, &Dev->CommonConfig, TRUE, OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DriverFeatureSelect), sizeof Selector, &Selector); if (EFI_ERROR (Status)) { return Status; } // // Write that half. // Status = Virtio10Transfer (Dev->PciIo, &Dev->CommonConfig, TRUE, OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DriverFeature), sizeof Features32[Selector], &Features32[Selector]); if (EFI_ERROR (Status)) { return Status; } } return EFI_SUCCESS; }
EFI_STATUS EFIAPI LibMtcGetNextHighMonotonicCount ( OUT UINT32 *HighCount ) { EFI_STATUS Status; EFI_TPL OldTpl; // // Check input parameters // if (HighCount == NULL) { return EFI_INVALID_PARAMETER; } if (!EfiAtRuntime ()) { // Use a lock if called before ExitBootServices() OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); } *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1; mEfiMtc = LShiftU64 (*HighCount, 32); if (!EfiAtRuntime ()) { gBS->RestoreTPL (OldTpl); } // // Update the NvRam store to match the new high part // Status = EfiSetVariable ( mEfiMtcName, &mEfiMtcGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof (UINT32), HighCount ); return Status; }
/** Copies the data in a caller supplied buffer to a specified range of PCI configuration space, and saves the value in the S3 script to be replayed on S3 resume. Writes the range of PCI configuration registers specified by StartAddress and Size from the buffer specified by Buffer. This function only allows the PCI configuration registers from a single PCI function to be written. Size is returned. When possible 32-bit PCI configuration write cycles are used to write from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit and 16-bit PCI configuration write cycles may be used at the beginning and the end of the range. If any reserved bits in StartAddress are set, then ASSERT(). If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). If Size > 0 and Buffer is NULL, then ASSERT(). @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, Function and Register. @param Size Size in bytes of the transfer. @param Buffer Pointer to a buffer containing the data to write. @return The parameter of Size. **/ UINTN EFIAPI S3PciSegmentWriteBuffer ( IN UINT64 StartAddress, IN UINTN Size, IN VOID *Buffer ) { RETURN_STATUS Status; Status = S3BootScriptSavePciCfg2Write ( S3BootScriptWidthUint8, RShiftU64 (StartAddress, 32) & 0xffff, PCI_SEGMENT_LIB_ADDRESS_TO_S3_BOOT_SCRIPT_PCI_ADDRESS (StartAddress), PciSegmentWriteBuffer (StartAddress, Size, Buffer), Buffer ); ASSERT_RETURN_ERROR (Status); return Size; }
/** Get corresponding bits in bitmap table according to the address. The value of bit 0 corresponds to the status of memory at given Address. No more than 64 bits can be retrieved in one call. @param[in] Address Start address to retrieve bits for. @param[in] BitNumber Number of bits to get. @param[in] BitMap Pointer to bitmap which covers the Address. @return An integer containing the bits information. **/ STATIC UINT64 GetBits ( IN EFI_PHYSICAL_ADDRESS Address, IN UINTN BitNumber, IN UINT64 *BitMap ) { UINTN StartBit; UINTN EndBit; UINTN Lsbs; UINTN Msbs; UINT64 Result; ASSERT (BitNumber <= GUARDED_HEAP_MAP_ENTRY_BITS); StartBit = (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address); EndBit = (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BITS; if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) { Msbs = GUARDED_HEAP_MAP_ENTRY_BITS - StartBit; Lsbs = (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS; } else { Msbs = BitNumber; Lsbs = 0; } if (StartBit == 0 && BitNumber == GUARDED_HEAP_MAP_ENTRY_BITS) { Result = *BitMap; } else { Result = RShiftU64((*BitMap), StartBit) & (LShiftU64(1, Msbs) - 1); if (Lsbs > 0) { BitMap += 1; Result |= LShiftU64 ((*BitMap) & (LShiftU64 (1, Lsbs) - 1), Msbs); } } return Result; }
/** Returns the bit position of the highest bit set in a 64-bit value. Equivalent to log2(x). This function computes the bit position of the highest bit set in the 64-bit value specified by Operand. If Operand is zero, then -1 is returned. Otherwise, a value between 0 and 63 is returned. @param Operand The 64-bit operand to evaluate. @return Position of the highest bit set in Operand if found. @retval -1 Operand is zero. **/ INTN EFIAPI HighBitSet64 ( IN UINT64 Operand ) { if (Operand == (UINT32)Operand) { // // Operand is just a 32-bit integer // return HighBitSet32 ((UINT32)Operand); } // // Operand is really a 64-bit integer // if (sizeof (UINTN) == sizeof (UINT32)) { return HighBitSet32 (((UINT32*)&Operand)[1]) + 32; } else { return HighBitSet32 ((UINT32)RShiftU64 (Operand, 32)) + 32; } }
/** Function for 'mm' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). **/ SHELL_STATUS EFIAPI ShellCommandRunMm ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev; UINT64 Address; UINT64 PciEAddress; UINT64 Value; UINT32 SegmentNumber; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width; EFI_ACCESS_TYPE AccessType; UINT64 Buffer; UINTN Index; UINTN Size; // CHAR16 *ValueStr; BOOLEAN Complete; CHAR16 *InputStr; BOOLEAN Interactive; EFI_HANDLE *HandleBuffer; UINTN BufferSize; UINTN ItemValue; LIST_ENTRY *Package; CHAR16 *ProblemParam; SHELL_STATUS ShellStatus; CONST CHAR16 *Temp; Value = 0; Address = 0; PciEAddress = 0; IoDev = NULL; HandleBuffer = NULL; BufferSize = 0; SegmentNumber = 0; ShellStatus = SHELL_SUCCESS; InputStr = NULL; // // Parse arguments // Width = EfiPciWidthUint8; Size = 1; AccessType = EfiMemory; // ValueStr = NULL; Interactive = TRUE; Package = NULL; Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); if (EFI_ERROR(Status)) { if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam); FreePool(ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } else { ASSERT(FALSE); } } else { if (ShellCommandLineGetCount(Package) < 2) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } else if (ShellCommandLineGetCount(Package) > 3) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } else if (ShellCommandLineGetFlag(Package, L"-w") && ShellCommandLineGetValue(Package, L"-w") == NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"-w"); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } else { if (ShellCommandLineGetFlag(Package, L"-mmio")) { AccessType = EFIMemoryMappedIo; if (ShellCommandLineGetFlag(Package, L"-mem") ||ShellCommandLineGetFlag(Package, L"-io") ||ShellCommandLineGetFlag(Package, L"-pci") ||ShellCommandLineGetFlag(Package, L"-pcie") ){ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } } else if (ShellCommandLineGetFlag(Package, L"-mem")) { AccessType = EfiMemory; if (ShellCommandLineGetFlag(Package, L"-io") ||ShellCommandLineGetFlag(Package, L"-pci") ||ShellCommandLineGetFlag(Package, L"-pcie") ){ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } } else if (ShellCommandLineGetFlag(Package, L"-io")) { AccessType = EfiIo; if (ShellCommandLineGetFlag(Package, L"-pci") ||ShellCommandLineGetFlag(Package, L"-pcie") ){ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } } else if (ShellCommandLineGetFlag(Package, L"-pci")) { AccessType = EfiPciConfig; if (ShellCommandLineGetFlag(Package, L"-pcie") ){ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } } else if (ShellCommandLineGetFlag(Package, L"-pcie")) { AccessType = EfiPciEConfig; } } // // Non interactive for a script file or for the specific parameter // if (gEfiShellProtocol->BatchIsActive() || ShellCommandLineGetFlag (Package, L"-n")) { Interactive = FALSE; } Temp = ShellCommandLineGetValue(Package, L"-w"); if (Temp != NULL) { ItemValue = ShellStrToUintn (Temp); switch (ItemValue) { case 1: Width = EfiPciWidthUint8; Size = 1; break; case 2: Width = EfiPciWidthUint16; Size = 2; break; case 4: Width = EfiPciWidthUint32; Size = 4; break; case 8: Width = EfiPciWidthUint64; Size = 8; break; default: ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"-w"); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } } Temp = ShellCommandLineGetRawValue(Package, 1); if (!ShellIsHexOrDecimalNumber(Temp, TRUE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp, (UINT64*)&Address, TRUE, FALSE))) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Temp); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } Temp = ShellCommandLineGetRawValue(Package, 2); if (Temp != NULL) { // // Per spec if value is specified, then -n is assumed. // Interactive = FALSE; if (!ShellIsHexOrDecimalNumber(Temp, TRUE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp, &Value, TRUE, FALSE))) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Temp); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } switch (Size) { case 1: if (Value > 0xFF) { ShellStatus = SHELL_INVALID_PARAMETER; } break; case 2: if (Value > 0xFFFF) { ShellStatus = SHELL_INVALID_PARAMETER; } break; case 4: if (Value > 0xFFFFFFFF) { ShellStatus = SHELL_INVALID_PARAMETER; } break; default: break; } if (ShellStatus != SHELL_SUCCESS) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Temp); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } } if ((Address & (Size - 1)) != 0) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, Address); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } // // locate DeviceIO protocol interface // if (AccessType != EfiMemory) { Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiPciRootBridgeIoProtocolGuid, NULL, &BufferSize, &HandleBuffer ); if (EFI_ERROR (Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle); ShellStatus = SHELL_NOT_FOUND; goto Done; } // // In the case of PCI or PCIE // Get segment number and mask the segment bits in Address // if (AccessType == EfiPciEConfig) { SegmentNumber = (UINT32) RShiftU64 (Address, 36) & 0xff; Address &= 0xfffffffffULL; } else { if (AccessType == EfiPciConfig) { SegmentNumber = (UINT32) RShiftU64 (Address, 32) & 0xff; Address &= 0xffffffff; } } // // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment number // for (Index = 0; Index < BufferSize; Index++) { Status = gBS->HandleProtocol ( HandleBuffer[Index], &gEfiPciRootBridgeIoProtocolGuid, (VOID *) &IoDev ); if (EFI_ERROR (Status)) { continue; } if (IoDev->SegmentNumber != SegmentNumber) { IoDev = NULL; } } if (IoDev == NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_SEGMENT_NOT_FOUND), gShellDebug1HiiHandle, SegmentNumber); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } } if (AccessType == EfiIo && Address + Size > 0x10000) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; goto Done; } if (AccessType == EfiPciEConfig) { GetPciEAddressFromInputAddress (Address, &PciEAddress); } // // Set value // if (ShellCommandLineGetRawValue(Package, 2) != NULL) { if (AccessType == EFIMemoryMappedIo) { IoDev->Mem.Write (IoDev, Width, Address, 1, &Value); } else if (AccessType == EfiIo) { IoDev->Io.Write (IoDev, Width, Address, 1, &Value); } else if (AccessType == EfiPciConfig) { IoDev->Pci.Write (IoDev, Width, Address, 1, &Value); } else if (AccessType == EfiPciEConfig) { IoDev->Pci.Write (IoDev, Width, PciEAddress, 1, &Value); } else { WriteMem (Width, Address, 1, &Value); } ASSERT(ShellStatus == SHELL_SUCCESS); goto Done; } // // non-interactive mode // if (!Interactive) { Buffer = 0; if (AccessType == EFIMemoryMappedIo) { if (!gEfiShellProtocol->BatchIsActive()) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MMIO), gShellDebug1HiiHandle); } IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer); } else if (AccessType == EfiIo) { if (!gEfiShellProtocol->BatchIsActive()) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_IO), gShellDebug1HiiHandle); } IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer); } else if (AccessType == EfiPciConfig) { if (!gEfiShellProtocol->BatchIsActive()) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCI), gShellDebug1HiiHandle); } IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer); } else if (AccessType == EfiPciEConfig) { if (!gEfiShellProtocol->BatchIsActive()) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE), gShellDebug1HiiHandle); } IoDev->Pci.Read (IoDev, Width, PciEAddress, 1, &Buffer); } else { if (!gEfiShellProtocol->BatchIsActive()) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MEM), gShellDebug1HiiHandle); } ReadMem (Width, Address, 1, &Buffer); } if (!gEfiShellProtocol->BatchIsActive()) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address); } if (Size == 1) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF2), gShellDebug1HiiHandle, (UINTN)Buffer); } else if (Size == 2) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF4), gShellDebug1HiiHandle, (UINTN)Buffer); } else if (Size == 4) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF8), gShellDebug1HiiHandle, (UINTN)Buffer); } else if (Size == 8) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF16), gShellDebug1HiiHandle, Buffer); } ShellPrintEx(-1, -1, L"\r\n"); ASSERT(ShellStatus == SHELL_SUCCESS); goto Done; } // // interactive mode // Complete = FALSE; do { if (AccessType == EfiIo && Address + Size > 0x10000) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE2), gShellDebug1HiiHandle); break; } Buffer = 0; if (AccessType == EFIMemoryMappedIo) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MMIO), gShellDebug1HiiHandle); IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer); } else if (AccessType == EfiIo) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_IO), gShellDebug1HiiHandle); IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer); } else if (AccessType == EfiPciConfig) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCI), gShellDebug1HiiHandle); IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer); } else if (AccessType == EfiPciEConfig) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE), gShellDebug1HiiHandle); IoDev->Pci.Read (IoDev, Width, PciEAddress, 1, &Buffer); } else { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MEM), gShellDebug1HiiHandle); ReadMem (Width, Address, 1, &Buffer); } ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address); if (Size == 1) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF2), gShellDebug1HiiHandle, (UINTN)Buffer); } else if (Size == 2) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF4), gShellDebug1HiiHandle, (UINTN)Buffer); } else if (Size == 4) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF8), gShellDebug1HiiHandle, (UINTN)Buffer); } else if (Size == 8) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF16), gShellDebug1HiiHandle, Buffer); } ShellPrintEx(-1, -1, L" > "); // // wait user input to modify // if (InputStr != NULL) { FreePool(InputStr); InputStr = NULL; } ShellPromptForResponse(ShellPromptResponseTypeFreeform, NULL, (VOID**)&InputStr); // // skip space characters // for (Index = 0; InputStr != NULL && InputStr[Index] == ' '; Index++); // // parse input string // if (InputStr != NULL && (InputStr[Index] == '.' || InputStr[Index] == 'q' || InputStr[Index] == 'Q')) { Complete = TRUE; } else if (InputStr == NULL || InputStr[Index] == CHAR_NULL) { // // Continue to next address // } else if (GetHex (InputStr + Index, &Buffer) && Buffer <= MaxNum[Width]) { if (AccessType == EFIMemoryMappedIo) { IoDev->Mem.Write (IoDev, Width, Address, 1, &Buffer); } else if (AccessType == EfiIo) { IoDev->Io.Write (IoDev, Width, Address, 1, &Buffer); } else if (AccessType == EfiPciConfig) { IoDev->Pci.Write (IoDev, Width, Address, 1, &Buffer); } else if (AccessType == EfiPciEConfig) { IoDev->Pci.Write (IoDev, Width, PciEAddress, 1, &Buffer); } else { WriteMem (Width, Address, 1, &Buffer); } } else { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle); continue; // PrintToken (STRING_TOKEN (STR_IOMOD_ERROR), HiiHandle); } Address += Size; if (AccessType == EfiPciEConfig) { GetPciEAddressFromInputAddress (Address, &PciEAddress); } ShellPrintEx(-1, -1, L"\r\n"); // Print (L"\n"); } while (!Complete); } ASSERT(ShellStatus == SHELL_SUCCESS); Done: if (InputStr != NULL) { FreePool(InputStr); } if (HandleBuffer != NULL) { FreePool (HandleBuffer); } if (Package != NULL) { ShellCommandLineFreeVarList (Package); } return ShellStatus; }
/** This function will get the memory cache type of the specific address. This function is mainly for debug purpose. @param Address The specific address @return Memory cache type of the sepcific address **/ MTRR_MEMORY_CACHE_TYPE EFIAPI MtrrGetMemoryAttribute ( IN PHYSICAL_ADDRESS Address ) { UINT64 TempQword; UINTN Index; UINTN SubIndex; UINT64 MtrrType; UINT64 TempMtrrType; MTRR_MEMORY_CACHE_TYPE CacheType; VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; UINT64 MtrrValidBitsMask; UINT64 MtrrValidAddressMask; UINTN VariableMtrrCount; if (!IsMtrrSupported ()) { return CacheUncacheable; } // // Check if MTRR is enabled, if not, return UC as attribute // TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE); MtrrType = MTRR_CACHE_INVALID_TYPE; if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { return CacheUncacheable; } // // If address is less than 1M, then try to go through the fixed MTRR // if (Address < BASE_1MB) { if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) { // // Go through the fixed MTRR // for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress && Address < ( mMtrrLibFixedMtrrTable[Index].BaseAddress + (mMtrrLibFixedMtrrTable[Index].Length * 8) ) ) { SubIndex = ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) / mMtrrLibFixedMtrrTable[Index].Length; TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr); MtrrType = RShiftU64 (TempQword, SubIndex * 8) & 0xFF; return GetMemoryCacheTypeFromMtrrType (MtrrType); } } } } MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask); MtrrGetMemoryAttributeInVariableMtrr( MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr ); // // Go through the variable MTRR // VariableMtrrCount = GetVariableMtrrCount (); ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR); for (Index = 0; Index < VariableMtrrCount; Index++) { if (VariableMtrr[Index].Valid) { if (Address >= VariableMtrr[Index].BaseAddress && Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) { TempMtrrType = VariableMtrr[Index].Type; MtrrType = MtrrPrecedence (MtrrType, TempMtrrType); } } } CacheType = GetMemoryCacheTypeFromMtrrType (MtrrType); return CacheType; }
/** This function will update any runtime platform specific information. This currently includes: Setting OEM table values, ID, table ID, creator ID and creator revision. Enabling the proper processor entries in the APIC tables. @param[in] Table The table to update. @retval EFI_SUCCESS The function completed successfully. **/ EFI_STATUS PlatformUpdateTables ( IN OUT EFI_ACPI_COMMON_HEADER *Table ) { EFI_ACPI_DESCRIPTION_HEADER *TableHeader; UINT8 *CurrPtr; UINT8 *EndPtr; ACPI_APIC_STRUCTURE_PTR *ApicPtr; UINT8 CurrProcessor; EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpService; UINTN MaximumNumberOfCPUs; UINTN NumberOfEnabledCPUs; UINTN BufferSize; ACPI_APIC_STRUCTURE_PTR *ProcessorLocalApicEntry; UINTN BspIndex; EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE *AsfEntry; EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *HpetTbl; UINT64 OemIdValue; UINT8 Index; EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Facp; EFI_ACPI_OSFR_TABLE *OsfrTable; EFI_ACPI_OSFR_OCUR_OBJECT *pOcurObject; EFI_ACPI_OSFR_OCUR_OBJECT OcurObject = {{0xB46F133D, 0x235F, 0x4634, 0x9F, 0x03, 0xB1, 0xC0, 0x1C, 0x54, 0x78, 0x5B}, 0, 0, 0, 0, 0}; CHAR16 *OcurMfgStringBuffer = NULL; CHAR16 *OcurModelStringBuffer = NULL; UINT8 *OcurRefDataBlockBuffer = NULL; UINTN OcurMfgStringBufferSize; UINTN OcurModelStringBufferSize; UINTN OcurRefDataBlockBufferSize; #if defined (IDCC2_SUPPORTED) && IDCC2_SUPPORTED EFI_ACPI_ASPT_TABLE *pSpttTable; #endif UINT16 NumberOfHpets; UINT16 HpetCapIdValue; UINT32 HpetBlockID; UINTN LocalApicCounter; EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; UINT8 TempVal; EFI_ACPI_3_0_IO_APIC_STRUCTURE *IOApicType; EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *APICTableHeader; CurrPtr = NULL; EndPtr = NULL; ApicPtr = NULL; LocalApicCounter = 0; CurrProcessor = 0; ProcessorLocalApicEntry = NULL; if (Table->Signature != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) { TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table; // // Update the OEMID. // OemIdValue = mPlatformInfo->AcpiOemId; *(UINT32 *)(TableHeader->OemId) = (UINT32)OemIdValue; *(UINT16 *)(TableHeader->OemId + 4) = *(UINT16*)(((UINT8 *)&OemIdValue) + 4); if ((Table->Signature != EFI_ACPI_2_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) { // // Update the OEM Table ID. // TableHeader->OemTableId = mPlatformInfo->AcpiOemTableId; } // // Update the OEM Table ID. // TableHeader->OemRevision = EFI_ACPI_OEM_REVISION; // // Update the creator ID. // TableHeader->CreatorId = EFI_ACPI_CREATOR_ID; // // Update the creator revision. // TableHeader->CreatorRevision = EFI_ACPI_CREATOR_REVISION; } // // Complete this function. // // // Locate the MP services protocol. // // // Find the MP Protocol. This is an MP platform, so MP protocol must be // there. // Status = gBS->LocateProtocol ( &gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpService ); if (EFI_ERROR (Status)) { return Status; } // // Determine the number of processors. // MpService->GetNumberOfProcessors ( MpService, &MaximumNumberOfCPUs, &NumberOfEnabledCPUs ); ASSERT (MaximumNumberOfCPUs <= MAX_CPU_NUM && NumberOfEnabledCPUs >= 1); // // Assign a invalid intial value for update. // // // Update the processors in the APIC table. // switch (Table->Signature) { case EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE_SIGNATURE: // // Update the table if ASF is enabled. Otherwise, return error so caller will not install. // if (mSystemConfig.Asf == 1) { return EFI_UNSUPPORTED; } AsfEntry = (EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE *) Table; TempVal = (mNumberSmbusAddress < ASF_ADDR_DEVICE_ARRAY_LENGTH)? mNumberSmbusAddress : ASF_ADDR_DEVICE_ARRAY_LENGTH; for (Index = 0; Index < TempVal; Index++) { AsfEntry->AsfAddr.FixedSmbusAddresses[Index] = mSmbusRsvdAddresses[Index]; } break; case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE: Status = MpService->WhoAmI ( MpService, &BspIndex ); // // PCAT_COMPAT Set to 1 indicate 8259 vectors should be disabled. // APICTableHeader = (EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)Table; APICTableHeader->Flags |= EFI_ACPI_3_0_PCAT_COMPAT; CurrPtr = (UINT8 *) &((EFI_ACPI_DESCRIPTION_HEADER *) Table)[1]; CurrPtr = CurrPtr + 8; // // Size of Local APIC Address & Flag. // EndPtr = (UINT8 *) Table; EndPtr = EndPtr + Table->Length; while (CurrPtr < EndPtr) { ApicPtr = (ACPI_APIC_STRUCTURE_PTR *) CurrPtr; switch (ApicPtr->AcpiApicCommon.Type) { case EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC: // // ESS override // Fix for Ordering of MADT to be maintained as it is in MADT table. // // Update processor enabled or disabled and keep the local APIC // order in MADT intact. // // Sanity check to make sure proc-id is not arbitrary. // DEBUG ((EFI_D_ERROR, "ApicPtr->AcpiLocalApic.AcpiProcessorId = %x, MaximumNumberOfCPUs = %x\n", \ ApicPtr->AcpiLocalApic.AcpiProcessorId, MaximumNumberOfCPUs)); if(ApicPtr->AcpiLocalApic.AcpiProcessorId > MaximumNumberOfCPUs) { ApicPtr->AcpiLocalApic.AcpiProcessorId = (UINT8)MaximumNumberOfCPUs; } BufferSize = 0; ApicPtr->AcpiLocalApic.Flags = 0; for (CurrProcessor = 0; CurrProcessor < MaximumNumberOfCPUs; CurrProcessor++) { Status = MpService->GetProcessorInfo ( MpService, CurrProcessor, &ProcessorInfoBuffer ); if (Status == EFI_SUCCESS && ProcessorInfoBuffer.ProcessorId == ApicPtr->AcpiLocalApic.ApicId) { // // Check to see whether or not a processor (or thread) is enabled. // if ((BspIndex == CurrProcessor) || ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0)) { // // Go on and check if Hyper Threading is enabled. If HT not enabled // hide this thread from OS by not setting the flag to 1. This is the // software way to disable Hyper Threading. Basically we just hide it // from the OS. // ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_1_0_LOCAL_APIC_ENABLED; if(ProcessorInfoBuffer.Location.Thread != 0) { ApicPtr->AcpiLocalApic.Flags = 0; } AppendCpuMapTableEntry (&(ApicPtr->AcpiLocalApic)); } break; } } // // If no APIC-ID match, the cpu may not be populated. // break; case EFI_ACPI_3_0_IO_APIC: IOApicType = (EFI_ACPI_3_0_IO_APIC_STRUCTURE *)CurrPtr; IOApicType->IoApicId = 0x02; // // IO APIC entries can be patched here. // break; } CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length; } break; case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: Facp = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) Table; Facp->Flags &= (UINT32)(~(3<<2)); break; case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: // // Patch the memory resource. // PatchDsdtTable ((EFI_ACPI_DESCRIPTION_HEADER *) Table); break; case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: // // Gv3 support // // TBD: Need re-design based on the ValleyTrail platform. // break; case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE: // // Adjust HPET Table to correct the Base Address. // // Enable HPET always as Hpet.asi always indicates that Hpet is enabled. // MmioOr8 (R_PCH_PCH_HPET + R_PCH_PCH_HPET_GCFG, B_PCH_PCH_HPET_GCFG_EN); HpetTbl = (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) Table; HpetTbl->BaseAddressLower32Bit.Address = HPET_BASE_ADDRESS; HpetTbl->EventTimerBlockId = *((UINT32*)(UINTN)HPET_BASE_ADDRESS); HpetCapIdValue = *(UINT16 *)(UINTN)(HPET_BASE_ADDRESS); NumberOfHpets = HpetCapIdValue & B_PCH_PCH_HPET_GCID_NT; // Bits [8:12] contains the number of Hpets HpetBlockID = EFI_ACPI_EVENT_TIMER_BLOCK_ID; if((NumberOfHpets) && (NumberOfHpets & B_PCH_PCH_HPET_GCID_NT)) { HpetBlockID |= (NumberOfHpets); } HpetTbl->EventTimerBlockId = HpetBlockID; break; case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE: // // Update MCFG base and end bus number. // ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *) Table)->Segment[0].BaseAddress = mPlatformInfo->PciData.PciExpressBase; ((EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *) Table)->Segment[0].EndBusNumber = (UINT8)RShiftU64 (mPlatformInfo->PciData.PciExpressSize, 20) - 1; break; case EFI_ACPI_OSFR_TABLE_SIGNATURE: // // Get size of OSFR variable. // OcurMfgStringBufferSize = 0; Status = gRT->GetVariable ( gACPIOSFRMfgStringVariableName, &gACPIOSFRMfgStringVariableGuid, NULL, &OcurMfgStringBufferSize, NULL ); if (Status != EFI_BUFFER_TOO_SMALL) { // // Variable must not be present on the system. // return EFI_UNSUPPORTED; } // // Allocate memory for variable data. // OcurMfgStringBuffer = AllocatePool (OcurMfgStringBufferSize); Status = gRT->GetVariable ( gACPIOSFRMfgStringVariableName, &gACPIOSFRMfgStringVariableGuid, NULL, &OcurMfgStringBufferSize, OcurMfgStringBuffer ); if (!EFI_ERROR (Status)) { OcurModelStringBufferSize = 0; Status = gRT->GetVariable ( gACPIOSFRModelStringVariableName, &gACPIOSFRModelStringVariableGuid, NULL, &OcurModelStringBufferSize, NULL ); if (Status != EFI_BUFFER_TOO_SMALL) { // // Variable must not be present on the system. // return EFI_UNSUPPORTED; } // // Allocate memory for variable data. // OcurModelStringBuffer = AllocatePool (OcurModelStringBufferSize); Status = gRT->GetVariable ( gACPIOSFRModelStringVariableName, &gACPIOSFRModelStringVariableGuid, NULL, &OcurModelStringBufferSize, OcurModelStringBuffer ); if (!EFI_ERROR (Status)) { OcurRefDataBlockBufferSize = 0; Status = gRT->GetVariable ( gACPIOSFRRefDataBlockVariableName, &gACPIOSFRRefDataBlockVariableGuid, NULL, &OcurRefDataBlockBufferSize, NULL ); if (Status == EFI_BUFFER_TOO_SMALL) { // // Allocate memory for variable data. // OcurRefDataBlockBuffer = AllocatePool (OcurRefDataBlockBufferSize); Status = gRT->GetVariable ( gACPIOSFRRefDataBlockVariableName, &gACPIOSFRRefDataBlockVariableGuid, NULL, &OcurRefDataBlockBufferSize, OcurRefDataBlockBuffer ); } OsfrTable = (EFI_ACPI_OSFR_TABLE *) Table; // // Currently only one object is defined: OCUR_OSFR_TABLE. // OsfrTable->ObjectCount = 1; // // Initialize table length to fixed portion of the ACPI OSFR table. // OsfrTable->Header.Length = sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION); *(UINT32 *)((UINTN) OsfrTable + sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION)) = \ (UINT32) (sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION) + sizeof (UINT32)); pOcurObject = (EFI_ACPI_OSFR_OCUR_OBJECT *)((UINTN) OsfrTable + sizeof (EFI_ACPI_OSFR_TABLE_FIXED_PORTION) + \ sizeof (UINT32)); CopyMem (pOcurObject, &OcurObject, sizeof (EFI_ACPI_OSFR_OCUR_OBJECT)); pOcurObject->ManufacturerNameStringOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \ sizeof (EFI_ACPI_OSFR_OCUR_OBJECT)); pOcurObject->ModelNameStringOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \ sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize); if (OcurRefDataBlockBufferSize > 0) { pOcurObject->MicrosoftReferenceOffset = (UINT32)((UINTN) pOcurObject - (UINTN) OsfrTable + \ sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize + OcurModelStringBufferSize); } CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT)), OcurMfgStringBuffer, \ OcurMfgStringBufferSize); CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize), \ OcurModelStringBuffer, OcurModelStringBufferSize); if (OcurRefDataBlockBufferSize > 0) { CopyMem ((UINTN *)((UINTN) pOcurObject + sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + OcurMfgStringBufferSize + \ OcurModelStringBufferSize),OcurRefDataBlockBuffer, OcurRefDataBlockBufferSize); } OsfrTable->Header.Length += (UINT32)(OcurMfgStringBufferSize + OcurModelStringBufferSize + OcurRefDataBlockBufferSize); OsfrTable->Header.Length += sizeof (EFI_ACPI_OSFR_OCUR_OBJECT) + sizeof (UINT32); } } gBS->FreePool (OcurMfgStringBuffer); gBS->FreePool (OcurModelStringBuffer); gBS->FreePool (OcurRefDataBlockBuffer); break; default: break; } // // // Update the hardware signature in the FACS structure. // // // Locate the SPCR table and update based on current settings. // The user may change CR settings via setup or other methods. // The SPCR table must match. // return EFI_SUCCESS; }
/** Check parameters to a CPU I/O PPI service request. @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation. @param[in] Width The width of the access. Enumerated in bytes. @param[in] Address The physical address of the access. @param[in] Count The number of accesses to perform. @param[in] Buffer A pointer to the buffer of data. @retval EFI_SUCCESS The parameters for this request pass the checks. @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. @retval EFI_INVALID_PARAMETER Buffer is NULL. @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count is not valid for this EFI system. **/ EFI_STATUS CpuIoCheckParameter ( IN BOOLEAN MmioOperation, IN EFI_PEI_CPU_IO_PPI_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer ) { UINT64 MaxCount; UINT64 Limit; // // Check to see if Buffer is NULL // if (Buffer == NULL) { return EFI_INVALID_PARAMETER; } // // Check to see if Width is in the valid range // if ((UINT32)Width >= EfiPeiCpuIoWidthMaximum) { return EFI_INVALID_PARAMETER; } // // For FIFO type, the target address won't increase during the access, // so treat Count as 1 // if (Width >= EfiPeiCpuIoWidthFifoUint8 && Width <= EfiPeiCpuIoWidthFifoUint64) { Count = 1; } // // Check to see if Width is in the valid range for I/O Port operations // Width = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03); if (!MmioOperation && (Width == EfiPeiCpuIoWidthUint64)) { return EFI_INVALID_PARAMETER; } // // Check to see if any address associated with this transfer exceeds the maximum // allowed address. The maximum address implied by the parameters passed in is // Address + Size * Count. If the following condition is met, then the transfer // is not supported. // // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1 // // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count // can also be the maximum integer value supported by the CPU, this range // check must be adjusted to avoid all overflow conditions. // // The following form of the range check is equivalent but assumes that // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1). // Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS); if (Count == 0) { if (Address > Limit) { return EFI_UNSUPPORTED; } } else { MaxCount = RShiftU64 (Limit, Width); if (MaxCount < (Count - 1)) { return EFI_UNSUPPORTED; } if (Address > LShiftU64 (MaxCount - Count + 1, Width)) { return EFI_UNSUPPORTED; } } return EFI_SUCCESS; }