diff options
Diffstat (limited to 'memtestEDK')
77 files changed, 21923 insertions, 0 deletions
diff --git a/memtestEDK/MdeModulePkg.dsc b/memtestEDK/MdeModulePkg.dsc new file mode 100644 index 0000000..c56162f --- /dev/null +++ b/memtestEDK/MdeModulePkg.dsc @@ -0,0 +1,504 @@ +## @file
+# EFI/PI Reference Module Package for All Architectures
+#
+# (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = MdeModule
+ PLATFORM_GUID = 587CE499-6CBE-43cd-94E2-186218569478
+ PLATFORM_VERSION = 0.98
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/MdeModule
+ SUPPORTED_ARCHITECTURES = IA32|X64|EBC|ARM|AARCH64|RISCV64
+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+[LibraryClasses]
+ #
+ # Entry point
+ #
+ # PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ # PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ # DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ # UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ #
+ # Basic
+ #
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ # SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ # IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ # PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+ # PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ # PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
+ # CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ # PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ # PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ # SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
+ #
+ # UEFI & PI
+ #
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ # UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ # UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+ # HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ # UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ # PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+ # PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ # DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ # DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ # UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ #
+ # Generic Modules
+ #
+ # UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+ # UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+ # SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+ # TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+ # SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
+ # CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ # CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
+ # FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
+ #
+ # Misc
+ #
+ # DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ # ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ # PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ # PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ # DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+ # PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
+ # ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
+ # SmbusLib|MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf
+ # S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
+ # CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
+ # PlatformBootManagerLib|MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
+ # PciHostBridgeLib|MdeModulePkg/Library/PciHostBridgeLibNull/PciHostBridgeLibNull.inf
+ # TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+ # AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
+ # VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+ # FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+ # NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
+
+ # FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenticationLibNull/FmpAuthenticationLibNull.inf
+ # CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ # BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
+ # SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+ # DisplayUpdateProgressLib|MdeModulePkg/Library/DisplayUpdateProgressLibGraphics/DisplayUpdateProgressLibGraphics.inf
+
+[LibraryClasses.EBC.PEIM]
+ # IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf
+
+[LibraryClasses.common.PEI_CORE]
+ # HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ # MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+
+[LibraryClasses.common.PEIM]
+ # HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ # MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ # ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+ # LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
+
+[LibraryClasses.common.DXE_CORE]
+ # HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+ # MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
+ # ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+ # HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ # LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+ # MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ # ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+ # CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+ # HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ # MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ # DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
+ # LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+ # CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+
+[LibraryClasses.common.SMM_CORE]
+ # HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ # MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
+ # SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf
+ # SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
+ # SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
+
+[LibraryClasses.common.DXE_SMM_DRIVER]
+ # HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ # DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ # MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+ # MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
+ # SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+ # LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
+ # SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+ # HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ # MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ # DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
+ # LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+
+[LibraryClasses.common.UEFI_APPLICATION]
+ # HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
+ # FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+
+[LibraryClasses.common.MM_STANDALONE]
+ # HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
+ # MemoryAllocationLib|MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
+ # StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
+ # MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
+
+[LibraryClasses.ARM, LibraryClasses.AARCH64]
+ # ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
+ # ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
+ # LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
+
+ #
+ # It is not possible to prevent ARM compiler calls to generic intrinsic functions.
+ # This library provides the instrinsic functions generated by a given compiler.
+ # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
+ #
+ NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+
+ #
+ # Since software stack checking may be heuristically enabled by the compiler
+ # include BaseStackCheckLib unconditionally.
+ #
+ NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+
+[LibraryClasses.EBC, LibraryClasses.RISCV64]
+ # LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
+
+[PcdsFeatureFlag]
+ # gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE
+ # gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE
+ # gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
+ # gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText|FALSE
+ # gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText|FALSE
+
+[PcdsFixedAtBuild]
+ # gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f
+ # gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
+ # gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0
+ # gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0
+ # gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|28
+
+[PcdsDynamicExDefault]
+ # gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"
+
+[Components]
+ Memtest/ConfigurationTable/ConfigurationTable.inf
+ Memtest/GetMemoryMap/GetMemoryMap.inf
+ Memtest/SingleComponents/TestScreenbuffer.inf
+ Memtest/ProtocolInformation/ProtocolInformation.inf
+ #Memtest/SingleComponents/TestCpuid.inf
+ Memtest/SingleComponents/TestConfig.inf
+ Memtest/SingleComponents/TestSmp.inf
+ Memtest/GetRootSystemDescriptionPointer/GetRootSystemDescriptionPointer.inf
+
+ # MdeModulePkg/Application/HelloWorld/HelloWorld.inf
+ # MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
+ # MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
+
+ # MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ # MdeModulePkg/Logo/Logo.inf
+ # MdeModulePkg/Logo/LogoDxe.inf
+ # MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
+ # MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
+ # MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
+ # MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
+ # MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+ # MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+ # MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
+ # MdeModulePkg/Library/PciHostBridgeLibNull/PciHostBridgeLibNull.inf
+ # MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf
+ # MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+ # MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
+ # MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
+
+ # MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+ # MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
+ # MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+ # MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
+ # MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+ # MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
+ # MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
+ # MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.inf
+ # MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf
+ # MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf
+ # MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
+ # MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
+ # MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
+ # MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
+ # MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
+ # MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf
+ # MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
+ # MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+ # MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+ # MdeModulePkg/Bus/Pci/UhciPei/UhciPei.inf
+ # MdeModulePkg/Bus/Pci/EhciPei/EhciPei.inf
+ # MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
+ # MdeModulePkg/Bus/Pci/IdeBusPei/IdeBusPei.inf
+ # MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
+ # MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPei.inf
+ # MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
+ # MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+ # MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+ # MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
+ # MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+ # MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+ # MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+ # MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+ # MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+ # MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf
+ # MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
+ # MdeModulePkg/Bus/I2c/I2cDxe/I2cBusDxe.inf
+ # MdeModulePkg/Bus/I2c/I2cDxe/I2cHostDxe.inf
+ # MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.inf
+ # MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
+ # MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
+ # MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
+ # MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
+
+ # MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+ # MdeModulePkg/Core/Pei/PeiMain.inf
+ # MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+
+ # MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ # MdeModulePkg/Library/UefiMemoryAllocationProfileLib/UefiMemoryAllocationProfileLib.inf
+ # MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
+ # MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationProfileLib.inf
+ # MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
+ # MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
+ # MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+ # MdeModulePkg/Library/DxeResetSystemLib/DxeResetSystemLib.inf
+ # MdeModulePkg/Library/DxePrintLibPrint2Protocol/DxePrintLibPrint2Protocol.inf
+ # MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.inf
+ # MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
+ # MdeModulePkg/Library/PeiResetSystemLib/PeiResetSystemLib.inf
+ # MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ # MdeModulePkg/Library/ResetUtilityLib/ResetUtilityLib.inf
+ # MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
+ # MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+ # MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ # MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ # MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ # MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+ # MdeModulePkg/Library/RuntimeResetSystemLib/RuntimeResetSystemLib.inf
+ # MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
+ # MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
+ # MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf
+ # MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
+ # MdeModulePkg/Library/PeiDebugPrintHobLib/PeiDebugPrintHobLib.inf
+ # MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
+ # MdeModulePkg/Library/PlatformHookLibSerialPortPpi/PlatformHookLibSerialPortPpi.inf
+ # MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
+ # MdeModulePkg/Library/PeiDebugLibDebugPpi/PeiDebugLibDebugPpi.inf
+ # MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ # MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
+ # MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
+ # MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+ # MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
+ # MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+ # MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
+ # MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
+ # MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf
+ # MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+ # MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.inf
+ # MdeModulePkg/Library/BaseIpmiLibNull/BaseIpmiLibNull.inf
+ # MdeModulePkg/Library/DxeIpmiLibIpmiProtocol/DxeIpmiLibIpmiProtocol.inf
+ # MdeModulePkg/Library/PeiIpmiLibIpmiPpi/PeiIpmiLibIpmiPpi.inf
+ # MdeModulePkg/Library/SmmIpmiLibSmmIpmiProtocol/SmmIpmiLibSmmIpmiProtocol.inf
+ # MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
+ # MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
+ # MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
+ # MdeModulePkg/Library/DisplayUpdateProgressLibGraphics/DisplayUpdateProgressLibGraphics.inf
+ # MdeModulePkg/Library/DisplayUpdateProgressLibText/DisplayUpdateProgressLibText.inf
+
+ # MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+ # MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf
+ # MdeModulePkg/Application/UiApp/UiApp.inf{
+ # <LibraryClasses>
+ # NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+ # NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
+ # NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
+ # }
+ # MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
+ # MdeModulePkg/Universal/BootManagerPolicyDxe/BootManagerPolicyDxe.inf
+ # MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
+ # MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf
+ # MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+ # MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+ # MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+ # MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+ # MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDxe.inf
+ # MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+ # MdeModulePkg/Universal/DebugPortDxe/DebugPortDxe.inf
+ # MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+ # MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+ # MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+ # MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+ # MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+ # MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+ # MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+ # MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
+ # MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+ # MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/GenericMemoryTestDxe.inf
+ # MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+ # MdeModulePkg/Universal/Metronome/Metronome.inf
+ # MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+ # MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf {
+ # <LibraryClasses>
+ # ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
+ # }
+ # MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf {
+ # <LibraryClasses>
+ # ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
+ # }
+ # MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+ # MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.inf
+
+ # MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf
+ # MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+ # MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+ # MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
+
+ # MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+ # MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+
+ # MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+ # MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ # MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+ # MdeModulePkg/Application/VariableInfo/VariableInfo.inf
+ # MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
+ # MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+ # MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ # MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf
+ # MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+
+ # MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
+ # MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+ # MdeModulePkg/Universal/HiiResourcesSampleDxe/HiiResourcesSampleDxe.inf
+ # MdeModulePkg/Universal/LegacyRegion2Dxe/LegacyRegion2Dxe.inf
+
+ # MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+ # MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+
+ # MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf {
+ # <LibraryClasses>
+ # LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
+ # }
+ # MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf
+ # MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
+ # MdeModulePkg/Universal/SectionExtractionDxe/SectionExtractionDxe.inf {
+ # <LibraryClasses>
+ # NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
+ # }
+ # MdeModulePkg/Universal/SectionExtractionPei/SectionExtractionPei.inf {
+ # <LibraryClasses>
+ # NULL|MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.inf
+ # }
+
+ # MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf
+ # MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
+ # MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf
+
+ # MdeModulePkg/Universal/FileExplorerDxe/FileExplorerDxe.inf {
+ # <LibraryClasses>
+ # FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+ # }
+
+ # MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
+ # MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.inf
+
+ # MdeModulePkg/Universal/DebugServicePei/DebugServicePei.inf
+
+ # MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf
+ # MdeModulePkg/Library/FmpAuthenticationLibNull/FmpAuthenticationLibNull.inf
+ # MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
+ # MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+
+[Components.IA32, Components.X64, Components.AARCH64]
+ # MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+ # MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
+ # MdeModulePkg/Universal/EbcDxe/EbcDebuggerConfig.inf
+
+[Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
+# MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliCustomDecompressLib.inf
+# MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+# MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+# MdeModulePkg/Core/Dxe/DxeMain.inf {
+# <LibraryClasses>
+# NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
+# }
+
+# !if $(TOOL_CHAIN_TAG) != "XCODE5"
+# MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteStandaloneMm.inf
+# MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
+# !endif
+
+[Components.IA32, Components.X64]
+ # MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf
+ # MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.inf
+ # MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
+ # MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
+ # MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
+ # <LibraryClasses>
+ # NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+ # NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
+ # NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
+ # }
+ # MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
+ # <LibraryClasses>
+ # NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+ # NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
+ # NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
+ # }
+ # MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+ # MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
+ # MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
+ # MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
+ # MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
+ # MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.inf
+ # MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf
+ # MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
+ # MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
+ # MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
+ # MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
+ # MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+ # MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
+ # MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
+ # MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.inf
+ # MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf
+ # MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+ # MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+ # MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.inf
+ # MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf
+ # MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
+ # MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf
+ # MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf
+ # MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.inf
+ # MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
+
+[Components.X64]
+ #MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
+
+[BuildOptions]
+ *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+
diff --git a/memtestEDK/Memtest/ConfigurationTable/ConfigurationTable.c b/memtestEDK/Memtest/ConfigurationTable/ConfigurationTable.c new file mode 100644 index 0000000..905a21e --- /dev/null +++ b/memtestEDK/Memtest/ConfigurationTable/ConfigurationTable.c @@ -0,0 +1,32 @@ + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + Print(L"This is the Memtest Application\n"); + + EFI_SYSTEM_TABLE *st = SystemTable; + EFI_CONFIGURATION_TABLE *ct = st->ConfigurationTable; + EFI_GUID guid = ct->VendorGuid; + UINT32 data1 = guid.Data1; + // UINT16 data2 = guid.Data2; + // UINT16 data3 ; + // UINT8 data4[8]; + + + // + // Use UefiLib Print API to print string to UEFI console + // + Print(L"Data1: %d\n", data1); + + return EFI_SUCCESS; +} + diff --git a/memtestEDK/Memtest/ConfigurationTable/ConfigurationTable.inf b/memtestEDK/Memtest/ConfigurationTable/ConfigurationTable.inf new file mode 100644 index 0000000..3fd61ee --- /dev/null +++ b/memtestEDK/Memtest/ConfigurationTable/ConfigurationTable.inf @@ -0,0 +1,32 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ConfigurationTable + FILE_GUID = 51d8cae0-272a-451f-a8d9-8451dff0ebd0 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC Etc... +# + +[Sources] + ConfigurationTable.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] diff --git a/memtestEDK/Memtest/ConfigurationTable/TODO b/memtestEDK/Memtest/ConfigurationTable/TODO new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/memtestEDK/Memtest/ConfigurationTable/TODO diff --git a/memtestEDK/Memtest/GetMemoryMap/GetMemoryMap.c b/memtestEDK/Memtest/GetMemoryMap/GetMemoryMap.c new file mode 100644 index 0000000..926849c --- /dev/null +++ b/memtestEDK/Memtest/GetMemoryMap/GetMemoryMap.c @@ -0,0 +1,172 @@ +#include <stdio.h> +//#include <stdlib.h> + + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + +#include "../SingleComponents/environment.h" + + +#define DATA_SIZE 1000 + +EFI_MEMORY_DESCRIPTOR getNextElement(EFI_MEMORY_DESCRIPTOR *memoryMap) { // TODO + return *memoryMap; +} + +const CHAR16 *memory_types[] = +{ + L"EfiReservedMemoryType", + L"EfiLoaderCode", + L"EfiLoaderData", + L"EfiBootServicesCode", + L"EfiBootServicesData", + L"EfiRuntimeServicesCode", + L"EfiRuntimeServicesData", + L"EfiConventionalMemory", + L"EfiUnusableMemory", + L"EfiACPIReclaimMemory", + L"EfiACPIMemoryNVS", + L"EfiMemoryMappedIO", + L"EfiMemoryMappedIOPortSpace", + L"EfiPalCode", +}; + +void printToFile() { + /* Variable to store user content */ + char data[DATA_SIZE]; + + /* File pointer to hold reference to our file */ + FILE * fPtr; + + + /* + * Open file in w (write) mode. + * "data/file1.txt" is complete path to create file + */ + fPtr = fopen("data/file1.txt", "w"); + + + /* fopen() return NULL if last operation was unsuccessful */ + if(fPtr == NULL) + { + /* File not created hence exit */ + printf("Unable to create file.\n"); + } + + + /* Write data to file */ + fputs(data, fPtr); + + + /* Close file to save file data */ + fclose(fPtr); + + + /* Success message */ + printf("File created and saved successfully. :) \n"); +} + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + Print(L"Application to get Memory Map\n"); + + UINTN MemoryMapSize = 0; + EFI_MEMORY_DESCRIPTOR *memoryMap = NULL; + UINTN LocalMapKey; + UINTN DescriptorSize; + UINT32 DescriptorVersion; + EFI_STATUS Status; + + EFI_BOOT_SERVICES *bs = SystemTable->BootServices; + + Status = bs->GetMemoryMap(&MemoryMapSize, memoryMap, &LocalMapKey, &DescriptorSize, &DescriptorVersion); +/* Print(L"MemoryMapSize: %d\n", MemoryMapSize); // size needed if the buffer was to small + Print(L"memoryMap pointer: %p\n", memoryMap); + Print(L"This time through the memory map loop, status = %r\n",Status);*/ + do { +/* Print(L"Buffer was too small!\n"); + Print(L"Trying with size %d\n", (UINTN) (MemoryMapSize + 1) ); + Print(L"MemoryMapSize: %d\n", MemoryMapSize); // size needed if the buffer was to small + Print(L"MemoryMap pointer: %p\n", memoryMap);*/ + + Status = bs->AllocatePool(EfiLoaderData, (UINTN) (MemoryMapSize + 1) , (void **)&memoryMap); +/* + Print(L"Status = %r\n", Status); + Print(L"MemoryMap pointer: %p\n", memoryMap); +*/ + Status = bs->GetMemoryMap(&MemoryMapSize, memoryMap, &LocalMapKey, &DescriptorSize, &DescriptorVersion); +/* Print(L"Status = %r\n", Status); + Print(L"After GetMemoryMap\n"); + Print(L"MemoryMapSize: %d\n", MemoryMapSize); // size needed if the buffer was to small + Print(L"memoryMap pointer: %p\n", memoryMap); + Print(L"This time through the memory map loop, status = %r\n",Status);*/ + } while (Status == EFI_BUFFER_TOO_SMALL); + + if (Status != EFI_SUCCESS) { + Print(L"Status = %r\n", Status); + } + + + Print(L"After GetMemoryMap\n"); + Print(L"MemoryMapSize: %d\n", MemoryMapSize); // size needed if the buffer was to small + Print(L"MemoryMap pointer: %p\n", memoryMap); + + EFI_MEMORY_DESCRIPTOR firstElement = *memoryMap; + Print(L"memoryMap location: %p\n", memoryMap); + Print(L"Size of first element: %d\n", sizeof(firstElement)); + Print(L"Type: %d\n", firstElement.Type); + Print(L"PhysicalStart: %p\n", firstElement.PhysicalStart); + Print(L"VirtualStart: %p\n", firstElement.VirtualStart); + Print(L"NumberOfPages: %d\n", firstElement.NumberOfPages); + Print(L"Attribute: %d\n", firstElement.Attribute); + + + EFI_MEMORY_DESCRIPTOR secondElement = *(memoryMap + 40); + Print(L"memoryMap location: %p\n", memoryMap); + Print(L"Size of first element: %d\n", sizeof(secondElement)); + Print(L"Type: %d\n", secondElement.Type); + Print(L"PhysicalStart: %p\n", secondElement.PhysicalStart); + Print(L"VirtualStart: %p\n", secondElement.VirtualStart); + Print(L"NumberOfPages: %d\n", secondElement.NumberOfPages); + Print(L"Attribute: %d\n", secondElement.Attribute); + + uint8_t *startOfMemoryMap = (uint8_t *)memoryMap; + uint8_t *endOfMemoryMap = startOfMemoryMap + MemoryMapSize; + + uint8_t *offset = startOfMemoryMap; + + uint32_t counter = 0; + uint64_t totalPages = 0; + + EFI_MEMORY_DESCRIPTOR *desc = NULL; + + while(offset < endOfMemoryMap) { + desc = (EFI_MEMORY_DESCRIPTOR *)offset; + + Print(L"Map %d:\n", counter); + Print(L" Type: %X, %s\n", desc->Type, memory_types[desc->Type]); + Print(L" PhysicalStart: %X\n", desc->PhysicalStart); + Print(L" VirtualStart: %X\n", desc->VirtualStart); + Print(L" NumberOfPages: %X (4k)\n", desc->NumberOfPages); + Print(L" Attribute: %X\n", desc->Attribute); + + totalPages += desc->NumberOfPages; + + offset += DescriptorSize; + counter++; + + uint64_t MemoryMapSize = totalPages * 4096; + Print(L"Memory detected: %d MB\n", MemoryMapSize / 1024 / 1024); + } + + + return EFI_SUCCESS; +} + diff --git a/memtestEDK/Memtest/GetMemoryMap/GetMemoryMap.inf b/memtestEDK/Memtest/GetMemoryMap/GetMemoryMap.inf new file mode 100644 index 0000000..87a9855 --- /dev/null +++ b/memtestEDK/Memtest/GetMemoryMap/GetMemoryMap.inf @@ -0,0 +1,32 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = GetMemoryMap + FILE_GUID = 51d8cae0-272a-661f-a8d9-8451dff0ebd0 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC Etc... +# + +[Sources] + GetMemoryMap.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] diff --git a/memtestEDK/Memtest/GetMemoryMap/TODO b/memtestEDK/Memtest/GetMemoryMap/TODO new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/memtestEDK/Memtest/GetMemoryMap/TODO diff --git a/memtestEDK/Memtest/GetRootSystemDescriptionPointer/GetRootSystemDescriptionPointer.c b/memtestEDK/Memtest/GetRootSystemDescriptionPointer/GetRootSystemDescriptionPointer.c new file mode 100644 index 0000000..b9e3e48 --- /dev/null +++ b/memtestEDK/Memtest/GetRootSystemDescriptionPointer/GetRootSystemDescriptionPointer.c @@ -0,0 +1,173 @@ +#include <stdio.h> + +#include <stdint.h> +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + +struct RSDPDescriptor { + char Signature[8]; + uint8_t Checksum; + char OEMID[6]; + uint8_t Revision; + uint32_t RsdtAddress; +} __attribute__ ((packed)); + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINTN NumberOfTableEntries = SystemTable->NumberOfTableEntries; + EFI_CONFIGURATION_TABLE *ConfigurationTable = SystemTable->ConfigurationTable; + + + + Print(L"NumberOfTableEntries: %d\n", NumberOfTableEntries); + + for (int i = 0; i < NumberOfTableEntries; i++) { + EFI_GUID guid = ConfigurationTable->VendorGuid; + UINT32 Data1 = guid.Data1; + UINT16 Data2 = guid.Data2; + UINT16 Data3 = guid.Data3; + UINT8 Data4[8]; + Data4[0] = guid.Data4[0]; + + if (Data1 == 0xEB9D2D30) { + // ACPI 1.0 + // TODO check other fields + // VOID *VendorTable + + Print(L"ConfigurationTable pointer: %p\n", ConfigurationTable); + Print(L"VendorGuid: %x\n", Data1); + Print(L"VendorGuid: %x\n", Data2); + Print(L"VendorGuid: %x\n", Data3); + for (int j = 0; j < 8; j++) { + Print(L"VendorGuid: %x\n", Data4[j]); + } + + struct RSDPDescriptor *VendorTable = ConfigurationTable->VendorTable; + + char Signature[8]; + for (int k = 0; k < 8; k++) { + Signature[k] = VendorTable->Signature[k]; + Print(L"Signature of RootSystemDescriptorTable: %c\n", Signature[k]); + } + //(L"Signature of RootSystemDescriptorTable: %s\n", Signature); + + + + uint8_t Checksum = VendorTable->Checksum; + Print(L"Checksum: %d\n", Checksum); + + char OEMID[6]; + for (int l = 0; l < 6; l++) { + OEMID[l] = VendorTable->OEMID[l]; + Print(L"OEMID: %c\n", OEMID[l]); + } + + uint8_t Revision = VendorTable->Revision; + Print(L"Revision: %d\n", Revision); + + uint32_t RsdtAddress = VendorTable->RsdtAddress; + Print(L"RsdtAddress: %p\n", RsdtAddress); + Print(L"VendorTable Adress: %p\n", VendorTable); + } +/* + if (Data1 == 0x8868E871) { + // ACPI 2.0 + // TODO check other fields + // VOID *VendorTable + + Print(L"ConfigurationTable pointer: %p\n", ConfigurationTable); + Print(L"VendorGuid: %x\n", Data1); + Print(L"VendorGuid: %x\n", Data2); + Print(L"VendorGuid: %x\n", Data3); + for (int j = 0; j < 8; j++) { + Print(L"VendorGuid: %x\n", Data4[j]); + } + + //VOID *VendorTable = ConfigurationTable->VendorTable; + + }*/ + + ConfigurationTable += 1; + } + + return EFI_SUCCESS; + +} + +/* + +//EFI_GUID + +typedef struct { +UINT32 Data1; +UINT16 Data2; +UINT16 Data3; +UINT8 +Data4[8]; +} EFI_GUID;*/ + +/* +typedef struct{ +EFI_GUID VendorGuid; 128-bit GUID +VOID *VendorTable; +} EFI_CONFIGURATION_TABLE; +*/ + +/* +In ACPI Version 1.0 it has this structure: + +struct RSDPDescriptor { + char Signature[8]; + uint8_t Checksum; + char OEMID[6]; + uint8_t Revision; + uint32_t RsdtAddress; +} __attribute__ ((packed)); + +since Version 2.0 it has been extended, and the following new fields have been added: + +struct RSDPDescriptor20 { + RSDPDescriptor firstPart; + + uint32_t Length; + uint64_t XsdtAddress; + uint8_t ExtendedChecksum; + uint8_t reserved[3]; +} __attribute__ ((packed));*/ + +/*UINTN NumberOfTableEntries The number of system configuration tables in the buffer +ConfigurationTable. +EFI_CONFIGURATION_TABLE *ConfigurationTable A pointer to the system configuration tables. The number of +entries in the table is NumberOfTableEntries.*/ + +/*ACPI5_1_Specification.pdf + +5.2.5.2 Finding the RSDP on UEFI Enabled Systems +In Unified Extensible Firmware Interface (UEFI) enabled systems, a pointer to the RSDP structure +exists within the EFI System Table. The OS loader is provided a pointer to the EFI System Table at +invocation. The OS loader must retrieve the pointer to the RSDP structure from the EFI System +Table and convey the pointer to OSPM, using an OS dependent data structure, as part of the hand off +of control from the OS loader to the OS. +The OS loader locates the pointer to the RSDP structure by examining the EFI Configuration Table +within the EFI System Table. EFI Configuration Table entries consist of Globally Unique Identifier +(GUID)/table pointer pairs. The UEFI specification defines two GUIDs for ACPI; one for ACPI 1.0 +and the other for ACPI 2.0 or later specification revisions. +The EFI GUID for a pointer to the ACPI 1.0 specification RSDP structure is: +• +EB9D2D30-2D88-11D3-9A16-0090273FC14D. +The EFI GUID for a pointer to the ACPI 2.0 or later specification RSDP structure is: +• +8868E871-E4F1-11D3-BC22-0080C73C8881. +The OS loader for an ACPI-compatible OS will search for an RSDP structure pointer using the +current revision GUID first and if it finds one, will use the corresponding RSDP structure pointer. If +the GUID is not found then the OS loader will search for the RSDP structure pointer using the ACPI +1.0 version GUID. +The OS loader must retrieve the pointer to the RSDP structure from the EFI System Table before +assuming platform control via the EFI ExitBootServices interface. See the UEFI Specification for +more information.*/
\ No newline at end of file diff --git a/memtestEDK/Memtest/GetRootSystemDescriptionPointer/GetRootSystemDescriptionPointer.inf b/memtestEDK/Memtest/GetRootSystemDescriptionPointer/GetRootSystemDescriptionPointer.inf new file mode 100644 index 0000000..e724962 --- /dev/null +++ b/memtestEDK/Memtest/GetRootSystemDescriptionPointer/GetRootSystemDescriptionPointer.inf @@ -0,0 +1,32 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = GetRootSystemDescriptionPointer + FILE_GUID = 51d8cae0-112a-661f-99d9-8451dff0ebd0 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC Etc... +# + +[Sources] + GetRootSystemDescriptionPointer.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] diff --git a/memtestEDK/Memtest/ProtocolInformation/ProtocolInformation.c b/memtestEDK/Memtest/ProtocolInformation/ProtocolInformation.c new file mode 100644 index 0000000..20ac4bc --- /dev/null +++ b/memtestEDK/Memtest/ProtocolInformation/ProtocolInformation.c @@ -0,0 +1,194 @@ +#include <stdio.h> + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ +/* + EFI_STATUS efiStatus; + + EFI_BOOT_SERVICES* bs = SystemTable->BootServices; + EFI_GUID sfspGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; + EFI_HANDLE* handleBuffer = NULL; + UINTN handleCount = 0; + UINTN HandleIndex; + EFI_GUID **ProtocolGuidArray; + UINTN ArrayCount; + UINTN ProtocolIndex; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo; + UINTN OpenInfoIndex; + UINTN OpenInfoCount; + + efiStatus = bs->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + handleCount, + &handleBuffer + ); + + Print(L"Number of handles found: %d\n", handleCount); + + if (!EFI_ERROR (efiStatus)) { + for (HandleIndex = 0; HandleIndex < handleCount; HandleIndex++) { + // + // Retrieve the list of all the protocols on each handle + // + efiStatus = bs->ProtocolsPerHandle ( + handleBuffer[HandleIndex], + &ProtocolGuidArray, + &ArrayCount + ); + + Print(L"Number of Protocols per Handle: %d\n", ArrayCount); + + if (!EFI_ERROR (efiStatus)) { + for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { + // + // Retrieve the protocol instance for each protocol + // + + efiStatus = bs->OpenProtocol ( + handleBuffer[HandleIndex], + ProtocolGuidArray[ProtocolIndex], + NULL, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + // + // Retrieve the list of agents that have opened each protocol + // + efiStatus = bs->OpenProtocolInformation ( + handleBuffer[HandleIndex], + ProtocolGuidArray[ProtocolIndex], + &OpenInfo, + &OpenInfoCount + ); + if (!EFI_ERROR (efiStatus)) { + for (OpenInfoIndex=0;OpenInfoIndex<OpenInfoCount;OpenInfoIndex++) { + // + // HandleBuffer[HandleIndex] is the handle + // ProtocolGuidArray[ProtocolIndex] is the protocol GUID + // Instance is the protocol instance for the protocol + // OpenInfo[OpenInfoIndex] is an agent that has opened a protocol + // + } + if (OpenInfo != NULL) { + bs->FreePool(OpenInfo); + } + } + } + if (ProtocolGuidArray != NULL) { + bs->FreePool(ProtocolGuidArray); + } + } + if (handleBuffer != NULL) { + bs->FreePool (handleBuffer); + } + } + } +*/ + /* efiStatus = bs->LocateHandleBuffer(ByProtocol, + &sfspGuid, + NULL, + &handleCount, + &handles); + + Print(L"Handle count: %d\n", handleCount); + + for (int index = 0; index < (int)handleCount; ++ index) + { + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs = NULL; + + Print(L"sfspGuid: %d\n", sfspGuid); + + efiStatus = bs->HandleProtocol( // TODO Should use OpenProtocol() in new implementations + handles[index], + &sfspGuid, + (void**)&fs + ); + Print(L"Status after HandleProtocol: %r\n", efiStatus); + Print(L"Volume %d found\n", index); + Print(L"fs pointer: %p\n", fs); + EFI_FILE_PROTOCOL* root = NULL; + efiStatus = fs->OpenVolume(fs, &root); + Print(L"Status after open volume: %r\n", efiStatus); + EFI_GUID fsiGuid = EFI_FILE_SYSTEM_INFO_ID; + UINTN bufSize = 0; + VOID* buffer = NULL; + + efiStatus = root->GetInfo( + root, + &fsiGuid, + &bufSize, + &buffer); + + Print(L"Status: %r\n", efiStatus); + Print(L"Required buffer size: %d\n", bufSize ); + + + efiStatus = bs->AllocatePool(EfiLoaderData, (UINTN) (bufSize) , (void **)&buffer); + + + efiStatus = root->GetInfo( + root, + &fsiGuid, + &bufSize, + &buffer); + + Print(L"Status: %r\n", efiStatus); + + EFI_FILE_SYSTEM_INFO* fhgf = buffer; + + Print(L"buffer pointer %p\n", buffer); + Print(L"fhgf pointer %p\n", fhgf); + + Print(L"VolumeLabel: %s\n", fhgf->VolumeLabel); + Print(L"Size: %d\n", fhgf->Size); + Print(L"ReadOnly: %d\n", fhgf->ReadOnly); + Print(L"VolumeSize: %d\n", fhgf->VolumeSize); + Print(L"FreeSpace: %d\n", fhgf->FreeSpace); + Print(L"BlockSize: %d\n", fhgf->BlockSize); + Print(L"Number of handle found %d\n", (index + 1)); + + efiStatus = bs->FreePool((void **)&buffer); + Print(L"efiStatus after FreePool: %r\n", efiStatus); + }*/ +/* +... + + + + + EFI_FILE_PROTOCOL* token = NULL; +efiStatus = root->Open( + root, + &token, + L"myfolder\\token.bin", + EFI_FILE_MODE_READ, + EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);*/ + +/* + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush;*/ + + return EFI_SUCCESS; +} + diff --git a/memtestEDK/Memtest/ProtocolInformation/ProtocolInformation.inf b/memtestEDK/Memtest/ProtocolInformation/ProtocolInformation.inf new file mode 100644 index 0000000..74d8662 --- /dev/null +++ b/memtestEDK/Memtest/ProtocolInformation/ProtocolInformation.inf @@ -0,0 +1,32 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = ProtocolInformation + FILE_GUID = 51d8cae0-112a-661f-a8d9-8451dff0ebd0 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC Etc... +# + +[Sources] + ProtocolInformation.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] diff --git a/memtestEDK/Memtest/ProtocolInformation/TODO b/memtestEDK/Memtest/ProtocolInformation/TODO new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/memtestEDK/Memtest/ProtocolInformation/TODO diff --git a/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/apic_test.c b/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/apic_test.c new file mode 100644 index 0000000..3e6ff2a --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/apic_test.c @@ -0,0 +1,161 @@ +#include <Library/UefiLib.h> + +/*#include "cpuid.h" +#include "smp.h"*/ + +#include "apic_test.h" + + +extern void smp_find_cpus(); + +// Defined in test.h +typedef unsigned long ulong; +#define E820MAX 127 +#define MAX_MEM_SEGMENTS E820MAX +#define BADRAM_MAXPATNS 10 +#define LINE_SCROLL 14 + +struct pair { + ulong adr; + ulong mask; +}; + +struct mmap { + ulong pbase_addr; + ulong *start; // VA of segment start + ulong *end; // VA of the last dword within the segment. +}; + +struct pmap { + ulong start; /* phys page number of RAM segment start, + in 4K pages. */ + ulong end; // phys page number (past the end? or inclusive?) +}; + +struct xadr { + ulong page; + ulong offset; +}; + +struct err_info { + struct xadr low_addr; + struct xadr high_addr; + unsigned long ebits; + long tbits; + short min_bits; + short max_bits; + unsigned long maxl; + unsigned long eadr; + unsigned long exor; + unsigned long cor_err; + short hdr_flag; +}; + +struct vars { + int pass; + int msg_line; + int ecount; + int ecc_ecount; + int msegs; // number of entries in pmap[] + int testsel; + int scroll_start; + int pass_ticks; + int total_ticks; + int pptr; + int tptr; + struct err_info erri; + // PA ranges from e820 table: + struct pmap pmap[MAX_MEM_SEGMENTS]; + // VA mappings: + volatile struct mmap map[MAX_MEM_SEGMENTS]; + ulong plim_lower; // phys page number + ulong plim_upper; // phys page number + ulong clks_msec; + ulong starth; + ulong startl; + ulong snaph; + ulong snapl; + int printmode; + int numpatn; + struct pair patn [BADRAM_MAXPATNS]; + ulong test_pages; + ulong selected_pages; + ulong reserved_pages; + int check_temp; + int fail_safe; + int each_sec; + int beepmode; + int debugging; // Set in selftest only +}; + +// Defined in main.c +struct vars variables = {}; +struct vars * const vv = &variables; + +#define PRINTMODE_ADDRESSES 1 + + + + + +void set_values() { +vv->printmode=PRINTMODE_ADDRESSES; +vv->numpatn=0; +vv->plim_lower = 0; +vv->plim_upper = vv->pmap[vv->msegs-1].end; +vv->pass = 0; +vv->msg_line = 0; +vv->ecount = 0; +vv->ecc_ecount = 0; +vv->msg_line = LINE_SCROLL-1; +vv->scroll_start = vv->msg_line * 160; +vv->debugging = 0; +vv->erri.low_addr.page = 0x7fffffff; +vv->erri.low_addr.offset = 0xfff; +vv->erri.high_addr.page = 0; +vv->erri.high_addr.offset = 0; +vv->erri.min_bits = 32; +vv->erri.max_bits = 0; +vv->erri.min_bits = 32; +vv->erri.max_bits = 0; +vv->erri.maxl = 0; +vv->erri.cor_err = 0; +vv->erri.ebits = 0; +vv->erri.hdr_flag = 0; +vv->erri.tbits = 0; +} + +void smp_find_cpus_test() { + +// TODO search rsdp and other stuff in efi system table + set_values(); + smp_find_cpus(); +} + +void read_mp_config_table_test() { + +} + +void APIC_WRITE_test() { + +} + +void APIC_READ_test() { + +} + +void SEND_IPI_test() { + +} + +void kick_cpu_test() { + +} + +void my_apic_id_test() { + +} + +void smp_my_cpu_num_test() { + +}
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/apic_test.h b/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/apic_test.h new file mode 100644 index 0000000..0a70d42 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/apic_test.h @@ -0,0 +1,8 @@ +void smp_find_cpus_test(); +void read_mp_config_table_test(); // Here apic_reg_t APIC is set +void APIC_WRITE_test(); +void APIC_READ_test(); +void SEND_IPI_test(); +void kick_cpu_test(); +void my_apic_id_test(); +void smp_my_cpu_num_test(); diff --git a/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/cpuid_test.c b/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/cpuid_test.c new file mode 100644 index 0000000..dfb364e --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/cpuid_test.c @@ -0,0 +1,57 @@ + +#include <Library/UefiLib.h> + + +#include "cpuid.h" +#include "smp.h" +#include "environment.h" +#include "cpuid_test.h" + +static inline void +__GET_CPUID_MODIFIED(int ax, uint32_t *regs) +{ + __asm__ __volatile__("\t" + /* save ebx in case -fPIC is being used */ + "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx" + : "=a" (regs[0]), "=D" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) + : "a" (ax) + : "memory" + ); +} + +#define GET_CPUID_MODIFIED(_ax,_bx,_cx,_dx) { \ + uint32_t regs[4]; \ + __GET_CPUID_MODIFIED(_ax,regs); \ + _ax = regs[0]; \ + _bx = regs[1]; \ + _cx = regs[2]; \ + _dx = regs[3]; \ +} + +void get_cpuid_Fn0000_0000() { + uint32_t ax = 0; + uint32_t bx; + uint32_t cx = 0; + uint32_t dx; + GET_CPUID_MODIFIED(ax, bx, cx, dx); + + uint32_t a[3]; + a[0] = bx; // The ASCII characters “h t u Aâ€. + a[2] = cx; // The ASCII characters “D M A câ€. + a[1] = dx; // The ASCII characters “i t n eâ€. + + Print(L"Value of register ax: %x\n", ax); + Print(L"Value of a0: %x\n", a[0]); + Print(L"Value of a1: %x\n", a[1]); + Print(L"Value of a2: %x\n", a[2]); + Print(L"Value of a %x\n", a); + Print(L"Value of a0: %d\n", a[0]); + Print(L"Value of a1: %d\n", a[1]); + Print(L"Value of a2: %d\n", a[2]); + Print(L"Value of a %d\n", a); + Print(L"Value of a0: %s\n", a[0]); + Print(L"Value of a1: %s\n", a[1]); + Print(L"Value of a2: %s\n", a[2]); + Print(L"Value of a %s\n", a); + +}
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/cpuid_test.h b/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/cpuid_test.h new file mode 100644 index 0000000..2ade8c9 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/SmpTestFunctions/cpuid_test.h @@ -0,0 +1,2 @@ + +void get_cpuid_Fn0000_0000();
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/TODO b/memtestEDK/Memtest/SingleComponents/TODO new file mode 100644 index 0000000..49124f5 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TODO @@ -0,0 +1,26 @@ +TestConfig +============== + + + +TestCpuid +============== + + + +TestDefs +============== + + + +TestDmi +============== + + +TestScreenbuffer +================== + + + +TestSMP +=================
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/TestConfig.c b/memtestEDK/Memtest/SingleComponents/TestConfig.c new file mode 100644 index 0000000..cfd4b6a --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestConfig.c @@ -0,0 +1,25 @@ + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + +#include "config.h" + +extern void popup(); + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + Print(L"Test for config\n\n"); + + popup(); + + Print(L"Test finished.\n"); + + return EFI_SUCCESS; +}
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/TestConfig.inf b/memtestEDK/Memtest/SingleComponents/TestConfig.inf new file mode 100644 index 0000000..885f235 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestConfig.inf @@ -0,0 +1,37 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = TestConfig + + #Copy and paste the GUID from http://www.guidgen.com/ here + FILE_GUID = d49e07b2-cd2c-4d2c-96c4-5a88b805c6a1 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC Etc... +# + +[Sources] + TestConfig.c + config.c + screen_buffer.c + dmi.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] diff --git a/memtestEDK/Memtest/SingleComponents/TestCpuid.c b/memtestEDK/Memtest/SingleComponents/TestCpuid.c new file mode 100644 index 0000000..2dffb1d --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestCpuid.c @@ -0,0 +1,23 @@ + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + +#include "cpuid.h" + + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + Print(L"Test for cpuid\n\n"); + + get_cpuid(); + + Print(L"Test finished.\n"); + + return EFI_SUCCESS; +}
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/TestCpuid.inf b/memtestEDK/Memtest/SingleComponents/TestCpuid.inf new file mode 100644 index 0000000..10509c5 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestCpuid.inf @@ -0,0 +1,35 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = TestCpuid + + #Copy and paste the GUID from http://www.guidgen.com/ here + FILE_GUID = d49e07b2-cd2c-4c2c-96c4-5a88b805c6a1 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC Etc... +# + +[Sources] + TestCpuid.c + cpuid.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] diff --git a/memtestEDK/Memtest/SingleComponents/TestDefs.c b/memtestEDK/Memtest/SingleComponents/TestDefs.c new file mode 100644 index 0000000..8a87f98 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestDefs.c @@ -0,0 +1,22 @@ + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + +#include "defs.h" + + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + Print(L"Test for defs\n\n"); + + + Print(L"Test finished.\n"); + + return EFI_SUCCESS; +}
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/TestDmi.c b/memtestEDK/Memtest/SingleComponents/TestDmi.c new file mode 100644 index 0000000..437da7e --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestDmi.c @@ -0,0 +1,22 @@ + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + +#include "dmi.h" + + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + Print(L"Test for dmi\n\n"); + + + Print(L"Test finished.\n"); + + return EFI_SUCCESS; +}
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/TestScreenbuffer.c b/memtestEDK/Memtest/SingleComponents/TestScreenbuffer.c new file mode 100644 index 0000000..3b7d7f2 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestScreenbuffer.c @@ -0,0 +1,42 @@ + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + +#include "screen_buffer.h" + + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + Print(L"Test for screen_buffer\n\n"); + + #define SCRN_DEBUG + + int y, x; + + for (y=0; y < 25; ++y){ + for (x=0; x < 80; ++x){ + set_scrn_buf(y, x, 'a'); + } + set_scrn_buf(y, 80, '\0'); + } + + /* + char get_scrn_buf(const int y, const int x); + void set_scrn_buf(const int y, const int x, const char val); + void tty_print_region(const int pi_top,const int pi_left, const int pi_bottom,const int pi_right); + void tty_print_line(int y, int x, const char *text); + void tty_print_screen(void); + void print_error(char *pstr); + */ + + Print(L"Test finished.\n"); + + return EFI_SUCCESS; +} + diff --git a/memtestEDK/Memtest/SingleComponents/TestScreenbuffer.inf b/memtestEDK/Memtest/SingleComponents/TestScreenbuffer.inf new file mode 100644 index 0000000..b9183ea --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestScreenbuffer.inf @@ -0,0 +1,35 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = TestScreenbuffer + + #Copy and paste the GUID from http://www.guidgen.com/ here + FILE_GUID = d49e07b2-cd2c-4c2c-96c4-5a78b805c6a1 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC Etc... +# + +[Sources] + TestScreenbuffer.c + screen_buffer.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] diff --git a/memtestEDK/Memtest/SingleComponents/TestSmp.c b/memtestEDK/Memtest/SingleComponents/TestSmp.c new file mode 100644 index 0000000..5a44cbd --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestSmp.c @@ -0,0 +1,30 @@ + +#define UEFI + + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + +#include "cpuid.h" +#include "smp.h" +#include "SmpTestFunctions/cpuid_test.h" +#include "SmpTestFunctions/apic_test.h" + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + Print(L"Test of smp.h\n\n"); + get_cpuid_Fn0000_0000(); + + Print(L"Test of smp.c\n\n"); + smp_find_cpus_test(); + + Print(L"Test finished.\n"); + + return EFI_SUCCESS; +} diff --git a/memtestEDK/Memtest/SingleComponents/TestSmp.inf b/memtestEDK/Memtest/SingleComponents/TestSmp.inf new file mode 100644 index 0000000..7c3d15e --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestSmp.inf @@ -0,0 +1,38 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = TestSmp + + #Copy and paste the GUID from http://www.guidgen.com/ here + FILE_GUID = d49e07a1-cd2c-4c2c-96c4-5a78b805c6a1 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC Etc... +# + +[Sources] + TestSmp.c + smp.c + cpuid.c + SmpTestFunctions/cpuid_test.c + SmpTestFunctions/apic_test.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + +[Pcd] diff --git a/memtestEDK/Memtest/SingleComponents/TestTest.c b/memtestEDK/Memtest/SingleComponents/TestTest.c new file mode 100644 index 0000000..8840f54 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/TestTest.c @@ -0,0 +1,22 @@ + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> + +#include "test.h" + + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + Print(L"Test for test\n\n"); + + + Print(L"Test finished.\n"); + + return EFI_SUCCESS; +}
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/bootsect.S b/memtestEDK/Memtest/SingleComponents/bootsect.S new file mode 100644 index 0000000..96aa22b --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/bootsect.S @@ -0,0 +1,383 @@ +/*
+ * bootsect.s Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
+ * itself out of the way to address 0x90000, and jumps there.
+ *
+ * It then loads 'setup' directly after itself (0x90200), and the system
+ * at 0x10000, using BIOS interrupts.
+ *
+ * The loader has been made as simple as possible, and continuos
+ * read errors will result in a unbreakable loop. Reboot by hand. It
+ * loads pretty fast by getting whole tracks at a time whenever possible.
+ *
+ * 1-Jan-96 Modified by Chris Brady for use as a boot loader for MemTest-86.
+ */
+
+#include "defs.h"
+
+ROOT_DEV = 0
+
+.code16
+.section ".bootsect", "ax", @progbits
+_boot:
+
+
+# ld86 requires an entry symbol. This may as well be the usual one.
+.globl _main
+_main:
+ movw $BOOTSEG, %ax
+ movw %ax, %ds
+ movw $INITSEG, %ax
+ movw %ax, %es
+ movw $256, %cx
+ subw %si, %si
+ subw %di, %di
+ cld
+ rep
+ movsw
+ ljmp $INITSEG, $go - _boot
+
+go:
+ movw %cs, %ax
+ movw $(0x4000-12), %dx # 0x4000 is arbitrary value >= length of
+ # bootsect + length of setup + room for stack
+ # 12 is disk parm size
+
+# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
+# wouldn't have to worry about this if we checked the top of memory. Also
+# my BIOS can be configured to put the wini drive tables in high memory
+# instead of in the vector table. The old stack might have clobbered the
+# drive table.
+
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss # put stack at INITSEG:0x4000-12.
+ movw %dx, %sp
+
+/*
+ * Many BIOS's default disk parameter tables will not
+ * recognize multi-sector reads beyond the maximum sector number
+ * specified in the default diskette parameter tables - this may
+ * mean 7 sectors in some cases.
+ *
+ * Since single sector reads are slow and out of the question,
+ * we must take care of this by creating new parameter tables
+ * (for the first disk) in RAM. We will set the maximum sector
+ * count to 18 - the most we will encounter on an HD 1.44.
+ *
+ * High doesn't hurt. Low does.
+ *
+ * Segments are as follows: ds=es=ss=cs - INITSEG,
+ * fs = 0, gs = parameter table segment
+ */
+ pushw $0
+ popw %fs
+ movw $0x78, %bx # fs:bx is parameter table address
+ lgs %fs:(%bx),%si # gs:si is source
+
+ movw %dx, %di # es:di is destination
+ movw $6, %cx # copy 12 bytes
+ cld
+
+ rep movsw %gs:(%si), (%di)
+
+ movw %dx, %di
+ movb $18, 4(%di) # patch sector count
+
+ movw %di, %fs:(%bx)
+ movw %es, %fs:2(%bx)
+
+ movw %cs, %ax
+ movw %ax, %fs
+ movw %ax, %gs
+
+ xorb %ah, %ah # reset FDC
+ xorb %dl, %dl
+ int $0x13
+
+# load the setup-sectors directly after the bootblock.
+# Note that 'es' is already set up.
+
+load_setup:
+ xorw %dx, %dx # drive 0, head 0
+ movw $0x0002, %cx # sector 2, track 0
+ movw $0x0200, %bx # address = 512, in INITSEG
+ movw $(0x0200 + SETUPSECS), %ax # service 2, nr of sectors
+ # (assume all on head 0, track 0)
+ int $0x13 # read it
+ jnc ok_load_setup # ok - continue
+
+ pushw %ax # dump error code
+ call print_nl
+ movw %sp, %bp
+ call print_hex
+ popw %ax
+
+ xorb %dl, %dl # reset FDC
+ xorb %ah, %ah
+ int $0x13
+ jmp load_setup
+
+ok_load_setup:
+
+# Get disk drive parameters, specifically nr of sectors/track
+
+
+/* It seems that there is no BIOS call to get the number of sectors. Guess
+ * 18 sectors if sector 18 can be read, 15 if sector 15 can be read.
+ * Otherwise guess 9
+ */
+
+ xorw %dx, %dx # drive 0, head 0
+ movw $0x0012, %cx # sector 18, track 0
+ movw $(0x200+(SETUPSECS*0x200)), %bx # address after setup (es = cs)
+ movw $0x0201, %ax # service 2, 1 sector
+ int $0x13
+ jnc got_sectors
+ movb $0x0f, %cl # sector 15
+ movw $0x0201, %ax # service 2, 1 sector
+ int $0x13
+ jnc got_sectors
+ movb $0x09, %cl
+
+got_sectors:
+ movw %cx, %cs:sectors - _boot
+ movw $INITSEG, %ax
+ movw %ax, %es
+
+# Print some inane message
+
+ movb $0x03, %ah # read cursor pos
+ xorb %bh, %bh
+ int $0x10
+
+ movw $9, %cx
+ movw $0x0007, %bx # page 0, attribute 7 (normal)
+ movw $msg1 - _boot, %bp
+ movw $0x1301, %ax # write string, move cursor
+ int $0x10
+
+# ok, we've written the message, now
+# we want to load the system (at 0x10000)
+
+ movw $TSTLOAD, %ax
+ movw %ax, %es # segment of 0x010000
+ call read_it
+ call kill_motor
+ call turnoffcursor
+ call print_nl
+
+# after that (everyting loaded), we jump to
+# the setup-routine loaded directly after
+# the bootblock:
+
+ ljmp $SETUPSEG,$0
+
+# This routine loads the system at address 0x10000, making sure
+# no 64kB boundaries are crossed. We try to load it as fast as
+# possible, loading whole tracks whenever we can.
+#
+# in: es - starting address segment (normally 0x1000)
+#
+sread: .word 1+SETUPSECS # sectors read of current track
+head: .word 0 # current head
+track: .word 0 # current track
+
+read_it:
+ movw %es, %ax
+ testw $0x0fff, %ax
+die:
+ jne die # es must be at 64kB boundary
+ xorw %bx,%bx # bx is starting address within segment
+rp_read:
+ movw %es, %ax
+ subw $TSTLOAD, %ax # have we loaded all yet?
+ cmpw syssize - _boot, %ax
+ jbe ok1_read
+ ret
+ok1_read:
+ movw %cs:sectors - _boot, %ax
+ subw sread - _boot, %ax
+ movw %ax, %cx
+ shlw $9, %cx
+ addw %bx, %cx
+ jnc ok2_read
+ je ok2_read
+ xorw %ax, %ax
+ subw %bx, %ax
+ shrw $9, %ax
+ok2_read:
+ call read_track
+ movw %ax, %cx
+ add sread - _boot, %ax
+ cmpw %cs:sectors - _boot, %ax
+ jne ok3_read
+ movw $1, %ax
+ subw head - _boot, %ax
+ jne ok4_read
+ incw track - _boot
+ok4_read:
+ movw %ax, head - _boot
+ xorw %ax, %ax
+ok3_read:
+ movw %ax, sread - _boot
+ shlw $9, %cx
+ addw %cx, %bx
+ jnc rp_read
+ movw %es, %ax
+ addb $0x10, %ah
+ movw %ax, %es
+ xorw %bx, %bx
+ jmp rp_read
+
+read_track:
+ pusha
+ pusha
+ movw $0xe2e, %ax # loading... message 2e = .
+ movw $7, %bx
+ int $0x10
+ popa
+
+ movw track - _boot, %dx
+ movw sread - _boot, %cx
+ incw %cx
+ movb %dl, %ch
+ movw head - _boot, %dx
+ movb %dl, %dh
+ andw $0x0100, %dx
+ movb $2, %ah
+
+ pushw %dx # save for error dump
+ pushw %cx
+ pushw %bx
+ pushw %ax
+
+ int $0x13
+ jc bad_rt
+ addw $8, %sp
+ popa
+ ret
+
+bad_rt:
+ pushw %ax # save error code
+ call print_all # ah = error, al = read
+
+ xorb %ah, %ah
+ xorb %dl, %dl
+ int $0x13
+
+ addw $10, %sp
+ popa
+ jmp read_track
+
+/*
+ * print_all is for debugging purposes.
+ * It will print out all of the registers. The assumption is that this is
+ * called from a routine, with a stack frame like
+ * dx
+ * cx
+ * bx
+ * ax
+ * error
+ * ret <- sp
+ *
+*/
+
+print_all:
+ movw $5, %cx # error code + 4 registers
+ movw %sp, %bp
+
+print_loop:
+ pushw %cx # save count left
+ call print_nl # nl for readability
+
+ cmpb 5, %cl # see if register name is needed
+ jae no_reg
+
+ movw $(0xe05 + 'A' - 1), %ax
+ subb %cl, %al
+ int $0x10
+ movb $'X', %al
+ int $0x10
+ movb $':', %al
+ int $0x10
+
+no_reg:
+ addw $2, %bp # next register
+ call print_hex # print it
+ popw %cx
+ loop print_loop
+ ret
+
+print_nl:
+ movw $0xe0d, %ax # CR
+ int $0x10
+ movb $0x0a, %al # LF
+ int $0x10
+ ret
+
+/*
+ * print_hex is for debugging purposes, and prints the word
+ * pointed to by ss:bp in hexadecmial.
+ */
+
+print_hex:
+ movw $4, %cx # 4 hex digits
+ movw (%bp), %dx # load word into dx
+
+print_digit:
+ rolw $4, %dx # rotate so that lowest 4 bits are used
+ movb $0xe, %ah
+ movb %dl, %al # mask off so we have only next nibble
+ andb $0xf, %al
+ addb $'0', %al # convert to 0-based digit
+ cmpb $'9', %al # check for overflow
+ jbe good_digit
+ addb $('A' - '0' - 10), %al
+
+good_digit:
+ int $0x10
+ loop print_digit
+ ret
+
+
+/*
+ * This procedure turns off the floppy drive motor, so
+ * that we enter the kernel in a known state, and
+ * don't have to worry about it later.
+ */
+kill_motor:
+ pushw %dx
+ movw $0x3f2, %dx
+ xorb %al, %al
+ outb %al, %dx
+ popw %dx
+ ret
+
+turnoffcursor:
+ movb $0x01, %ah # turn off the cursor
+ movb $0x00, %bh
+ movw $0x2000, %cx
+ int $0x10
+ ret
+
+sectors:
+ .word 0
+
+msg1:
+ .byte 13,10
+ .ascii "Loading"
+
+.org 497
+setup_sects:
+ .byte SETUPSECS
+.org 500
+syssize:
+ .word _syssize
+.org 508
+root_dev:
+ .word ROOT_DEV
+boot_flag:
+ .word 0xAA55
+_eboot:
diff --git a/memtestEDK/Memtest/SingleComponents/config.c b/memtestEDK/Memtest/SingleComponents/config.c new file mode 100644 index 0000000..47c2b71 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/config.c @@ -0,0 +1,537 @@ +/* config.c - MemTest-86 Version 3.4 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + * ---------------------------------------------------- + * MemTest86+ V5.00 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.x86-secret.com - http://www.memtest.org + */ +#include "test.h" +#include "screen_buffer.h" +#include "dmi.h" +#include "environment.h" + + +#include <Library/UefiLib.h> + +extern int bail, beepmode; +extern struct tseq tseq[]; +extern short e820_nr; +void performance(); +extern volatile short cpu_mode; +extern volatile int test; +extern void find_chunks(); +extern volatile short start_seq; +extern short restart_flag; +extern short onepass; +extern short btflag; + +extern void get_list(int x, int y, int len, char *buf); + +char save[2][POP_H][POP_W]; +char save2[2][POP2_H][POP2_W]; + +void get_config() +{ + int flag = 0, sflag = 0, i, j, k, n, m, prt = 0; + int reprint_screen = 0; + char cp[64]; + ulong page; + + popup(); + wait_keyup(); + while(!flag) { + cprint(POP_Y+1, POP_X+2, "Settings:"); + cprint(POP_Y+3, POP_X+6, "(1) Test Selection"); + cprint(POP_Y+4, POP_X+6, "(2) Address Range"); + cprint(POP_Y+5, POP_X+6, "(3) Error Report Mode"); + cprint(POP_Y+6, POP_X+6, "(4) Core Selection"); + cprint(POP_Y+7, POP_X+6, "(5) Refresh Screen"); + cprint(POP_Y+8, POP_X+6, "(6) Display DMI Data"); + cprint(POP_Y+9, POP_X+6, "(7) Display SPD Data"); + cprint(POP_Y+11, POP_X+6, "(0) Continue"); + + /* Wait for key release */ + /* Fooey! This nuts'es up the serial input. */ + sflag = 0; + switch(get_key()) { + case 2: + /* 1 - Test Selection */ + popclear(); + cprint(POP_Y+1, POP_X+2, "Test Selection:"); + cprint(POP_Y+3, POP_X+6, "(1) Default Tests"); + cprint(POP_Y+4, POP_X+6, "(2) Skip Current Test"); + cprint(POP_Y+5, POP_X+6, "(3) Select Test"); + cprint(POP_Y+6, POP_X+6, "(4) Enter Test List"); + cprint(POP_Y+7, POP_X+6, "(0) Cancel"); + if (vv->testsel < 0) { + cprint(POP_Y+3, POP_X+5, ">"); + } else { + cprint(POP_Y+5, POP_X+5, ">"); + } + wait_keyup(); + while (!sflag) { + switch(get_key()) { + case 2: + /* Default - All tests */ + i = 0; + while (tseq[i].cpu_sel) { + tseq[i].sel = 1; + i++; + } + find_ticks_for_pass(); + sflag++; + break; + case 3: + /* Skip test */ + bail++; + sflag++; + break; + case 4: + /* Select test */ + popclear(); + cprint(POP_Y+1, POP_X+3, + "Test Selection:"); + cprint(POP_Y+4, POP_X+5, + "Test Number [1-11]: "); + n = getval(POP_Y+4, POP_X+24, 0) - 1; + if (n <= 11) + { + /* Deselect all tests */ + i = 0; + while (tseq[i].cpu_sel) { + tseq[i].sel = 0; + i++; + } + /* Now set the selection */ + tseq[n].sel = 1; + vv->pass = -1; + test = n; + find_ticks_for_pass(); + sflag++; + bail++; + } + break; + case 5: + /* Enter a test list */ + popclear(); + cprint(POP_Y+1, POP_X+3, + "Enter a comma separated list"); + cprint(POP_Y+2, POP_X+3, + "of tests to execute:"); + cprint(POP_Y+5, POP_X+5, "List: "); + /* Deselect all tests */ + k = 0; + while (tseq[k].cpu_sel) { + tseq[k].sel = 0; + k++; + } + + /* Get the list */ + for (i=0; i<64; i++) cp[i] = 0; + get_list(POP_Y+5, POP_X+10, 64, cp); + + /* Now enable all of the tests in the + * list */ + i = j = m = 0; + while (1) { + if (mt86_isdigit(cp[i])) { + n = cp[i]-'0'; + j = j*10 + n; + i++; + if (cp[i] == ',' || cp[i] == 0){ + if (j < k) { + tseq[j].sel = 1; + m++; + } + if (cp[i] == 0) break; + j = 0; + i++; + } + } + } + + /* If we didn't select at least one + * test turn them all back on */ + if (m == 0) { + k = 0; + while (tseq[k].cpu_sel) { + tseq[k].sel = 1; + k++; + } + } + vv->pass = -1; + test = n; + find_ticks_for_pass(); + sflag++; + bail++; + break; + case 11: + case 57: + sflag++; + break; + } + } + popclear(); + break; + case 3: + /* 2 - Address Range */ + popclear(); + cprint(POP_Y+1, POP_X+2, "Test Address Range:"); + cprint(POP_Y+3, POP_X+6, "(1) Set Lower Limit"); + cprint(POP_Y+4, POP_X+6, "(2) Set Upper Limit"); + cprint(POP_Y+5, POP_X+6, "(3) Test All Memory"); + cprint(POP_Y+6, POP_X+6, "(0) Cancel"); + wait_keyup(); + while (!sflag) { + switch(get_key()) { + case 2: + /* Lower Limit */ + popclear(); + cprint(POP_Y+2, POP_X+4, + "Lower Limit: "); + cprint(POP_Y+4, POP_X+4, + "Current: "); + aprint(POP_Y+4, POP_X+13, vv->plim_lower); + cprint(POP_Y+6, POP_X+4, + "New: "); + page = getval(POP_Y+6, POP_X+9, 12); + if (page + 1 <= vv->plim_upper) { + vv->plim_lower = page; + test--; + bail++; + } + adj_mem(); + find_chunks(); + find_ticks_for_pass(); + sflag++; + break; + case 3: + /* Upper Limit */ + popclear(); + cprint(POP_Y+2, POP_X+4, + "Upper Limit: "); + cprint(POP_Y+4, POP_X+4, + "Current: "); + aprint(POP_Y+4, POP_X+13, vv->plim_upper); + cprint(POP_Y+6, POP_X+4, + "New: "); + page = getval(POP_Y+6, POP_X+9, 12); + if (page - 1 >= vv->plim_lower) { + vv->plim_upper = page; + bail++; + test--; + } + adj_mem(); + find_chunks(); + find_ticks_for_pass(); + sflag++; + break; + case 4: + /* All of memory */ + vv->plim_lower = 0; + vv->plim_upper = + vv->pmap[vv->msegs - 1].end; + test--; + bail++; + adj_mem(); + find_chunks(); + find_ticks_for_pass(); + sflag++; + break; + case 11: + case 57: + /* 0/CR - Continue */ + sflag++; + break; + } + } + popclear(); + break; + case 4: + /* Error Mode */ + popclear(); + cprint(POP_Y+1, POP_X+2, "Printing Mode:"); + cprint(POP_Y+3, POP_X+6, "(1) Error Summary"); + cprint(POP_Y+4, POP_X+6, "(2) Individual Errors"); + cprint(POP_Y+5, POP_X+6, "(3) BadRAM Patterns"); + cprint(POP_Y+6, POP_X+6, "(4) Error Counts Only"); + cprint(POP_Y+7, POP_X+6, "(5) Beep on Error"); + cprint(POP_Y+8, POP_X+6, "(0) Cancel"); + cprint(POP_Y+3+vv->printmode, POP_X+5, ">"); + if (beepmode) { cprint(POP_Y+7, POP_X+5, ">"); } + wait_keyup(); + while (!sflag) { + switch(get_key()) { + case 2: + /* Error Summary */ + vv->printmode=PRINTMODE_SUMMARY; + vv->erri.eadr = 0; + vv->erri.hdr_flag = 0; + sflag++; + break; + case 3: + /* Separate Addresses */ + vv->printmode=PRINTMODE_ADDRESSES; + vv->erri.eadr = 0; + vv->erri.hdr_flag = 0; + vv->msg_line = LINE_SCROLL-1; + sflag++; + break; + case 4: + /* BadRAM Patterns */ + vv->printmode=PRINTMODE_PATTERNS; + vv->erri.hdr_flag = 0; + sflag++; + prt++; + break; + case 5: + /* Error Counts Only */ + vv->printmode=PRINTMODE_NONE; + vv->erri.hdr_flag = 0; + sflag++; + break; + case 6: + /* Set Beep On Error mode */ + beepmode = !beepmode; + sflag++; + break; + case 11: + case 57: + /* 0/CR - Continue */ + sflag++; + break; + } + } + popclear(); + break; + case 5: + /* CPU Mode */ + reprint_screen = 1; + popclear(); + cprint(POP_Y+1, POP_X+2, "CPU Selection Mode:"); + cprint(POP_Y+3, POP_X+6, "(1) Parallel (All)"); + cprint(POP_Y+4, POP_X+6, "(2) Round Robin (RRb)"); + cprint(POP_Y+5, POP_X+6, "(3) Sequential (Seq)"); + cprint(POP_Y+6, POP_X+6, "(0) Cancel"); + cprint(POP_Y+2+cpu_mode, POP_X+5, ">"); + wait_keyup(); + while(!sflag) { + switch(get_key()) { + case 2: + if (cpu_mode != CPM_ALL) bail++; + cpu_mode = CPM_ALL; + sflag++; + popdown(); + cprint(9,34,"All"); + popup(); + break; + case 3: + if (cpu_mode != CPM_RROBIN) bail++; + cpu_mode = CPM_RROBIN; + sflag++; + popdown(); + cprint(9,34,"RRb"); + popup(); + break; + case 4: + if (cpu_mode != CPM_SEQ) bail++; + cpu_mode = CPM_SEQ; + sflag++; + popdown(); + cprint(9,34,"Seq"); + popup(); + break; + case 11: + case 57: + /* 0/CR - Continue */ + sflag++; + break; + } + } + popclear(); + break; + case 6: + reprint_screen = 1; + flag++; + break; + case 7: + /* Display DMI Memory Info */ + pop2up(); + print_dmi_info(); + pop2down(); + break; + case 8: + /* Display SPD Data */ + popdown(); + show_spd(); + popup(); + sflag++; + break; + case 11: + case 57: + case 28: + /* 0/CR/SP - Continue */ + flag++; + break; + } + } + popdown(); + if (prt) { + printpatn(); + } + if (reprint_screen){ + tty_print_screen(); + } +} + +void popup() +{ + Print(L"start popup\n"); + int i, j; + char *pp; + + for (i=POP_Y; i<POP_Y + POP_H; i++) { + for (j=POP_X; j<POP_X + POP_W; j++) { + pp = (char *)(MAX_BLOCK_SIZE)(SCREEN_ADR + (i * 160) + (j * 2)); + save[0][i-POP_Y][j-POP_X] = *pp; /* Save screen */ + set_scrn_buf(i, j, ' '); + *pp = ' '; /* Clear */ + pp++; + save[1][i-POP_Y][j-POP_X] = *pp; + *pp = 0x07; /* Change Background to black */ + } + } + tty_print_region(POP_Y, POP_X, POP_Y+POP_H, POP_X+POP_W); + Print(L"end popup\n"); +} + +void popdown() +{ + int i, j; + char *pp; + + for (i=POP_Y; i<POP_Y + POP_H; i++) { + for (j=POP_X; j<POP_X + POP_W; j++) { + pp = (char *)(MAX_BLOCK_SIZE)(SCREEN_ADR + (i * 160) + (j * 2)); + *pp = save[0][i-POP_Y][j-POP_X]; /* Restore screen */ + set_scrn_buf(i, j, save[0][i-POP_Y][j-POP_X]); + pp++; + *pp = save[1][i-POP_Y][j-POP_X]; /* Restore color */ + } + } + tty_print_region(POP_Y, POP_X, POP_Y+POP_H, POP_X+POP_W); +} + +void popclear() +{ + int i, j; + char *pp; + + for (i=POP_Y; i<POP_Y + POP_H; i++) { + for (j=POP_X; j<POP_X + POP_W; j++) { + pp = (char *)(MAX_BLOCK_SIZE)(SCREEN_ADR + (i * 160) + (j * 2)); + *pp = ' '; /* Clear popup */ + set_scrn_buf(i, j, ' '); + pp++; + } + } + tty_print_region(POP_Y, POP_X, POP_Y+POP_H, POP_X+POP_W); +} + +void pop2up() +{ + int i, j; + char *pp; + + for (i=POP2_Y; i<POP2_Y + POP2_H; i++) { + for (j=POP2_X; j<POP2_X + POP2_W; j++) { + pp = (char *)(MAX_BLOCK_SIZE)(SCREEN_ADR + (i * 160) + (j * 2)); + save2[0][i-POP2_Y][j-POP2_X] = *pp; /* Save screen */ + set_scrn_buf(i, j, ' '); + *pp = ' '; /* Clear */ + pp++; + save2[1][i-POP2_Y][j-POP2_X] = *pp; + *pp = 0x07; /* Change Background to black */ + } + } + tty_print_region(POP2_Y, POP2_X, POP2_Y+POP2_H, POP2_X+POP2_W); +} + +void pop2down() +{ + int i, j; + char *pp; + + for (i=POP2_Y; i<POP2_Y + POP2_H; i++) { + for (j=POP2_X; j<POP2_X + POP2_W; j++) { + pp = (char *)(MAX_BLOCK_SIZE)(SCREEN_ADR + (i * 160) + (j * 2)); + *pp = save2[0][i-POP2_Y][j-POP2_X]; /* Restore screen */ + set_scrn_buf(i, j, save2[0][i-POP2_Y][j-POP2_X]); + pp++; + *pp = save2[1][i-POP2_Y][j-POP2_X]; /* Restore color */ + } + } + tty_print_region(POP2_Y, POP2_X, POP2_Y+POP2_H, POP2_X+POP2_W); +} + +void pop2clear() +{ + int i, j; + char *pp; + + for (i=POP2_Y; i<POP2_Y + POP2_H; i++) { + for (j=POP2_X; j<POP2_X + POP2_W; j++) { + pp = (char *)(MAX_BLOCK_SIZE)(SCREEN_ADR + (i * 160) + (j * 2)); + *pp = ' '; /* Clear popup */ + set_scrn_buf(i, j, ' '); + pp++; + } + } + tty_print_region(POP2_Y, POP2_X, POP2_Y+POP2_H, POP2_X+POP2_W); +} + + +void adj_mem(void) +{ + int i; + + vv->selected_pages = 0; + for (i=0; i< vv->msegs; i++) { + /* Segment inside limits ? */ + if (vv->pmap[i].start >= vv->plim_lower && + vv->pmap[i].end <= vv->plim_upper) { + vv->selected_pages += (vv->pmap[i].end - vv->pmap[i].start); + continue; + } + /* Segment starts below limit? */ + if (vv->pmap[i].start < vv->plim_lower) { + /* Also ends below limit? */ + if (vv->pmap[i].end < vv->plim_lower) { + continue; + } + + /* Ends past upper limit? */ + if (vv->pmap[i].end > vv->plim_upper) { + vv->selected_pages += + vv->plim_upper - vv->plim_lower; + } else { + /* Straddles lower limit */ + vv->selected_pages += + (vv->pmap[i].end - vv->plim_lower); + } + continue; + } + /* Segment ends above limit? */ + if (vv->pmap[i].end > vv->plim_upper) { + /* Also starts above limit? */ + if (vv->pmap[i].start > vv->plim_upper) { + continue; + } + /* Straddles upper limit */ + vv->selected_pages += + (vv->plim_upper - vv->pmap[i].start); + } + } +} diff --git a/memtestEDK/Memtest/SingleComponents/config.h b/memtestEDK/Memtest/SingleComponents/config.h new file mode 100644 index 0000000..086b243 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/config.h @@ -0,0 +1,53 @@ +/* + * MemTest86+ V5 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + * ------------------------------------------------ + * config.h - MemTest-86 Version 3.3 + * + * Compile time configuration options + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + */ + +/* CONSERVATIVE_SMP - If set to 0, SMP will be enabled by default */ +/* Might be enabled in future revision after extensive testing */ +/* In all cases, SMP is disabled by defaut on server platform */ +#define CONSERVATIVE_SMP 1 + +/* BEEP_MODE - Beep on error. Default off, Change to 1 to enable */ +#define BEEP_MODE 0 + +/* BEEP_END_NO_ERROR - Beep at end of each pass without error. Default off, Change to 1 to enable */ +#define BEEP_END_NO_ERROR 0 + +/* PARITY_MEM - Enables support for reporting memory parity errors */ +/* Experimental, normally enabled */ +#define PARITY_MEM + +/* SERIAL_CONSOLE_DEFAULT - The default state of the serial console. */ +/* This is normally off since it slows down testing. Change to a 1 */ +/* to enable. */ +#define SERIAL_CONSOLE_DEFAULT 0 + +/* SERIAL_TTY - The default serial port to use. 0=ttyS0, 1=ttyS1 */ +#define SERIAL_TTY 0 + +/* SERIAL_BAUD_RATE - Baud rate for the serial console */ +#define SERIAL_BAUD_RATE 9600 + +/* SCRN_DEBUG - extra check for SCREEN_BUFFER + */ +/* #define SCRN_DEBUG */ + +/* APM - Turns off APM at boot time to avoid blanking the screen */ +/* Normally enabled */ +#define APM_OFF + +/* USB_WAR - Enables a workaround for errors caused by BIOS USB keyboard */ +/* and mouse support*/ +/* Normally enabled */ +#define USB_WAR + +//void popup(); diff --git a/memtestEDK/Memtest/SingleComponents/controller.c b/memtestEDK/Memtest/SingleComponents/controller.c new file mode 100644 index 0000000..6d3f202 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/controller.c @@ -0,0 +1,4155 @@ +/* + * MemTest86+ V5 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + */ + +//#include "defs.h" +#include "config.h" +//#include "test.h" +#include "pci.h" +#include "controller.h" +#include "spd.h" +#include "test.h" +#include "stdint.h" +#include "cpuid.h" +#include "msr.h" +#include "dmi.h" + +int col, col2; +int nhm_bus = 0x3F; + +extern ulong extclock; +extern unsigned long imc_type; +extern struct cpu_ident cpu_id; +/* + #define rdmsr(msr,val1,val2) \ + __asm__ __volatile__("rdmsr" \ + : "=a" (val1), "=d" (val2) \ + : "c" (msr) : "edi") + + #define wrmsr(msr,val1,val2) \ + __asm__ __volatile__("wrmsr" \ + : \ + : "c" (msr), "a" (val1), "d" (val2) : "edi") +*/ +/* controller ECC capabilities and mode */ +#define __ECC_UNEXPECTED 1 /* Unknown ECC capability present */ +#define __ECC_DETECT 2 /* Can detect ECC errors */ +#define __ECC_CORRECT 4 /* Can correct some ECC errors */ +#define __ECC_SCRUB 8 /* Can scrub corrected ECC errors */ +#define __ECC_CHIPKILL 16 /* Can corrected multi-errors */ + +#define ECC_UNKNOWN (~0UL) /* Unknown error correcting ability/status */ +#define ECC_NONE 0 /* Doesnt support ECC (or is BIOS disabled) */ +#define ECC_RESERVED __ECC_UNEXPECTED /* Reserved ECC type */ +#define ECC_DETECT __ECC_DETECT +#define ECC_CORRECT (__ECC_DETECT | __ECC_CORRECT) +#define ECC_CHIPKILL (__ECC_DETECT | __ECC_CORRECT | __ECC_CHIPKILL) +#define ECC_SCRUB (__ECC_DETECT | __ECC_CORRECT | __ECC_SCRUB) + + +static struct ecc_info { + int index; + int poll; + unsigned bus; + unsigned dev; + unsigned fn; + unsigned cap; + unsigned mode; +} ctrl = + { + .index = 0, + /* I know of no case where the memory controller is not on the + * host bridge, and the host bridge is not on bus 0 device 0 + * fn 0. But just in case leave these as variables. + */ + .bus = 0, + .dev = 0, + .fn = 0, + /* Properties of the current memory controller */ + .cap = ECC_UNKNOWN, + .mode = ECC_UNKNOWN, + }; + + +void coretemp(void) +{ + unsigned int msrl, msrh; + unsigned int tjunc, tabs, tnow; + unsigned long rtcr; + double amd_raw_temp; + + // Only enable coretemp if IMC is known + if(imc_type == 0) { return; } + + tnow = 0; + + // Intel CPU + if(cpu_id.vend_id.char_array[0] == 'G' && cpu_id.max_cpuid >= 6) + { + if(cpu_id.dts_pmp & 1){ + rdmsr(MSR_IA32_THERM_STATUS, msrl, msrh); + tabs = ((msrl >> 16) & 0x7F); + rdmsr(MSR_IA32_TEMPERATURE_TARGET, msrl, msrh); + tjunc = ((msrl >> 16) & 0x7F); + if(tjunc < 50 || tjunc > 125) { tjunc = 90; } // assume Tjunc = 90°C if boggus value received. + tnow = tjunc - tabs; + dprint(LINE_CPU+1, 30, vv->check_temp, 3, 0); + vv->check_temp = tnow; + } + return; + } + + // AMD CPU + if(cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.extendedFamily > 0) + { + pci_conf_read(0, 24, 3, 0xA4, 4, &rtcr); + amd_raw_temp = ((rtcr >> 21) & 0x7FF); + vv->check_temp = (int)(amd_raw_temp / 8); + dprint(LINE_CPU+1, 30, vv->check_temp, 3, 0); + } + + +} + +void print_cpu_line(float dram_freq, float fsb_freq, int ram_type) +{ + int cur_col = COL_SPEC; + + cprint(LINE_CPU, cur_col, "RAM: "); + cur_col += 5; + dprint(LINE_CPU, cur_col, dram_freq, 4, 1); + cur_col += 4; + cprint(LINE_CPU, cur_col, "MHz ("); + cur_col += 5; + + switch(ram_type) + { + default: + case 1: + cprint(LINE_CPU, cur_col, "DDR-"); + cur_col += 4; + break; + case 2: + cprint(LINE_CPU, cur_col, "DDR2-"); + cur_col += 5; + break; + case 3: + cprint(LINE_CPU, cur_col, "DDR3-"); + cur_col += 5; + break; + } + + if(dram_freq < 500) + { + dprint(LINE_CPU, cur_col, dram_freq*2, 3, 0); + cur_col += 3; + } else { + dprint(LINE_CPU, cur_col, dram_freq*2, 4, 0); + cur_col += 4; + } + cprint(LINE_CPU, cur_col, ")"); + cur_col++; + + if(fsb_freq > 10) + { + cprint(LINE_CPU, cur_col, " - BCLK: "); + cur_col += 9; + + dprint(LINE_CPU, cur_col, fsb_freq, 3, 0); + } + +} + +void print_ram_line(float cas, int rcd, int rp, int ras, int chan) +{ + int cur_col = COL_SPEC; + + cprint(LINE_RAM, cur_col, "Timings: CAS "); + cur_col += 13; + + // CAS Latency (tCAS) + if (cas == 1.5) { + cprint(LINE_RAM, cur_col, "1.5"); cur_col += 3; + } else if (cas == 2.5) { + cprint(LINE_RAM, cur_col, "2.5"); cur_col += 3; + } else if (cas < 10) { + dprint(LINE_RAM, cur_col, cas, 1, 0); cur_col += 1; + } else { + dprint(LINE_RAM, cur_col, cas, 2, 0); cur_col += 2; + } + cprint(LINE_RAM, cur_col, "-"); cur_col += 1; + + // RAS-To-CAS (tRCD) + if (rcd < 10) { + dprint(LINE_RAM, cur_col, rcd, 1, 0); + cur_col += 1; + } else { + dprint(LINE_RAM, cur_col, rcd, 2, 0); + cur_col += 2; + } + cprint(LINE_RAM, cur_col, "-"); cur_col += 1; + + // RAS Precharge (tRP) + if (rp < 10) { + dprint(LINE_RAM, cur_col, rp, 1, 0); + cur_col += 1; + } else { + dprint(LINE_RAM, cur_col, rp, 2, 0); + cur_col += 2; + } + cprint(LINE_RAM, cur_col, "-"); cur_col += 1; + + // RAS Active to precharge (tRAS) + if (ras < 10) { + dprint(LINE_RAM, cur_col, ras, 1, 0); + cur_col += 1; + } else { + dprint(LINE_RAM, cur_col, ras, 2, 0); + cur_col += 2; + } + + + switch(chan) + { + case 0: + break; + case 1: + cprint(LINE_RAM, cur_col, " @ 64-bit Mode"); + break; + case 2: + cprint(LINE_RAM, cur_col, " @ 128-bit Mode"); + break; + case 3: + cprint(LINE_RAM, cur_col, " @ 192-bit Mode"); + break; + case 4: + cprint(LINE_RAM, cur_col, " @ 256-bit Mode"); + break; + } +} + +static void poll_fsb_nothing(void) +{ + + char *name; + + /* Print the controller name */ + name = controllers[ctrl.index].name; + cprint(LINE_CPU, COL_SPEC, "Chipset: "); + cprint(LINE_CPU, COL_SPEC+9, name); + return; +} + +static void poll_timings_nothing(void) +{ + char *ram_type; + + /* Print the controller name */ + ram_type = controllers[ctrl.index].ram_type; + cprint(LINE_RAM, COL_SPEC, "RAM Type: "); + cprint(LINE_RAM, COL_SPEC+10, ram_type); + return; +} + +static void setup_nothing(void) +{ + ctrl.cap = ECC_NONE; + ctrl.mode = ECC_NONE; +} + +static void poll_nothing(void) +{ + /* Code to run when we don't know how, or can't ask the memory + * controller about memory errors. + */ + return; +} + +static void setup_wmr(void) +{ + ulong dev0; + + // Activate MMR I/O + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + if (!(dev0 & 0x1)) { + pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1); + } + +} + + +static void setup_nhm(void) +{ + static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; + unsigned long did, vid, mc_control, mc_ssrcontrol; + int i; + + //Nehalem supports Scrubbing */ + ctrl.cap = ECC_SCRUB; + ctrl.mode = ECC_NONE; + + /* First, locate the PCI bus where the MCH is located */ + + for(i = 0; i < (sizeof(possible_nhm_bus) / + sizeof(possible_nhm_bus[0])); i++) { + pci_conf_read( possible_nhm_bus[i], 3, 4, 0x00, 2, &vid); + pci_conf_read( possible_nhm_bus[i], 3, 4, 0x02, 2, &did); + vid &= 0xFFFF; + did &= 0xFF00; + if(vid == 0x8086 && did >= 0x2C00) { + nhm_bus = possible_nhm_bus[i]; + } + } + + /* Now, we have the last IMC bus number in nhm_bus */ + /* Check for ECC & Scrub */ + + pci_conf_read(nhm_bus, 3, 0, 0x4C, 2, &mc_control); + if((mc_control >> 4) & 1) { + ctrl.mode = ECC_CORRECT; + pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol); + if(mc_ssrcontrol & 3) { + ctrl.mode = ECC_SCRUB; + } + } + +} + +static void setup_nhm32(void) +{ + static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; + unsigned long did, vid, mc_control, mc_ssrcontrol; + int i; + + //Nehalem supports Scrubbing */ + ctrl.cap = ECC_SCRUB; + ctrl.mode = ECC_NONE; + + /* First, locate the PCI bus where the MCH is located */ + for(i = 0; i < (sizeof(possible_nhm_bus) / + sizeof(possible_nhm_bus[0])); i++) { + pci_conf_read( possible_nhm_bus[i], 3, 4, 0x00, 2, &vid); + pci_conf_read( possible_nhm_bus[i], 3, 4, 0x02, 2, &did); + vid &= 0xFFFF; + did &= 0xFF00; + if(vid == 0x8086 && did >= 0x2C00) { + nhm_bus = possible_nhm_bus[i]; + } + } + + /* Now, we have the last IMC bus number in nhm_bus */ + /* Check for ECC & Scrub */ + pci_conf_read(nhm_bus, 3, 0, 0x48, 2, &mc_control); + if((mc_control >> 1) & 1) { + ctrl.mode = ECC_CORRECT; + pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol); + if(mc_ssrcontrol & 1) { + ctrl.mode = ECC_SCRUB; + } + } + +} + +static void setup_amd64(void) +{ + static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_RESERVED, ECC_CHIPKILL }; + unsigned long nbxcfg; + unsigned int mcgsrl; + unsigned int mcgsth; + unsigned long mcanb; + unsigned long dramcl; + + /* All AMD64 support Chipkill */ + ctrl.cap = ECC_CHIPKILL; + + /* Check First if ECC DRAM Modules are used */ + pci_conf_read(0, 24, 2, 0x90, 4, &dramcl); + + if (cpu_id.vers.bits.extendedModel >= 4) { + /* NEW K8 0Fh Family 90 nm */ + + if ((dramcl >> 19)&1){ + /* Fill in the correct memory capabilites */ + pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg); + ctrl.mode = ddim[(nbxcfg >> 22)&3]; + } else { + ctrl.mode = ECC_NONE; + } + /* Enable NB ECC Logging by MSR Write */ + rdmsr(0x017B, mcgsrl, mcgsth); + wrmsr(0x017B, 0x10, mcgsth); + + /* Clear any previous error */ + pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb); + pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF ); + + } else { + /* OLD K8 130 nm */ + + if ((dramcl >> 17)&1){ + /* Fill in the correct memory capabilites */ + pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg); + ctrl.mode = ddim[(nbxcfg >> 22)&3]; + } else { + ctrl.mode = ECC_NONE; + } + /* Enable NB ECC Logging by MSR Write */ + rdmsr(0x017B, mcgsrl, mcgsth); + wrmsr(0x017B, 0x10, mcgsth); + + /* Clear any previous error */ + pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb); + pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7F801EFC ); + } +} + +static void setup_k10(void) +{ + static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_CHIPKILL, ECC_CHIPKILL }; + unsigned long nbxcfg; + unsigned int mcgsrl; + unsigned int mcgsth; + unsigned long mcanb; + unsigned long dramcl; + ulong msr_low, msr_high; + + // All AMD64 support Chipkill */ + ctrl.cap = ECC_CHIPKILL; + + // Check First if ECC DRAM Modules are used */ + pci_conf_read(0, 24, 2, 0x90, 4, &dramcl); + + if ((dramcl >> 19)&1){ + // Fill in the correct memory capabilites */ + pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg); + ctrl.mode = ddim[(nbxcfg >> 22)&3]; + } else { + ctrl.mode = ECC_NONE; + } + // Enable NB ECC Logging by MSR Write */ + rdmsr(0x017B, mcgsrl, mcgsth); + wrmsr(0x017B, 0x10, mcgsth); + + // Clear any previous error */ + pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb); + pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF ); + + /* Enable ECS */ + rdmsr(0xC001001F, msr_low, msr_high); + wrmsr(0xC001001F, msr_low, (msr_high | 0x4000)); + rdmsr(0xC001001F, msr_low, msr_high); + +} + +static void setup_apu(void) +{ + + ulong msr_low, msr_high; + + /* Enable ECS */ + rdmsr(0xC001001F, msr_low, msr_high); + wrmsr(0xC001001F, msr_low, (msr_high | 0x4000)); + rdmsr(0xC001001F, msr_low, msr_high); + +} + +/* + static void poll_amd64(void) + { + + unsigned long mcanb; + unsigned long page, offset; + unsigned long celog_syndrome; + unsigned long mcanb_add; + + pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb); + + if (((mcanb >> 31)&1) && ((mcanb >> 14)&1)) { + // Find out about the first correctable error + // Syndrome code -> bits use a complex matrix. Will add this later + // Read the error location + pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add); + + // Read the syndrome + celog_syndrome = (mcanb >> 15)&0xFF; + + // Parse the error location + page = (mcanb_add >> 12); + offset = (mcanb_add >> 3) & 0xFFF; + + // Report the error + print_ecc_err(page, offset, 1, celog_syndrome, 0); + + // Clear the error registers + pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF ); + } + if (((mcanb >> 31)&1) && ((mcanb >> 13)&1)) { + // Found out about the first uncorrectable error + // Read the error location + pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add); + + // Parse the error location + page = (mcanb_add >> 12); + offset = (mcanb_add >> 3) & 0xFFF; + + // Report the error + print_ecc_err(page, offset, 0, 0, 0); + + // Clear the error registers + pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFF ); + + } + + } +*/ + +static void setup_amd751(void) +{ + unsigned long dram_status; + + /* Fill in the correct memory capabilites */ + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5a, 2, &dram_status); + ctrl.cap = ECC_CORRECT; + ctrl.mode = (dram_status & (1 << 2))?ECC_CORRECT: ECC_NONE; +} + +/* + static void poll_amd751(void) + { + unsigned long ecc_status; + unsigned long bank_addr; + unsigned long bank_info; + unsigned long page; + int bits; + int i; + + // Read the error status + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, &ecc_status); + if (ecc_status & (3 << 8)) { + for(i = 0; i < 6; i++) { + if (!(ecc_status & (1 << i))) { + continue; + } + // Find the bank the error occured on + bank_addr = 0x40 + (i << 1); + + // Now get the information on the erroring bank + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 2, &bank_info); + + // Parse the error location and error type + page = (bank_info & 0xFF80) << 4; + bits = (((ecc_status >> 8) &3) == 2)?1:2; + + // Report the error + print_ecc_err(page, 0, bits==1?1:0, 0, 0); + + } + + // Clear the error status + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, 0); + } + } + + // Still waiting for the CORRECT intel datasheet + static void setup_i85x(void) + { + unsigned long drc; + ctrl.cap = ECC_CORRECT; + + pci_conf_read(ctrl.bus, ctrl.dev, 1, 0x70, 4, &drc); + ctrl.mode = ((drc>>20)&1)?ECC_CORRECT:ECC_NONE; + + } +*/ + +static void setup_amd76x(void) +{ + static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT }; + unsigned long ecc_mode_status; + + /* Fill in the correct memory capabilites */ + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status); + ctrl.cap = ECC_CORRECT; + ctrl.mode = ddim[(ecc_mode_status >> 10)&3]; +} + +/* + static void poll_amd76x(void) + { + unsigned long ecc_mode_status; + unsigned long bank_addr; + unsigned long bank_info; + unsigned long page; + + // Read the error status + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status); + // Multibit error + if (ecc_mode_status & (1 << 9)) { + // Find the bank the error occured on + bank_addr = 0xC0 + (((ecc_mode_status >> 4) & 0xf) << 2); + + // Now get the information on the erroring bank + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info); + + // Parse the error location and error type + page = (bank_info & 0xFF800000) >> 12; + + // Report the error + print_ecc_err(page, 0, 1, 0, 0); + + } + // Singlebit error + if (ecc_mode_status & (1 << 8)) { + // Find the bank the error occured on + bank_addr = 0xC0 + (((ecc_mode_status >> 0) & 0xf) << 2); + + // Now get the information on the erroring bank + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info); + + // Parse the error location and error type + page = (bank_info & 0xFF800000) >> 12; + + // Report the error + print_ecc_err(page, 0, 0, 0, 0); + + } + // Clear the error status + if (ecc_mode_status & (3 << 8)) { + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, ecc_mode_status); + } + } +*/ + +static void setup_cnb20(void) +{ + /* Fill in the correct memory capabilites */ + ctrl.cap = ECC_CORRECT; + + /* FIXME add ECC error polling. I don't have the documentation + * do it right now. + */ +} + +static void setup_E5400(void) +{ + unsigned long mcs; + + + /* Read the hardware capabilities */ + pci_conf_read(ctrl.bus, 16, 1, 0x40, 4, &mcs); + + /* Fill in the correct memory capabilities */ + ctrl.mode = 0; + ctrl.cap = ECC_SCRUB; + + /* Checking and correcting enabled */ + if (((mcs >> 5) & 1) == 1) { + ctrl.mode |= ECC_CORRECT; + } + + /* scrub enabled */ + if (((mcs >> 7) & 1) == 1) { + ctrl.mode |= __ECC_SCRUB; + } +} + + +static void setup_iE7xxx(void) +{ + unsigned long mchcfgns; + unsigned long drc; + unsigned long device; + unsigned long dvnp; + + /* Read the hardare capabilities */ + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchcfgns); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc); + + /* This is a check for E7205 */ + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x02, 2, &device); + + /* Fill in the correct memory capabilities */ + ctrl.mode = 0; + ctrl.cap = ECC_CORRECT; + + /* checking and correcting enabled */ + if (((drc >> 20) & 3) == 2) { + ctrl.mode |= ECC_CORRECT; + } + + /* E7205 doesn't support scrubbing */ + if (device != 0x255d) { + /* scrub enabled */ + /* For E7501, valid SCRUB operations is bit 0 / D0:F0:R70-73 */ + ctrl.cap = ECC_SCRUB; + if (mchcfgns & 1) { + ctrl.mode |= __ECC_SCRUB; + } + + /* Now, we can active Dev1/Fun1 */ + /* Thanks to Tyan for providing us the board to solve this */ + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE0, 2, &dvnp); + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn , 0xE0, 2, (dvnp & 0xFE)); + + /* Clear any routing of ECC errors to interrupts that the BIOS might have set up */ + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x88, 1, 0x0); + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8A, 1, 0x0); + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8C, 1, 0x0); + + + } + + /* Clear any prexisting error reports */ + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, 3); + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, 3); + + +} + +static void setup_iE7520(void) +{ + unsigned long mchscrb; + unsigned long drc; + unsigned long dvnp1; + + /* Read the hardare capabilities */ + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchscrb); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc); + + /* Fill in the correct memory capabilities */ + ctrl.mode = 0; + ctrl.cap = ECC_CORRECT; + + /* Checking and correcting enabled */ + if (((drc >> 20) & 3) != 0) { + ctrl.mode |= ECC_CORRECT; + } + + /* scrub enabled */ + ctrl.cap = ECC_SCRUB; + if ((mchscrb & 3) == 2) { + ctrl.mode |= __ECC_SCRUB; + } + + /* Now, we can activate Fun1 */ + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xF4, 1, &dvnp1); + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn , 0xF4, 1, (dvnp1 | 0x20)); + + /* Clear any prexisting error reports */ + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, 0x4747); + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, 0x4747); + +} + +/* + static void poll_iE7xxx(void) + { + unsigned long ferr; + unsigned long nerr; + + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, &ferr); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, &nerr); + + if (ferr & 1) { + // Find out about the first correctable error + unsigned long celog_add; + unsigned long celog_syndrome; + unsigned long page; + + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4, &celog_add); + // Read the syndrome + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xD0, 2, &celog_syndrome); + + // Parse the error location + page = (celog_add & 0x0FFFFFC0) >> 6; + + // Report the error + print_ecc_err(page, 0, 1, celog_syndrome, 0); + + // Clear Bit + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3); + } + + if (ferr & 2) { + // Found out about the first uncorrectable error + unsigned long uccelog_add; + unsigned long page; + + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xB0, 4, &uccelog_add); + + // Parse the error location + page = (uccelog_add & 0x0FFFFFC0) >> 6; + + // Report the error + print_ecc_err(page, 0, 0, 0, 0); + + // Clear Bit + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3); + } + + // Check if DRAM_NERR contains data + if (nerr & 3) { + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, nerr & 3); + } + + } +*/ + +static void setup_i440gx(void) +{ + static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT }; + unsigned long nbxcfg; + + /* Fill in the correct memory capabilites */ + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 4, &nbxcfg); + ctrl.cap = ECC_CORRECT; + ctrl.mode = ddim[(nbxcfg >> 7)&3]; +} + +/* + static void poll_i440gx(void) + { + unsigned long errsts; + unsigned long page; + int bits; + // Read the error status + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, &errsts); + if (errsts & 0x11) { + unsigned long eap; + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, &eap); + + // Parse the error location and error type + page = (eap & 0xFFFFF000) >> 12; + bits = 0; + if (eap &3) { + bits = ((eap & 3) == 1)?1:2; + } + + if (bits) { + // Report the error + print_ecc_err(page, 0, bits==1?1:0, 0, 0); + } + + // Clear the error status + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, 0x11); + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, 3); + } + + } +*/ + + +static void setup_i840(void) +{ + static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT }; + unsigned long mchcfg; + + /* Fill in the correct memory capabilites */ + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg); + ctrl.cap = ECC_CORRECT; + ctrl.mode = ddim[(mchcfg >> 7)&3]; +} + +/* + static void poll_i840(void) + { + unsigned long errsts; + unsigned long page; + unsigned long syndrome; + int channel; + int bits; + // Read the error status + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts); + if (errsts & 3) { + unsigned long eap; + unsigned long derrctl_sts; + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts); + + // Parse the error location and error type + page = (eap & 0xFFFFF800) >> 11; + channel = eap & 1; + syndrome = derrctl_sts & 0xFF; + bits = ((errsts & 3) == 1)?1:2; + + // Report the error + print_ecc_err(page, 0, bits==1?1:0, syndrome, channel); + + // Clear the error status + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, 3 << 10); + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3); + } + } +*/ + + +static void setup_i875(void) +{ + + long *ptr; + ulong dev0, dev6 ; + + /* Fill in the correct memory capabilites */ + + ctrl.cap = ECC_CORRECT; + ctrl.mode = ECC_NONE; + + /* From my article : http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm */ + /* Activate Device 6 */ + pci_conf_read( 0, 0, 0, 0xF4, 1, &dev0); + pci_conf_write( 0, 0, 0, 0xF4, 1, (dev0 | 0x2)); + + /* Activate Device 6 MMR */ + pci_conf_read( 0, 6, 0, 0x04, 2, &dev6); + pci_conf_write( 0, 6, 0, 0x04, 2, (dev6 | 0x2)); + + /* Read the MMR Base Address & Define the pointer*/ + pci_conf_read( 0, 6, 0, 0x10, 4, &dev6); + ptr=(long*)(dev6+0x68); + + if (((*ptr >> 18)&1) == 1) { ctrl.mode = ECC_CORRECT; } + + /* Reseting state */ + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81); +} + +static void setup_i925(void) +{ + + // Activate MMR I/O + ulong dev0, drc; + unsigned long tolm; + long *ptr; + + pci_conf_read( 0, 0, 0, 0x54, 4, &dev0); + dev0 = dev0 | 0x10000000; + pci_conf_write( 0, 0, 0, 0x54, 4, dev0); + + // CDH start + pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); + if (!(dev0 & 0xFFFFC000)) { + pci_conf_read( 0, 0, 0, 0x9C, 1, &tolm); + pci_conf_write( 0, 0, 0, 0x47, 1, tolm & 0xF8); + } + // CDH end + + // ECC Checking + ctrl.cap = ECC_CORRECT; + + dev0 &= 0xFFFFC000; + ptr=(long*)(dev0+0x120); + drc = *ptr & 0xFFFFFFFF; + + if (((drc >> 20) & 3) == 2) { + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3); + ctrl.mode = ECC_CORRECT; + } else { + ctrl.mode = ECC_NONE; + } + +} + +static void setup_p35(void) +{ + + // Activate MMR I/O + ulong dev0, capid0; + + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + if (!(dev0 & 0x1)) { + pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1); + } + + // ECC Checking (No poll on X38/48 for now) + pci_conf_read( 0, 0, 0, 0xE4, 4, &capid0); + if ((capid0 >> 8) & 1) { + ctrl.cap = ECC_NONE; + } else { + ctrl.cap = ECC_CORRECT; + } + + ctrl.mode = ECC_NONE; + + /* + ulong toto; + pci_conf_write(0, 31, 3, 0x40, 1, 0x1); + pci_conf_read(0, 31, 3, 0x0, 4, &toto); + hprint(11,0,toto); + pci_conf_read(0, 31, 3, 0x10, 4, &toto); + hprint(11,10,toto) ; + pci_conf_read(0, 31, 3, 0x20, 4, &toto); + hprint(11,20,toto) ; + pci_conf_read(0, 28, 0, 0x0, 4, &toto); + hprint(11,30,toto); + pci_conf_read(0, 31, 0, 0x0, 4, &toto); + hprint(11,40,toto) ; + pci_conf_read(0, 31, 1, 0x0, 4, &toto); + hprint(11,50,toto) ; + pci_conf_read(0, 31, 2, 0x0, 4, &toto); + hprint(11,60,toto) ; + */ +} + +/* + static void poll_i875(void) + { + unsigned long errsts; + unsigned long page; + unsigned long des; + unsigned long syndrome; + int channel; + int bits; + // Read the error status + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts); + if (errsts & 0x81) { + unsigned long eap; + unsigned long derrsyn; + // Read the error location, syndrome and channel + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrsyn); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5D, 1, &des); + + // Parse the error location and error type + page = (eap & 0xFFFFF000) >> 12; + syndrome = derrsyn; + channel = des & 1; + bits = (errsts & 0x80)?0:1; + + // Report the error + print_ecc_err(page, 0, bits, syndrome, channel); + + // Clear the error status + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81); + } + } +*/ + +static void setup_i845(void) +{ + static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED }; + unsigned long drc; + + // Fill in the correct memory capabilites + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc); + ctrl.cap = ECC_CORRECT; + ctrl.mode = ddim[(drc >> 20)&3]; +} + +/* + static void poll_i845(void) + { + unsigned long errsts; + unsigned long page, offset; + unsigned long syndrome; + int bits; + // Read the error status + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts); + if (errsts & 3) { + unsigned long eap; + unsigned long derrsyn; + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x8C, 4, &eap); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x86, 1, &derrsyn); + + // Parse the error location and error type + offset = (eap & 0xFE) << 4; + page = (eap & 0x3FFFFFFE) >> 8; + syndrome = derrsyn; + bits = ((errsts & 3) == 1)?1:2; + + // Report the error + print_ecc_err(page, offset, bits==1?1:0, syndrome, 0); + + // Clear the error status + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3); + } + } +*/ + + +static void setup_i820(void) +{ + static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT }; + unsigned long mchcfg; + + // Fill in the correct memory capabilites + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xbe, 2, &mchcfg); + ctrl.cap = ECC_CORRECT; + ctrl.mode = ddim[(mchcfg >> 7)&3]; +} + +/* + static void poll_i820(void) + { + unsigned long errsts; + unsigned long page; + unsigned long syndrome; + int bits; + // Read the error status + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts); + if (errsts & 3) { + unsigned long eap; + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xc4, 4, &eap); + + // Parse the error location and error type + page = (eap & 0xFFFFF000) >> 4; + syndrome = eap & 0xFF; + bits = ((errsts & 3) == 1)?1:2; + + // Report the error + print_ecc_err(page, 0, bits==1?1:0, syndrome, 0); + + // Clear the error status + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3); + } + } +*/ + +static void setup_i850(void) +{ + static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED }; + unsigned long mchcfg; + + // Fill in the correct memory capabilites + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg); + ctrl.cap = ECC_CORRECT; + ctrl.mode = ddim[(mchcfg >> 7)&3]; +} + +/* + static void poll_i850(void) + { + unsigned long errsts; + unsigned long page; + unsigned long syndrome; + int channel; + int bits; + // Read the error status + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts); + if (errsts & 3) { + unsigned long eap; + unsigned long derrctl_sts; + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts); + + // Parse the error location and error type + page = (eap & 0xFFFFF800) >> 11; + channel = eap & 1; + syndrome = derrctl_sts & 0xFF; + bits = ((errsts & 3) == 1)?1:2; + + // Report the error + print_ecc_err(page, 0, bits==1?1:0, syndrome, channel); + + // Clear the error status + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3); + } + } +*/ + +static void setup_i860(void) +{ + static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED }; + unsigned long mchcfg; + unsigned long errsts; + + // Fill in the correct memory capabilites + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg); + ctrl.cap = ECC_CORRECT; + ctrl.mode = ddim[(mchcfg >> 7)&3]; + + // Clear any prexisting error reports + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts); + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3); +} + +/* + static void poll_i860(void) + { + unsigned long errsts; + unsigned long page; + unsigned char syndrome; + int channel; + int bits; + // Read the error status + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts); + if (errsts & 3) { + unsigned long eap; + unsigned long derrctl_sts; + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts); + + // Parse the error location and error type + page = (eap & 0xFFFFFE00) >> 9; + channel = eap & 1; + syndrome = derrctl_sts & 0xFF; + bits = ((errsts & 3) == 1)?1:2; + + // Report the error + print_ecc_err(page, 0, bits==1?1:0, syndrome, channel); + + // Clear the error status + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3); + } + } + + + static void poll_iE7221(void) + { + unsigned long errsts; + unsigned long page; + unsigned char syndrome; + int channel; + int bits; + int errocc; + + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts); + + errocc = errsts & 3; + + if ((errocc == 1) || (errocc == 2)) { + unsigned long eap, offset; + unsigned long derrctl_sts; + + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrctl_sts); + + // Parse the error location and error type + channel = eap & 1; + eap = eap & 0xFFFFFF80; + page = eap >> 12; + offset = eap & 0xFFF; + syndrome = derrctl_sts & 0xFF; + bits = errocc & 1; + + // Report the error + print_ecc_err(page, offset, bits, syndrome, channel); + + // Clear the error status + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3); + } + + else if (errocc == 3) { + + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3); + + } + } + + + static void poll_iE7520(void) + { + unsigned long ferr; + unsigned long nerr; + + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, &ferr); + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, &nerr); + + if (ferr & 0x0101) { + // Find out about the first correctable error + unsigned long celog_add; + unsigned long celog_syndrome; + unsigned long page; + + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4,&celog_add); + // Read the syndrome + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xC4, 2, &celog_syndrome); + + // Parse the error location + page = (celog_add & 0x7FFFFFFC) >> 2; + + // Report the error + print_ecc_err(page, 0, 1, celog_syndrome, 0); + + // Clear Bit + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr& 0x0101); + } + + if (ferr & 0x4646) { + // Found out about the first uncorrectable error + unsigned long uccelog_add; + unsigned long page; + + // Read the error location + pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA4, 4, &uccelog_add); + + // Parse the error location + page = (uccelog_add & 0x7FFFFFFC) >> 2; + + // Report the error + print_ecc_err(page, 0, 0, 0, 0); + + // Clear Bit + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr & 0x4646); + } + + // Check if DRAM_NERR contains data + if (nerr & 0x4747) { + pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, nerr & 0x4747); + } + } +*/ + + + +/* ----------------- Here's the code for FSB detection ----------------- */ +/* --------------------------------------------------------------------- */ + +static float athloncoef[] = {11, 11.5, 12.0, 12.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.5}; +static float athloncoef2[] = {12, 19.0, 12.0, 20.0, 13.0, 13.5, 14.0, 21.0, 15.0, 22, 16.0, 16.5, 17.0, 18.0, 23.0, 24.0}; +static float p4model1ratios[] = {16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 12, 13, 14, 15}; + +static float getP4PMmultiplier(void) +{ + //unsigned int msr_lo, msr_hi; + int msr_lo, msr_hi; + float coef; + + + /* Find multiplier (by MSR) */ + if (cpu_id.vers.bits.family == 6) + { + if(cpu_id.fid.bits.eist & 1) + { + rdmsr(0x198, msr_lo, msr_hi); + coef = ((msr_lo) >> 8) & 0x1F; + if ((msr_lo >> 14) & 0x1) { coef += 0.5f; } + // Atom Fix + if(coef == 6) + { + coef = ((msr_hi) >> 8) & 0x1F; + if ((msr_hi >> 14) & 0x1) { coef += 0.5f; } + } + } else { + rdmsr(0x2A, msr_lo, msr_hi); + coef = (msr_lo >> 22) & 0x1F; + } + } + else + { + if (cpu_id.vers.bits.model < 2) + { + rdmsr(0x2A, msr_lo, msr_hi); + coef = (msr_lo >> 8) & 0xF; + coef = p4model1ratios[(int)coef]; + } + else + { + rdmsr(0x2C, msr_lo, msr_hi); + coef = (msr_lo >> 24) & 0x1F; + } + } + + return coef; +} + +static float getNHMmultiplier(void) +{ + unsigned int msr_lo, msr_hi; + float coef; + + /* Find multiplier (by MSR) */ + /* First, check if Flexible Ratio is Enabled */ + rdmsr(0x194, msr_lo, msr_hi); + if((msr_lo >> 16) & 1){ + coef = (msr_lo >> 8) & 0xFF; + } else { + rdmsr(0xCE, msr_lo, msr_hi); + coef = (msr_lo >> 8) & 0xFF; + } + + return coef; +} +static float getSNBmultiplier(void) +{ + unsigned int msr_lo, msr_hi; + float coef; + + rdmsr(0xCE, msr_lo, msr_hi); + coef = (msr_lo >> 8) & 0xFF; + + return coef; +} + +static void poll_fsb_ct(void) +{ + unsigned long mcr, mdr; + double dramratio, dramclock, fsb; + float coef = getP4PMmultiplier(); + + /* Build the MCR Message*/ + mcr = (0x10 << 24); // 10h = Read - 11h = Write + mcr += (0x01 << 16); // DRAM Registers located on port 01h + mcr += (0x01 << 8); // DRP = 00h, DTR0 = 01h, DTR1 = 02h, DTR2 = 03h + mcr &= 0xFFFFFFF0; // bit 03:00 RSVD + + /* Send Message to GMCH */ + pci_conf_write(0, 0, 0, 0xD0, 4, mcr); + + /* Read Answer from Sideband bus */ + pci_conf_read(0, 0, 0, 0xD4, 4, &mdr); + + /* Get RAM ratio */ + switch (mdr & 0x3) { + default: + case 0: dramratio = 3.0f; break; + case 1: dramratio = 4.0f; break; + case 2: dramratio = 5.0f; break; + case 3: dramratio = 6.0f; break; + } + + // Compute FSB & RAM Frequency + fsb = ((extclock / 1000) / coef); + dramclock = fsb * dramratio; + + // Print'em all. Whoa ! + print_cpu_line(dramclock, fsb, 3); + +} + +static void poll_fsb_amd64(void) { + + unsigned int mcgsrl; + unsigned int mcgsth; + unsigned long fid, temp2; + unsigned long dramchr; + float clockratio; + double dramclock; + unsigned int dummy[3]; + int ram_type; + + float coef = 10; + + cpuid(0x80000007, &dummy[0], &dummy[1], &dummy[2], &dummy[3]); + + /* First, got the FID by MSR */ + /* First look if Cool 'n Quiet is supported to choose the best msr */ + if (((dummy[3] >> 1) & 1) == 1) { + rdmsr(0xc0010042, mcgsrl, mcgsth); + fid = (mcgsrl & 0x3F); + } else { + rdmsr(0xc0010015, mcgsrl, mcgsth); + fid = ((mcgsrl >> 24)& 0x3F); + } + + /* Extreme simplification. */ + coef = ( fid / 2 ) + 4.0; + + /* Support for .5 coef */ + if (fid & 1) { coef = coef + 0.5; } + + /* Next, we need the clock ratio */ + if (cpu_id.vers.bits.extendedModel >= 4) { + /* K8 0FH */ + pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); + temp2 = (dramchr & 0x7); + clockratio = coef; + ram_type = 2; + + switch (temp2) { + case 0x0: + clockratio = (int)(coef); + break; + case 0x1: + clockratio = (int)(coef * 3.0f/4.0f); + break; + case 0x2: + clockratio = (int)(coef * 3.0f/5.0f); + break; + case 0x3: + clockratio = (int)(coef * 3.0f/6.0f); + break; + } + + } else { + /* OLD K8 */ + pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); + temp2 = (dramchr >> 20) & 0x7; + ram_type = 1; + clockratio = coef; + + switch (temp2) { + case 0x0: + clockratio = (int)(coef * 2.0f); + break; + case 0x2: + clockratio = (int)((coef * 3.0f/2.0f) + 0.81f); + break; + case 0x4: + clockratio = (int)((coef * 4.0f/3.0f) + 0.81f); + break; + case 0x5: + clockratio = (int)((coef * 6.0f/5.0f) + 0.81f); + break; + case 0x6: + clockratio = (int)((coef * 10.0f/9.0f) + 0.81f); + break; + case 0x7: + clockratio = (int)(coef + 0.81f); + break; + } + } + + /* Compute the final DRAM Clock */ + dramclock = (extclock / 1000) / clockratio; + + /* ...and print */ + print_cpu_line(dramclock, (extclock / 1000 / coef), ram_type); + +} + +static void poll_fsb_k10(void) { + + unsigned int mcgsrl; + unsigned int mcgsth; + unsigned long temp2; + unsigned long dramchr; + unsigned long mainPllId; + double dramclock; + ulong offset = 0; + int ram_type = 2; + + /* First, we need the clock ratio */ + pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); + temp2 = (dramchr & 0x7); + + switch (temp2) { + case 0x7: temp2++; + case 0x6: temp2++; + case 0x5: temp2++; + case 0x4: temp2++; + default: temp2 += 3; + } + + /* Compute the final DRAM Clock */ + if (((cpu_id.vers.bits.extendedModel >> 4) & 0xFF) == 1) { + dramclock = ((temp2 * 200) / 3.0) + 0.25; + } else { + unsigned long target; + unsigned long dx; + unsigned divisor; + + target = temp2 * 400; + + /* Get the FID by MSR */ + rdmsr(0xc0010071, mcgsrl, mcgsth); + + pci_conf_read(0, 24, 3, 0xD4, 4, &mainPllId); + + if ( mainPllId & 0x40 ) + mainPllId &= 0x3F; + else + mainPllId = 8; /* FID for 1600 */ + + mcgsth = (mcgsth >> 17) & 0x3F; + if ( mcgsth ) { + if ( mainPllId > mcgsth ) + mainPllId = mcgsth; + } + + dx = (mainPllId + 8) * 1200; + for ( divisor = 3; divisor < 100; divisor++ ) + if ( (dx / divisor) <= target ) + break; + + + pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); + + // If Channel A not enabled, switch to channel B + if(((dramchr>>14) & 0x1)) + { + offset = 0x100; + pci_conf_read(0, 24, 2, 0x94+offset, 4, &dramchr); + } + + //DDR2 or DDR3 + if ((dramchr >> 8)&1) { + ram_type = 3; + } else { + ram_type = 2;; + } + + dramclock = ((dx / divisor) / 6.0) + 0.25; + } + + /* ...and print */ + print_cpu_line(dramclock, 0, ram_type); + +} + +static void poll_fsb_k12(void) { + + unsigned long temp2; + unsigned long dramchr; + double dramratio, dramclock, fsb, did; + unsigned int mcgsrl,mcgsth, fid, did_raw; + + // Get current FID & DID + rdmsr(0xc0010071, mcgsrl, mcgsth); + did_raw = mcgsrl & 0xF; + fid = (mcgsrl >> 4) & 0xF; + + switch(did_raw) + { + default: + case 0x0: + did = 1.0f; + break; + case 0x1: + did = 1.5f; + break; + case 0x2: + did = 2.0f; + break; + case 0x3: + did = 3.0f; + break; + case 0x4: + did = 4.0f; + break; + case 0x5: + did = 6.0f; + break; + case 0x6: + did = 8.0f; + break; + case 0x7: + did = 12.0f; + break; + case 0x8: + did = 16.0f; + break; + } + + fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / did)); + + /* Finaly, we need the clock ratio */ + pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); + + if(((dramchr >> 14) & 0x1) == 1) + { + pci_conf_read(0, 24, 2, 0x194, 4, &dramchr); + } + + temp2 = (dramchr & 0x1F); + + switch (temp2) { + default: + case 0x06: + dramratio = 4.0f; + break; + case 0x0A: + dramratio = 16.0f / 3.0f; + break; + case 0x0E: + dramratio = 20.0f / 3.0f; + break; + case 0x12: + dramratio = 8.0f; + break; + case 0x16: + dramratio = 28.0f / 3.0f; + break; + } + + dramclock = fsb * dramratio; + + /* print */ + print_cpu_line(dramclock, fsb, 3); + +} + +static void poll_fsb_k16(void) +{ + + unsigned long dramchr; + double dramratio, dramclock, fsb; + + // FIXME: Unable to find a real way to detect multiplier. + fsb = 100.0f; + + /* Clock ratio */ + pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); + + switch (dramchr & 0x1F) { + default: + case 0x04: /* 333 */ + dramratio = 10.0f / 3.0f; + break; + case 0x06: /* 400 */ + dramratio = 4.0f; + break; + case 0x0A: /* 533 */ + dramratio = 16.0f / 3.0f; + break; + case 0x0E: /* 667 */ + dramratio = 20.0f / 3.0f; + break; + case 0x12: /* 800 */ + dramratio = 8.0f; + break; + case 0x16: /* 933 */ + dramratio = 28.0f / 3.0f; + break; + case 0x19: /* 1050 */ + dramratio = 21.0f / 2.0f; + break; + case 0x1A: /* 1066 */ + dramratio = 32.0f / 3.0f; + break; + } + + dramclock = fsb * dramratio; + + /* print */ + print_cpu_line(dramclock, fsb, 3); + +} + +static void poll_fsb_k15(void) { + + unsigned long temp2; + unsigned long dramchr; + double dramratio, dramclock, fsb; + unsigned int mcgsrl,mcgsth, fid, did; + + // Get current FID & DID + rdmsr(0xc0010071, mcgsrl, mcgsth); + fid = mcgsrl & 0x3F; + did = (mcgsrl >> 6) & 0x7; + + fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / (2^did)) / 2); + + /* Finaly, we need the clock ratio */ + pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); + + if(((dramchr >> 14) & 0x1) == 1) + { + pci_conf_read(0, 24, 2, 0x194, 4, &dramchr); + } + + temp2 = (dramchr & 0x1F); + + switch (temp2) { + case 0x04: + dramratio = 10.0f / 3.0f; + break; + default: + case 0x06: + dramratio = 4.0f; + break; + case 0x0A: + dramratio = 16.0f / 3.0f; + break; + case 0x0E: + dramratio = 20.0f / 3.0f; + break; + case 0x12: + dramratio = 8.0f; + break; + case 0x16: + dramratio = 28.0f / 3.0f; + break; + case 0x1A: + dramratio = 32.0f / 3.0f; + break; + case 0x1F: + dramratio = 36.0f / 3.0f; + break; + } + + dramclock = fsb * dramratio; + + /* print */ + print_cpu_line(dramclock, fsb, 3); + +} + +static void poll_fsb_k14(void) +{ + + unsigned long dramchr; + double dramratio, dramclock, fsb; + + // FIXME: Unable to find a real way to detect multiplier. + fsb = 100.0f; + + /* Clock ratio */ + pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); + + switch (dramchr & 0x1F) { + default: + case 0x06: + dramratio = 4.0f; + break; + case 0x0A: + dramratio = 16.0f / 3.0f; + break; + case 0x0E: + dramratio = 20.0f / 3.0f; + break; + case 0x12: + dramratio = 8.0f; + break; + } + + dramclock = fsb * dramratio; + + /* print */ + print_cpu_line(dramclock, fsb, 3); + +} + + +static void poll_fsb_i925(void) { + + double dramclock, dramratio, fsb; + unsigned long mchcfg, mchcfg2, dev0, drc, idetect; + float coef = getP4PMmultiplier(); + long *ptr; + int ddr_type; + + pci_conf_read( 0, 0, 0, 0x02, 2, &idetect); + + /* Find dramratio */ + pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); + dev0 = dev0 & 0xFFFFC000; + ptr=(long*)(dev0+0xC00); + mchcfg = *ptr & 0xFFFF; + ptr=(long*)(dev0+0x120); + drc = *ptr & 0xFFFF; + dramratio = 1; + + mchcfg2 = (mchcfg >> 4)&3; + + if ((drc&3) != 2) { + // We are in DDR1 Mode + if (mchcfg2 == 1) { dramratio = 0.8; } else { dramratio = 1; } + ddr_type = 1; + } else { + // We are in DDR2 Mode + ddr_type = 2; + if ((mchcfg >> 2)&1) { + // We are in FSB1066 Mode + if (mchcfg2 == 2) { dramratio = 0.75; } else { dramratio = 1; } + } else { + switch (mchcfg2) { + case 1: + dramratio = 0.66667; + break; + case 2: + if (idetect != 0x2590) { dramratio = 1; } else { dramratio = 1.5; } + break; + case 3: + // Checking for FSB533 Mode & Alviso + if ((mchcfg & 1) == 0) { dramratio = 1.33334; } + else if (idetect == 0x2590) { dramratio = 2; } + else { dramratio = 1.5; } + } + } + } + // Compute RAM Frequency + fsb = ((extclock / 1000) / coef); + dramclock = fsb * dramratio; + + + print_cpu_line(dramclock, fsb, ddr_type); + +} + +static void poll_fsb_i945(void) { + + double dramclock, dramratio, fsb; + unsigned long mchcfg, dev0; + float coef = getP4PMmultiplier(); + long *ptr; + + /* Find dramratio */ + pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); + dev0 &= 0xFFFFC000; + ptr=(long*)(dev0+0xC00); + mchcfg = *ptr & 0xFFFF; + dramratio = 1; + + switch ((mchcfg >> 4)&7) { + case 1: dramratio = 1.0; break; + case 2: dramratio = 1.33334; break; + case 3: dramratio = 1.66667; break; + case 4: dramratio = 2.0; break; + } + + // Compute RAM Frequency + fsb = ((extclock / 1000) / coef); + + dramclock = fsb * dramratio; + + // Print + print_cpu_line(dramclock, fsb, 2); + +} + +static void poll_fsb_i945gme(void) { + + double dramclock, dramratio, fsb; + unsigned long mchcfg, dev0, fsb_mch; + float coef = getP4PMmultiplier(); + long *ptr; + + /* Find dramratio */ + pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); + dev0 &= 0xFFFFC000; + ptr=(long*)(dev0+0xC00); + mchcfg = *ptr & 0xFFFF; + dramratio = 1; + + switch (mchcfg & 7) { + case 0: fsb_mch = 400; break; + default: + case 1: fsb_mch = 533; break; + case 2: fsb_mch = 667; break; + } + + + switch (fsb_mch) { + case 400: + switch ((mchcfg >> 4)&7) { + case 2: dramratio = 1.0f; break; + case 3: dramratio = 4.0f/3.0f; break; + case 4: dramratio = 5.0f/3.0f; break; + } + break; + + default: + case 533: + switch ((mchcfg >> 4)&7) { + case 2: dramratio = 3.0f/4.0f; break; + case 3: dramratio = 1.0f; break; + case 4: dramratio = 5.0f/4.0f; break; + } + break; + + case 667: + switch ((mchcfg >> 4)&7) { + case 2: dramratio = 3.0f/5.0f; break; + case 3: dramratio = 4.0f/5.0f; break; + case 4: dramratio = 1.0f; break; + } + break; + } + + // Compute RAM Frequency + fsb = ((extclock / 1000) / coef); + dramclock = fsb * dramratio * 2; + + print_cpu_line(dramclock, fsb, 2); + +} + + +static void poll_fsb_i975(void) { + + double dramclock, dramratio, fsb; + unsigned long mchcfg, dev0, fsb_mch; + float coef = getP4PMmultiplier(); + long *ptr; + + /* Find dramratio */ + pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); + dev0 &= 0xFFFFC000; + ptr=(long*)(dev0+0xC00); + mchcfg = *ptr & 0xFFFF; + dramratio = 1; + + switch (mchcfg & 7) { + case 1: fsb_mch = 533; break; + case 2: fsb_mch = 800; break; + case 3: fsb_mch = 667; break; + default: fsb_mch = 1066; break; + } + + + switch (fsb_mch) { + case 533: + switch ((mchcfg >> 4)&7) { + case 0: dramratio = 1.25; break; + case 1: dramratio = 1.5; break; + case 2: dramratio = 2.0; break; + } + break; + + default: + case 800: + switch ((mchcfg >> 4)&7) { + case 1: dramratio = 1.0; break; + case 2: dramratio = 1.33334; break; + case 3: dramratio = 1.66667; break; + case 4: dramratio = 2.0; break; + } + break; + + case 1066: + switch ((mchcfg >> 4)&7) { + case 1: dramratio = 0.75; break; + case 2: dramratio = 1.0; break; + case 3: dramratio = 1.25; break; + case 4: dramratio = 1.5; break; + } + break; + } + + // Compute RAM Frequency + fsb = ((extclock / 1000) / coef); + dramclock = fsb * dramratio; + + print_cpu_line(dramclock, fsb, 2); + +} + +static void poll_fsb_i965(void) { + + double dramclock, dramratio, fsb; + unsigned long mchcfg, dev0, fsb_mch; + float coef = getP4PMmultiplier(); + long *ptr; + + /* Find dramratio */ + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + ptr=(long*)(dev0+0xC00); + mchcfg = *ptr & 0xFFFF; + dramratio = 1; + + switch (mchcfg & 7) { + case 0: fsb_mch = 1066; break; + case 1: fsb_mch = 533; break; + default: case 2: fsb_mch = 800; break; + case 3: fsb_mch = 667; break; + case 4: fsb_mch = 1333; break; + case 6: fsb_mch = 1600; break; + } + + + switch (fsb_mch) { + case 533: + switch ((mchcfg >> 4)&7) { + case 1: dramratio = 2.0; break; + case 2: dramratio = 2.5; break; + case 3: dramratio = 3.0; break; + } + break; + + default: + case 800: + switch ((mchcfg >> 4)&7) { + case 0: dramratio = 1.0; break; + case 1: dramratio = 5.0f/4.0f; break; + case 2: dramratio = 5.0f/3.0f; break; + case 3: dramratio = 2.0f; break; + case 4: dramratio = 8.0f/3.0f; break; + case 5: dramratio = 10.0f/3.0f; break; + } + break; + + case 1066: + switch ((mchcfg >> 4)&7) { + case 1: dramratio = 1.0f; break; + case 2: dramratio = 5.0f/4.0f; break; + case 3: dramratio = 3.0f/2.0f; break; + case 4: dramratio = 2.0f; break; + case 5: dramratio = 5.0f/2.0f; break; + } + break; + + case 1333: + switch ((mchcfg >> 4)&7) { + case 2: dramratio = 1.0f; break; + case 3: dramratio = 6.0f/5.0f; break; + case 4: dramratio = 8.0f/5.0f; break; + case 5: dramratio = 2.0f; break; + } + break; + + case 1600: + switch ((mchcfg >> 4)&7) { + case 3: dramratio = 1.0f; break; + case 4: dramratio = 4.0f/3.0f; break; + case 5: dramratio = 3.0f/2.0f; break; + case 6: dramratio = 2.0f; break; + } + break; + + } + + // Compute RAM Frequency + fsb = ((extclock / 1000) / coef); + dramclock = fsb * dramratio; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 2); + +} + +static void poll_fsb_p35(void) { + + double dramclock, dramratio, fsb; + unsigned long mchcfg, dev0, fsb_mch, Device_ID, Memory_Check, c0ckectrl, offset; + float coef = getP4PMmultiplier(); + long *ptr; + int ram_type; + + pci_conf_read( 0, 0, 0, 0x02, 2, &Device_ID); + Device_ID &= 0xFFFF; + + /* Find dramratio */ + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0+0x260); + c0ckectrl = *ptr & 0xFFFFFFFF; + + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); + + ptr=(long*)(dev0+0xC00); + mchcfg = *ptr & 0xFFFF; + dramratio = 1; + + switch (mchcfg & 7) { + case 0: fsb_mch = 1066; break; + case 1: fsb_mch = 533; break; + default: case 2: fsb_mch = 800; break; + case 3: fsb_mch = 667; break; + case 4: fsb_mch = 1333; break; + case 6: fsb_mch = 1600; break; + } + + + switch (fsb_mch) { + case 533: + switch ((mchcfg >> 4)&7) { + case 1: dramratio = 2.0; break; + case 2: dramratio = 2.5; break; + case 3: dramratio = 3.0; break; + } + break; + + default: + case 800: + switch ((mchcfg >> 4)&7) { + case 0: dramratio = 1.0; break; + case 1: dramratio = 5.0f/4.0f; break; + case 2: dramratio = 5.0f/3.0f; break; + case 3: dramratio = 2.0; break; + case 4: dramratio = 8.0f/3.0f; break; + case 5: dramratio = 10.0f/3.0f; break; + } + break; + + case 1066: + switch ((mchcfg >> 4)&7) { + case 1: dramratio = 1.0f; break; + case 2: dramratio = 5.0f/4.0f; break; + case 3: dramratio = 3.0f/2.0f; break; + case 4: dramratio = 2.0f; break; + case 5: dramratio = 5.0f/2.0f; break; + } + break; + + case 1333: + switch ((mchcfg >> 4)&7) { + case 2: dramratio = 1.0f; break; + case 3: dramratio = 6.0f/5.0f; break; + case 4: dramratio = 8.0f/5.0f; break; + case 5: dramratio = 2.0f; break; + } + break; + + case 1600: + switch ((mchcfg >> 4)&7) { + case 3: dramratio = 1.0f; break; + case 4: dramratio = 4.0f/3.0f; break; + case 5: dramratio = 3.0f/2.0f; break; + case 6: dramratio = 2.0f; break; + } + break; + + } + + // On P45, check 1A8 + if(Device_ID > 0x2E00 && imc_type != 8) { + ptr = (long*)(dev0+offset+0x1A8); + Memory_Check = *ptr & 0xFFFFFFFF; + Memory_Check >>= 2; + Memory_Check &= 1; + Memory_Check = !Memory_Check; + } else if (imc_type == 8) { + ptr = (long*)(dev0+offset+0x224); + Memory_Check = *ptr & 0xFFFFFFFF; + Memory_Check &= 1; + Memory_Check = !Memory_Check; + } else { + ptr = (long*)(dev0+offset+0x1E8); + Memory_Check = *ptr & 0xFFFFFFFF; + } + + //Determine DDR-II or DDR-III + if (Memory_Check & 1) { + ram_type = 2; + } else { + ram_type = 3; + } + + // Compute RAM Frequency + fsb = ((extclock / 1000) / coef); + dramclock = fsb * dramratio; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, ram_type); + +} + +static void poll_fsb_im965(void) { + + double dramclock, dramratio, fsb; + unsigned long mchcfg, dev0, fsb_mch; + float coef = getP4PMmultiplier(); + long *ptr; + + /* Find dramratio */ + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + ptr=(long*)(dev0+0xC00); + mchcfg = *ptr & 0xFFFF; + dramratio = 1; + + switch (mchcfg & 7) { + case 1: fsb_mch = 533; break; + default: case 2: fsb_mch = 800; break; + case 3: fsb_mch = 667; break; + case 6: fsb_mch = 1066; break; + } + + + switch (fsb_mch) { + case 533: + switch ((mchcfg >> 4)&7) { + case 1: dramratio = 5.0f/4.0f; break; + case 2: dramratio = 3.0f/2.0f; break; + case 3: dramratio = 2.0f; break; + } + break; + + case 667: + switch ((mchcfg >> 4)&7) { + case 1: dramratio = 1.0f; break; + case 2: dramratio = 6.0f/5.0f; break; + case 3: dramratio = 8.0f/5.0f; break; + case 4: dramratio = 2.0f; break; + case 5: dramratio = 12.0f/5.0f; break; + } + break; + default: + case 800: + switch ((mchcfg >> 4)&7) { + case 1: dramratio = 5.0f/6.0f; break; + case 2: dramratio = 1.0f; break; + case 3: dramratio = 4.0f/3.0f; break; + case 4: dramratio = 5.0f/3.0f; break; + case 5: dramratio = 2.0f; break; + } + break; + case 1066: + switch ((mchcfg >> 4)&7) { + case 5: dramratio = 3.0f/2.0f; break; + case 6: dramratio = 2.0f; break; + } + break; + } + + // Compute RAM Frequency + fsb = ((extclock / 1000) / coef); + dramclock = fsb * dramratio; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 2); + +} + + +static void poll_fsb_5400(void) { + + double dramclock, dramratio, fsb; + unsigned long ambase_low, ambase_high, ddrfrq; + float coef = getP4PMmultiplier(); + + /* Find dramratio */ + pci_conf_read( 0, 16, 0, 0x48, 4, &ambase_low); + ambase_low &= 0xFFFE0000; + pci_conf_read( 0, 16, 0, 0x4C, 4, &ambase_high); + ambase_high &= 0xFF; + pci_conf_read( 0, 16, 1, 0x56, 1, &ddrfrq); + ddrfrq &= 7; + dramratio = 1; + + switch (ddrfrq) { + case 0: + case 1: + case 4: + dramratio = 1.0; + break; + case 2: + dramratio = 5.0f/4.0f; + break; + case 3: + case 7: + dramratio = 4.0f/5.0f; + break; + } + + + // Compute RAM Frequency + fsb = ((extclock / 1000) / coef); + dramclock = fsb * dramratio; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 2); + +} + + +static void poll_fsb_nf4ie(void) { + + double dramclock, dramratio, fsb; + float mratio, nratio; + unsigned long reg74, reg60; + float coef = getP4PMmultiplier(); + + /* Find dramratio */ + pci_conf_read(0, 0, 2, 0x74, 2, ®74); + pci_conf_read(0, 0, 2, 0x60, 4, ®60); + mratio = reg74 & 0xF; + nratio = (reg74 >> 4) & 0xF; + + // If M or N = 0, then M or N = 16 + if (mratio == 0) { mratio = 16; } + if (nratio == 0) { nratio = 16; } + + // Check if synchro or pseudo-synchro mode + if((reg60 >> 22) & 1) { + dramratio = 1; + } else { + dramratio = nratio / mratio; + } + + /* Compute RAM Frequency */ + fsb = ((extclock /1000) / coef); + dramclock = fsb * dramratio; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 2); + +} + +static void poll_fsb_i875(void) { + + double dramclock, dramratio, fsb; + unsigned long mchcfg, smfs; + float coef = getP4PMmultiplier(); + + /* Find dramratio */ + pci_conf_read(0, 0, 0, 0xC6, 2, &mchcfg); + smfs = (mchcfg >> 10)&3; + dramratio = 1; + + if ((mchcfg&3) == 3) { dramratio = 1; } + if ((mchcfg&3) == 2) { + if (smfs == 2) { dramratio = 1; } + if (smfs == 1) { dramratio = 1.25; } + if (smfs == 0) { dramratio = 1.5; } + } + if ((mchcfg&3) == 1) { + if (smfs == 2) { dramratio = 0.6666666666; } + if (smfs == 1) { dramratio = 0.8; } + if (smfs == 0) { dramratio = 1; } + } + if ((mchcfg&3) == 0) { dramratio = 0.75; } + + + /* Compute RAM Frequency */ + dramclock = ((extclock /1000) / coef) / dramratio; + fsb = ((extclock /1000) / coef); + + /* Print DRAM Freq */ + print_cpu_line(dramclock, fsb, 2); +} + +static void poll_fsb_p4(void) { + + ulong fsb, idetect; + float coef = getP4PMmultiplier(); + char *name; + int col,temp; + + fsb = ((extclock /1000) / coef); + + /* For synchro only chipsets */ + pci_conf_read( 0, 0, 0, 0x02, 2, &idetect); + if (idetect == 0x2540 || idetect == 0x254C) + { + print_cpu_line(fsb, fsb, 1); + } else { + /* Print the controller name */ + col = COL_SPEC; + cprint(LINE_CPU, col, "Chipset: "); + col += 9; + /* Print the controller name */ + name = controllers[ctrl.index].name; + cprint(LINE_CPU, col, name); + /* Now figure out how much I just printed */ + temp = 20; + while(name[temp - 20] != '\0') { + col++; + temp++; + } + + if(temp < 36){ + cprint(LINE_CPU, col +1, "- FSB : "); + col += 9; + dprint(LINE_CPU, col, fsb, 3,0); + col += 3; + } + + } +} + +static void poll_fsb_i855(void) { + + + double dramclock, dramratio, fsb ; + unsigned int msr_lo, msr_hi; + ulong mchcfg, idetect; + int coef; + + pci_conf_read( 0, 0, 0, 0x02, 2, &idetect); + + /* Find multiplier (by MSR) */ + + /* Is it a Pentium M ? */ + if (cpu_id.vers.bits.family == 6) { + rdmsr(0x2A, msr_lo, msr_hi); + coef = (msr_lo >> 22) & 0x1F; + } else { + rdmsr(0x2C, msr_lo, msr_hi); + coef = (msr_lo >> 24) & 0x1F; + } + + fsb = ((extclock /1000) / coef); + + + /* Compute DRAM Clock */ + + dramratio = 1; + if (idetect == 0x3580) { + pci_conf_read( 0, 0, 3, 0xC0, 2, &mchcfg); + mchcfg = mchcfg & 0x7; + + if (mchcfg == 1 || mchcfg == 2 || mchcfg == 4 || mchcfg == 5) { dramratio = 1; } + if (mchcfg == 0 || mchcfg == 3) { dramratio = 1.333333333; } + if (mchcfg == 6) { dramratio = 1.25; } + if (mchcfg == 7) { dramratio = 1.666666667; } + + } else { + pci_conf_read( 0, 0, 0, 0xC6, 2, &mchcfg); + if (((mchcfg >> 10)&3) == 0) { dramratio = 1; } + else if (((mchcfg >> 10)&3) == 1) { dramratio = 1.666667; } + else { dramratio = 1.333333333; } + } + + + dramclock = fsb * dramratio; + + /* ...and print */ + print_cpu_line(dramclock, fsb, 1); + +} + +static void poll_fsb_amd32(void) { + + unsigned int mcgsrl; + unsigned int mcgsth; + unsigned long temp; + double dramclock; + double coef2; + int col; + char *name; + + /* First, got the FID */ + rdmsr(0x0c0010015, mcgsrl, mcgsth); + temp = (mcgsrl >> 24)&0x0F; + + if ((mcgsrl >> 19)&1) { coef2 = athloncoef2[temp]; } + else { coef2 = athloncoef[temp]; } + + if (coef2 == 0) { coef2 = 1; }; + + /* Compute the final FSB Clock */ + dramclock = (extclock /1000) / coef2; + + /* Print the controller name */ + col = COL_SPEC; + cprint(LINE_CPU, col, "Chipset: "); + col += 9; + /* Print the controller name */ + name = controllers[ctrl.index].name; + cprint(LINE_CPU, col, name); + /* Now figure out how much I just printed */ + temp = 20; + while(name[temp - 20] != '\0') { + col++; + temp++; + } + + if(temp < 36){ + cprint(LINE_CPU, col +1, "- FSB : "); + col += 9; + dprint(LINE_CPU, col, dramclock, 3,0); + col += 3; + } + + +} + +static void poll_fsb_nf2(void) { + + unsigned int mcgsrl; + unsigned int mcgsth; + unsigned long temp, mempll; + double dramclock, fsb; + double mem_m, mem_n; + float coef; + coef = 10; + + /* First, got the FID */ + rdmsr(0x0c0010015, mcgsrl, mcgsth); + temp = (mcgsrl >> 24)&0x0F; + + if ((mcgsrl >> 19)&1) { coef = athloncoef2[temp]; } + else { coef = athloncoef[temp]; } + + /* Get the coef (COEF = N/M) - Here is for Crush17 */ + pci_conf_read(0, 0, 3, 0x70, 4, &mempll); + mem_m = (mempll&0x0F); + mem_n = ((mempll >> 4) & 0x0F); + + /* If something goes wrong, the chipset is probably a Crush18 */ + if ( mem_m == 0 || mem_n == 0 ) { + pci_conf_read(0, 0, 3, 0x7C, 4, &mempll); + mem_m = (mempll&0x0F); + mem_n = ((mempll >> 4) & 0x0F); + } + + /* Compute the final FSB Clock */ + dramclock = ((extclock /1000) / coef) * (mem_n/mem_m); + fsb = ((extclock /1000) / coef); + + /* ...and print */ + print_cpu_line(dramclock, fsb, 1); + +} + +static void poll_fsb_us15w(void) { + + double dramclock, dramratio, fsb; + unsigned long msr; + + /* Find dramratio */ + /* D0 MsgRd, 05 Zunit, 03 MSR */ + pci_conf_write(0, 0, 0, 0xD0, 4, 0xD0050300 ); + pci_conf_read(0, 0, 0, 0xD4, 4, &msr ); + fsb = ( msr >> 3 ) & 1; + + dramratio = 0.5; + + // Compute RAM Frequency + if (( msr >> 3 ) & 1) { + fsb = 533; + } else { + fsb = 400; + } + + /* + switch (( msr >> 0 ) & 7) { + case 0: + gfx = 100; + break; + case 1: + gfx = 133; + break; + case 2: + gfx = 150; + break; + case 3: + gfx = 178; + break; + case 4: + gfx = 200; + break; + case 5: + gfx = 266; + break; + default: + gfx = 0; + break; + } + */ + + dramclock = fsb * dramratio; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 1); + +} + +static void poll_fsb_nhm(void) { + + double dramclock, dramratio, fsb; + unsigned long mc_dimm_clk_ratio; + float coef = getNHMmultiplier(); + //unsigned long qpi_pll_status; + //float qpi_speed; + + + fsb = ((extclock /1000) / coef); + + /* Print QPI Speed (if ECC not supported) */ + /* + if(ctrl.mode == ECC_NONE && cpu_id.vers.bits.model == 10) { + pci_conf_read(nhm_bus, 2, 1, 0x50, 2, &qpi_pll_status); + qpi_speed = (qpi_pll_status & 0x7F) * ((extclock / 1000) / coef) * 2; + cprint(LINE_CPU+5, col +1, "/ QPI : "); + col += 9; + dprint(LINE_CPU+5, col, qpi_speed/1000, 1,0); + col += 1; + cprint(LINE_CPU+5, col, "."); + col += 1; + qpi_speed = ((qpi_speed / 1000) - (int)(qpi_speed / 1000)) * 10; + dprint(LINE_CPU+5, col, qpi_speed, 1,0); + col += 1; + cprint(LINE_CPU+5, col +1, "GT/s"); + col += 5; + } + */ + + /* Get the clock ratio */ + + pci_conf_read(nhm_bus, 3, 4, 0x54, 2, &mc_dimm_clk_ratio); + dramratio = (mc_dimm_clk_ratio & 0x1F); + + // Compute RAM Frequency + fsb = ((extclock / 1000) / coef); + dramclock = fsb * dramratio / 2; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 3); + +} + +static void poll_fsb_nhm32(void) { + + double dramclock, dramratio, fsb; + unsigned long mc_dimm_clk_ratio; + float coef = getNHMmultiplier(); + //unsigned long qpi_pll_status; + //float qpi_speed; + + fsb = ((extclock /1000) / coef); + + /* Print QPI Speed (if ECC not supported) */ + /* + if(ctrl.mode == ECC_NONE && cpu_id.vers.bits.model == 12) { + pci_conf_read(nhm_bus, 2, 1, 0x50, 2, &qpi_pll_status); + qpi_speed = (qpi_pll_status & 0x7F) * ((extclock / 1000) / coef) * 2; + cprint(LINE_CPU+5, col +1, "/ QPI : "); + col += 9; + dprint(LINE_CPU+5, col, qpi_speed/1000, 1,0); + col += 1; + cprint(LINE_CPU+5, col, "."); + col += 1; + qpi_speed = ((qpi_speed / 1000) - (int)(qpi_speed / 1000)) * 10; + dprint(LINE_CPU+5, col, qpi_speed, 1,0); + col += 1; + cprint(LINE_CPU+5, col +1, "GT/s"); + col += 5; + } + */ + + /* Get the clock ratio */ + + pci_conf_read(nhm_bus, 3, 4, 0x50, 2, &mc_dimm_clk_ratio); + dramratio = (mc_dimm_clk_ratio & 0x1F); + + // Compute RAM Frequency + fsb = ((extclock / 1000) / coef); + dramclock = fsb * dramratio / 2; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 3); + +} + +static void poll_fsb_wmr(void) { + + double dramclock, dramratio, fsb; + unsigned long dev0; + float coef = getNHMmultiplier(); + long *ptr; + + fsb = ((extclock / 1000) / coef); + + /* Find dramratio */ + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + ptr=(long*)(dev0+0x2C20); + dramratio = 1; + + /* Get the clock ratio */ + dramratio = 0.25 * (float)(*ptr & 0x1F); + + // Compute RAM Frequency + dramclock = fsb * dramratio; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 3); + +} + +static void poll_fsb_snb(void) { + + double dramclock, dramratio, fsb; + unsigned long dev0; + float coef = getSNBmultiplier(); + long *ptr; + + fsb = ((extclock / 1000) / coef); + + /* Find dramratio */ + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + ptr=(long*)(dev0+0x5E04); + dramratio = 1; + + /* Get the clock ratio */ + dramratio = (float)(*ptr & 0x1F) * (133.34f / 100.0f); + + // Compute RAM Frequency + dramclock = fsb * dramratio; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 3); + +} + +static void poll_fsb_ivb(void) { + + double dramclock, dramratio, fsb; + unsigned long dev0, mchcfg; + float coef = getSNBmultiplier(); + long *ptr; + + fsb = ((extclock / 1000) / coef); + + /* Find dramratio */ + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + ptr=(long*)(dev0+0x5E04); + mchcfg = *ptr & 0xFFFF; + dramratio = 1; + + /* Get the clock ratio */ + switch((mchcfg >> 8) & 0x01) + { + case 0x0: + dramratio = (float)(*ptr & 0x1F) * (133.34f / 100.0f); + break; + case 0x1: + dramratio = (float)(*ptr & 0x1F) * (100.0f / 100.0f); + break; + } + + // Compute RAM Frequency + dramclock = fsb * dramratio; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 3); + +} + +static void poll_fsb_snbe(void) { + + double dramclock, dramratio, fsb; + unsigned long dev0; + float coef = getSNBmultiplier(); + + fsb = ((extclock / 1000) / coef); + + /* Find dramratio */ + pci_conf_read( 0xFF, 10, 1, 0x98, 4, &dev0); + dev0 &= 0xFFFFFFFF; + dramratio = 1; + + /* Get the clock ratio */ + dramratio = (float)(dev0 & 0x3F) * (66.67f / 100.0f); + + // Compute RAM Frequency + dramclock = fsb * dramratio; + + // Print DRAM Freq + print_cpu_line(dramclock, fsb, 3); + + + +} + +/* ------------------ Here the code for Timings detection ------------------ */ +/* ------------------------------------------------------------------------- */ + +static void poll_timings_nf4ie(void) { + + + ulong regd0, reg8c, reg9c, reg80; + int cas, rcd, rp, ras, chan; + + //Now, read Registers + pci_conf_read( 0, 1, 1, 0xD0, 4, ®d0); + pci_conf_read( 0, 1, 1, 0x80, 1, ®80); + pci_conf_read( 0, 1, 0, 0x8C, 4, ®8c); + pci_conf_read( 0, 1, 0, 0x9C, 4, ®9c); + + // Then, detect timings + cas = (regd0 >> 4) & 0x7; + rcd = (reg8c >> 24) & 0xF; + rp = (reg9c >> 8) & 0xF; + ras = (reg8c >> 16) & 0x3F; + + if (reg80 & 0x3) { + chan = 2; + } else { + chan = 1; + } + print_ram_line(cas, rcd, rp, ras, chan); +} + +static void poll_timings_i875(void) { + + ulong dev6, dev62; + ulong temp; + float cas; + int rcd, rp, ras, chan; + long *ptr, *ptr2; + + pci_conf_read( 0, 6, 0, 0x40, 4, &dev62); + ptr2=(long*)(dev6+0x68); + + /* Read the MMR Base Address & Define the pointer */ + pci_conf_read( 0, 6, 0, 0x10, 4, &dev6); + + /* Now, we could check some additionnals timings infos) */ + ptr=(long*)(dev6+0x60); + // CAS Latency (tCAS) + temp = ((*ptr >> 5)& 0x3); + if (temp == 0x0) { cas = 2.5; } else if (temp == 0x1) { cas = 2; } else { cas = 3; } + + // RAS-To-CAS (tRCD) + temp = ((*ptr >> 2)& 0x3); + if (temp == 0x0) { rcd = 4; } else if (temp == 0x1) { rcd = 3; } else { rcd = 2; } + + // RAS Precharge (tRP) + temp = (*ptr&0x3); + if (temp == 0x0) { rp = 4; } else if (temp == 0x1) { rp = 3; } else { rp = 2; } + + // RAS Active to precharge (tRAS) + temp = ((*ptr >> 7)& 0x7); + ras = 10 - temp; + + // Print 64 or 128 bits mode + if (((*ptr2 >> 21)&3) > 0) { + chan = 2; + } else { + chan = 1; + } + print_ram_line(cas, rcd, rp, ras, chan); +} + +static void poll_timings_i925(void) { + + // Thanks for CDH optis + float cas; + int rcd,rp,ras,chan; + ulong dev0, drt, drc, dcc, idetect, temp; + long *ptr; + + //Now, read MMR Base Address + pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); + pci_conf_read( 0, 0, 0, 0x02, 2, &idetect); + dev0 &= 0xFFFFC000; + + //Set pointer for DRT + ptr=(long*)(dev0+0x114); + drt = *ptr & 0xFFFFFFFF; + + //Set pointer for DRC + ptr=(long*)(dev0+0x120); + drc = *ptr & 0xFFFFFFFF; + + //Set pointer for DCC + ptr=(long*)(dev0+0x200); + dcc = *ptr & 0xFFFFFFFF; + + // CAS Latency (tCAS) + temp = ((drt >> 8)& 0x3); + + if ((drc & 3) == 2){ + // Timings DDR-II + if (temp == 0x0) { cas = 5; } + else if (temp == 0x1) { cas = 4; } + else if (temp == 0x2) { cas = 3; } + else { cas = 6; } + } else { + // Timings DDR-I + if (temp == 0x0) { cas = 3; } + else if (temp == 0x1) { cas = 2.5f;} + else { cas = 2; } + } + + // RAS-To-CAS (tRCD) + rcd = ((drt >> 4)& 0x3)+2; + + // RAS Precharge (tRP) + rp = (drt&0x3)+2; + + // RAS Active to precharge (tRAS) + // If Lakeport, than change tRAS computation (Thanks to CDH, again) + if (idetect > 0x2700) + ras = ((drt >> 19)& 0x1F); + else + ras = ((drt >> 20)& 0x0F); + + + temp = (dcc&0x3); + if (temp == 1) { chan = 2; } + else if (temp == 2) { chan = 2; } + else { chan = 1; } + + print_ram_line(cas, rcd, rp, ras, chan); + +} + +static void poll_timings_i965(void) { + + // Thanks for CDH optis + ulong dev0, c0ckectrl, c1ckectrl, offset; + ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register; + long *ptr; + int rcd,rp,ras,chan; + float cas; + + //Now, read MMR Base Address + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0+0x260); + c0ckectrl = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+0x660); + c1ckectrl = *ptr & 0xFFFFFFFF; + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); + + ptr = (long*)(dev0+offset+0x29C); + ODT_Control_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x250); + Precharge_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x252); + ACT_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x258); + Read_Register = *ptr & 0xFFFFFFFF; + + + // CAS Latency (tCAS) + cas = ((ODT_Control_Register >> 17)& 7) + 3.0f; + + // RAS-To-CAS (tRCD) + rcd = (Read_Register >> 16) & 0xF; + + // RAS Precharge (tRP) + rp = (ACT_Register >> 13) & 0xF; + + // RAS Active to precharge (tRAS) + ras = (Precharge_Register >> 11) & 0x1F; + + if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) { + chan = 2; + } else { + chan = 1; + } + + print_ram_line(cas, rcd, rp, ras, chan); +} + +static void poll_timings_im965(void) { + + // Thanks for CDH optis + ulong dev0, c0ckectrl, c1ckectrl, offset; + ulong ODT_Control_Register, Precharge_Register; + long *ptr; + int rcd,rp,ras,chan; + float cas; + + //Now, read MMR Base Address + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0+0x1200); + c0ckectrl = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+0x1300); + c1ckectrl = *ptr & 0xFFFFFFFF; + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x100); + + ptr = (long*)(dev0+offset+0x121C); + ODT_Control_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x1214); + Precharge_Register = *ptr & 0xFFFFFFFF; + + // CAS Latency (tCAS) + cas = ((ODT_Control_Register >> 23)& 7) + 3.0f; + + // RAS-To-CAS (tRCD) + rcd = ((Precharge_Register >> 5)& 7) + 2.0f; + + // RAS Precharge (tRP) + rp = (Precharge_Register & 7) + 2.0f; + + // RAS Active to precharge (tRAS) + ras = (Precharge_Register >> 21) & 0x1F; + + + if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) { + chan = 2; + } else { + chan = 1; + } + print_ram_line(cas, rcd, rp, ras, chan); +} + +static void poll_timings_p35(void) { + + // Thanks for CDH optis + float cas; + int rcd, rp, ras, chan; + ulong dev0, Device_ID, c0ckectrl, c1ckectrl, offset; + ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register; + long *ptr; + + pci_conf_read( 0, 0, 0, 0x02, 2, &Device_ID); + Device_ID &= 0xFFFF; + + //Now, read MMR Base Address + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0+0x260); + c0ckectrl = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+0x660); + c1ckectrl = *ptr & 0xFFFFFFFF; + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); + + ptr = (long*)(dev0+offset+0x265); + ODT_Control_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x25D); + Precharge_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x252); + ACT_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x258); + Read_Register = *ptr & 0xFFFFFFFF; + + + // CAS Latency (tCAS) + if(Device_ID > 0x2E00 && imc_type != 8) { + cas = ((ODT_Control_Register >> 8)& 0x3F) - 6.0f; + } else { + cas = ((ODT_Control_Register >> 8)& 0x3F) - 9.0f; + } + + // RAS-To-CAS (tRCD) + rcd = (Read_Register >> 17) & 0xF; + + // RAS Precharge (tRP) + rp = (ACT_Register >> 13) & 0xF; + + // RAS Active to precharge (tRAS) + ras = Precharge_Register & 0x3F; + + if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) { + chan = 2; + } else { + chan = 1; + } + print_ram_line(cas, rcd, rp, ras, chan); +} + +static void poll_timings_wmr(void) { + + float cas; + int rcd, rp, ras, chan; + ulong dev0, c0ckectrl, c1ckectrl, offset; + ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, MRC_Register; + long *ptr; + + //Now, read MMR Base Address + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + + ptr = (long*)(dev0+0x260); + c0ckectrl = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+0x660); + c1ckectrl = *ptr & 0xFFFFFFFF; + + // If DIMM 0 not populated, check DIMM 1 + ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); + + ptr = (long*)(dev0+offset+0x265); + ODT_Control_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x25D); + Precharge_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x252); + ACT_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x258); + Read_Register = *ptr & 0xFFFFFFFF; + + ptr = (long*)(dev0+offset+0x240); + MRC_Register = *ptr & 0xFFFFFFFF; + + // CAS Latency (tCAS) + if(MRC_Register & 0xF) { + cas = (MRC_Register & 0xF) + 3.0f; + } else { + cas = ((ODT_Control_Register >> 8)& 0x3F) - 5.0f; + } + + // RAS-To-CAS (tRCD) + rcd = (Read_Register >> 17) & 0xF; + + // RAS Precharge (tRP) + rp = (ACT_Register >> 13) & 0xF; + + // RAS Active to precharge (tRAS) + ras = Precharge_Register & 0x3F; + + if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) { + chan = 2; + } else { + chan = 1; + } + + print_ram_line(cas, rcd, rp, ras, chan); + +} + +static void poll_timings_snb(void) { + + float cas; + int rcd, rp, ras, chan; + ulong dev0, offset; + ulong IMC_Register, MCMain0_Register, MCMain1_Register; + long *ptr; + + //Now, read MMR Base Address + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + + offset = 0x0000; + + ptr = (long*)(dev0+offset+0x4000); + IMC_Register = *ptr & 0xFFFFFFFF; + + // CAS Latency (tCAS) + cas = (float)((IMC_Register >> 8) & 0x0F); + + // RAS-To-CAS (tRCD) + rcd = IMC_Register & 0x0F; + + // RAS Precharge (tRP) + rp = (IMC_Register >> 4) & 0x0F; + + // RAS Active to precharge (tRAS) + ras = (IMC_Register >> 16) & 0xFF; + + // Channels + ptr = (long*)(dev0+offset+0x5004); + MCMain0_Register = *ptr & 0xFFFF; + ptr = (long*)(dev0+offset+0x5008); + MCMain1_Register = *ptr & 0xFFFF; + + if(MCMain0_Register == 0 || MCMain1_Register == 0) { + chan = 1; + } else { + chan = 2; + } + + print_ram_line(cas, rcd, rp, ras, chan); +} + +static void poll_timings_hsw(void) { + + float cas; + int rcd, rp, ras, chan; + ulong dev0, offset = 0; + ulong IMC_Register, MCMain0_Register, MCMain1_Register; + long *ptr; + + //Now, read MMR Base Address + pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); + dev0 &= 0xFFFFC000; + + // Channels + ptr = (long*)(dev0+offset+0x5004); + MCMain0_Register = *ptr & 0xFFFF; + + ptr = (long*)(dev0+offset+0x5008); + MCMain1_Register = *ptr & 0xFFFF; + + if(MCMain0_Register && MCMain1_Register) { + chan = 2; + } else { + chan = 1; + } + + if(MCMain0_Register) { offset = 0x0000; } else { offset = 0x0400; } + + // CAS Latency (tCAS) + ptr = (long*)(dev0+offset+0x4014); + IMC_Register = *ptr & 0xFFFFFFFF; + cas = (float)(IMC_Register & 0x1F); + + ptr = (long*)(dev0+offset+0x4000); + IMC_Register = *ptr & 0xFFFFFFFF; + + // RAS-To-CAS (tRCD) + rcd = IMC_Register & 0x1F; + + // RAS Precharge (tRP) + rp = (IMC_Register >> 5) & 0x1F; + + // RAS Active to precharge (tRAS) + ras = (IMC_Register >> 10) & 0x3F; + + + print_ram_line(cas, rcd, rp, ras, chan); +} + +static void poll_timings_snbe(void) { + + float cas; + int rcd, rp, ras; + int nb_channel = 0, current_channel = 0; + ulong temp, IMC_Register; + long *ptr; + + //Read Channel #1 + pci_conf_read(0xFF, 16, 2, 0x80, 4, &temp); + temp &= 0x3F; + if(temp != 0xB) { current_channel = 0; nb_channel++; } + + //Read Channel #2 + pci_conf_read(0xFF, 16, 3, 0x80, 4, &temp); + temp &= 0x3F; + if(temp != 0xB) { current_channel = 1; nb_channel++; } + + //Read Channel #3 + pci_conf_read(0xFF, 16, 6, 0x80, 4, &temp); + temp &= 0x3F; + if(temp != 0xB) { current_channel = 4; nb_channel++; } + + //Read Channel #4 + pci_conf_read(0xFF, 16, 7, 0x80, 4, &temp); + temp &= 0x3F; + if(temp != 0xB) { current_channel = 5; nb_channel++; } + + + pci_conf_read(0, 5, 0, 0x84, 4, &temp); + ptr = (long*)((temp & 0xFC000000) + (MAKE_PCIE_ADDRESS(0xFF,16,current_channel) | 0x200)); + IMC_Register = *ptr & 0xFFFFFFFF; + + // CAS Latency (tCAS) + cas = (float)((IMC_Register >> 9) & 0x1F); + + // RAS-To-CAS (tRCD) + rcd = IMC_Register & 0x1F; + + // RAS Precharge (tRP) + rp = (IMC_Register >> 5) & 0x0F; + + // RAS Active to precharge (tRAS) + ras = (IMC_Register >> 19) & 0x3F; + + + print_ram_line(cas, rcd, rp, ras, nb_channel); + +} + +static void poll_timings_5400(void) { + + // Thanks for CDH optis + ulong ambase, mtr1, mtr2, offset, mca; + long *ptr; + float cas; + int rcd, rp, ras, chan; + + //Hard-coded Ambase value (should not be realocated by software when using Memtest86+ + ambase = 0xFE000000; + offset = mtr1 = mtr2 = 0; + + // Will loop until a valid populated channel is found + // Bug : DIMM 0 must be populated or it will fall in an endless loop + while(((mtr2 & 0xF) < 3) || ((mtr2 & 0xF) > 6)) { + ptr = (long*)(ambase+0x378+offset); + mtr1 = *ptr & 0xFFFFFFFF; + + ptr = (long*)(ambase+0x37C+offset); + mtr2 = *ptr & 0xFFFFFFFF; + offset += 0x8000; + } + + pci_conf_read( 0, 16, 1, 0x58, 4, &mca); + + //This chipset only supports FB-DIMM (Removed => too long) + //cprint(LINE_CPU+5, col +1, "- Type : FBD"); + + // Now, detect timings + + // CAS Latency (tCAS) + cas = mtr2 & 0xF; + + // RAS-To-CAS (tRCD) + rcd = 6 - ((mtr1 >> 10) & 3); + + // RAS Precharge (tRP) + rp = 6 - ((mtr1 >> 8) & 3); + + // RAS Active to precharge (tRAS) + ras = 16 - (3 * ((mtr1 >> 29) & 3)) + ((mtr1 >> 12) & 3); + if(((mtr1 >> 12) & 3) == 3 && ((mtr1 >> 29) & 3) == 2) { ras = 9; } + + + if ((mca >> 14) & 1) { + chan = 1; + } else { + chan = 2; + } + + print_ram_line(cas, rcd, rp, ras, chan); + +} + +static void poll_timings_E7520(void) { + + ulong drt, ddrcsr; + float cas; + int rcd, rp, ras, chan; + + pci_conf_read( 0, 0, 0, 0x78, 4, &drt); + pci_conf_read( 0, 0, 0, 0x9A, 2, &ddrcsr); + + cas = ((drt >> 2) & 3) + 2; + rcd = ((drt >> 10) & 1) + 3; + rp = ((drt >> 9) & 1) + 3; + ras = ((drt >> 14) & 3) + 11; + + if ((ddrcsr & 0xF) >= 0xC) { + chan = 2; + } else { + chan = 1; + } + + print_ram_line(cas, rcd, rp, ras, chan); +} + + +static void poll_timings_i855(void) { + + ulong drt, temp; + float cas; + int rcd, rp, ras; + + pci_conf_read( 0, 0, 0, 0x78, 4, &drt); + + /* Now, we could print some additionnals timings infos) */ + cprint(LINE_CPU+6, col2 +1, "/ CAS : "); + col2 += 9; + + // CAS Latency (tCAS) + temp = ((drt >> 4)&0x1); + if (temp == 0x0) { cas = 2.5; } + else { cas = 2; } + + // RAS-To-CAS (tRCD) + temp = ((drt >> 2)& 0x1); + if (temp == 0x0) { rcd = 3; } + else { rcd = 2; } + + // RAS Precharge (tRP) + temp = (drt&0x1); + if (temp == 0x0) { rp = 3 ; } + else { rp = 2; } + + // RAS Active to precharge (tRAS) + temp = 7-((drt >> 9)& 0x3); + if (temp == 0x0) { ras = 7; } + if (temp == 0x1) { ras = 6; } + if (temp == 0x2) { ras = 5; } + + print_ram_line(cas, rcd, rp, ras, 1); + +} + +static void poll_timings_E750x(void) { + + ulong drt, drc, temp; + float cas; + int rcd, rp, ras, chan; + + pci_conf_read( 0, 0, 0, 0x78, 4, &drt); + pci_conf_read( 0, 0, 0, 0x7C, 4, &drc); + + if ((drt >> 4) & 1) { cas = 2; } else { cas = 2.5; }; + if ((drt >> 1) & 1) { rcd = 2; } else { rcd = 3; }; + if (drt & 1) { rp = 2; } else { rp = 3; }; + + temp = ((drt >> 9) & 3); + if (temp == 2) { ras = 5; } else if (temp == 1) { ras = 6; } else { ras = 7; } + + if (((drc >> 22)&1) == 1) { + chan = 2; + } else { + chan = 1; + } + + print_ram_line(cas, rcd, rp, ras, chan); + +} + +static void poll_timings_i852(void) { + + ulong drt, temp; + float cas; + int rcd, rp, ras; + + pci_conf_read( 0, 0, 1, 0x60, 4, &drt); + + /* Now, we could print some additionnals timings infos) */ + cprint(LINE_CPU+6, col2 +1, "/ CAS : "); + col2 += 9; + + // CAS Latency (tCAS) + temp = ((drt >> 5)&0x1); + if (temp == 0x0) { cas = 2.5; } + else { cas = 2; } + + // RAS-To-CAS (tRCD) + temp = ((drt >> 2)& 0x3); + if (temp == 0x0) { rcd = 4; } + if (temp == 0x1) { rcd = 3; } + else { rcd = 2; } + + // RAS Precharge (tRP) + temp = (drt&0x3); + if (temp == 0x0) { rp = 4; } + if (temp == 0x1) { rp = 3; } + else { rp = 2; } + + // RAS Active to precharge (tRAS) + temp = ((drt >> 9)& 0x3); + if (temp == 0x0) { ras = 8; } + if (temp == 0x1) { ras = 7; } + if (temp == 0x2) { ras = 6; } + if (temp == 0x3) { ras = 5; } + + print_ram_line(cas, rcd, rp, ras, 1); + +} + +static void poll_timings_amd64(void) { + + ulong dramtlr, dramclr; + int temp, chan; + float tcas; + int trcd, trp, tras ; + + pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr); + pci_conf_read(0, 24, 2, 0x90, 4, &dramclr); + + if (cpu_id.vers.bits.extendedModel >= 4) { + /* NEW K8 0Fh Family 90 nm (DDR2) */ + + // CAS Latency (tCAS) + tcas = (dramtlr & 0x7) + 1; + + // RAS-To-CAS (tRCD) + trcd = ((dramtlr >> 4) & 0x3) + 3; + + // RAS Precharge (tRP) + trp = ((dramtlr >> 8) & 0x3) + 3; + + // RAS Active to precharge (tRAS) + tras = ((dramtlr >> 12) & 0xF) + 3; + + // Print 64 or 128 bits mode + if ((dramclr >> 11)&1) { + chan = 2; + } else { + chan = 1; + } + + } else { + /* OLD K8 (DDR1) */ + + // CAS Latency (tCAS) + temp = (dramtlr & 0x7); + if (temp == 0x1) { tcas = 2; } + if (temp == 0x2) { tcas = 3; } + if (temp == 0x5) { tcas = 2.5; } + + // RAS-To-CAS (tRCD) + trcd = ((dramtlr >> 12) & 0x7); + + // RAS Precharge (tRP) + trp = ((dramtlr >> 24) & 0x7); + + // RAS Active to precharge (tRAS) + tras = ((dramtlr >> 20) & 0xF); + + // Print 64 or 128 bits mode + if (((dramclr >> 16)&1) == 1) { + chan = 2; + } else { + chan = 1; + } + } + + print_ram_line(tcas, trcd, trp, tras, chan); + +} + +static void poll_timings_k10(void) { + + ulong dramtlr, dramclr, dramchr, dramchrb; + ulong offset = 0; + int cas, rcd, rp, ras, chan; + + pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); + pci_conf_read(0, 24, 2, 0x194, 4, &dramchrb); + + if(((dramchr>>14) & 0x1) || ((dramchr>>14) & 0x1)) { chan = 1; } else { chan = 2; } + + // If Channel A not enabled, switch to channel B + if(((dramchr>>14) & 0x1)) + { + offset = 0x100; + pci_conf_read(0, 24, 2, 0x94+offset, 4, &dramchr); + } + + pci_conf_read(0, 24, 2, 0x88+offset, 4, &dramtlr); + pci_conf_read(0, 24, 2, 0x110, 4, &dramclr); + + // CAS Latency (tCAS) + if(((dramchr >> 8)&1) || ((dramchr & 0x7) == 0x4)){ + // DDR3 or DDR2-1066 + cas = (dramtlr & 0xF) + 4; + rcd = ((dramtlr >> 4) & 0x7) + 5; + rp = ((dramtlr >> 7) & 0x7) + 5; + ras = ((dramtlr >> 12) & 0xF) + 15; + } else { + // DDR2-800 or less + cas = (dramtlr & 0xF) + 1; + rcd = ((dramtlr >> 4) & 0x3) + 3; + rp = ((dramtlr >> 8) & 0x3) + 3; + ras = ((dramtlr >> 12) & 0xF) + 3; + } + + print_ram_line(cas, rcd, rp, ras, chan); +} + +static void poll_timings_k12(void) { + + ulong dramt0, dramlow, dimma, dimmb; + int cas, rcd, rp, ras, chan = 0; + + pci_conf_read(0, 24, 2, 0x94, 4, &dimma); + pci_conf_read(0, 24, 2, 0x194, 4, &dimmb); + + if(((dimma >> 14) & 0x1) == 0) + { + chan++; + pci_conf_read(0, 24, 2, 0x88, 4, &dramlow); + pci_conf_write(0, 24, 2, 0xF0, 4, 0x00000040); + pci_conf_read(0, 24, 2, 0xF4, 4, &dramt0); + } + + if(((dimmb >> 14) & 0x1) == 0) + { + chan++; + pci_conf_read(0, 24, 2, 0x188, 4, &dramlow); + pci_conf_write(0, 24, 2, 0x1F0, 4, 0x00000040); + pci_conf_read(0, 24, 2, 0x1F4, 4, &dramt0); + } + + cas = (dramlow & 0xF) + 4; + rcd = (dramt0 & 0xF) + 5; + rp = ((dramt0 >> 8) & 0xF) + 5; + ras = ((dramt0 >> 16) & 0x1F) + 15; + + print_ram_line(cas, rcd, rp, ras, chan); +} + + +static void poll_timings_k14(void) { + + ulong dramt0, dramlow; + int cas, rcd, rp, ras; + + pci_conf_read(0, 24, 2, 0x88, 4, &dramlow); + pci_conf_write(0, 24, 2, 0xF0, 4, 0x00000040); + pci_conf_read(0, 24, 2, 0xF4, 4, &dramt0); + + cas = (dramlow & 0xF) + 4; + rcd = (dramt0 & 0xF) + 5; + rp = ((dramt0 >> 8) & 0xF) + 5; + ras = ((dramt0 >> 16) & 0x1F) + 15; + + print_ram_line(cas, rcd, rp, ras, 1); +} + +static void poll_timings_k15(void) { + + ulong dramp1, dramp2, dimma, dimmb; + int cas, rcd, rp, ras, chan = 0; + + pci_conf_read(0, 24, 2, 0x94, 4, &dimma); + pci_conf_read(0, 24, 2, 0x194, 4, &dimmb); + if(((dimma>>14) & 0x1) || ((dimmb>>14) & 0x1)) { chan = 1; } else { chan = 2; } + + pci_conf_read(0, 24, 2, 0x200, 4, &dramp1); + pci_conf_read(0, 24, 2, 0x204, 4, &dramp2); + + cas = dramp1 & 0x1F; + rcd = (dramp1 >> 8) & 0x1F; + rp = (dramp1 >> 16) & 0x1F; + ras = (dramp1 >> 24) & 0x3F; + + print_ram_line(cas, rcd, rp, ras, chan); +} + +static void poll_timings_k16(void) { + + ulong dramt0, dramt1; + int cas, rcd, rp, /*rc,*/ ras; + + pci_conf_read(0, 24, 2, 0x200, 4, &dramt0); + pci_conf_read(0, 24, 2, 0x204, 4, &dramt1); + + cas = (dramt0 & 0x1F); + rcd = ((dramt0 >> 8) & 0x1F); + rp = ((dramt0 >> 16) & 0x1F); + ras = ((dramt0 >> 24) & 0x3F); + + // rc = (dramt1 & 0x3F); + + print_ram_line(cas, rcd, rp, ras, 1); +} + +static void poll_timings_EP80579(void) { + + ulong drt1, drt2; + float cas; + int rcd, rp, ras; + + pci_conf_read( 0, 0, 0, 0x78, 4, &drt1); + pci_conf_read( 0, 0, 0, 0x64, 4, &drt2); + + cas = ((drt1 >> 3) & 0x7) + 3; + rcd = ((drt1 >> 9) & 0x7) + 3; + rp = ((drt1 >> 6) & 0x7) + 3; + ras = ((drt2 >> 28) & 0xF) + 8; + + print_ram_line(cas, rcd, rp, ras, 0); +} + +static void poll_timings_nf2(void) { + + ulong dramtlr, dramtlr2, dramtlr3, temp; + ulong dimm1p, dimm2p, dimm3p; + float cas; + int rcd, rp, ras, chan; + + pci_conf_read(0, 0, 1, 0x90, 4, &dramtlr); + pci_conf_read(0, 0, 1, 0xA0, 4, &dramtlr2); + pci_conf_read(0, 0, 1, 0x84, 4, &dramtlr3); + pci_conf_read(0, 0, 2, 0x40, 4, &dimm1p); + pci_conf_read(0, 0, 2, 0x44, 4, &dimm2p); + pci_conf_read(0, 0, 2, 0x48, 4, &dimm3p); + + // CAS Latency (tCAS) + temp = ((dramtlr2 >> 4) & 0x7); + if (temp == 0x2) { cas = 2; } + if (temp == 0x3) { cas = 3; } + if (temp == 0x6) { cas = 2.5; } + + // RAS-To-CAS (tRCD) + rcd = ((dramtlr >> 20) & 0xF); + + // RAS Precharge (tRP) + rp = ((dramtlr >> 28) & 0xF); + + // RAS Active to precharge (tRAS) + ras = ((dramtlr >> 15) & 0xF); + + // Print 64 or 128 bits mode + // If DIMM1 & DIMM3 or DIMM1 & DIMM2 populated, than Dual Channel. + + if ((dimm3p&1) + (dimm2p&1) == 2 || (dimm3p&1) + (dimm1p&1) == 2 ) { + chan = 2; + } else { + chan = 1; + } + print_ram_line(cas, rcd, rp, ras, chan); +} + +static void poll_timings_us15w(void) { + + // Thanks for CDH optis + ulong dtr; + float cas; + int rcd, rp; + + /* Find dramratio */ + /* D0 MsgRd, 01 Dunit, 01 DTR */ + pci_conf_write(0, 0, 0, 0xD0, 4, 0xD0010100 ); + pci_conf_read(0, 0, 0, 0xD4, 4, &dtr ); + + // CAS Latency (tCAS) + cas = ((dtr >> 4) & 0x3) + 3; + + // RAS-To-CAS (tRCD) + rcd = ((dtr >> 2) & 0x3) + 3; + + // RAS Precharge (tRP) + rp = ((dtr >> 0) & 0x3) + 3; + + print_ram_line(cas, rcd, rp, 9, 1); + +} + +static void poll_timings_nhm(void) { + + ulong mc_channel_bank_timing, mc_control, mc_channel_mrs_value; + float cas; + int rcd, rp, ras, chan; + int fvc_bn = 4; + + /* Find which channels are populated */ + pci_conf_read(nhm_bus, 3, 0, 0x48, 2, &mc_control); + mc_control = (mc_control >> 8) & 0x7; + + /* Get the first valid channel */ + if(mc_control & 1) { + fvc_bn = 4; + } else if(mc_control & 2) { + fvc_bn = 5; + } else if(mc_control & 4) { + fvc_bn = 6; + } + + // Now, detect timings + // CAS Latency (tCAS) / RAS-To-CAS (tRCD) / RAS Precharge (tRP) / RAS Active to precharge (tRAS) + pci_conf_read(nhm_bus, fvc_bn, 0, 0x88, 4, &mc_channel_bank_timing); + pci_conf_read(nhm_bus, fvc_bn, 0, 0x70, 4, &mc_channel_mrs_value); + cas = ((mc_channel_mrs_value >> 4) & 0xF ) + 4.0f; + rcd = (mc_channel_bank_timing >> 9) & 0xF; + ras = (mc_channel_bank_timing >> 4) & 0x1F; + rp = mc_channel_bank_timing & 0xF; + + // Print 1, 2 or 3 Channels + if (mc_control == 1 || mc_control == 2 || mc_control == 4 ) { + chan = 1; + } else if (mc_control == 7) { + chan = 3; + } else { + chan = 2; + } + print_ram_line(cas, rcd, rp, ras, chan); + +} + +static void poll_timings_ct(void) +{ + + unsigned long mcr,mdr; + float cas; + int rcd, rp, ras; + + /* Build the MCR Message*/ + mcr = (0x10 << 24); // 10h = Read - 11h = Write + mcr += (0x01 << 16); // DRAM Registers located on port 01h + mcr += (0x01 << 8); // DRP = 00h, DTR0 = 01h, DTR1 = 02h, DTR2 = 03h + mcr &= 0xFFFFFFF0; // bit 03:00 RSVD + + /* Send Message to GMCH */ + pci_conf_write(0, 0, 0, 0xD0, 4, mcr); + + /* Read Answer from Sideband bus */ + pci_conf_read(0, 0, 0, 0xD4, 4, &mdr); + + // CAS Latency (tCAS) + cas = ((mdr >> 12)& 0x7) + 5.0f; + + // RAS-To-CAS (tRCD) + rcd = ((mdr >> 8)& 0x7) + 5; + + // RAS Precharge (tRP) + rp = ((mdr >> 4)& 0x7) + 5; + + // RAS is in DTR1. Read Again. + mcr = 0x10010200; // Quick Mode ! Awesome ! + pci_conf_write(0, 0, 0, 0xD0, 4, mcr); + pci_conf_read(0, 0, 0, 0xD4, 4, &mdr); + + // RAS Active to precharge (tRAS) + ras = (mdr >> 20) & 0xF; + + // Print + print_ram_line(cas, rcd, rp, ras, 1); + +} + +/* ------------------ Let's continue ------------------ */ +/* ---------------------------------------------------- */ + +struct pci_memory_controller controllers[] = { + /* Default unknown chipset */ + { 0, 0, "","", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + + /* AMD */ + { 0x1022, 0x7006, "AMD 751","SDRAM PC-100", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd751, poll_nothing }, + { 0x1022, 0x700c, "AMD 762","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_nothing }, + { 0x1022, 0x700e, "AMD 761","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_nothing }, + + /* SiS */ + { 0x1039, 0x0600, "SiS 600","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0620, "SiS 620","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x5600, "SiS 5600","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0645, "SiS 645","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0646, "SiS 645DX","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0630, "SiS 630","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0650, "SiS 650","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0651, "SiS 651","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0730, "SiS 730","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0735, "SiS 735","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0740, "SiS 740","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0745, "SiS 745","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0748, "SiS 748","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0655, "SiS 655","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0656, "SiS 656","DDR/DDR2-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0648, "SiS 648","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0649, "SiS 649","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0661, "SiS 661","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0671, "SiS 671","DDR2-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1039, 0x0672, "SiS 672","DDR2-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + + /* ALi */ + { 0x10b9, 0x1531, "ALi Aladdin 4","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x10b9, 0x1541, "ALi Aladdin 5","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x10b9, 0x1644, "ALi Aladdin M1644","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + + /* ATi */ + { 0x1002, 0x5830, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1002, 0x5831, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1002, 0x5832, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1002, 0x5833, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1002, 0x5954, "ATi Xpress 200","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1002, 0x5A41, "ATi Xpress 200","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + + /* nVidia */ + { 0x10de, 0x01A4, "nVidia nForce","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x10de, 0x01E0, "nVidia nForce2 SPP","", 0, poll_fsb_nf2, poll_timings_nf2, setup_nothing, poll_nothing }, + { 0x10de, 0x0071, "nForce4 SLI","", 0, poll_fsb_nf4ie, poll_timings_nf4ie, setup_nothing, poll_nothing }, + + /* VIA */ + { 0x1106, 0x0305, "VIA KT133/KT133A","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0391, "VIA KX133","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0501, "VIA MVP4","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0585, "VIA VP/VPX","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0595, "VIA VP2","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0597, "VIA VP3","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0598, "VIA MVP3","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0691, "VIA Apollo Pro 133(A)","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0693, "VIA Apollo Pro+","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0601, "VIA PLE133","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x3099, "VIA KT266(A)/KT333","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x3189, "VIA KT400(A)/600","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0269, "VIA KT880","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x3205, "VIA KM400","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x3116, "VIA KM266","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x3156, "VIA KN266","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x3123, "VIA CLE266","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x0198, "VIA PT800","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x1106, 0x3258, "VIA PT880","DDR2-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + + /* Serverworks */ + { 0x1166, 0x0008, "CNB20HE","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing }, + { 0x1166, 0x0009, "CNB20LE","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing }, + + /* Intel */ + { 0x8086, 0x1130, "Intel i815","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x122d, "Intel i430FX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x1235, "Intel i430MX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x1237, "Intel i440FX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x1250, "Intel i430HX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x1A21, "Intel i840","RDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i840, poll_nothing }, + { 0x8086, 0x1A30, "Intel i845","SDR/DDR", 0, poll_fsb_p4, poll_timings_nothing, setup_i845, poll_nothing }, + { 0x8086, 0x2560, "Intel i845E/G/PE/GE","", 0, poll_fsb_p4, poll_timings_nothing, setup_i845, poll_nothing }, + { 0x8086, 0x2500, "Intel i820","RDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i820, poll_nothing }, + { 0x8086, 0x2530, "Intel i850","RDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_i850, poll_nothing }, + { 0x8086, 0x2531, "Intel i860","RDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i860, poll_nothing }, + { 0x8086, 0x7030, "Intel i430VX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x7100, "Intel i430TX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x7120, "Intel i810","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x7122, "Intel i810","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x7124, "Intel i810E","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x7180, "Intel i440[LE]X","SDRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x7190, "Intel i440BX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x7192, "Intel i440BX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x71A0, "Intel i440GX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_nothing }, + { 0x8086, 0x71A2, "Intel i440GX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_nothing }, + { 0x8086, 0x84C5, "Intel i450GX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x2540, "Intel E7500","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_nothing }, + { 0x8086, 0x254C, "Intel E7501","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_nothing }, + { 0x8086, 0x255d, "Intel E7205","DDR-SDRAM",0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_nothing }, + { 0x8086, 0x3592, "Intel E7320","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E7520, setup_iE7520, poll_nothing }, + { 0x8086, 0x2588, "Intel E7221","DDR-SDRAM",0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing }, + { 0x8086, 0x3590, "Intel E7520","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E7520, setup_iE7520, poll_nothing }, + { 0x8086, 0x2600, "Intel E8500","DDR-SDRAM",0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, + { 0x8086, 0x2570, "Intel i848/i865","", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_nothing }, + { 0x8086, 0x2578, "Intel i875P","", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_nothing }, + { 0x8086, 0x2550, "Intel E7505","DDR-SDRAM",0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_nothing }, + { 0x8086, 0x3580, "Intel i852P/i855G","", 0, poll_fsb_i855, poll_timings_i852, setup_nothing, poll_nothing }, + { 0x8086, 0x3340, "Intel i855PM","", 0, poll_fsb_i855, poll_timings_i855, setup_nothing, poll_nothing }, + { 0x8086, 0x2580, "Intel i915P/G","", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing }, + { 0x8086, 0x2590, "Intel i915PM/GM","", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing }, + { 0x8086, 0x2584, "Intel i925X/XE","", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing }, + { 0x8086, 0x2770, "Intel i945P/G","", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing }, + { 0x8086, 0x27A0, "Intel i945GM/PM","", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing }, + { 0x8086, 0x27AC, "Intel i945GME","", 0, poll_fsb_i945gme, poll_timings_i925, setup_i925, poll_nothing }, + { 0x8086, 0x2774, "Intel i955X","", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing}, + { 0x8086, 0x277C, "Intel i975X","", 0, poll_fsb_i975, poll_timings_i925, setup_i925, poll_nothing}, + { 0x8086, 0x2970, "Intel i946PL/GZ","", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing}, + { 0x8086, 0x2990, "Intel Q963/Q965","", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing}, + { 0x8086, 0x29A0, "Intel P965/G965","", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing}, + { 0x8086, 0x2A00, "Intel GM965/GL960","", 0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing}, + { 0x8086, 0x2A10, "Intel GME965/GLE960","", 0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing}, + { 0x8086, 0x2A40, "Intel PM/GM45/47","", 0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing}, + { 0x8086, 0x29B0, "Intel Q35","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, + { 0x8086, 0x29C0, "Intel P35/G33","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, + { 0x8086, 0x29D0, "Intel Q33","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, + { 0x8086, 0x29E0, "Intel X38/X48","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, + { 0x8086, 0x29F0, "Intel 3200/3210","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, + { 0x8086, 0x2E10, "Intel Q45/Q43","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, + { 0x8086, 0x2E20, "Intel P45/G45","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, + { 0x8086, 0x2E30, "Intel G41","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, + { 0x8086, 0x4001, "Intel 5400A","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, + { 0x8086, 0x4003, "Intel 5400B","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, + { 0x8086, 0x25D8, "Intel 5000P","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, + { 0x8086, 0x25D4, "Intel 5000V","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, + { 0x8086, 0x25C0, "Intel 5000X","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, + { 0x8086, 0x25D0, "Intel 5000Z","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, + { 0x8086, 0x5020, "Intel EP80579","", 0, poll_fsb_p4, poll_timings_EP80579, setup_nothing, poll_nothing }, + { 0x8086, 0x8100, "Intel US15W","", 0, poll_fsb_us15w, poll_timings_us15w, setup_nothing, poll_nothing}, + { 0x8086, 0x8101, "Intel UL11L/US15L","", 0, poll_fsb_us15w, poll_timings_us15w, setup_nothing, poll_nothing}, + + /* INTEL IMC (Integrated Memory Controllers) */ + { 0xFFFF, 0x0001, "Core IMC","", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing}, + { 0xFFFF, 0x0002, "Core IMC","", 0, poll_fsb_nhm32, poll_timings_nhm, setup_nhm32, poll_nothing}, + { 0xFFFF, 0x0003, "Core IMC","", 0, poll_fsb_wmr, poll_timings_wmr, setup_wmr, poll_nothing}, + { 0xFFFF, 0x0004, "SNB IMC","", 0, poll_fsb_snb, poll_timings_snb, setup_wmr, poll_nothing}, + { 0xFFFF, 0x0005, "SNB-E IMC","", 0, poll_fsb_snbe, poll_timings_snbe, setup_wmr, poll_nothing}, + { 0xFFFF, 0x0006, "IVB IMC","", 0, poll_fsb_ivb, poll_timings_snb, setup_wmr, poll_nothing}, + { 0xFFFF, 0x0007, "HSW IMC","", 0, poll_fsb_ivb, poll_timings_hsw, setup_wmr, poll_nothing}, + { 0xFFFF, 0x0008, "PineView IMC","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, + { 0xFFFF, 0x0009, "CedarTrail IMC","", 0, poll_fsb_ct, poll_timings_ct, setup_nothing, poll_nothing}, + + /* AMD IMC (Integrated Memory Controllers) */ + { 0xFFFF, 0x0100, "AMD K8 IMC","", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_nothing }, + { 0xFFFF, 0x0101, "AMD K10 IMC","", 0, poll_fsb_k10, poll_timings_k10, setup_k10, poll_nothing }, + { 0xFFFF, 0x0102, "AMD K12 IMC","", 0, poll_fsb_k12, poll_timings_k12, setup_apu, poll_nothing }, + { 0xFFFF, 0x0103, "AMD K14 IMC","", 0, poll_fsb_k14, poll_timings_k14, setup_apu, poll_nothing }, + { 0xFFFF, 0x0104, "AMD K15 IMC","", 0, poll_fsb_k15, poll_timings_k15, setup_apu, poll_nothing }, + { 0xFFFF, 0x0105, "AMD K16 IMC","", 0, poll_fsb_k16, poll_timings_k16, setup_apu, poll_nothing } +}; + +static void print_memory_controller(void) +{ + + /* Print memory controller info */ + if (ctrl.index == 0) { + return; + } + + /* Now print the memory controller capabilities */ + /* + cprint(LINE_CPU+5, col, " "); col++; + if (ctrl.cap == ECC_UNKNOWN) { + return; + } + if (ctrl.cap & __ECC_DETECT) { + int on; + on = ctrl.mode & __ECC_DETECT; + cprint(LINE_CPU+5, col, "(ECC : "); + cprint(LINE_CPU+5, col +7, on?"Detect":"Disabled)"); + on?(col += 13):(col += 16); + } + if (ctrl.mode & __ECC_CORRECT) { + int on; + on = ctrl.mode & __ECC_CORRECT; + cprint(LINE_CPU+5, col, " / "); + if (ctrl.cap & __ECC_CHIPKILL) { + cprint(LINE_CPU+5, col +3, on?"Correct -":""); + on?(col += 12):(col +=3); + } else { + cprint(LINE_CPU+5, col +3, on?"Correct)":""); + on?(col += 11):(col +=3); + } + } + if (ctrl.mode & __ECC_DETECT) { + if (ctrl.cap & __ECC_CHIPKILL) { + int on; + on = ctrl.mode & __ECC_CHIPKILL; + cprint(LINE_CPU+5, col, " Chipkill : "); + cprint(LINE_CPU+5, col +12, on?"On)":"Off)"); + on?(col += 15):(col +=16); + }} + if (ctrl.mode & __ECC_SCRUB) { + int on; + on = ctrl.mode & __ECC_SCRUB; + cprint(LINE_CPU+5, col, " Scrub"); + cprint(LINE_CPU+5, col +6, on?"+ ":"- "); + col += 7; + } + if (ctrl.cap & __ECC_UNEXPECTED) { + int on; + on = ctrl.mode & __ECC_UNEXPECTED; + cprint(LINE_CPU+5, col, "Unknown"); + cprint(LINE_CPU+5, col +7, on?"+ ":"- "); + col += 9; + } + */ + + + + /* Print advanced caracteristics */ + col2 = 0; + + controllers[ctrl.index].poll_fsb(); + controllers[ctrl.index].poll_timings(); + +} + + +void find_controller(void) +{ + unsigned long vendor; + unsigned long device; + int i; + int result; + result = pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, PCI_VENDOR_ID, 2, &vendor); + result = pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, PCI_DEVICE_ID, 2, &device); + + // Detect IMC by CPUID + if(imc_type) { vendor = 0xFFFF; device = imc_type; } + if(vv->fail_safe & 1) { vendor = 0xFFFF; device = 0xFFFF; } + + //hprint(11,0,vendor); hprint(11,10,device); + + ctrl.index = 0; + if (result == 0 || imc_type) { + for(i = 1; i < sizeof(controllers)/sizeof(controllers[0]); i++) { + if ((controllers[i].vendor == vendor) && (controllers[i].device == device)) { + ctrl.index = i; + break; + } + } + } + + controllers[ctrl.index].setup_ecc(); + /* Don't enable ECC polling by default unless it has + * been well tested. + */ + //set_ecc_polling(-1); + print_memory_controller(); + + if(imc_type) { print_dmi_startup_info(); } + +} + +void poll_errors(void) +{ + if (ctrl.poll) { + controllers[ctrl.index].poll_errors(); + } +} + +/* + void set_ecc_polling(int val) + { + int tested = controllers[ctrl.index].tested; + if (val == -1) { + val = tested; + } + if (val && (ctrl.mode & __ECC_DETECT)) { + ctrl.poll = 1; + cprint(LINE_INFO, COL_ECC, tested? " on": " ON"); + } else { + ctrl.poll = 0; + cprint(LINE_INFO, COL_ECC, "off"); + } + } +*/ + diff --git a/memtestEDK/Memtest/SingleComponents/controller.h b/memtestEDK/Memtest/SingleComponents/controller.h new file mode 100644 index 0000000..da64ef1 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/controller.h @@ -0,0 +1,23 @@ +#ifndef MEMTEST_CONTROLLER_H +#define MEMTEST_CONTROLLER_H + +struct pci_memory_controller { + unsigned vendor; + unsigned device; + char *name; + char *ram_type; + int tested; + void (*poll_fsb)(void); + void (*poll_timings)(void); + void (*setup_ecc)(void); + void (*poll_errors)(void); +}; + +void find_controller(void); +void poll_errors(void); +void set_ecc_polling(int val); +void coretemp(void); +extern struct pci_memory_controller controllers[]; + + +#endif /* MEMTEST_CONTROLLER_H */ diff --git a/memtestEDK/Memtest/SingleComponents/cpuid.c b/memtestEDK/Memtest/SingleComponents/cpuid.c new file mode 100644 index 0000000..4c25ede --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/cpuid.c @@ -0,0 +1,87 @@ +/* + * cpuid.c -- + * + * Implements CPUID querying functions + * + */ +#include "stdin.h" +#include "cpuid.h" + +struct cpu_ident cpu_id; + +void get_cpuid() +{ + unsigned int *v, dummy[3]; + char *p, *q; + + /* Get max std cpuid & vendor ID */ + cpuid(0x0, &cpu_id.max_cpuid, &cpu_id.vend_id.uint32_array[0], + &cpu_id.vend_id.uint32_array[2], &cpu_id.vend_id.uint32_array[1]); + cpu_id.vend_id.char_array[11] = 0; + + /* Get processor family information & feature flags */ + if (cpu_id.max_cpuid >= 1) { + cpuid(0x00000001, &cpu_id.vers.flat, &cpu_id.info.flat, + &cpu_id.fid.uint32_array[1], &cpu_id.fid.uint32_array[0]); + } + + /* Get the digital thermal sensor & power management status bits */ + if(cpu_id.max_cpuid >= 6) { + cpuid(0x00000006, &cpu_id.dts_pmp, &dummy[0], &dummy[1], &dummy[2]); + } + + /* Get the max extended cpuid */ + cpuid(0x80000000, &cpu_id.max_xcpuid, &dummy[0], &dummy[1], &dummy[2]); + + /* Get extended feature flags, only save EDX */ + if (cpu_id.max_xcpuid >= 0x80000001) { + cpuid(0x80000001, &dummy[0], &dummy[1], + &dummy[2], &cpu_id.fid.uint32_array[2]); + } + + /* Get the brand ID */ + if (cpu_id.max_xcpuid >= 0x80000004) { + v = (unsigned int *)&cpu_id.brand_id; + cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]); + cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]); + cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); + cpu_id.brand_id.char_array[47] = 0; + } + /* + * Intel chips right-justify this string for some dumb reason; + * undo that brain damage: + */ + p = q = &cpu_id.brand_id.char_array[0]; + while (*p == ' ') + p++; + if (p != q) { + while (*p) + *q++ = *p++; + while (q <= &cpu_id.brand_id.char_array[48]) + *q++ = '\0'; /* Zero-pad the rest */ + } + + /* Get cache information */ + switch(cpu_id.vend_id.char_array[0]) { + case 'A': + /* AMD Processors */ + /* The cache information is only in ecx and edx so only save + * those registers */ + if (cpu_id.max_xcpuid >= 0x80000005) { + cpuid(0x80000005, &dummy[0], &dummy[1], + &cpu_id.cache_info.uint[0], &cpu_id.cache_info.uint[1]); + } + if (cpu_id.max_xcpuid >= 0x80000006) { + cpuid(0x80000006, &dummy[0], &dummy[1], + &cpu_id.cache_info.uint[2], &cpu_id.cache_info.uint[3]); + } + break; + case 'G': + /* Intel Processors, Need to do this in init.c */ + break; + } + + /* Turn off mon bit since monitor based spin wait may not be reliable */ + cpu_id.fid.bits.mon = 0; + +} diff --git a/memtestEDK/Memtest/SingleComponents/cpuid.h b/memtestEDK/Memtest/SingleComponents/cpuid.h new file mode 100644 index 0000000..0460315 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/cpuid.h @@ -0,0 +1,204 @@ +#ifndef CPUID_H_ +#define CPUID_H_ + +#include "stdin.h" + +/* + * cpuid.h -- + * contains the data structures required for CPUID + * implementation. + */ + +#define CPUID_VENDOR_LENGTH 3 /* 3 GPRs hold vendor ID */ +#define CPUID_VENDOR_STR_LENGTH (CPUID_VENDOR_LENGTH * sizeof(uint32_t) + 1) +#define CPUID_BRAND_LENGTH 12 /* 12 GPRs hold vendor ID */ +#define CPUID_BRAND_STR_LENGTH (CPUID_BRAND_LENGTH * sizeof(uint32_t) + 1) + +extern struct cpu_ident cpu_id; + +static inline void __cpuid(unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + /* ecx is often an input as well as an output. */ + asm volatile("\t" + "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" + : "=a" (*eax), + "=D" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (*eax), "2" (*ecx)); +} + +static inline void cpuid(unsigned int op, + unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + *eax = op; + *ecx = 0; + __cpuid(eax, ebx, ecx, edx); +} + +/* Some CPUID calls want 'count' to be placed in ecx */ +static inline void cpuid_count(unsigned int op, int count, + unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + *eax = op; + *ecx = count; + __cpuid(eax, ebx, ecx, edx); +} + +/* Typedef for storing the Cache Information */ +typedef union { + unsigned char ch[48]; + uint32_t uint[12]; + struct { + uint32_t fill1:24; /* Bit 0 */ + uint32_t l1_i_sz:8; + uint32_t fill2:24; + uint32_t l1_d_sz:8; + uint32_t fill3:16; + uint32_t l2_sz:16; + uint32_t fill4:18; + uint32_t l3_sz:14; + uint32_t fill5[8]; + } amd; +} cpuid_cache_info_t; + +/* Typedef for storing the CPUID Vendor String */ +typedef union { + /* Note: the extra byte in the char array is for '\0'. */ + char char_array[CPUID_VENDOR_STR_LENGTH]; + uint32_t uint32_array[CPUID_VENDOR_LENGTH]; +} cpuid_vendor_string_t; + +/* Typedef for storing the CPUID Brand String */ +typedef union { + /* Note: the extra byte in the char array is for '\0'. */ + char char_array[CPUID_BRAND_STR_LENGTH]; + uint32_t uint32_array[CPUID_BRAND_LENGTH]; +} cpuid_brand_string_t; + +/* Typedef for storing CPUID Version */ +typedef union { + uint32_t flat; + struct { + uint32_t stepping:4; /* Bit 0 */ + uint32_t model:4; + uint32_t family:4; + uint32_t processorType:2; + uint32_t reserved1514:2; + uint32_t extendedModel:4; + uint32_t extendedFamily:8; + uint32_t reserved3128:4; /* Bit 31 */ + } bits; +} cpuid_version_t; + +/* Typedef for storing CPUID Processor Information */ +typedef union { + uint32_t flat; + struct { + uint32_t brandIndex:8; /* Bit 0 */ + uint32_t cflushLineSize:8; + uint32_t logicalProcessorCount:8; + uint32_t apicID:8; /* Bit 31 */ + } bits; +} cpuid_proc_info_t; + +/* Typedef for storing CPUID Feature flags */ +typedef union { + uint32_t flat; + struct { + uint32_t :1; + } bits; +} cpuid_custom_features; + +/* Typedef for storing CPUID Feature flags */ +typedef union { + uint32_t uint32_array[3]; + struct { + uint32_t fpu:1; /* EDX feature flags, bit 0 */ + uint32_t vme:1; + uint32_t de:1; + uint32_t pse:1; + uint32_t rdtsc:1; + uint32_t msr:1; + uint32_t pae:1; + uint32_t mce:1; + uint32_t cx8:1; + uint32_t apic:1; + uint32_t bit10:1; + uint32_t sep:1; + uint32_t mtrr:1; + uint32_t pge:1; + uint32_t mca:1; + uint32_t cmov:1; + uint32_t pat:1; + uint32_t pse36:1; + uint32_t psn:1; + uint32_t cflush:1; + uint32_t bit20:1; + uint32_t ds:1; + uint32_t acpi:1; + uint32_t mmx:1; + uint32_t fxsr:1; + uint32_t sse:1; + uint32_t sse2:1; + uint32_t ss:1; + uint32_t htt:1; + uint32_t tm:1; + uint32_t bit30:1; + uint32_t pbe:1; /* EDX feature flags, bit 31 */ + uint32_t sse3:1; /* ECX feature flags, bit 0 */ + uint32_t mulq:1; + uint32_t bit2:1; + uint32_t mon:1; + uint32_t dscpl:1; + uint32_t vmx:1; + uint32_t smx:1; + uint32_t eist:1; + uint32_t tm2:1; + uint32_t bits_9_31:23; + uint32_t bits0_28:29; /* EDX extended feature flags, bit 0 */ + uint32_t lm:1; /* Long Mode */ + uint32_t bits_30_31:2; /* EDX extended feature flags, bit 32 */ + } bits; +} cpuid_feature_flags_t; + +/* An overall structure to cache all of the CPUID information */ +struct cpu_ident { + uint32_t max_cpuid; + uint32_t max_xcpuid; + uint32_t dts_pmp; + cpuid_version_t vers; + cpuid_proc_info_t info; + cpuid_feature_flags_t fid; + cpuid_vendor_string_t vend_id; + cpuid_brand_string_t brand_id; + cpuid_cache_info_t cache_info; + cpuid_custom_features custom; +}; + +struct cpuid4_eax { + uint32_t ctype:5; + uint32_t level:3; + uint32_t is_self_initializing:1; + uint32_t is_fully_associative:1; + uint32_t reserved:4; + uint32_t num_threads_sharing:12; + uint32_t num_cores_on_die:6; +}; + +struct cpuid4_ebx { + uint32_t coherency_line_size:12; + uint32_t physical_line_partition:10; + uint32_t ways_of_associativity:10; +}; + +struct cpuid4_ecx { + uint32_t number_of_sets:32; +}; + +void get_cpuid(); + +#endif // CPUID_H_ diff --git a/memtestEDK/Memtest/SingleComponents/defs.h b/memtestEDK/Memtest/SingleComponents/defs.h new file mode 100644 index 0000000..1b77f2c --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/defs.h @@ -0,0 +1,26 @@ +/* defs.h - MemTest-86 Version 3.3 + * assembler/compiler definitions + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + */ + +#define SETUPSECS 4 /* Number of setup sectors */ + +/* + * Caution!! There is magic in the build process. Read + * README.build-process before you change anything. + * Unlike earlier versions all of the settings are in defs.h + * so the build process should be more robust. + */ +#define LOW_TEST_ADR 0x00010000 /* Final adrs for test code */ + +#define BOOTSEG 0x07c0 /* Segment adrs for initial boot */ +#define INITSEG 0x9000 /* Segment adrs for relocated boot */ +#define SETUPSEG (INITSEG+0x20) /* Segment adrs for relocated setup */ +#define TSTLOAD 0x1000 /* Segment adrs for load of test */ + +#define KERNEL_CS 0x10 /* 32 bit segment adrs for code */ +#define KERNEL_DS 0x18 /* 32 bit segment adrs for data */ +#define REAL_CS 0x20 /* 16 bit segment adrs for code */ +#define REAL_DS 0x28 /* 16 bit segment adrs for data */ diff --git a/memtestEDK/Memtest/SingleComponents/dmi.c b/memtestEDK/Memtest/SingleComponents/dmi.c new file mode 100644 index 0000000..0b1a4e0 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/dmi.c @@ -0,0 +1,439 @@ +/* dmi.c using the DMI from SMBIOS to read information about the hardware's + * memory devices capabilities and where they are mapped into the address space + * + * Copyright (c) Joachim Deguara, AMD 2006 + * + * Release under the GPL version 2 + * ---------------------------------------------------- + * Memtest86+ V4.00 - Added compliance with SMBIOS Spec V2.6.1 + */ + + +#include "test.h" +#include "stdint.h" +#include "environment.h" + +#define round_up(x,y) (((x) + (y) - 1) & ~((y)-1)) +#define round_down(x,y) ((x) & ~((y)-1)) + +struct dmi_eps { + uint8_t anchor[4]; + int8_t checksum; + uint8_t length; + uint8_t majorversion; + uint8_t minorversion; + uint16_t maxstructsize; + uint8_t revision; + uint8_t pad[5]; + uint8_t intanchor[5]; + int8_t intchecksum; + uint16_t tablelength; + uint32_t tableaddress; + uint16_t numstructs; + uint8_t SMBIOSrev; +} __attribute__((packed)); + +struct tstruct_header{ + uint8_t type; + uint8_t length; + uint16_t handle; +} __attribute__((packed)); + +struct system_map { + struct tstruct_header header; + uint8_t manufacturer; + uint8_t productname; + uint8_t version; + uint8_t serialnumber; + uint8_t uuidbytes[16]; + uint8_t wut; +} __attribute__((packed)); + +struct cpu_map { + struct tstruct_header header; + uint8_t cpu_socket; + uint8_t cpu_type; + uint8_t cpu_family; + uint8_t cpu_manufacturer; + uint32_t cpu_id; + uint8_t cpu_version; + uint8_t cpu_voltage; + uint16_t ext_clock; + uint16_t max_speed; + uint16_t cur_speed; + uint8_t cpu_status; + uint8_t cpu_upgrade; + uint16_t l1_handle; + uint16_t l2_handle; + uint16_t l3_handle; + uint8_t cpu_serial; + uint8_t cpu_asset_tag; + uint8_t cpu_part_number; + uint8_t core_count; + uint8_t core_enabled; + uint8_t thread_count; + uint16_t cpu_specs; + uint16_t cpu_family_2; +} __attribute__((packed)); + +struct mem_dev { + struct tstruct_header header; + uint16_t pma_handle; + uint16_t err_handle; + uint16_t tot_width; + uint16_t dat_width; + uint16_t size; + uint8_t form; + uint8_t set; + uint8_t dev_locator; + uint8_t bank_locator; + uint8_t type; + uint16_t typedetail; + uint16_t speed; + uint8_t manufacturer; + uint8_t serialnum; + uint8_t asset; + uint8_t partnum; + uint8_t attributes; + uint8_t ext_size; + uint8_t conf_ram_speed; + uint8_t min_voltage; + uint8_t max_votage; + uint8_t conf_voltage; +} __attribute__((packed)); + +struct md_map{ + struct tstruct_header header; + uint32_t start; + uint32_t end; + uint16_t md_handle; + uint16_t mama_handle; + uint8_t row_pos; + uint8_t interl_pos; + uint8_t interl_depth; +} __attribute__((packed)); + +struct pma{ + struct tstruct_header header; + uint8_t location; + uint8_t use; + uint8_t ecc; + uint32_t capacity; + uint16_t errhandle; + uint16_t numdevs; +} __attribute__((packed)); + +static char *form_factors[] = { + "?", + "Other", "Unknown", "SIMM", "SIP", "Chip", "DIP", "ZIP", + "Proprietary Card", "DIMM", "TSOP", "Row of chips", "RIMM", + "SODIMM", "SRIMM", "FB-DIMM", "Die" +}; + + +static char *memory_types[] = { + "?", + "Other", "????", "DRAM", "EDRAM", "VRAM", "SRAM", "RAM", + "ROM", "FLASH", "EEPROM", "FEPROM", "EPROM", "CDRAM", "3DRAM", + "SDRAM", "SGRAM", "RDRAM", "DDR", "DDR2", "DDR2 FB", "RSVD", + "RSVD","RSVD","DDR3","FBD2", "DDR4", "LPDDR", "LPDDR2", "LPDDR3", + "LPDDR4", "LNVD", "HBM", "HBM2", "DDR5", "LPDDR5" +}; + + +struct mem_dev * mem_devs[MAX_DMI_MEMDEVS]; +int mem_devs_count=0; +struct md_map * md_maps[MAX_DMI_MEMDEVS]; +struct system_map * dmi_system_info; +struct cpu_map * dmi_cpu_info; +int md_maps_count=0; +int dmi_err_cnts[MAX_DMI_MEMDEVS]; +short dmi_initialized=0; + +char * get_tstruct_string(struct tstruct_header *header, int n){ + if(n<1) + return 0; + char * a = (char *)header + header->length; + n--; + do{ + if (!*a) + n--; + if (!n && *a) + return a; + a++; + }while (!(*a==0 && *(a-1)==0)); + return 0; +} + + +int open_dmi(void){ + char *dmi, *dmi_search_start, *dmi_start; + int found=0; + struct dmi_eps *eps; + char *table_start; + int tstruct_count=0; + dmi_search_start = (char *)DMI_SEARCH_START; + + //find anchor + for(dmi = dmi_search_start; dmi < dmi_search_start + 0xf0000; dmi +=16){ + if( *dmi == '_' && + *(dmi+1) == 'S' && + *(dmi+2) == 'M' && + *(dmi+3) == '_'){ + found =1; + break; + } + } + if (!found) { + return -1; + } + dmi_start=dmi; + eps=(struct dmi_eps *)dmi; + + //check checksum + int8_t checksum=0; + for (; dmi < dmi_start + eps->length; dmi++) + checksum += *dmi; + if (checksum){ + return -1; + } + + //we need at least revision 2.1 of SMBIOS + if ( eps->majorversion < 2 && + eps->minorversion < 1){ + return -1; + } + + table_start=(char *)(MAX_BLOCK_SIZE)eps->tableaddress; + dmi=table_start; +//look at all structs + while(dmi < table_start + eps->tablelength){ + struct tstruct_header *header = (struct tstruct_header *)dmi; + + if (header->type == 17) + mem_devs[mem_devs_count++] = (struct mem_dev *)dmi; + + // Mem Dev Map + if (header->type == 20) + md_maps[md_maps_count++] = (struct md_map *)dmi; + + // MB_SPEC + if (header->type == 2) + { + dmi_system_info = (struct system_map *)dmi; + } + + // CPU_SPEC + if (header->type == 4) + { + dmi_cpu_info = (struct cpu_map *)dmi; + } + + dmi+=header->length; + + while( ! (*dmi == 0 && *(dmi+1) == 0 ) ) + dmi++; + dmi+=2; + + if (++tstruct_count > eps->numstructs) + return -1; + } + return 0; +} + +void init_dmi(void){ + int i; + for(i=0; i < MAX_DMI_MEMDEVS; i++) + dmi_err_cnts[i]=0; + open_dmi(); + dmi_initialized=1; +} + +void print_dmi_startup_info(void) +{ + char *string1; + char *string2; + char *string3; + int dmicol = 78; + int slenght; + int sl1, sl2, sl3; + + if(!dmi_initialized) { init_dmi(); } + + string1 = get_tstruct_string(&dmi_system_info->header,dmi_system_info->manufacturer); + sl1 = mt86_strlen(string1); + string2 = get_tstruct_string(&dmi_system_info->header,dmi_system_info->productname); + sl2 = mt86_strlen(string2); + string3 = get_tstruct_string(&dmi_cpu_info->header,dmi_cpu_info->cpu_socket); + sl3 = mt86_strlen(string3); + + slenght = sl1 + sl2; + if(sl3 > 2) { slenght += sl3 + 4; } else { slenght++; } + + if(sl1 && sl2) + { + //dmicol -= slenght; // right align + dmicol = 39 - slenght/2; // center align + cprint(LINE_DMI, dmicol, string1); + dmicol += sl1 + 1; + cprint(LINE_DMI, dmicol, string2); + dmicol += sl2 + 1; + + if(sl3 > 2){ + cprint(LINE_DMI, dmicol, "("); + dmicol++; + cprint(LINE_DMI, dmicol, string3); + dmicol += sl3; + cprint(LINE_DMI, dmicol, ")"); + } + } +} + +void print_dmi_info(void){ + int i,j,page; + char * string=0; + + if(!dmi_initialized) + init_dmi(); + + if (mem_devs_count == 0){ + cprint(POP2_Y+1, POP2_X+2, "No valid DMI Memory Devices info found"); + while (get_key() == 0); + return; + } + + for(page=1; page <= 1 + (mem_devs_count-1)/8; page++){ + pop2clear(); + cprint(POP2_Y+1, POP2_X+2, "DMI Memory Device Info (page "); + itoa(string,page); + cprint(POP2_Y+1, POP2_X+32, string); + cprint(POP2_Y+1, POP2_X+33, "/"); + itoa(string,1 + (mem_devs_count-1)/8); + cprint(POP2_Y+1, POP2_X+34, string); + cprint(POP2_Y+1, POP2_X+35, ")"); + + cprint(POP2_Y+3, POP2_X+4, "Location Size(MB) Speed(MHz) Type Form"); + cprint(POP2_Y+4, POP2_X+4, "--------------------------------------------------------------"); + + for(i=8*(page-1); i<mem_devs_count && i<8*page; i++){ + int size_in_mb; + int yof; + + yof = POP2_Y+5+2*(i-8*(page-1)); + cprint(yof, POP2_X+4, get_tstruct_string(&(mem_devs[i]->header), mem_devs[i]->dev_locator)); + + if (mem_devs[i]->size == 0){ + cprint(yof, POP2_X+4+18, "Empty"); + }else if (mem_devs[i]->size == 0xFFFF){ + cprint(yof, POP2_X+4+18, "Unknown"); + }else if (mem_devs[i]->size == 0x7FFF){ + // SMBIOS 2.7+ + size_in_mb = mem_devs[i]->ext_size; + itoa(string, size_in_mb); + cprint(yof, POP2_X+4+18, string); + }else{ + size_in_mb = 0xFFFF & mem_devs[i]->size; + if (mem_devs[i]->size & 0x8000) + size_in_mb <<= 10; + itoa(string, size_in_mb); + cprint(yof, POP2_X+4+18, string); + } + + //this is the only field that needs to be SMBIOS 2.3+ + if ( mem_devs[i]->speed && + mem_devs[i]->header.length > 21){ + itoa(string, mem_devs[i]->speed); + cprint(yof, POP2_X+4+27, string); + }else{ + cprint(yof, POP2_X+4+27, "Unknown"); + } + cprint(yof, POP2_X+4+37, memory_types[mem_devs[i]->type]); + cprint(yof, POP2_X+4+44, form_factors[mem_devs[i]->form]); + + //print mappings + int mapped=0,of=0; + cprint(yof+1, POP2_X+6,"mapped to: "); + for(j=0; j<md_maps_count; j++) + { + if (mem_devs[i]->header.handle != md_maps[j]->md_handle) + continue; + if (mapped++){ + cprint(yof+1, POP2_X+17+of, ","); + of++; + } + hprint3(yof+1, POP2_X+17+of, md_maps[j]->start>>22, 4); + of += 4; + hprint3(yof+1, POP2_X+17+of, md_maps[j]->start<<10, 8); + of += 8; + cprint(yof+1, POP2_X+17+of, "-"); + of++; + hprint3(yof+1, POP2_X+17+of, md_maps[j]->end>>22, 4); + of += 4; + hprint3(yof+1, POP2_X+17+of, ((md_maps[j]->end+1)<<10) - 1, 8); + of += 8; + if(md_maps[j]->end == 0) { hprint3(yof+1, POP2_X+17+of-8,0,8); } + } + if (!mapped) + { + cprint(yof+1, POP2_X+17, "No mapping (Interleaved Device)"); + } + + } + + wait_keyup(); + while (get_key() == 0); + } +} + +//return 1 if the list of bad memory devices changes, 0 otherwise, -1 if no mapped +int add_dmi_err(ulong adr){ + int i,j,found=-1; + + if(!dmi_initialized) + init_dmi(); + + for(i=0; i < md_maps_count; i++){ + if ( adr < (md_maps[i]->start<<10) || + adr > (md_maps[i]->end<<10) ) + continue; + + //matching map found, now check find corresponding dev + for(j=0; j < mem_devs_count; j++){ + if (mem_devs[j]->header.handle != md_maps[i]->md_handle) + continue; + if (dmi_err_cnts[j]){ + found=0; + }else{ + found = dmi_err_cnts[j] = 1; + } + } + } + + return found; +} + +void print_dmi_err(void){ + int i,count,of; + char *string; + + scroll(); + + cprint(vv->msg_line, 0,"Bad Memory Devices: "); + of=20; + for ( i=count=0; i < MAX_DMI_MEMDEVS; i++){ + if (!dmi_err_cnts[i]) + continue; + struct mem_dev *md = mem_devs[i]; + if(count++){ + cprint(vv->msg_line, of, ", "); + of+=2; + } + string=get_tstruct_string((struct tstruct_header *)md,md->dev_locator); + if (mt86_strlen(string) + of > 80){ + scroll(); + of=7; + } + cprint(vv->msg_line, of, string); + of += mt86_strlen(string); + } +} diff --git a/memtestEDK/Memtest/SingleComponents/dmi.h b/memtestEDK/Memtest/SingleComponents/dmi.h new file mode 100644 index 0000000..c90fedd --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/dmi.h @@ -0,0 +1,7 @@ +#ifndef __DMI_H__ +#define __DMI_H__ +int add_dmi_err(ulong adr); +void print_dmi_err(void); +void print_dmi_info(void); +void print_dmi_startup_info(void); +#endif diff --git a/memtestEDK/Memtest/SingleComponents/elf.h b/memtestEDK/Memtest/SingleComponents/elf.h new file mode 100644 index 0000000..72efaac --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/elf.h @@ -0,0 +1,590 @@ +#ifndef ELF_H +#define ELF_H + +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for e_type. */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ + +/* Values for e_machine (architecute). */ +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386+ */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_486 6 /* Perhaps disused */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ + +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ + +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_AT19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_NUM 95 + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ + + +#define ELF_PROGRAM_RETURNS_BIT 0x8000000 /* e_flags bit 31 */ + +#define EI_MAG0 0 +#define ELFMAG0 0x7f + +#define EI_MAG1 1 +#define ELFMAG1 'E' + +#define EI_MAG2 2 +#define ELFMAG2 'L' + +#define EI_MAG3 3 +#define ELFMAG3 'F' + +#define ELFMAG "\177ELF" + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +#define EI_DATA 5 /* Data encodeing byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement little endian */ +#define ELFDATA2MSB 2 /* 2's complement big endian */ + +#define EI_VERSION 6 /* File version byte index */ + /* Value must be EV_CURRENT */ + +#define EV_NONE 0 /* Invalid ELF Version */ +#define EV_CURRENT 1 /* Current version */ + +#define ELF32_PHDR_SIZE (8*4) /* Size of an elf program header */ + +#ifndef ASSEMBLY + +#include "stdint.h" + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef uint16_t Elf32_Section; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; +typedef uint32_t Elf32_Size; + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef uint16_t Elf64_Section; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Size; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* + * ELF header. + */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Program header. + */ +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address (not used). */ + Elf32_Addr p_paddr; /* Physical address. */ + Elf32_Size p_filesz; /* Size of contents in file. */ + Elf32_Size p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Size p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address (not used). */ + Elf64_Addr p_paddr; /* Physical address. */ + Elf64_Size p_filesz; /* Size of contents in file. */ + Elf64_Size p_memsz; /* Size of contents in memory. */ + Elf64_Size p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + + +/* Dynamic section entry. */ + +typedef struct +{ + Elf32_Sword d_tag; /* Dynamic entry type */ + union + { + Elf32_Word d_val; /* Integer value */ + Elf32_Addr d_ptr; /* Address value */ + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* Dynamic entry type */ + union + { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + +/* Legal values for d_tag (dynamic entry type). */ + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_NEEDED 1 /* Name of needed library */ +#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +#define DT_PLTGOT 3 /* Processor defined value */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_STRSZ 10 /* Size of string table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ +#define DT_INIT 12 /* Address of init function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Name of shared object */ +#define DT_RPATH 15 /* Library search path (deprecated) */ +#define DT_SYMBOLIC 16 /* Start symbol search here */ +#define DT_REL 17 /* Address of Rel relocs */ +#define DT_RELSZ 18 /* Total size of Rel relocs */ +#define DT_RELENT 19 /* Size of one Rel reloc */ +#define DT_PLTREL 20 /* Type of reloc in PLT */ +#define DT_DEBUG 21 /* For debugging; unspecified */ +#define DT_TEXTREL 22 /* Reloc might modify .text */ +#define DT_JMPREL 23 /* Address of PLT relocs */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used */ +#define DT_LOOS 0x6000000d /* Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +#define DT_PROCNUM 0x32 /* Most used by any processor */ + +/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's + approach. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting + the following DT_* entry. */ +#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +#define DT_VALNUM 12 + +/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + + If any adjustment is made to the ELF object after it has been + built these entries will need to be adjusted. */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +#define DT_MOVETAB 0x6ffffefe /* Move table. */ +#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 10 + +/* The versioning entry types. The next are defined as part of the + GNU extension. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + +/* These were chosen by Sun. */ +#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +#define DT_VERDEF 0x6ffffffc /* Address of version definition + table */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +#define DT_VERNEED 0x6ffffffe /* Address of table with needed + versions */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGNUM 16 + +/* Sun added these machine-independent extensions in the "processor-specific" + range. Be compatible. */ +#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) +#define DT_EXTRANUM 3 + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not + generally available. */ + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Section group handling. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ + +/* Symbol table entry. */ + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) + + +/* Intel 80386 specific definitions. */ + +/* i386 relocs. */ + +#define R_386_NONE 0 /* No reloc */ +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ +#define R_386_GOT32 3 /* 32 bit GOT entry */ +#define R_386_PLT32 4 /* 32 bit PLT address */ +#define R_386_COPY 5 /* Copy symbol at runtime */ +#define R_386_GLOB_DAT 6 /* Create GOT entry */ +#define R_386_JMP_SLOT 7 /* Create PLT entry */ +#define R_386_RELATIVE 8 /* Adjust by program base */ +#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ +#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS + block offset */ +#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block + offset */ +#define R_386_TLS_LE 17 /* Offset relative to static TLS + block */ +#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of + general dynamic thread local data */ +#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of + local dynamic thread local data + in LE code */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic + thread local data */ +#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +#define R_386_TLS_GD_CALL 26 /* Relocation for call to + __tls_get_addr() */ +#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic + thread local data in LE code */ +#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +#define R_386_TLS_LDM_CALL 30 /* Relocation for call to + __tls_get_addr() in LDM code */ +#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS + block offset */ +#define R_386_TLS_LE_32 34 /* Negated offset relative to static + TLS block */ +#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +/* Keep this the last entry. */ +#define R_386_NUM 38 + +#endif /* ASSEMBLY */ + +#endif /* ELF_H */ diff --git a/memtestEDK/Memtest/SingleComponents/environment.h b/memtestEDK/Memtest/SingleComponents/environment.h new file mode 100644 index 0000000..8546099 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/environment.h @@ -0,0 +1,23 @@ + +#include "stdin.h" + + +#if __linux__ // or #if __GNUC__ + #if __x86_64__ || __ppc64__ + #define ENVIRONMENT64 + #else + #define ENVIRONMENT32 + #endif +#else + #if _WIN32 + #define ENVIRONMENT32 + #else + #define ENVIRONMENT64 + #endif +#endif // __linux__ + +#ifdef ENVIRONMENT64 + #define MAX_BLOCK_SIZE uint64_t +#else + #define MAX_BLOCK_SIZE uint32_t +#endif // ENVIRONMENT64
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/error.c b/memtestEDK/Memtest/SingleComponents/error.c new file mode 100644 index 0000000..4b4f1f0 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/error.c @@ -0,0 +1,629 @@ +/* error.c - MemTest-86 Version 4.1 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + */ +#include "stddef.h" +#include "stdint.h" +#include "test.h" +#include "config.h" +#include "cpuid.h" +#include "smp.h" +#include "dmi.h" +#include "controller.h" + +extern int dmi_err_cnts[MAX_DMI_MEMDEVS]; +extern int beepmode; +extern short dmi_initialized; +extern struct cpu_ident cpu_id; +extern struct barrier_s *barr; +extern int test_ticks, nticks; +extern struct tseq tseq[]; +extern volatile int test; +void poll_errors(); +extern int num_cpus; + +static void update_err_counts(void); +static void print_err_counts(void); +static void common_err(); +static int syn, chan, len=1; + +static void paint_line(int msg_line, unsigned vga_color) { + if (msg_line < 24) { + char* pp; + int i; + for(i=0, pp=(char *)((SCREEN_ADR+msg_line*160+1)); + i<76; i++, pp+=2) { + *pp = vga_color; + } + } +} + +/* + * Report an assertion failure. This is typically NOT a memory error. + */ +void assert_fail(const char* file, int line_no) { + spin_lock(&barr->mutex); + + scroll(); + cprint(vv->msg_line, 0, " *** INTERNAL ERROR *** line "); + dprint(vv->msg_line, 31, line_no, 5, 1); + cprint(vv->msg_line, 37, file); + paint_line(vv->msg_line, 0x0E /* yellow on black */); + + spin_unlock(&barr->mutex); + + // Ensure the message remains visible for a while + // before it scrolls away. Assert-fails should be rare + // and may indicate that subsequent result aren't valid. + sleep(60, 0, 0, 0); +} + +/* + * Display data error message. Don't display duplicate errors. + */ +void mt86_error(ulong *adr, ulong good, ulong bad) +{ + ulong xor; + + spin_lock(&barr->mutex); + + xor = good ^ bad; + +#ifdef USB_WAR + /* Skip any errors that appear to be due to the BIOS using location + * 0x4e0 for USB keyboard support. This often happens with Intel + * 810, 815 and 820 chipsets. It is possible that we will skip + * a real error but the odds are very low. + */ + if ((ulong)adr == 0x4e0 || (ulong)adr == 0x410) { + return; + } +#endif + + common_err(adr, good, bad, xor, 0); + spin_unlock(&barr->mutex); +} + +/* + * Display address error message. + * Since this is strictly an address test, trying to create BadRAM + * patterns does not make sense. Just report the error. + */ +void ad_err1(ulong *adr1, ulong *mask, ulong bad, ulong good) +{ + spin_lock(&barr->mutex); + common_err(adr1, good, bad, (ulong)mask, 1); + spin_unlock(&barr->mutex); +} + +/* + * Display address error message. + * Since this type of address error can also report data errors go + * ahead and generate BadRAM patterns. + */ +void ad_err2(ulong *adr, ulong bad) +{ + spin_lock(&barr->mutex); + common_err(adr, (ulong)adr, bad, ((ulong)adr) ^ bad, 0); + spin_unlock(&barr->mutex); +} + +static void update_err_counts(void) +{ + if (beepmode){ + beep(600); + beep(1000); + } + + if (vv->pass && vv->ecount == 0) { + cprint(LINE_MSG, COL_MSG, + " "); + } + ++(vv->ecount); + tseq[test].errors++; +} + +static void print_err_counts(void) +{ + if ((vv->ecount > 4096) && (vv->ecount % 256 != 0)) return; + + dprint(LINE_INFO, 72, vv->ecount, 6, 0); + /* + dprint(LINE_INFO, 56, vv->ecc_ecount, 6, 0); + */ + + /* Paint the error messages on the screen red to provide a vivid */ + /* indicator that an error has occured */ + if ((vv->printmode == PRINTMODE_ADDRESSES || + vv->printmode == PRINTMODE_PATTERNS)) { + paint_line(vv->msg_line, 0x47 /* gray-on-red */); + } +} + +/* + * Print an individual error + */ +void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type) +{ + int i, j, n, x, flag=0; + ulong page, offset; + int patnchg; + ulong mb; + + update_err_counts(); + + switch(vv->printmode) { + case PRINTMODE_SUMMARY: + /* Don't do anything for a parity error. */ + if (type == 3) { + return; + } + + /* Address error */ + if (type == 1) { + xor = good ^ bad; + } + + /* Ecc correctable errors */ + if (type == 2) { + /* the bad value is the corrected flag */ + if (bad) { + vv->erri.cor_err++; + } + page = (ulong)adr; + offset = good; + } else { + page = page_of(adr); + offset = (ulong)adr & 0xFFF; + } + + /* Calc upper and lower error addresses */ + if (vv->erri.low_addr.page > page) { + vv->erri.low_addr.page = page; + vv->erri.low_addr.offset = offset; + flag++; + } else if (vv->erri.low_addr.page == page && + vv->erri.low_addr.offset > offset) { + vv->erri.low_addr.offset = offset; + vv->erri.high_addr.offset = offset; + flag++; + } else if (vv->erri.high_addr.page < page) { + vv->erri.high_addr.page = page; + flag++; + } + if (vv->erri.high_addr.page == page && + vv->erri.high_addr.offset < offset) { + vv->erri.high_addr.offset = offset; + flag++; + } + + /* Calc bits in error */ + for (i=0, n=0; i<32; i++) { + if (xor>>i & 1) { + n++; + } + } + vv->erri.tbits += n; + if (n > vv->erri.max_bits) { + vv->erri.max_bits = n; + flag++; + } + if (n < vv->erri.min_bits) { + vv->erri.min_bits = n; + flag++; + } + if (vv->erri.ebits ^ xor) { + flag++; + } + vv->erri.ebits |= xor; + + /* Calc max contig errors */ + len = 1; + if ((ulong)adr == (ulong)vv->erri.eadr+4 || + (ulong)adr == (ulong)vv->erri.eadr-4 ) { + len++; + } + if (len > vv->erri.maxl) { + vv->erri.maxl = len; + flag++; + } + vv->erri.eadr = (ulong)adr; + + if (vv->erri.hdr_flag == 0) { + clear_scroll(); + cprint(LINE_HEADER+0, 1, "Error Confidence Value:"); + cprint(LINE_HEADER+1, 1, " Lowest Error Address:"); + cprint(LINE_HEADER+2, 1, " Highest Error Address:"); + cprint(LINE_HEADER+3, 1, " Bits in Error Mask:"); + cprint(LINE_HEADER+4, 1, " Bits in Error - Total:"); + cprint(LINE_HEADER+4, 29, "Min: Max: Avg:"); + cprint(LINE_HEADER+5, 1, " Max Contiguous Errors:"); + x = 24; + if (dmi_initialized) { + for ( i=0; i < MAX_DMI_MEMDEVS;){ + n = LINE_HEADER+7; + for (j=0; j<4; j++) { + if (dmi_err_cnts[i] >= 0) { + dprint(n, x, i, 2, 0); + cprint(n, x+2, ": 0"); + } + i++; + n++; + } + x += 10; + } + } + + cprint(LINE_HEADER+0, 64, "Test Errors"); + vv->erri.hdr_flag++; + } + if (flag) { + /* Calc bits in error */ + for (i=0, n=0; i<32; i++) { + if (vv->erri.ebits>>i & 1) { + n++; + } + } + page = vv->erri.low_addr.page; + offset = vv->erri.low_addr.offset; + mb = page >> 8; + hprint(LINE_HEADER+1, 25, page); + hprint2(LINE_HEADER+1, 33, offset, 3); + cprint(LINE_HEADER+1, 36, " - . MB"); + dprint(LINE_HEADER+1, 39, mb, 5, 0); + dprint(LINE_HEADER+1, 45, ((page & 0xF)*10)/16, 1, 0); + page = vv->erri.high_addr.page; + offset = vv->erri.high_addr.offset; + mb = page >> 8; + hprint(LINE_HEADER+2, 25, page); + hprint2(LINE_HEADER+2, 33, offset, 3); + cprint(LINE_HEADER+2, 36, " - . MB"); + dprint(LINE_HEADER+2, 39, mb, 5, 0); + dprint(LINE_HEADER+2, 45, ((page & 0xF)*10)/16, 1, 0); + hprint(LINE_HEADER+3, 25, vv->erri.ebits); + dprint(LINE_HEADER+4, 25, n, 2, 1); + dprint(LINE_HEADER+4, 34, vv->erri.min_bits, 2, 1); + dprint(LINE_HEADER+4, 42, vv->erri.max_bits, 2, 1); + dprint(LINE_HEADER+4, 50, vv->erri.tbits/vv->ecount, 2, 1); + dprint(LINE_HEADER+5, 25, vv->erri.maxl, 7, 1); + x = 28; + for ( i=0; i < MAX_DMI_MEMDEVS;){ + n = LINE_HEADER+7; + for (j=0; j<4; j++) { + if (dmi_err_cnts[i] > 0) { + dprint (n, x, dmi_err_cnts[i], 7, 1); + } + i++; + n++; + } + x += 10; + } + + for (i=0; tseq[i].msg != NULL; i++) { + dprint(LINE_HEADER+1+i, 66, i, 2, 0); + dprint(LINE_HEADER+1+i, 68, tseq[i].errors, 8, 0); + } + } + if (vv->erri.cor_err) { + dprint(LINE_HEADER+6, 25, vv->erri.cor_err, 8, 1); + } + break; + + case PRINTMODE_ADDRESSES: + /* Don't display duplicate errors */ + if ((ulong)adr == (ulong)vv->erri.eadr && + xor == vv->erri.exor) { + return; + } + if (vv->erri.hdr_flag == 0) { + clear_scroll(); + cprint(LINE_HEADER, 0, + "Tst Pass Failing Address Good Bad Err-Bits Count CPU"); + cprint(LINE_HEADER+1, 0, + "--- ---- ----------------------- -------- -------- -------- ----- ----"); + vv->erri.hdr_flag++; + } + /* Check for keyboard input */ + check_input(); + scroll(); + + if ( type == 2 || type == 3) { + page = (ulong)adr; + offset = good; + } else { + page = page_of(adr); + offset = ((unsigned long)adr) & 0xFFF; + } + mb = page >> 8; + dprint(vv->msg_line, 0, test+1, 3, 0); + dprint(vv->msg_line, 4, vv->pass, 5, 0); + hprint(vv->msg_line, 11, page); + hprint2(vv->msg_line, 19, offset, 3); + cprint(vv->msg_line, 22, " - . MB"); + dprint(vv->msg_line, 25, mb, 5, 0); + dprint(vv->msg_line, 31, ((page & 0xF)*10)/16, 1, 0); + + if (type == 3) { + /* ECC error */ + cprint(vv->msg_line, 36, + bad?"corrected ": "uncorrected "); + hprint2(vv->msg_line, 60, syn, 4); + cprint(vv->msg_line, 68, "ECC"); + dprint(vv->msg_line, 74, chan, 2, 0); + } else if (type == 2) { + cprint(vv->msg_line, 36, "Parity error detected "); + } else { + hprint(vv->msg_line, 36, good); + hprint(vv->msg_line, 46, bad); + hprint(vv->msg_line, 56, xor); + dprint(vv->msg_line, 66, vv->ecount, 5, 0); + dprint(vv->msg_line, 74, smp_my_cpu_num(), 2,1); + vv->erri.exor = xor; + } + vv->erri.eadr = (ulong)adr; + print_err_counts(); + break; + + case PRINTMODE_PATTERNS: + if (vv->erri.hdr_flag == 0) { + clear_scroll(); + vv->erri.hdr_flag++; + } + /* Do not do badram patterns from test 0 or 5 */ + if (test == 0 || test == 5) { + return; + } + /* Only do patterns for data errors */ + if ( type != 0) { + return; + } + /* Process the address in the pattern administration */ + patnchg=insertaddress ((ulong) adr); + if (patnchg) { + printpatn(); + } + break; + + case PRINTMODE_NONE: + if (vv->erri.hdr_flag == 0) { + clear_scroll(); + vv->erri.hdr_flag++; + } + break; + } +} + +/* + * Print an ecc error + */ +void print_ecc_err(unsigned long page, unsigned long offset, + int corrected, unsigned short syndrome, int channel) +{ + ++(vv->ecc_ecount); + syn = syndrome; + chan = channel; + common_err((ulong *)page, offset, corrected, 0, 2); +} + +#ifdef PARITY_MEM +/* + * Print a parity error message + */ +void parity_err( unsigned long edi, unsigned long esi) +{ + unsigned long addr; + + if (test == 5) { + addr = esi; + } else { + addr = edi; + } + common_err((ulong *)addr, addr & 0xFFF, 0, 0, 3); +} +#endif + +/* + * Print the pattern array as a LILO boot option addressing BadRAM support. + */ +void printpatn (void) +{ + int idx=0; + int x; + + /* Check for keyboard input */ + check_input(); + + if (vv->numpatn == 0) + return; + + scroll(); + + cprint (vv->msg_line, 0, "badram="); + x=7; + + for (idx = 0; idx < vv->numpatn; idx++) { + + if (x > 80-22) { + scroll(); + x=7; + } + cprint (vv->msg_line, x, "0x"); + hprint (vv->msg_line, x+2, vv->patn[idx].adr ); + cprint (vv->msg_line, x+10, ",0x"); + hprint (vv->msg_line, x+13, vv->patn[idx].mask); + if (idx+1 < vv->numpatn) + cprint (vv->msg_line, x+21, ","); + x+=22; + } +} + +/* + * Show progress by displaying elapsed time and update bar graphs + */ +short spin_idx[MAX_CPUS]; +char spin[4] = {'|','/','-','\\'}; + +void do_tick(int me) +{ + int i, j, pct; + ulong h, l, n, t; + extern int mstr_cpu; + + if (++spin_idx[me] > 3) { + spin_idx[me] = 0; + } + cplace(8, me+7, spin[spin_idx[me]]); + + + /* Check for keyboard input */ + if (me == mstr_cpu) { + check_input(); + } + /* A barrier here holds the other CPUs until the configuration + * changes are done */ + s_barrier(); + + /* Only the first selected CPU does the update */ + if (me != mstr_cpu) { + return; + } + + /* FIXME only print serial error messages from the tick handler */ + if (vv->ecount) { + print_err_counts(); + } + + nticks++; + vv->total_ticks++; + + if (test_ticks) { + pct = 100*nticks/test_ticks; + if (pct > 100) { + pct = 100; + } + } else { + pct = 0; + } + dprint(2, COL_MID+4, pct, 3, 0); + i = (BAR_SIZE * pct) / 100; + while (i > vv->tptr) { + if (vv->tptr >= BAR_SIZE) { + break; + } + cprint(2, COL_MID+9+vv->tptr, "#"); + vv->tptr++; + } + + if (vv->pass_ticks) { + pct = 100*vv->total_ticks/vv->pass_ticks; + if (pct > 100) { + pct = 100; + } + } else { + pct = 0; + } + dprint(1, COL_MID+4, pct, 3, 0); + i = (BAR_SIZE * pct) / 100; + while (i > vv->pptr) { + if (vv->pptr >= BAR_SIZE) { + break; + } + cprint(1, COL_MID+9+vv->pptr, "#"); + vv->pptr++; + } + + if (vv->ecount && vv->printmode == PRINTMODE_SUMMARY) { + /* Compute confidence score */ + pct = 0; + + /* If there are no errors within 1mb of start - end addresses */ + h = vv->pmap[vv->msegs - 1].end - 0x100; + if (vv->erri.low_addr.page > 0x100 && + vv->erri.high_addr.page < h) { + pct += 8; + } + + /* Errors for only some tests */ + if (vv->pass) { + for (i=0, n=0; tseq[i].msg != NULL; i++) { + if (tseq[i].errors == 0) { + n++; + } + } + pct += n*3; + } else { + for (i=0, n=0; i<test; i++) { + if (tseq[i].errors == 0) { + n++; + } + } + pct += n*2; + + } + + /* Only some bits in error */ + n = 0; + if (vv->erri.ebits & 0xf) n++; + if (vv->erri.ebits & 0xf0) n++; + if (vv->erri.ebits & 0xf00) n++; + if (vv->erri.ebits & 0xf000) n++; + if (vv->erri.ebits & 0xf0000) n++; + if (vv->erri.ebits & 0xf00000) n++; + if (vv->erri.ebits & 0xf000000) n++; + if (vv->erri.ebits & 0xf0000000) n++; + pct += (8-n)*2; + + /* Adjust the score */ + pct = pct*100/22; + /* + if (pct > 100) { + pct = 100; + } + */ + dprint(LINE_HEADER+0, 25, pct, 3, 1); + } + + + /* We can't do the elapsed time unless the rdtsc instruction + * is supported + */ + if (cpu_id.fid.bits.rdtsc) { + asm __volatile__( + "rdtsc":"=a" (l),"=d" (h)); + asm __volatile__ ( + "subl %2,%0\n\t" + "sbbl %3,%1" + :"=a" (l), "=d" (h) + :"g" (vv->startl), "g" (vv->starth), + "0" (l), "1" (h)); + t = h * ((unsigned)0xffffffff / vv->clks_msec) / 1000; + t += (l / vv->clks_msec) / 1000; + i = t % 60; + j = i % 10; + + if(j != vv->each_sec) + { + + dprint(LINE_TIME, COL_TIME+9, i % 10, 1, 0); + dprint(LINE_TIME, COL_TIME+8, i / 10, 1, 0); + t /= 60; + i = t % 60; + dprint(LINE_TIME, COL_TIME+6, i % 10, 1, 0); + dprint(LINE_TIME, COL_TIME+5, i / 10, 1, 0); + t /= 60; + dprint(LINE_TIME, COL_TIME, t, 4, 0); + + if(vv->check_temp > 0 && !(vv->fail_safe & 4)) + { + coretemp(); + } + vv->each_sec = j; + } + } + + /* Poll for ECC errors */ + /* + poll_errors(); + */ +} diff --git a/memtestEDK/Memtest/SingleComponents/extra.c b/memtestEDK/Memtest/SingleComponents/extra.c new file mode 100644 index 0000000..ff580f2 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/extra.c @@ -0,0 +1,981 @@ +// This is the extra stuff added to the memtest+ from memtest.org +// Code from Eric Nelson and Wee +// (Checked without vendor-specific optimization before adding) +/* extra.c - + * + * Released under version 2 of the Gnu Public License. + * + */ + +#include "test.h" +#include "screen_buffer.h" +#include "pci.h" +#include "extra.h" + +static int ctrl = -1; + +struct memory_controller { + unsigned vendor; + unsigned device; + int worked; + void (*change_timing)(int cas, int rcd, int rp, int ras); +}; + +static struct memory_controller mem_ctr[] = { + + /* AMD 64*/ + { 0x1022, 0x1100, 1, change_timing_amd64}, //AMD64 hypertransport link + + /* nVidia */ + { 0x10de, 0x01E0, 0, change_timing_nf2}, // nforce2 + + /* Intel */ + { 0x8086, 0x2570, 0, change_timing_i875}, //Intel i848/i865 + { 0x8086, 0x2578, 0, change_timing_i875}, //Intel i875P + { 0x8086, 0x2580, 0, change_timing_i925}, //Intel i915P/G + { 0x8086, 0x2584, 0, change_timing_i925}, //Intel i925X + { 0x8086, 0x2770, 0, change_timing_i925}, //Intel Lakeport + { 0x8086, 0x3580, 0, change_timing_i852}, //Intel i852GM - i855GM/GME (But not i855PM) +}; + +struct drc { + unsigned t_rwt; + unsigned t_wrt; + unsigned t_ref; + unsigned t_en2t; + unsigned t_rwqb; + unsigned t_rct; + unsigned t_rrd; + unsigned t_wr; +}; + +static struct drc a64; + +void find_memctr(void) // Basically copy from the find_controller function +{ + unsigned long vendor; + unsigned long device; + unsigned long a64; + int i= 0; + int result; + + result = pci_conf_read(0, 0, 0, PCI_VENDOR_ID, 2, &vendor); + result = pci_conf_read(0, 0, 0, PCI_DEVICE_ID, 2, &device); + + pci_conf_read(0, 24, 0, 0x00, 4, &a64); + + if( a64 == 0x11001022) { + ctrl = 0; + return; + } + + if (result == 0) { + for(i = 1; i < sizeof(mem_ctr)/sizeof(mem_ctr[0]); i++) { + if ((mem_ctr[i].vendor == vendor) && + (mem_ctr[i].device == device)) + { + ctrl = i; + return; + } + } + } + ctrl = -1; +} + +void a64_parameter(void) +{ + + ulong dramtlr; + + if ( 0 == pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr) ) + { + a64.t_rct = 7 + ((dramtlr>>4) & 0x0F); + a64.t_rrd = 0 + ((dramtlr>>16) & 0x7); + a64.t_wr = 2 + ((dramtlr>>28) & 0x1); + } + + if ( 0 == pci_conf_read(0, 24, 2, 0x8C, 4, &dramtlr) ) + { + a64.t_rwt = 1 + ((dramtlr>>4) & 0x07); + a64.t_wrt = 1 + (dramtlr & 0x1); + a64.t_ref = 1 + ((dramtlr>>11) & 0x3); + } + + if ( 0 == pci_conf_read(0, 24, 2, 0x90, 4, &dramtlr) ) + { + a64.t_en2t = 1 + ((dramtlr>>28) & 0x1); + a64.t_rwqb = 2 << ((dramtlr>>14) & 0x3); + } +} + + + +void change_timing(int cas, int rcd, int rp, int ras) +{ + find_memctr(); + if ((ctrl == -1) || ( ctrl > sizeof(mem_ctr)/sizeof(mem_ctr[0]))) + { + return; + } + + mem_ctr[ctrl].change_timing(cas, rcd, rp, ras); + restart(); +} + +void amd64_option() +{ + int rwt=0, wrt=0, ref=0, en2t=0, rct=0, rrd=0, rwqb=0, wr = 0, flag=0; + + if ((ctrl == -1) || ( ctrl > sizeof(mem_ctr)/sizeof(mem_ctr[0]))) + { + return; + } + + if (mem_ctr[ctrl].worked) + { + a64_parameter(); + cprint(POP_Y+1, POP_X+4, "AMD64 options"); + + cprint(POP_Y+3, POP_X+4, "(1) Rd-Wr Delay : "); + dprint(POP_Y+3, POP_X+24, a64.t_rwt, 2, 0); + + cprint(POP_Y+4, POP_X+4, "(2) Wr-Rd Delay : "); + dprint(POP_Y+4, POP_X+24, a64.t_wrt, 2, 0); + + cprint(POP_Y+5, POP_X+4, "(3) Rd/Wr Bypass : "); + dprint(POP_Y+5, POP_X+24, a64.t_rwqb, 2, 0); + + cprint(POP_Y+6, POP_X+4, "(4) Refresh Rate : "); + switch ( a64.t_ref) + { + case 1 : cprint(POP_Y+6, POP_X+23, "15.6us"); break; + case 2 : cprint(POP_Y+6, POP_X+23, " 7.8us"); break; + case 3 : cprint(POP_Y+6, POP_X+23, " 3.9us"); break; + } + cprint(POP_Y+7, POP_X+4, "(5) Command Rate :"); + dprint(POP_Y+7, POP_X+24, a64.t_en2t, 2, 0); + cprint(POP_Y+7, POP_X+26, "T "); + + cprint(POP_Y+8, POP_X+4, "(6) Row Cycle Time: "); + dprint(POP_Y+8, POP_X+24, a64.t_rct, 2, 0); + + cprint(POP_Y+9, POP_X+4, "(7) RAS-RAS Delay : "); + dprint(POP_Y+9, POP_X+24, a64.t_rrd, 2, 0); + + cprint(POP_Y+10, POP_X+4, "(8) Write Recovery: "); + dprint(POP_Y+10, POP_X+24, a64.t_wr, 2, 0); + + cprint(POP_Y+11, POP_X+4,"(0) Cancel "); + + while(!flag) + { + switch(get_key()) + { + case 2: + popclear(); + // read-to-write delay + cprint(POP_Y+3, POP_X+4, "Rd-Wr delay "); + cprint(POP_Y+4, POP_X+4, " (2 - 6 cycles)"); + cprint(POP_Y+5, POP_X+4, "Current: "); + dprint(POP_Y+5, POP_X+14, a64.t_rwt, 4, 0); + cprint(POP_Y+7, POP_X+4, "New: "); + rwt = getval(POP_Y+7, POP_X+12, 0); + amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); + break; + + case 3: + popclear(); + // read-to-write delay + cprint(POP_Y+3, POP_X+4, "Wr-Rd delay "); + cprint(POP_Y+4, POP_X+4, " (1 - 2 cycles)"); + cprint(POP_Y+5, POP_X+4, "Current: "); + dprint(POP_Y+5, POP_X+14, a64.t_wrt, 4, 0); + cprint(POP_Y+7, POP_X+4, "New: "); + wrt = getval(POP_Y+7, POP_X+12, 0); + amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); + break; + + case 4: + popclear(); + // Read write queue bypass count + cprint(POP_Y+3, POP_X+4, "Rd/Wr bypass "); + cprint(POP_Y+4, POP_X+4, " (2, 4 or 8 )"); + cprint(POP_Y+5, POP_X+4, "Current: "); + dprint(POP_Y+5, POP_X+14, a64.t_rwqb, 2, 0); + cprint(POP_Y+7, POP_X+4, "New: "); + rwqb = getval(POP_Y+7, POP_X+11, 0); + amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); + break; + + case 5: + popclear(); + // refresh rate + cprint(POP_Y+3, POP_X+4, "Refresh rate "); + cprint(POP_Y+4, POP_X+4, "Current: "); + switch ( a64.t_ref){ + case 1 : cprint(POP_Y+4, POP_X+14, "15.6us"); break; + case 2 : cprint(POP_Y+4, POP_X+14, "7.8us "); break; + case 3 : cprint(POP_Y+4, POP_X+14, "3.9us "); break; + } + cprint(POP_Y+6, POP_X+4, "New: "); + cprint(POP_Y+7, POP_X+4, "(1) 15.6us"); + cprint(POP_Y+8, POP_X+4, "(2) 7.8us "); + cprint(POP_Y+9, POP_X+4, "(3) 3.9us "); + ref = getval(POP_Y+6, POP_X+11, 0); + amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); + break; + + case 6: + popclear(); + //Enable 2T command and addressing + cprint(POP_Y+3, POP_X+4, "Command rate:"); + cprint(POP_Y+5, POP_X+4, "(1) 1T "); //only supoprted by CG revision and later + cprint(POP_Y+6, POP_X+4, "(2) 2T "); + en2t = getval(POP_Y+3, POP_X+22, 0); + amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); + break; + + case 7: + popclear(); + //Row cycle time + cprint(POP_Y+3, POP_X+4, "Row cycle time: "); + cprint(POP_Y+4, POP_X+4, " (7 - 20 cycles)"); + cprint(POP_Y+5, POP_X+4, "Current: "); + dprint(POP_Y+5, POP_X+14, a64.t_rct, 4, 0); + cprint(POP_Y+7, POP_X+4, "New: "); + rct = getval(POP_Y+7, POP_X+12, 0); + amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); + break; + + case 8: + popclear(); + //Active-to-Active RAS Delay + cprint(POP_Y+3, POP_X+4, "RAS-RAS Delay: "); + cprint(POP_Y+4, POP_X+4, " (2 - 4 cycles)"); + cprint(POP_Y+5, POP_X+4, "Current: "); + dprint(POP_Y+5, POP_X+14, a64.t_rrd, 2, 0); + cprint(POP_Y+7, POP_X+4, "New: "); + rrd = getval(POP_Y+7, POP_X+12, 0); + amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); + break; + + case 9: + popclear(); + //Active-to-Active RAS Delay + cprint(POP_Y+3, POP_X+4, "Write Recovery: "); + cprint(POP_Y+4, POP_X+4, " (2 - 3 cycles)"); + cprint(POP_Y+5, POP_X+4, "Current: "); + dprint(POP_Y+5, POP_X+14, a64.t_wr, 2, 0); + cprint(POP_Y+7, POP_X+4, "New: "); + wr = getval(POP_Y+7, POP_X+12, 0); + amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); + break; + + case 11: + case 57: + flag++; + /* 0/CR - Cancel */ + break; + } + } + } +} + +void get_option() +{ + int cas =0, rp=0, rcd=0, ras=0, sflag = 0 ; + + while(!sflag) + { + switch(get_key()) + { + case 2: + popclear(); + cas = get_cas(); + popclear(); + + cprint(POP_Y+3, POP_X+8, "tRCD: "); + rcd = getval(POP_Y+3, POP_X+15, 0); + popclear(); + + cprint(POP_Y+3, POP_X+8, "tRP: "); + rp = getval(POP_Y+3, POP_X+15, 0); + popclear(); + + cprint(POP_Y+3, POP_X+8, "tRAS: "); + ras = getval(POP_Y+3, POP_X+15, 0); + popclear(); + change_timing(cas, rcd, rp, ras); + break; + + case 3: + popclear(); + cas = get_cas(); + change_timing(cas, 0, 0, 0); + sflag++; + break; + + case 4: + popclear(); + cprint(POP_Y+3, POP_X+8, "tRCD: "); + rcd =getval(POP_Y+3, POP_X+15, 0); + change_timing(0, rcd, 0, 0); + sflag++; + break; + + case 5: + popclear(); + cprint(POP_Y+3, POP_X+8, "tRP: "); + rp =getval(POP_Y+3, POP_X+15, 0); + change_timing(0, 0, rp, 0); + sflag++; + break; + + case 6: + popclear(); + cprint(POP_Y+3, POP_X+8, "tRAS: "); + ras =getval(POP_Y+3, POP_X+15, 0); + change_timing(0, 0, 0, ras); + sflag++; + break; + + case 7: + popclear(); + amd64_option(); + sflag++; + popclear(); + break; + + case 8: + break; + + case 11: + case 57: + sflag++; + /* 0/CR - Cancel */ + break; + } + } +} + +void get_option_1() +{ + int rp=0, rcd=0, ras=0, sflag = 0 ; + + while(!sflag) + { + switch(get_key()) + { + case 2: + popclear(); + cprint(POP_Y+3, POP_X+8, "tRCD: "); + rcd = getval(POP_Y+3, POP_X+15, 0); + popclear(); + + cprint(POP_Y+3, POP_X+8, "tRP: "); + rp = getval(POP_Y+3, POP_X+15, 0); + popclear(); + + cprint(POP_Y+3, POP_X+8, "tRAS: "); + ras = getval(POP_Y+3, POP_X+15, 0); + popclear(); + change_timing(0, rcd, rp, ras); + break; + + case 3: + popclear(); + cprint(POP_Y+3, POP_X+8, "tRCD: "); + rcd =getval(POP_Y+3, POP_X+15, 0); + change_timing(0, rcd, 0, 0); + break; + + case 4: + popclear(); + cprint(POP_Y+3, POP_X+8, "tRP: "); + rp =getval(POP_Y+3, POP_X+15, 0); + change_timing(0, 0, rp, 0); + break; + + case 5: + popclear(); + cprint(POP_Y+3, POP_X+8, "tRAS: "); + ras =getval(POP_Y+3, POP_X+15, 0); + change_timing(0, 0, 0, ras); + break; + + case 6: + popclear(); + amd64_option(); + sflag++; + popclear(); + break; + + case 7: + break; + + case 11: + case 57: + sflag++; + /* 0/CR - Cancel */ + break; + } + } +} + + +void get_menu(void) +{ + int menu ; + + find_memctr(); + + switch(ctrl) + { + case 0: menu = 2; break; + case 1: + case 2: + case 3: + case 4: menu = 0; break; + case 5: menu = 1; break; + case 6: menu = 0; break; + default: menu = -1; break; + } + + if (menu == -1) + { + popclear(); + } + else if (menu == 0) + { + cprint(POP_Y+1, POP_X+2, "Modify Timing:"); + cprint(POP_Y+3, POP_X+5, "(1) Modify All "); + cprint(POP_Y+4, POP_X+5, "(2) Modify tCAS "); + cprint(POP_Y+5, POP_X+5, "(3) Modify tRCD "); + cprint(POP_Y+6, POP_X+5, "(4) Modify tRP "); + cprint(POP_Y+7, POP_X+5, "(5) Modify tRAS "); + cprint(POP_Y+8, POP_X+5, "(0) Cancel"); + wait_keyup(); + get_option(); + } + else if (menu == 1) + { + cprint(POP_Y+1, POP_X+2, "Modify Timing:"); + cprint(POP_Y+3, POP_X+5, "(1) Modify All "); + cprint(POP_Y+4, POP_X+5, "(2) Modify tRCD "); + cprint(POP_Y+5, POP_X+5, "(3) Modify tRP "); + cprint(POP_Y+6, POP_X+5, "(4) Modify tRAS "); + cprint(POP_Y+7, POP_X+5, "(0) Cancel"); + wait_keyup(); + get_option(); + } + else // AMD64 special menu + { + cprint(POP_Y+1, POP_X+2, "Modify Timing:"); + cprint(POP_Y+3, POP_X+5, "(1) Modify All "); + cprint(POP_Y+4, POP_X+5, "(2) Modify tRCD "); + cprint(POP_Y+5, POP_X+5, "(3) Modify tRP "); + cprint(POP_Y+6, POP_X+5, "(4) Modify tRAS "); + cprint(POP_Y+7, POP_X+5, "(5) AMD64 Options"); + cprint(POP_Y+8, POP_X+5, "(0) Cancel"); + wait_keyup(); + get_option_1(); + } +} + +int get_cas(void) +{ + int i852=0, cas=0; + ulong drc, ddr; + long *ptr; + + switch(ctrl) + { + case 0: ddr = 1; break; + case 1: + case 2: + case 3: ddr = 1; break; + case 4: + pci_conf_read( 0, 0, 0, 0x44, 4, &ddr); + ddr &= 0xFFFFC000; + ptr=(long*)(ddr+0x120); + drc = *ptr; + + if ((drc & 3) == 2) ddr = 2; + else ddr = 1; + break; + case 5: ddr = 2; break; + case 6: ddr = 1; i852 = 1; break; + default: ddr = 1; + } + + if (ddr == 1) + { + cprint(POP_Y+3, POP_X+8, "tCAS: "); + cprint(POP_Y+5, POP_X+8, "(1) CAS 2.5 "); + cprint(POP_Y+6, POP_X+8, "(2) CAS 2 "); + if(!i852) { + cprint(POP_Y+7, POP_X+8, "(3) CAS 3 "); + } + cas = getval(POP_Y+3, POP_X+15, 0); + } + else if (ddr == 2) + { + cprint(POP_Y+3, POP_X+8, "tCAS: "); + cprint(POP_Y+5, POP_X+8, "(1) CAS 4 "); + cprint(POP_Y+6, POP_X+8, "(2) CAS 3 "); + cprint(POP_Y+7, POP_X+8, "(3) CAS 5 "); + cas = getval(POP_Y+3, POP_X+15, 0); + } + else + { + cas = -1; + } + + popclear(); + return (cas); +} + +///////////////////////////////////////////////////////// +// here we go for the exciting timing change part... // +///////////////////////////////////////////////////////// + +void change_timing_i852(int cas, int rcd, int rp, int ras) { + + ulong dramtlr; + ulong int1, int2; + + pci_conf_read(0, 0, 1, 0x60, 4, &dramtlr); + + // CAS Latency (tCAS) + int1 = dramtlr & 0xFF9F; + if (cas == 2) { int2 = int1 ^ 0x20; } + else if (cas == 1) { int2 = int1; } + else { int2 = dramtlr; } + + + // RAS-To-CAS (tRCD) + int1 = int2 & 0xFFF3; + if (rcd == 2) { int2 = int1 ^ 0x8; } + else if (rcd == 3) { int2 = int1 ^ 0x4; } + else if (rcd == 4) { int2 = int1; } + // else { int2 = int2; } + + + // RAS Precharge (tRP) + int1 = int2 & 0xFFFC; + if (rp == 2) { int2 = int1 ^ 0x2; } + else if (rp == 3) { int2 = int1 ^ 0x1; } + else if (rp == 4) { int2 = int1; } + // else { int2 = int2; } + + + // RAS Active to precharge (tRAS) + int1 = int2 & 0xF9FF; + if (ras == 5) { int2 = int1 ^ 0x0600; } + else if (ras == 6) { int2 = int1 ^ 0x0400; } + else if (ras == 7) { int2 = int1 ^ 0x0200; } + else if (ras == 8) { int2 = int1; } + // else { int2 = int2; } + + pci_conf_write(0, 0, 1, 0x60, 4, int2); + __delay(500); +} + +void change_timing_i925(int cas, int rcd, int rp, int ras) +{ + ulong int1, dev0, temp; + long *ptr; + + //read MMRBAR + pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); + dev0 &= 0xFFFFC000; + + ptr=(long*)(dev0+0x114); + temp = *ptr; + + // RAS-To-CAS (tRCD) + int1 = temp | 0x70; + if (rcd == 2) { temp = int1 ^ 0x70; } + else if (rcd == 3) { temp = int1 ^ 0x60; } + else if (rcd == 4) { temp = int1 ^ 0x50; } + else if (rcd == 5) { temp = int1 ^ 0x40; } + // else { temp = temp;} + + //RAS precharge (tRP) + int1 = temp | 0x7; + if (rp == 2) { temp = int1 ^ 0x7; } + else if (rp == 3) { temp = int1 ^ 0x6; } + else if (rp == 4) { temp = int1 ^ 0x5; } + else if (rp == 5) { temp = int1 ^ 0x4; } + // else { temp = temp;} + + if (mem_ctr[ctrl].device == 0x2770 ) // Lakeport? + { + // RAS Active to precharge (tRAS) + int1 = temp | 0xF80000; // bits 23:19 + if (ras == 4) { temp = int1 ^ 0xD80000; } + else if (ras == 5) { temp = int1 ^ 0xD00000; } + else if (ras == 6) { temp = int1 ^ 0xC80000; } + else if (ras == 7) { temp = int1 ^ 0xC00000; } + else if (ras == 8) { temp = int1 ^ 0xB80000; } + else if (ras == 9) { temp = int1 ^ 0xB00000; } + else if (ras == 10) { temp = int1 ^ 0xA80000; } + else if (ras == 11) { temp = int1 ^ 0xA00000; } + else if (ras == 12) { temp = int1 ^ 0x980000; } + else if (ras == 13) { temp = int1 ^ 0x900000; } + else if (ras == 14) { temp = int1 ^ 0x880000; } + else if (ras == 15) { temp = int1 ^ 0x800000; } + // else { temp = temp;} + } + else + { + // RAS Active to precharge (tRAS) + int1 = temp | 0xF00000; // bits 23:20 + if (ras == 4) { temp = int1 ^ 0xB00000; } + else if (ras == 5) { temp = int1 ^ 0xA00000; } + else if (ras == 6) { temp = int1 ^ 0x900000; } + else if (ras == 7) { temp = int1 ^ 0x800000; } + else if (ras == 8) { temp = int1 ^ 0x700000; } + else if (ras == 9) { temp = int1 ^ 0x600000; } + else if (ras == 10) { temp = int1 ^ 0x500000; } + else if (ras == 11) { temp = int1 ^ 0x400000; } + else if (ras == 12) { temp = int1 ^ 0x300000; } + else if (ras == 13) { temp = int1 ^ 0x200000; } + else if (ras == 14) { temp = int1 ^ 0x100000; } + else if (ras == 15) { temp = int1 ^ 0x000000; } + // else { temp = temp;} + } + + // CAS Latency (tCAS) + int1 = temp | 0x0300; + if (cas == 1) { temp = int1 ^ 0x200; } // cas 2.5 + else if (cas == 2) { temp = int1 ^ 0x100; } + else if (cas == 3) { temp = int1 ^ 0x300; } + // else { temp = temp;} + + *ptr = temp; + __delay(500); + return; +} + +void change_timing_Lakeport(int cas, int rcd, int rp, int ras) +{ + ulong int1, dev0, temp; + long *ptr; + + //read MMRBAR + pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); + dev0 &= 0xFFFFC000; + + ptr=(long*)(dev0+0x114); + temp = *ptr; + + // RAS-To-CAS (tRCD) + int1 = temp | 0x70; + if (rcd == 2) { temp = int1 ^ 0x70; } + else if (rcd == 3) { temp = int1 ^ 0x60; } + else if (rcd == 4) { temp = int1 ^ 0x50; } + else if (rcd == 5) { temp = int1 ^ 0x40; } + // else { temp = temp;} + + //RAS precharge (tRP) + int1 = temp | 0x7; + if (rp == 2) { temp = int1 ^ 0x7; } + else if (rp == 3) { temp = int1 ^ 0x6; } + else if (rp == 4) { temp = int1 ^ 0x5; } + else if (rp == 5) { temp = int1 ^ 0x4; } + // else { temp = temp;} + + + // CAS Latency (tCAS) + int1 = temp | 0x0300; + if (cas == 1) { temp = int1 ^ 0x200; } // cas 2.5 + else if (cas == 2) { temp = int1 ^ 0x100; } + else if (cas == 3) { temp = int1 ^ 0x300; } + // else { temp = temp;} + + *ptr = temp; + __delay(500); + return; +} + +void change_timing_i875(int cas, int rcd, int rp, int ras){ + + ulong int1, dev6, temp; + long *ptr; + + /* Read the MMR Base Address & Define the pointer from the BAR6 overflow register */ + pci_conf_read( 0, 6, 0, 0x10, 4, &dev6); + + ptr=(long*)(dev6+0x60); + + temp = *ptr; + + // RAS-To-CAS (tRCD) + int1 = temp | 0xC; + if (rcd == 2) { temp = int1 ^ 0x4; } + else if (rcd == 3) { temp = int1 ^ 0x8; } + else if (rcd == 4) { temp = int1 ^ 0xC; } + else if (rcd == 5) { temp = int1 ^ 0xC; } + // else { temp = temp;} + + + //RAS precharge (tRP) + int1 = temp | 0x3; + if (rp == 2) { temp = int1 ^ 0x1; } + else if (rp == 3) { temp = int1 ^ 0x2; } + else if (rp == 4) { temp = int1 ^ 0x3; } + else if (rp == 5) { temp = int1 ^ 0x3; } + // else { temp = temp;} + + + // RAS Active to precharge (tRAS) + int1 = temp | 0x380; + if (ras == 5) { temp = int1 ^ 0x100; } + else if (ras == 6) { temp = int1 ^ 0x180; } + else if (ras == 7) { temp = int1 ^ 0x200; } + else if (ras == 8) { temp = int1 ^ 0x280; } + else if (ras == 9) { temp = int1 ^ 0x300; } + else if (ras == 10) { temp = int1 ^ 0x380; } + // else { temp = temp;} + + // CAS Latency (tCAS) + int1 = temp | 0x60; + if (cas == 1) { temp = int1 ^ 0x60; } // cas 2.5 + else if (cas == 2) { temp = int1 ^ 0x40; } + else if (cas == 3) { temp = int1 ^ 0x20; } + // else { temp = temp; } + + *ptr = temp; + __delay(500); + return; +} + + +void change_timing_nf2(int cas, int rcd, int rp, int ras) { + + ulong dramtlr, dramtlr2; + ulong int1, int2; + + pci_conf_read(0, 0, 1, 0x90, 4, &dramtlr); + pci_conf_read(0, 0, 1, 0xA0, 4, &dramtlr2); + + + // CAS Latency (tCAS) + int1 = dramtlr2 | 0x0070; + if (cas == 1) { int2 = int1 ^ 0x10; } // cas = 2.5 + else if (cas == 2) { int2 = int1 ^ 0x50; } + else if (cas == 3) { int2 = int1 ^ 0x40; } + else { int2 = dramtlr2; } + + pci_conf_write(0, 0, 1, 0xA0, 4, int2); + + // RAS-To-CAS (tRCD) + + int1 = dramtlr | 0x700000; + if (rcd == 2) { int2 = int1 ^ 0x500000; } + else if (rcd == 3) { int2 = int1 ^ 0x400000; } + else if (rcd == 4) { int2 = int1 ^ 0x300000; } + else if (rcd == 5) { int2 = int1 ^ 0x200000; } + else if (rcd == 6) { int2 = int1 ^ 0x100000; } + else { int2 = dramtlr;} + + + // RAS Precharge (tRP) + int1 = int2 | 0x70000000; + if (rp == 2) { int2 = int1 ^ 0x50000000; } + else if (rp == 3) { int2 = int1 ^ 0x40000000; } + else if (rp == 4) { int2 = int1 ^ 0x30000000; } + else if (rp == 5) { int2 = int1 ^ 0x20000000; } + else if (rp == 6) { int2 = int1 ^ 0x10000000; } + // else { int2 = int2;} + + + // RAS Active to precharge (tRAS) + + int1 = int2 | 0x78000; + if (ras == 4) { int2 = int1 ^ 0x58000; } + else if (ras == 5) { int2 = int1 ^ 0x50000; } + else if (ras == 6) { int2 = int1 ^ 0x48000; } + else if (ras == 7) { int2 = int1 ^ 0x40000; } + else if (ras == 8) { int2 = int1 ^ 0x38000; } + else if (ras == 9) { int2 = int1 ^ 0x30000; } + else if (ras == 10) { int2 = int1 ^ 0x28000; } + else if (ras == 11) { int2 = int1 ^ 0x20000; } + else if (ras == 12) { int2 = int1 ^ 0x18000; } + else if (ras == 13) { int2 = int1 ^ 0x10000; } + else if (ras == 14) { int2 = int1 ^ 0x08000; } + // else { int2 = int2;} + + + pci_conf_write(0, 0, 1, 0x90, 4, int2); + __delay(500); +} + + +void change_timing_amd64(int cas, int rcd, int rp, int ras) { + + ulong dramtlr; + ulong int1= 0x0; + + pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr); + + // RAS-To-CAS (tRCD) + int1 = dramtlr | 0x7000; + if (rcd == 2) { dramtlr = int1 ^ 0x5000; } + else if (rcd == 3) { dramtlr = int1 ^ 0x4000; } + else if (rcd == 4) { dramtlr = int1 ^ 0x3000; } + else if (rcd == 5) { dramtlr = int1 ^ 0x2000; } + else if (rcd == 6) { dramtlr = int1 ^ 0x1000; } + else if (rcd == 1) { dramtlr = int1 ^ 0x6000; } + // else { dramtlr = dramtlr;} + + + //RAS precharge (tRP) + int1 = dramtlr | 0x7000000; + if (rp == 2) { dramtlr = int1 ^ 0x5000000; } + else if (rp == 3) { dramtlr = int1 ^ 0x4000000; } + else if (rp == 1) { dramtlr = int1 ^ 0x6000000; } + else if (rp == 4) { dramtlr = int1 ^ 0x3000000; } + else if (rp == 5) { dramtlr = int1 ^ 0x2000000; } + else if (rp == 6) { dramtlr = int1 ^ 0x1000000; } + // else { dramtlr = dramtlr;} + + + // RAS Active to precharge (tRAS) + int1 = dramtlr | 0xF00000; + if (ras == 5) { dramtlr = int1 ^ 0xA00000; } + else if (ras == 6) { dramtlr = int1 ^ 0x900000; } + else if (ras == 7) { dramtlr = int1 ^ 0x800000; } + else if (ras == 8) { dramtlr = int1 ^ 0x700000; } + else if (ras == 9) { dramtlr = int1 ^ 0x600000; } + else if (ras == 10) { dramtlr = int1 ^ 0x500000; } + else if (ras == 11) { dramtlr = int1 ^ 0x400000; } + else if (ras == 12) { dramtlr = int1 ^ 0x300000; } + else if (ras == 13) { dramtlr = int1 ^ 0x200000; } + else if (ras == 14) { dramtlr = int1 ^ 0x100000; } + // else { dramtlr = dramtlr;} + + + // CAS Latency (tCAS) + int1 = dramtlr | 0x7; // some changes will cause the system hang, tried Draminit to no avail + if (cas == 1) { dramtlr = int1 ^ 0x2; } // cas 2.5 + else if (cas == 2) { dramtlr = int1 ^ 0x6; } + else if (cas == 3) { dramtlr = int1 ^ 0x5; } + else if (cas == 4) { dramtlr = int1 ^ 0x7; } //cas 1.5 on a64 + // else { dramtlr = dramtlr; } + +// pci_conf_read(0, 24, 2, 0x90, 4, &dramcr);// use dram init + pci_conf_write(0, 24, 2, 0x88, 4, dramtlr); + __delay(500); + +//////////////////////////////////////////////////////////////// +// trying using the draminit, but do not work +} + +// copy from lib.c code to add delay to chipset timing modification +void __delay(ulong loops) +{ + int d0; + __asm__ __volatile__( + "\tjmp 1f\n" + ".align 16\n" + "1:\tjmp 2f\n" + ".align 16\n" + "2:\tdecl %0\n\tjns 2b" + :"=&a" (d0) + :"0" (loops)); +} + +void amd64_tweak(int rwt, int wrt, int ref, int en2t, int rct, int rrd, int rwqb, int wr) +{ + ulong dramtlr; + ulong int1= 0x0; + + pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr); + + // Row Cycle time + int1 = dramtlr | 0xF0; + if (rct == 7 ) { dramtlr = int1 ^ 0xF0; } + else if (rct == 8 ) { dramtlr = int1 ^ 0xE0; } + else if (rct == 9 ) { dramtlr = int1 ^ 0xD0; } + else if (rct == 10) { dramtlr = int1 ^ 0xC0; } + else if (rct == 11) { dramtlr = int1 ^ 0xB0; } + else if (rct == 12) { dramtlr = int1 ^ 0xA0; } + else if (rct == 13) { dramtlr = int1 ^ 0x90; } + else if (rct == 14) { dramtlr = int1 ^ 0x80; } + else if (rct == 15) { dramtlr = int1 ^ 0x70; } + else if (rct == 16) { dramtlr = int1 ^ 0x60; } + else if (rct == 17) { dramtlr = int1 ^ 0x50; } + else if (rct == 18) { dramtlr = int1 ^ 0x40; } + else if (rct == 19) { dramtlr = int1 ^ 0x30; } + else if (rct == 20) { dramtlr = int1 ^ 0x20; } + // else { dramtlr = dramtlr;} + + //Active-avtive ras-ras delay + int1 = dramtlr | 0x70000; + if (rrd == 2) { dramtlr = int1 ^ 0x50000; } // 2 bus clocks + else if (rrd == 3) { dramtlr = int1 ^ 0x40000; } // 3 bus clocks + else if (rrd == 4) { dramtlr = int1 ^ 0x30000; } // 4 bus clocks + // else { dramtlr = dramtlr;} + + //Write recovery time + int1 = dramtlr | 0x10000000; + if (wr == 2) { dramtlr = int1 ^ 0x10000000; } // 2 bus clocks + else if (wr == 3) { dramtlr = int1 ^ 0x00000000; } // 3 bus clocks + // else { dramtlr = dramtlr;} + + pci_conf_write(0, 24, 2, 0x88, 4, dramtlr); + __delay(500); + ////////////////////////////////////////////// + + pci_conf_read(0, 24, 2, 0x8C, 4, &dramtlr); + + // Write-to read delay + int1 = dramtlr | 0x1; + if (wrt == 2) { dramtlr = int1 ^ 0x0; } + else if (wrt == 1) { dramtlr = int1 ^ 0x1; } + // else { dramtlr = dramtlr;} + + // Read-to Write delay + int1 = dramtlr | 0x70; + if (rwt == 1) { dramtlr = int1 ^ 0x70; } + else if (rwt == 2) { dramtlr = int1 ^ 0x60; } + else if (rwt == 3) { dramtlr = int1 ^ 0x50; } + else if (rwt == 4) { dramtlr = int1 ^ 0x40; } + else if (rwt == 5) { dramtlr = int1 ^ 0x30; } + else if (rwt == 6) { dramtlr = int1 ^ 0x20; } + // else { dramtlr = dramtlr;} + + //Refresh Rate + int1 = dramtlr | 0x1800; + if (ref == 1) { dramtlr = int1 ^ 0x1800; } // 15.6us + else if (ref == 2) { dramtlr = int1 ^ 0x1000; } // 7.8us + else if (ref == 3) { dramtlr = int1 ^ 0x0800; } // 3.9us + // else { dramtlr = dramtlr;} + + pci_conf_write(0, 24, 2, 0x8c, 4, dramtlr); + __delay(500); + ///////////////////////////////////// + + pci_conf_read(0, 24, 2, 0x90, 4, &dramtlr); + + // Enable 2t command + int1 = dramtlr | 0x10000000; + if (en2t == 2) { dramtlr = int1 ^ 0x00000000; } // 2T + else if (en2t == 1) { dramtlr = int1 ^ 0x10000000; } // 1T + // else { dramtlr = dramtlr;} + + // Read Write queue bypass count + int1 = dramtlr | 0xC000; + if (rwqb == 2) { dramtlr = int1 ^ 0xC000; } + else if (rwqb == 4) { dramtlr = int1 ^ 0x8000; } + else if (rwqb == 8) { dramtlr = int1 ^ 0x4000; } + else if (rwqb == 16) { dramtlr = int1 ^ 0x0000; } + // else { dramtlr = dramtlr;} + + pci_conf_write(0, 24, 2, 0x90, 4, dramtlr); + __delay(500); + restart(); +} + diff --git a/memtestEDK/Memtest/SingleComponents/extra.h b/memtestEDK/Memtest/SingleComponents/extra.h new file mode 100644 index 0000000..9bd7045 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/extra.h @@ -0,0 +1,27 @@ +// This is the extra stuff added to the memtest+ from memtest.org +// Code from Eric Nelson and Wee +/* extra.c + * + * Released under version 2 of the Gnu Public License. + * + */ + +#ifndef MEMTEST_EXTRA_H +#define MEMTEST_EXTRA_H + +void change_timing(int cas, int rcd, int rp, int ras); +void find_memctr(void); +void disclaimer(void); +void get_option(void); +void get_menu(void); +void a64_parameter(void); +int get_cas(void); +void change_timing_i852(int cas, int rcd, int rp, int ras); +void change_timing_i925(int cas, int rcd, int rp, int ras); +void change_timing_i875(int cas, int rcd, int rp, int ras); +void change_timing_nf2(int cas, int rcd, int rp, int ras); +void change_timing_amd64(int cas, int rcd, int rp, int ras); +void amd64_tweak(int rwt, int wrt, int ref, int en2t, int rct, int rrd, int rwqb, int wr); +void __delay(ulong loops); + +#endif /* MEMTEST_EXTRA_H */ diff --git a/memtestEDK/Memtest/SingleComponents/head.S b/memtestEDK/Memtest/SingleComponents/head.S new file mode 100644 index 0000000..d551336 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/head.S @@ -0,0 +1,847 @@ +/* + * linux/boot/head.S + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * head.S contains the 32-bit startup code. + * + * 1-Jan-96 Modified by Chris Brady for use as a boot/loader for MemTest-86. + * Setup the memory management for flat non-paged linear addressing. + * 17 May 2004 : Added X86_PWRCAP for AMD64 (Memtest86+ - Samuel D.) + */ + +.text +#define __ASSEMBLY__ +#include "defs.h" +#include "config.h" +#include "test.h" + + .code32 + .globl startup_32 +startup_32: + cld + cli + + /* Ensure I have a boot_stack pointer */ + testl %esp, %esp + jnz 0f + movl $(LOW_TEST_ADR + _GLOBAL_OFFSET_TABLE_), %esp + leal boot_stack_top@GOTOFF(%esp), %esp +0: + + /* Load the GOT pointer */ + call 0f +0: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx + + /* Pick the appropriate boot_stack address */ + leal boot_stack_top@GOTOFF(%ebx), %esp + + /* Reload all of the segment registers */ + leal gdt@GOTOFF(%ebx), %eax + movl %eax, 2 + gdt_descr@GOTOFF(%ebx) + lgdt gdt_descr@GOTOFF(%ebx) + leal flush@GOTOFF(%ebx), %eax + pushl $KERNEL_CS + pushl %eax + lret +flush: movl $KERNEL_DS, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + +/* + * Zero BSS + */ + cmpl $1, zerobss@GOTOFF(%ebx) + jnz zerobss_done + xorl %eax, %eax + leal _bss@GOTOFF(%ebx), %edi + leal _end@GOTOFF(%ebx), %ecx + subl %edi, %ecx +1: movl %eax, (%edi) + addl $4, %edi + subl $4, %ecx + jnz 1b + movl $0, zerobss@GOTOFF(%ebx) +zerobss_done: + +/* + * Setup an exception handler + */ + leal idt@GOTOFF(%ebx), %edi + + leal vec0@GOTOFF(%ebx), %edx + movl $(KERNEL_CS << 16),%eax + movw %dx, %ax /* selector = 0x0010 = cs */ + movw $0x8E00, %dx /* interrupt gate - dpl=0, present */ + movl %eax, (%edi) + movl %edx, 4(%edi) + addl $8, %edi + + leal vec1@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec2@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec3@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec4@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec5@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec6@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec7@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec8@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec9@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec10@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec11@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec12@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec13@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec14@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec15@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec16@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec17@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec18@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + leal vec19@GOTOFF(%ebx),%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + + /* Now that it is initialized load the interrupt descriptor table */ + leal idt@GOTOFF(%ebx), %eax + movl %eax, 2 + idt_descr@GOTOFF(%ebx) + lidt idt_descr@GOTOFF(%ebx) + + leal _dl_start@GOTOFF(%ebx), %eax + call *%eax + + /* Never forget to initialize the FPU ... Never ! */ + finit + + call test_start + + /* In case we return simulate an exception */ + pushfl + pushl %cs + call 0f +0: pushl $0 /* error code */ + pushl $257 /* vector */ + jmp int_hand + +vec0: + pushl $0 /* error code */ + pushl $0 /* vector */ + jmp int_hand +vec1: + pushl $0 /* error code */ + pushl $1 /* vector */ + jmp int_hand + +vec2: + pushl $0 /* error code */ + pushl $2 /* vector */ + jmp int_hand + +vec3: + pushl $0 /* error code */ + pushl $3 /* vector */ + jmp int_hand + +vec4: + pushl $0 /* error code */ + pushl $4 /* vector */ + jmp int_hand + +vec5: + pushl $0 /* error code */ + pushl $5 /* vector */ + jmp int_hand + +vec6: + pushl $0 /* error code */ + pushl $6 /* vector */ + jmp int_hand + +vec7: + pushl $0 /* error code */ + pushl $7 /* vector */ + jmp int_hand + +vec8: + /* error code */ + pushl $8 /* vector */ + jmp int_hand + +vec9: + pushl $0 /* error code */ + pushl $9 /* vector */ + jmp int_hand + +vec10: + /* error code */ + pushl $10 /* vector */ + jmp int_hand + +vec11: + /* error code */ + pushl $11 /* vector */ + jmp int_hand + +vec12: + /* error code */ + pushl $12 /* vector */ + jmp int_hand + +vec13: + /* error code */ + pushl $13 /* vector */ + jmp int_hand + +vec14: + /* error code */ + pushl $14 /* vector */ + jmp int_hand + +vec15: + pushl $0 /* error code */ + pushl $15 /* vector */ + jmp int_hand + +vec16: + pushl $0 /* error code */ + pushl $16 /* vector */ + jmp int_hand + +vec17: + /* error code */ + pushl $17 /* vector */ + jmp int_hand + +vec18: + pushl $0 /* error code */ + pushl $18 /* vector */ + jmp int_hand + +vec19: + pushl $0 /* error code */ + pushl $19 /* vector */ + jmp int_hand + +int_hand: + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + pushl %edi + pushl %esi + pushl %ebp + + /* original boot_stack pointer */ + leal 48(%esp), %eax + pushl %eax + pushl %ds + pushl %ss + pushl %esp /* pointer to trap regs struct on the boot_stack */ + call inter + addl $8, %esp + + popl %ebp + popl %esi + popl %edi + popl %edx + popl %ecx + popl %ebx + popl %eax + iret + +/* + * The interrupt descriptor table has room for 32 idt's + */ +.align 4 +.word 0 +idt_descr: + .word 20*8-1 # idt contains 32 entries + .long 0 + +idt: + .fill 20,8,0 # idt is uninitialized + +gdt_descr: + .word gdt_end - gdt - 1 + .long 0 + +.align 4 +.globl gdt, gdt_end +gdt: + .quad 0x0000000000000000 /* NULL descriptor */ + .quad 0x0000000000000000 /* not used */ + .quad 0x00cf9b000000ffff /* 0x10 main 4gb code at 0x000000 */ + .quad 0x00cf93000000ffff /* 0x18 main 4gb data at 0x000000 */ + + .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB) + .word 0 # base address = SETUPSEG + .byte 0x00, 0x9b # code read/exec/accessed + .byte 0x00, 0x00 # granularity = bytes + + + .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB) + .word 0 # base address = SETUPSEG + .byte 0x00, 0x93 # data read/write/accessed + .byte 0x00, 0x00 # granularity = bytes + +gdt_end: + +.data + +.macro ptes64 start, count=64 +.quad \start + 0x0000000 + 0xE3 +.quad \start + 0x0200000 + 0xE3 +.quad \start + 0x0400000 + 0xE3 +.quad \start + 0x0600000 + 0xE3 +.quad \start + 0x0800000 + 0xE3 +.quad \start + 0x0A00000 + 0xE3 +.quad \start + 0x0C00000 + 0xE3 +.quad \start + 0x0E00000 + 0xE3 +.if \count-1 +ptes64 "(\start+0x01000000)",\count-1 +.endif +.endm + +.macro maxdepth depth=1 +.if \depth-1 +maxdepth \depth-1 +.endif +.endm + +maxdepth + +# Page Directory Tables: +# There are 4 tables, the first two map the first 2 GB of memory. The last two are used with # PAE to map +# the rest of memory in 2 GB segments. The last two tables are changed in vmem.c to map each segment. +# We use 2 MB pages so only the Page Directory Table is used (no page tables). +.balign 4096 +.globl pd0 +pd0: + ptes64 0x0000000000000000 + +.balign 4096 +.globl pd1 +pd1: + ptes64 0x0000000040000000 + +.balign 4096 +.globl pd2 +pd2: + ptes64 0x0000000080000000 + +.balign 4096 +.globl pd3 +pd3: + ptes64 0x00000000C0000000 + +# Legacy Mode Page Directory Pointer Table: +# 4 Entries, pointing to the Page Directory Tables +.balign 4096 +.globl pdp +pdp: + .long pd0 + 1 + .long 0 + .long pd1 + 1 + .long 0 + .long pd2 + 1 + .long 0 + .long pd3 + 1 + .long 0 + +# Long Mode Page Directory Pointer Table: +# 4 Entries, pointing to the Page Directory Tables +.balign 4096 +lpdp: + .long pd0 + 3 + .long 0 + .long pd1 + 3 + .long 0 + .long pd2 + 3 + .long 0 + .long pd3 + 3 + .long 0 + + +# The long mode level 4 page map table +.balign 4096 +.globl pml4 +pml4: + .long lpdp + 3 + .long 0 +.previous + +#define RSTART startup_32 + + .globl query_pcbios +query_pcbios: + /* Save the caller save registers */ + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + call 1f +1: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx + + /* Compute the reloc address */ + leal RSTART@GOTOFF(%ebx), %esi + + /* Fixup real code pointer */ + movl %esi, %eax + shrl $4, %eax + movw %ax, 2 + realptr@GOTOFF(%ebx) + + /* Fixup protected code pointer */ + leal prot@GOTOFF(%ebx), %eax + movl %eax, protptr@GOTOFF(%ebx) + + /* Compute the gdt fixup */ + movl %esi, %eax + shll $16, %eax # Base low + + movl %esi, %ecx + shrl $16, %ecx + andl $0xff, %ecx + + movl %esi, %edx + andl $0xff000000, %edx + orl %edx, %ecx + + /* Fixup the gdt */ + andl $0x0000ffff, REAL_CS + 0 + gdt@GOTOFF(%ebx) + orl %eax, REAL_CS + 0 + gdt@GOTOFF(%ebx) + andl $0x00ffff00, REAL_CS + 4 + gdt@GOTOFF(%ebx) + orl %ecx, REAL_CS + 4 + gdt@GOTOFF(%ebx) + andl $0x0000ffff, REAL_DS + 0 + gdt@GOTOFF(%ebx) + orl %eax, REAL_DS + 0 + gdt@GOTOFF(%ebx) + andl $0x00ffff00, REAL_DS + 4 + gdt@GOTOFF(%ebx) + orl %ecx, REAL_DS + 4 + gdt@GOTOFF(%ebx) + + /* Fixup the gdt_descr */ + leal gdt@GOTOFF(%ebx), %eax + movl %eax, 2 + gdt_descr@GOTOFF(%ebx) + + lidt idt_real@GOTOFF(%ebx) + + /* Don't disable the a20 line */ + + /* Load 16bit data segments, to ensure the segment limits are set */ + movl $REAL_DS, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %ss + movl %eax, %fs + movl %eax, %gs + + /* Compute the boot_stack base */ + leal boot_stack@GOTOFF(%ebx), %ecx + /* Compute the address of meminfo */ + leal mem_info@GOTOFF(%ebx), %edi + + /* switch to 16bit mode */ + ljmp $REAL_CS, $1f - RSTART +1: + .code16 + /* Disable Paging and protected mode */ + /* clear the PG & PE bits of CR0 */ + movl %cr0,%eax + andl $~((1 << 31)|(1<<0)),%eax + movl %eax,%cr0 + + /* make intersegment jmp to flush the processor pipeline + * and reload %cs:%eip (to clear upper 16 bits of %eip). + */ + ljmp *(realptr - RSTART) +real: + /* we are in real mode now + * set up the real mode segment registers : %ds, %ss, %es, %gs, %fs + */ + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + /* Adjust the boot_stack pointer */ + movl %ecx, %eax + shrl $4, %eax + movw %ax, %ss + subl %ecx, %esp + + /* Save my base pointer */ + pushl %ebx + + /* Setup %ds to point to my data area */ + shrl $4, %edi + movl %edi, %ds + + /* Enable interrupts or BIOS's go crazy */ + sti + +# Get memory size (extended mem, kB) + +#define SMAP 0x534d4150 + + xorl %eax, %eax + movl %eax, (E88) + movl %eax, (E801) + movl %eax, (E820NR) + +# Try three different memory detection schemes. First, try +# e820h, which lets us assemble a memory map, then try e801h, +# which returns a 32-bit memory size, and finally 88h, which +# returns 0-64m + +# method E820H: +# the memory map from hell. e820h returns memory classified into +# a whole bunch of different types, and allows memory holes and +# everything. We scan through this memory map and build a list +# of the first 32 memory areas, which we return at [E820MAP]. +# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm + +meme820: + xorl %ebx, %ebx # continuation counter + movw $E820MAP, %di # point into the whitelist + # so we can have the bios + # directly write into it. + +jmpe820: + movl $0x0000e820, %eax # e820, upper word zeroed + movl $SMAP, %edx # ascii 'SMAP' + movl $20, %ecx # size of the e820rec + pushw %ds # data record. + popw %es + int $0x15 # make the call + jc bail820 # fall to e801 if it fails + + cmpl $SMAP, %eax # check the return is `SMAP' + jne bail820 # fall to e801 if it fails + +# cmpl $1, 16(%di) # is this usable memory? +# jne again820 + + # If this is usable memory, we save it by simply advancing %di by + # sizeof(e820rec). + # +good820: + movb (E820NR), %al # up to 32 entries + cmpb $E820MAX, %al + jnl bail820 + + incb (E820NR) + movw %di, %ax + addw $E820ENTRY_SIZE, %ax + movw %ax, %di +again820: + cmpl $0, %ebx # check to see if + jne jmpe820 # %ebx is set to EOF +bail820: + + +# method E801H: +# memory size is in 1k chunksizes, to avoid confusing loadlin. +# we store the 0xe801 memory size in a completely different place, +# because it will most likely be longer than 16 bits. + +meme801: + stc # fix to work around buggy + xorw %cx,%cx # BIOSes which dont clear/set + xorw %dx,%dx # carry on pass/error of + # e801h memory size call + # or merely pass cx,dx though + # without changing them. + movw $0xe801, %ax + int $0x15 + jc mem88 + + cmpw $0x0, %cx # Kludge to handle BIOSes + jne e801usecxdx # which report their extended + cmpw $0x0, %dx # memory in AX/BX rather than + jne e801usecxdx # CX/DX. The spec I have read + movw %ax, %cx # seems to indicate AX/BX + movw %bx, %dx # are more reasonable anyway... + +e801usecxdx: + andl $0xffff, %edx # clear sign extend + shll $6, %edx # and go from 64k to 1k chunks + movl %edx, (E801) # store extended memory size + andl $0xffff, %ecx # clear sign extend + addl %ecx, (E801) # and add lower memory into + # total size. + +# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or +# 64mb, depending on the bios) in ax. +mem88: + + movb $0x88, %ah + int $0x15 + movw %ax, (E88) + +#ifdef APM_OFF +# check for APM BIOS + movw $0x5300, %ax # APM BIOS installation check + xorw %bx, %bx + int $0x15 + jc done_apm_bios # error -> no APM BIOS + + cmpw $0x504d, %bx # check for "PM" signature + jne done_apm_bios # no signature -> no APM BIOS + + movw $0x5304, %ax # Disconnect first just in case + xorw %bx, %bx + int $0x15 # ignore return code + + movw $0x5301, %ax # Real Mode connect + xorw %bx, %bx + int $0x15 + jc done_apm_bios # error + + movw $0x5308, %ax # Disable APM + mov $0xffff, %bx + xorw %cx, %cx + int $0x15 + +done_apm_bios: +#endif + + /* O.k. the BIOS query is done switch back to protected mode */ + cli + + /* Restore my saved variables */ + popl %ebx + + /* Get an convinient %ds */ + movw %cs, %ax + movw %ax, %ds + + /* Load the global descriptor table */ + addr32 lgdt gdt_descr - RSTART + + /* Turn on protected mode */ + /* Set the PE bit in CR0 */ + movl %cr0,%eax + orl $(1<<0),%eax + movl %eax,%cr0 + + /* flush the prefetch queue, and relaod %cs:%eip */ + data32 ljmp *(protptr - RSTART) +prot: + .code32 + /* Reload other segment registers */ + movl $KERNEL_DS, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + /* Adjust the boot_stack pointer */ + leal boot_stack@GOTOFF(%ebx), %eax + addl %eax, %esp + + /* Restore the caller saved registers */ + popl %ebp + popl %edi + popl %esi + popl %ebx + movl $1, %eax + ret + +realptr: + .word real - RSTART + .word 0x0000 +protptr: + .long 0 + .long KERNEL_CS + +idt_real: + .word 0x400 - 1 # idt limit ( 256 entries) + .word 0, 0 # idt base = 0L + +/* _ap_trampoline_start is the entry point for cpus other than the + * bootstrap cpu. The code between _ap_trampoline_start to + * _ap_trampoline_protmode is copied to BootCodeStart(0x9000). + * The ljmp after turning on CR0.PE will jump to the + * relocatable code which usually resides at 0x10000 + _ap_trampoline_protmode. + * + * The trampoline code uses a temporary GDT. The entries of this temporary + * GDT must match the first few entries of the GDT used by the relocatble + * memtest code(see 'gdt' sybmol in this file). + * + */ + .globl _ap_trampoline_start + .globl _ap_trampoline_protmode + .code16 +_ap_trampoline_start: + lgdt 0x0 /* will be fixed up later, see smp.c:BootAP()*/ + movl %cr0, %eax + orl $1, %eax + movl %eax, %cr0 + data32 ljmp $KERNEL_CS, $_ap_trampoline_protmode +_ap_trampoline_protmode: + .code32 + movw $KERNEL_DS, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + movl $(LOW_TEST_ADR + _GLOBAL_OFFSET_TABLE_), %esp + leal boot_stack_top@GOTOFF(%esp), %esp + pushl $0 + popf + call startup_32 + /* if we ever return, we'll just loop forever */ + cli +2: hlt + jmp 2b +.data +zerobss: .long 1 +.previous +.data +.balign 16 + .globl mem_info +mem_info: + . = . + MEMINFO_SIZE +.previous +.bss +.balign 16 +boot_stack: + .globl boot_stack + . = . + 4096 +boot_stack_top: + .globl boot_stack_top +.previous diff --git a/memtestEDK/Memtest/SingleComponents/init.c b/memtestEDK/Memtest/SingleComponents/init.c new file mode 100644 index 0000000..32bff7f --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/init.c @@ -0,0 +1,1296 @@ +/* + * MemTest86+ V5 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + * ------------------------------------------------ + * init.c - MemTest-86 Version 3.6 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + */ + + +#include "stdin.h" +#include "stddef.h" +#include "test.h" +#include "defs.h" +#include "config.h" +#include "cpuid.h" +#include "smp.h" +#include "io.h" +#include "spd.h" +#include "pci.h" +#include "controller.h" + +extern struct tseq tseq[]; +extern short memsz_mode; +extern int num_cpus; +extern int act_cpus; +extern int found_cpus; +unsigned long imc_type = 0; +extern int maxcpus; +extern char cpu_mask[]; +extern void initialise_cpus(); + +/* Here we store all of the cpuid data */ +extern struct cpu_ident cpu_id; + +int l1_cache=0, l2_cache=0, l3_cache=0; +int tsc_invariable = 0; +ulong extclock; + +ulong memspeed(ulong src, ulong len, int iter); +static void cpu_type(void); +static int cpuspeed(void); +static void get_cache_size(); +static void cpu_cache_speed(); +void get_cpuid(); +int beepmode; +extern short dmi_initialized; +extern int dmi_err_cnts[MAX_DMI_MEMDEVS]; + +/* Failsafe function */ +/* msec: number of ms to wait - scs: scancode expected to stop */ +/* bits: 0 = extended detection - 1: SMP - 2: Temp Check */ +/* 3: MP SMP - 4-7: RSVD */ +void failsafe(int msec, int scs) +{ + int i; + ulong sh, sl, l, h, t; + unsigned char c; + volatile char *pp; + + for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(18*2)+1); i<40; i++, pp+=2) { + *pp = 0x1E; + } + for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(18*2)+1); i<3; i++, pp+=2) { + *pp = 0x9E; + } + for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(55*2)+1); i<3; i++, pp+=2) { + *pp = 0x9E; + } + + cprint(18, 18, "==> Press F1 to enter Fail-Safe Mode <=="); + + if(vv->fail_safe & 2) + { + cprint(19, 15, "==> Press F2 to force Multi-Threading (SMP) <=="); + } + + /* save the starting time */ + asm __volatile__ + ("rdtsc":"=a" (sl),"=d" (sh)); + + /* loop for n seconds */ + while (1) { + asm __volatile__( + "rdtsc":"=a" (l),"=d" (h)); + asm __volatile__ ( + "subl %2,%0\n\t" + "sbbl %3,%1" + :"=a" (l), "=d" (h) + :"g" (sl), "g" (sh), + "0" (l), "1" (h)); + + t = h * ((unsigned)0xffffffff / vv->clks_msec); + t += (l / vv->clks_msec); + + /* Is the time up? */ + if (t >= msec) { break; } + + /* Is expected Scan code pressed? */ + c = get_key(); + c &= 0x7f; + + /* F1 */ + if(c == scs) { vv->fail_safe |= 1; break; } + + /* F2 */ + if(c == scs+1) + { + vv->fail_safe ^= 2; + break; + + } + + /* F3 */ + if(c == scs+2) + { + if(vv->fail_safe & 2) { vv->fail_safe ^= 2; } + vv->fail_safe |= 8; + break; + } + } + + cprint(18, 18, " "); + cprint(19, 15, " "); + + for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(18*2)+1); i<40; i++, pp+=2) { + *pp = 0x17; + } +} + +static void display_init(void) +{ + int i; + volatile char *pp; + + /* Set HW cursor out of screen boundaries */ + __outb(0x0F, 0x03D4); + __outb(0xFF, 0x03D5); + + __outb(0x0E, 0x03D4); + __outb(0xFF, 0x03D5); + + + serial_echo_init(); + serial_echo_print("[LINE_SCROLL;24r"); /* Set scroll area row 7-23 */ + serial_echo_print("[H[2J"); /* Clear Screen */ + serial_echo_print("[37m[44m"); + serial_echo_print("[0m"); + serial_echo_print("[37m[44m"); + + /* Clear screen & set background to blue */ + for(i=0, pp=(char *)(SCREEN_ADR); i<80*24; i++) { + *pp++ = ' '; + *pp++ = 0x17; + } + + /* Make the name background green */ + for(i=0, pp=(char *)(SCREEN_ADR+1); i<TITLE_WIDTH; i++, pp+=2) { + *pp = 0x20; + } + cprint(0, 0, " Memtest86 5.31b "); + + /* Set Blinking "+" */ + for(i=0, pp=(char *)(SCREEN_ADR+1); i<2; i++, pp+=30) { + *pp = 0xA4; + } + cprint(0, 15, "+"); + + /* Do reverse video for the bottom display line */ + for(i=0, pp=(char *)(SCREEN_ADR+1+(24 * 160)); i<80; i++, pp+=2) { + *pp = 0x71; + } + + serial_echo_print("[0m"); +} + +/* + * Initialize test, setup screen and find out how much memory there is. + */ +void init(void) +{ + int i; + + outb(0x8, 0x3f2); /* Kill Floppy Motor */ + + /* Turn on cache */ + set_cache(1); + + /* Setup the display */ + display_init(); + + cprint(5, 60, "| Time: 0:00:00"); + cprint(1, COL_MID,"Pass %"); + cprint(2, COL_MID,"Test %"); + cprint(3, COL_MID,"Test #"); + cprint(4, COL_MID,"Testing: "); + cprint(5, COL_MID,"Pattern: "); + cprint(1, 0, "CLK: (32b Mode)"); + cprint(2, 0, "L1 Cache: Unknown "); + cprint(3, 0, "L2 Cache: Unknown "); + cprint(4, 0, "L3 Cache: None "); + cprint(5, 0, "Memory : "); + cprint(6, 0, "------------------------------------------------------------------------------"); + cprint(7, 0, "Core#:"); + cprint(8, 0, "State:"); + cprint(9, 0, "Cores: Active / Total (Run: All) | Pass: 0 Errors: 0 "); + cprint(10, 0, "------------------------------------------------------------------------------"); + + /* + for(i=0, pp=(char *)(SCREEN_ADR+(5*160)+(53*2)+1); i<20; i++, pp+=2) { + *pp = 0x92; + } + + for(i=0, pp=(char *)(SCREEN_ADR+0*160+1); i<80; i++, pp+=2) { + *pp = 0x47; + } + */ + + cprint(7, 39, "| Chipset : Unknown"); + cprint(8, 39, "| Memory Type : Unknown"); + + for(i=0; i < 6; i++) { + cprint(i, COL_MID-2, "| "); + } + + footer(); + + aprint(5, 10, vv->test_pages); + + vv->pass = 0; + vv->msg_line = 0; + vv->ecount = 0; + vv->ecc_ecount = 0; + vv->testsel = -1; + vv->msg_line = LINE_SCROLL-1; + vv->scroll_start = vv->msg_line * 160; + vv->erri.low_addr.page = 0x7fffffff; + vv->erri.low_addr.offset = 0xfff; + vv->erri.high_addr.page = 0; + vv->erri.high_addr.offset = 0; + vv->erri.min_bits = 32; + vv->erri.max_bits = 0; + vv->erri.min_bits = 32; + vv->erri.max_bits = 0; + vv->erri.maxl = 0; + vv->erri.cor_err = 0; + vv->erri.ebits = 0; + vv->erri.hdr_flag = 0; + vv->erri.tbits = 0; + for (i=0; tseq[i].msg != NULL; i++) { + tseq[i].errors = 0; + } + if (dmi_initialized) { + for (i=0; i < MAX_DMI_MEMDEVS; i++){ + if (dmi_err_cnts[i] > 0) { + dmi_err_cnts[i] = 0; + } + } + } + + /* setup beep mode */ + beepmode = BEEP_MODE; + + /* Get the cpu and cache information */ + get_cpuid(); + + /* setup pci */ + pci_init(); + + get_cache_size(); + + cpu_type(); + + cpu_cache_speed(); + + /* Check fail safe */ + failsafe(5000, 0x3B); + + /* Initalize SMP */ + initialise_cpus(); + + for (i = 0; i <num_cpus; i++) { + dprint(7, i+7, i%10, 1, 0); + cprint(8, i+7, "S"); + } + + dprint(9, 19, num_cpus, 2, 0); + + if((vv->fail_safe & 3) == 2) + { + cprint(LINE_CPU,9, "(SMP: Disabled)"); + cprint(LINE_RAM,9, "Running..."); + } + // dprint(10, 5, found_cpus, 2, 0); + + /* Find Memory Specs */ + if(vv->fail_safe & 1) + { + cprint(LINE_CPU, COL_SPEC, " **** FAIL SAFE **** FAIL SAFE **** "); + cprint(LINE_RAM, COL_SPEC, " No detection, same reliability "); + } else { + find_controller(); + get_spd_spec(); + if(num_cpus <= 16 && !(vv->fail_safe & 4)) { coretemp(); } + } + + if(vv->check_temp > 0 && !(vv->fail_safe & 4)) + { + cprint(LINE_CPU, 26, "| CPU Temp"); + cprint(LINE_CPU+1, 26, "| øC"); + } + + beep(600); + beep(1000); + + /* Record the start time */ + asm __volatile__ ("rdtsc":"=a" (vv->startl),"=d" (vv->starth)); + vv->snapl = vv->startl; + vv->snaph = vv->starth; + if (l1_cache == 0) { l1_cache = 64; } + if (l2_cache == 0) { l1_cache = 512; } + vv->printmode=PRINTMODE_ADDRESSES; + vv->numpatn=0; +} + +/* Get cache sizes for most AMD and Intel CPUs, exceptions for old CPUs are + * handled in CPU detection */ +void get_cache_size() +{ + int i, j, n, size; + unsigned int v[4]; + unsigned char *dp = (unsigned char *)v; + struct cpuid4_eax *eax = (struct cpuid4_eax *)&v[0]; + struct cpuid4_ebx *ebx = (struct cpuid4_ebx *)&v[1]; + struct cpuid4_ecx *ecx = (struct cpuid4_ecx *)&v[2]; + + switch(cpu_id.vend_id.char_array[0]) { + /* AMD Processors */ + case 'A': + //l1_cache = cpu_id.cache_info.amd.l1_i_sz; + l1_cache = cpu_id.cache_info.amd.l1_d_sz; + l2_cache = cpu_id.cache_info.amd.l2_sz; + l3_cache = cpu_id.cache_info.amd.l3_sz; + l3_cache *= 512; + break; + case 'G': + /* Intel Processors */ + l1_cache = 0; + l2_cache = 0; + l3_cache = 0; + + /* Use CPUID(4) if it is available */ + if (cpu_id.max_cpuid > 3) { + + /* figure out how many cache leaves */ + n = -1; + do + { + ++n; + /* Do cpuid(4) loop to find out num_cache_leaves */ + cpuid_count(4, n, &v[0], &v[1], &v[2], &v[3]); + } while ((eax->ctype) != 0); + + /* loop through all of the leaves */ + for (i=0; i<n; i++) + { + cpuid_count(4, i, &v[0], &v[1], &v[2], &v[3]); + + /* Check for a valid cache type */ + if (eax->ctype == 1 || eax->ctype == 3) + { + + /* Compute the cache size */ + size = (ecx->number_of_sets + 1) * + (ebx->coherency_line_size + 1) * + (ebx->physical_line_partition + 1) * + (ebx->ways_of_associativity + 1); + size /= 1024; + + switch (eax->level) + { + case 1: + l1_cache += size; + break; + case 2: + l2_cache += size; + break; + case 3: + l3_cache += size; + break; + } + } + } + return; + } + + /* No CPUID(4) so we use the older CPUID(2) method */ + /* Get number of times to iterate */ + cpuid(2, &v[0], &v[1], &v[2], &v[3]); + n = v[0] & 0xff; + for (i=0 ; i<n ; i++) { + cpuid(2, &v[0], &v[1], &v[2], &v[3]); + + /* If bit 31 is set, this is an unknown format */ + for (j=0 ; j<3 ; j++) { + if (v[j] & (1 << 31)) { + v[j] = 0; + } + } + + /* Byte 0 is level count, not a descriptor */ + for (j = 1 ; j < 16 ; j++) { + switch(dp[j]) { + case 0x6: + case 0xa: + case 0x66: + l1_cache += 8; + break; + case 0x8: + case 0xc: + case 0xd: + case 0x60: + case 0x67: + l1_cache += 16; + break; + case 0xe: + l1_cache += 24; + break; + case 0x9: + case 0x2c: + case 0x30: + case 0x68: + l1_cache += 32; + break; + case 0x39: + case 0x3b: + case 0x41: + case 0x79: + l2_cache += 128; + break; + case 0x3a: + l2_cache += 192; + break; + case 0x21: + case 0x3c: + case 0x3f: + case 0x42: + case 0x7a: + case 0x82: + l2_cache += 256; + break; + case 0x3d: + l2_cache += 384; + break; + case 0x3e: + case 0x43: + case 0x7b: + case 0x7f: + case 0x80: + case 0x83: + case 0x86: + l2_cache += 512; + break; + case 0x44: + case 0x78: + case 0x7c: + case 0x84: + case 0x87: + l2_cache += 1024; + break; + case 0x45: + case 0x7d: + case 0x85: + l2_cache += 2048; + break; + case 0x48: + l2_cache += 3072; + break; + case 0x4e: + l2_cache += 6144; + break; + case 0x23: + case 0xd0: + l3_cache += 512; + break; + case 0xd1: + case 0xd6: + l3_cache += 1024; + break; + case 0x25: + case 0xd2: + case 0xd7: + case 0xdc: + case 0xe2: + l3_cache += 2048; + break; + case 0x29: + case 0x46: + case 0x49: + case 0xd8: + case 0xdd: + case 0xe3: + l3_cache += 4096; + break; + case 0x4a: + l3_cache += 6144; + break; + case 0x47: + case 0x4b: + case 0xde: + case 0xe4: + l3_cache += 8192; + break; + case 0x4c: + case 0xea: + l3_cache += 12288; + break; + case 0x4d: + l3_cache += 16384; + break; + case 0xeb: + l3_cache += 18432; + break; + case 0xec: + l3_cache += 24576; + break; + } /* end switch */ + } /* end for 1-16 */ + } /* end for 0 - n */ + } +} + +/* + * Find IMC type and set global variables accordingly + */ +void detect_imc(void) +{ + // Check AMD IMC + if(cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.family == 0xF) + { + switch(cpu_id.vers.bits.extendedFamily) + { + case 0x0: + imc_type = 0x0100; // Old K8 + break; + case 0x1: + case 0x2: + imc_type = 0x0101; // K10 (Family 10h & 11h) + break; + case 0x3: + imc_type = 0x0102; // A-Series APU (Family 12h) + break; + case 0x5: + imc_type = 0x0103; // C- / E- / Z- Series APU (Family 14h) + break; + case 0x6: + imc_type = 0x0104; // FX Series (Family 15h) + break; + case 0x7: + imc_type = 0x0105; // Kabini & related (Family 16h) + break; + } + return; + } + + // Check Intel IMC + if(cpu_id.vend_id.char_array[0] == 'G' && cpu_id.vers.bits.family == 6 && cpu_id.vers.bits.extendedModel) + { + switch(cpu_id.vers.bits.model) + { + case 0x5: + if(cpu_id.vers.bits.extendedModel == 2) { imc_type = 0x0003; } // Core i3/i5 1st Gen 45 nm (NHM) + if(cpu_id.vers.bits.extendedModel == 3) { vv->fail_safe |= 4; } // Atom Clover Trail + if(cpu_id.vers.bits.extendedModel == 4) { imc_type = 0x0007; } // HSW-ULT + break; + case 0x6: + if(cpu_id.vers.bits.extendedModel == 3) { + imc_type = 0x0009; // Atom Cedar Trail + vv->fail_safe |= 4; // Disable Core temp + } + break; + case 0xA: + switch(cpu_id.vers.bits.extendedModel) + { + case 0x1: + imc_type = 0x0001; // Core i7 1st Gen 45 nm (NHME) + break; + case 0x2: + imc_type = 0x0004; // Core 2nd Gen (SNB) + break; + case 0x3: + imc_type = 0x0006; // Core 3nd Gen (IVB) + break; + } + break; + case 0xC: + switch(cpu_id.vers.bits.extendedModel) + { + case 0x1: + if(cpu_id.vers.bits.stepping > 9) { imc_type = 0x0008; } // Atom PineView + vv->fail_safe |= 4; // Disable Core temp + break; + case 0x2: + imc_type = 0x0002; // Core i7 1st Gen 32 nm (WMR) + break; + case 0x3: + imc_type = 0x0007; // Core 4nd Gen (HSW) + break; + } + break; + case 0xD: + imc_type = 0x0005; // SNB-E + break; + case 0xE: + imc_type = 0x0001; // Core i7 1st Gen 45 nm (NHM) + break; + } + + if(imc_type) { tsc_invariable = 1; } + return; + } +} + +void smp_default_mode(void) +{ + int i, result; + char *cpupsn = cpu_id.brand_id.char_array; + char *disabledcpu[] = { "Opteron", "Xeon", "EPYC", "Genuine Intel" }; + + for(i = 0; i < 3; i++) + { + result = mt86_strstr(cpupsn , disabledcpu[i]); + if(result != -1) { vv->fail_safe |= 0b10; } + } + + // For 5.01 release, SMP disabled by defualt by config.h toggle + if(CONSERVATIVE_SMP) { vv->fail_safe |= 0b10; } + +} + +/* + * Find CPU type + */ +void cpu_type(void) +{ + /* If we can get a brand string use it, and we are done */ + if (cpu_id.max_xcpuid >= 0x80000004) { + cprint(0, COL_MID, cpu_id.brand_id.char_array); + //If we have a brand string, maybe we have an IMC. Check that. + detect_imc(); + smp_default_mode(); + return; + } + + /* The brand string is not available so we need to figure out + * CPU what we have */ + switch(cpu_id.vend_id.char_array[0]) { + /* AMD Processors */ + case 'A': + switch(cpu_id.vers.bits.family) { + case 4: + switch(cpu_id.vers.bits.model) { + case 3: + cprint(0, COL_MID, "AMD 486DX2"); + break; + case 7: + cprint(0, COL_MID, "AMD 486DX2-WB"); + break; + case 8: + cprint(0, COL_MID, "AMD 486DX4"); + break; + case 9: + cprint(0, COL_MID, "AMD 486DX4-WB"); + break; + case 14: + cprint(0, COL_MID, "AMD 5x86-WT"); + break; + case 15: + cprint(0, COL_MID, "AMD 5x86-WB"); + break; + } + /* Since we can't get CPU speed or cache info return */ + return; + case 5: + switch(cpu_id.vers.bits.model) { + case 0: + case 1: + case 2: + case 3: + cprint(0, COL_MID, "AMD K5"); + l1_cache = 8; + break; + case 6: + case 7: + cprint(0, COL_MID, "AMD K6"); + break; + case 8: + cprint(0, COL_MID, "AMD K6-2"); + break; + case 9: + cprint(0, COL_MID, "AMD K6-III"); + break; + case 13: + cprint(0, COL_MID, "AMD K6-III+"); + break; + } + break; + case 6: + + switch(cpu_id.vers.bits.model) { + case 1: + cprint(0, COL_MID, "AMD Athlon (0.25)"); + break; + case 2: + case 4: + cprint(0, COL_MID, "AMD Athlon (0.18)"); + break; + case 6: + if (l2_cache == 64) { + cprint(0, COL_MID, "AMD Duron (0.18)"); + } else { + cprint(0, COL_MID, "Athlon XP (0.18)"); + } + break; + case 8: + case 10: + if (l2_cache == 64) { + cprint(0, COL_MID, "AMD Duron (0.13)"); + } else { + cprint(0, COL_MID, "Athlon XP (0.13)"); + } + break; + case 3: + case 7: + cprint(0, COL_MID, "AMD Duron"); + /* Duron stepping 0 CPUID for L2 is broken */ + /* (AMD errata T13)*/ + if (cpu_id.vers.bits.stepping == 0) { /* stepping 0 */ + /* Hard code the right L2 size */ + l2_cache = 64; + } else { + } + break; + } + break; + + /* All AMD family values >= 10 have the Brand ID + * feature so we don't need to find the CPU type */ + } + break; + + /* Intel or Transmeta Processors */ + case 'G': + if ( cpu_id.vend_id.char_array[7] == 'T' ) { /* GenuineTMx86 */ + if (cpu_id.vers.bits.family == 5) { + cprint(0, COL_MID, "TM 5x00"); + } else if (cpu_id.vers.bits.family == 15) { + cprint(0, COL_MID, "TM 8x00"); + } + l1_cache = cpu_id.cache_info.ch[3] + cpu_id.cache_info.ch[7]; + l2_cache = (cpu_id.cache_info.ch[11]*256) + cpu_id.cache_info.ch[10]; + } else { /* GenuineIntel */ + if (cpu_id.vers.bits.family == 4) { + switch(cpu_id.vers.bits.model) { + case 0: + case 1: + cprint(0, COL_MID, "Intel 486DX"); + break; + case 2: + cprint(0, COL_MID, "Intel 486SX"); + break; + case 3: + cprint(0, COL_MID, "Intel 486DX2"); + break; + case 4: + cprint(0, COL_MID, "Intel 486SL"); + break; + case 5: + cprint(0, COL_MID, "Intel 486SX2"); + break; + case 7: + cprint(0, COL_MID, "Intel 486DX2-WB"); + break; + case 8: + cprint(0, COL_MID, "Intel 486DX4"); + break; + case 9: + cprint(0, COL_MID, "Intel 486DX4-WB"); + break; + } + /* Since we can't get CPU speed or cache info return */ + return; + } + + + switch(cpu_id.vers.bits.family) { + case 5: + switch(cpu_id.vers.bits.model) { + case 0: + case 1: + case 2: + case 3: + case 7: + cprint(0, COL_MID, "Pentium"); + if (l1_cache == 0) { + l1_cache = 8; + } + break; + case 4: + case 8: + cprint(0, COL_MID, "Pentium-MMX"); + if (l1_cache == 0) { + l1_cache = 16; + } + break; + } + break; + case 6: + switch(cpu_id.vers.bits.model) { + case 0: + case 1: + cprint(0, COL_MID, "Pentium Pro"); + break; + case 3: + case 4: + cprint(0, COL_MID, "Pentium II"); + break; + case 5: + if (l2_cache == 0) { + cprint(0, COL_MID, "Celeron"); + } else { + cprint(0, COL_MID, "Pentium II"); + } + break; + case 6: + if (l2_cache == 128) { + cprint(0, COL_MID, "Celeron"); + } else { + cprint(0, COL_MID, "Pentium II"); + } + } + break; + case 7: + case 8: + case 11: + if (l2_cache == 128) { + cprint(0, COL_MID, "Celeron"); + } else { + cprint(0, COL_MID, "Pentium III"); + } + break; + case 9: + if (l2_cache == 512) { + cprint(0, COL_MID, "Celeron M (0.13)"); + } else { + cprint(0, COL_MID, "Pentium M (0.13)"); + } + break; + case 10: + cprint(0, COL_MID, "Pentium III Xeon"); + break; + case 12: + l1_cache = 24; + cprint(0, COL_MID, "Atom (0.045)"); + break; + case 13: + if (l2_cache == 1024) { + cprint(0, COL_MID, "Celeron M (0.09)"); + } else { + cprint(0, COL_MID, "Pentium M (0.09)"); + } + break; + case 14: + cprint(0, COL_MID, "Intel Core"); + break; + case 15: + if (l2_cache == 1024) { + cprint(0, COL_MID, "Pentium E"); + } else { + cprint(0, COL_MID, "Intel Core 2"); + } + break; + } + break; + case 15: + switch(cpu_id.vers.bits.model) { + case 0: + case 1: + case 2: + if (l2_cache == 128) { + cprint(0, COL_MID, "Celeron"); + } else { + cprint(0, COL_MID, "Pentium 4"); + } + break; + case 3: + case 4: + if (l2_cache == 256) { + cprint(0, COL_MID, "Celeron (0.09)"); + } else { + cprint(0, COL_MID, "Pentium 4 (0.09)"); + } + break; + case 6: + cprint(0, COL_MID, "Pentium D (65nm)"); + break; + default: + cprint(0, COL_MID, "Unknown Intel"); + break; + break; + } + + } + break; + + /* VIA/Cyrix/Centaur Processors with CPUID */ + case 'C': + if ( cpu_id.vend_id.char_array[1] == 'e' ) { /* CentaurHauls */ + l1_cache = cpu_id.cache_info.ch[3] + cpu_id.cache_info.ch[7]; + l2_cache = cpu_id.cache_info.ch[11]; + switch(cpu_id.vers.bits.family){ + case 5: + cprint(0, COL_MID, "Centaur 5x86"); + break; + case 6: // VIA C3 + switch(cpu_id.vers.bits.model){ + default: + if (cpu_id.vers.bits.stepping < 8) { + cprint(0, COL_MID, "VIA C3 Samuel2"); + } else { + cprint(0, COL_MID, "VIA C3 Eden"); + } + break; + case 10: + cprint(0, COL_MID, "VIA C7 (C5J)"); + l1_cache = 64; + l2_cache = 128; + break; + case 13: + cprint(0, COL_MID, "VIA C7 (C5R)"); + l1_cache = 64; + l2_cache = 128; + break; + case 15: + cprint(0, COL_MID, "VIA Isaiah (CN)"); + l1_cache = 64; + l2_cache = 128; + break; + } + } + } else { /* CyrixInstead */ + switch(cpu_id.vers.bits.family) { + case 5: + switch(cpu_id.vers.bits.model) { + case 0: + cprint(0, COL_MID, "Cyrix 6x86MX/MII"); + break; + case 4: + cprint(0, COL_MID, "Cyrix GXm"); + break; + } + return; + + case 6: // VIA C3 + switch(cpu_id.vers.bits.model) { + case 6: + cprint(0, COL_MID, "Cyrix III"); + break; + case 7: + if (cpu_id.vers.bits.stepping < 8) { + cprint(0, COL_MID, "VIA C3 Samuel2"); + } else { + cprint(0, COL_MID, "VIA C3 Ezra-T"); + } + break; + case 8: + cprint(0, COL_MID, "VIA C3 Ezra-T"); + break; + case 9: + cprint(0, COL_MID, "VIA C3 Nehemiah"); + break; + } + // L1 = L2 = 64 KB from Cyrix III to Nehemiah + l1_cache = 64; + l2_cache = 64; + break; + } + } + break; + /* Unknown processor */ + default: + /* Make a guess at the family */ + switch(cpu_id.vers.bits.family) { + case 5: + cprint(0, COL_MID, "586"); + case 6: + cprint(0, COL_MID, "686"); + default: + cprint(0, COL_MID, "Unidentified Processor"); + } + } +} + +#define STEST_ADDR 0x100000 /* Measure memory speed starting at 1MB */ + +/* Measure and display CPU and cache sizes and speeds */ +void cpu_cache_speed() +{ + int i, off = 4; + ulong speed; + + + /* Print CPU speed */ + if ((speed = cpuspeed()) > 0) { + if (speed < 999499) { + speed += 50; /* for rounding */ + cprint(1, off, " . MHz"); + dprint(1, off+1, speed/1000, 3, 1); + dprint(1, off+5, (speed/100)%10, 1, 0); + } else { + speed += 500; /* for rounding */ + cprint(1, off, " MHz"); + dprint(1, off, speed/1000, 5, 0); + } + extclock = speed; + } + + /* Print out L1 cache info */ + /* To measure L1 cache speed we use a block size that is 1/4th */ + /* of the total L1 cache size since half of it is for instructions */ + if (l1_cache) { + cprint(2, 0, "L1 Cache: K "); + dprint(2, 11, l1_cache, 3, 0); + if ((speed=memspeed(STEST_ADDR, (l1_cache/2)*1024, 200))) { + cprint(2, 16, " MB/s"); + dprint(2, 16, speed, 6, 0); + } + } + + /* Print out L2 cache info */ + /* We measure the L2 cache speed by using a block size that is */ + /* the size of the L1 cache. We have to fudge if the L1 */ + /* cache is bigger than the L2 */ + if (l2_cache) { + cprint(3, 0, "L2 Cache: K "); + dprint(3, 10, l2_cache, 4, 0); + + if (l2_cache < l1_cache) { + i = l1_cache / 4 + l2_cache / 4; + } else { + i = l1_cache; + } + if ((speed=memspeed(STEST_ADDR, i*1024, 200))) { + cprint(3, 16, " MB/s"); + dprint(3, 16, speed, 6, 0); + } + } + /* Print out L3 cache info */ + /* We measure the L3 cache speed by using a block size that is */ + /* 2X the size of the L2 cache. */ + + if (l3_cache) + { + cprint(4, 0, "L3 Cache: K "); + aprint(4, 10, l3_cache/4); + //dprint(4, 10, l3_cache, 4, 0); + + i = l2_cache*2; + + if ((speed=memspeed(STEST_ADDR, i*1024, 150))) { + cprint(4, 16, " MB/s"); + dprint(4, 16, speed, 6, 0); + } + } +} + +/* Measure and display memory speed, multitasked using all CPUs */ +ulong spd[MAX_CPUS]; +void get_mem_speed(int me, int ncpus) +{ + int i; + ulong speed=0; + + /* Determine memory speed. To find the memory speed we use + * A block size that is the sum of all the L1, L2 & L3 caches + * in all cpus * 6 */ + i = (l3_cache + l2_cache + l1_cache) * 4; + + /* Make sure that we have enough memory to do the test */ + /* If not use all we have */ + if ((1 + (i * 2)) > (vv->plim_upper << 2)) { + i = ((vv->plim_upper <<2) - 1) / 2; + } + + speed = memspeed(STEST_ADDR, i * 1024, 100); + cprint(5, 16, " MB/s"); + dprint(5, 16, speed, 6, 0); + +} + +/* #define TICKS 5 * 11832 (count = 6376)*/ +/* #define TICKS (65536 - 12752) */ +#define TICKS 59659 /* 50 ms */ + +/* Returns CPU clock in khz */ +ulong stlow, sthigh; +static int cpuspeed(void) +{ + int loops; + ulong end_low, end_high; + + if (cpu_id.fid.bits.rdtsc == 0 ) { + return(-1); + } + + /* Setup timer */ + outb((inb(0x61) & ~0x02) | 0x01, 0x61); + outb(0xb0, 0x43); + outb(TICKS & 0xff, 0x42); + outb(TICKS >> 8, 0x42); + + asm __volatile__ ("rdtsc":"=a" (stlow),"=d" (sthigh)); + + loops = 0; + do { + loops++; + } while ((inb(0x61) & 0x20) == 0); + + asm __volatile__ ( + "rdtsc\n\t" \ + "subl stlow,%%eax\n\t" \ + "sbbl sthigh,%%edx\n\t" \ + :"=a" (end_low), "=d" (end_high) + ); + + /* Make sure we have a credible result */ + if (loops < 4 || end_low < 50000) { + return(-1); + } + vv->clks_msec = end_low/50; + + if (tsc_invariable) end_low = correct_tsc(end_low); + + return(vv->clks_msec); +} + +/* Measure cache speed by copying a block of memory. */ +/* Returned value is kbytes/second */ +ulong memspeed(ulong src, ulong len, int iter) +{ + int i; + ulong dst, wlen; + ulong st_low, st_high; + ulong end_low, end_high; + ulong cal_low, cal_high; + + if (cpu_id.fid.bits.rdtsc == 0 ) { + return(-1); + } + if (len == 0) return(-2); + + dst = src + len; + wlen = len / 4; /* Length is bytes */ + + /* Calibrate the overhead with a zero word copy */ + asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high)); + for (i=0; i<iter; i++) { + asm __volatile__ ( + "movl %0,%%esi\n\t" \ + "movl %1,%%edi\n\t" \ + "movl %2,%%ecx\n\t" \ + "cld\n\t" \ + "rep\n\t" \ + "movsl\n\t" \ + :: "g" (src), "g" (dst), "g" (0) + : "esi", "edi", "ecx" + ); + } + asm __volatile__ ("rdtsc":"=a" (cal_low),"=d" (cal_high)); + + /* Compute the overhead time */ + asm __volatile__ ( + "subl %2,%0\n\t" + "sbbl %3,%1" + :"=a" (cal_low), "=d" (cal_high) + :"g" (st_low), "g" (st_high), + "0" (cal_low), "1" (cal_high) + ); + + + /* Now measure the speed */ + /* Do the first copy to prime the cache */ + asm __volatile__ ( + "movl %0,%%esi\n\t" \ + "movl %1,%%edi\n\t" \ + "movl %2,%%ecx\n\t" \ + "cld\n\t" \ + "rep\n\t" \ + "movsl\n\t" \ + :: "g" (src), "g" (dst), "g" (wlen) + : "esi", "edi", "ecx" + ); + asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high)); + for (i=0; i<iter; i++) { + asm __volatile__ ( + "movl %0,%%esi\n\t" \ + "movl %1,%%edi\n\t" \ + "movl %2,%%ecx\n\t" \ + "cld\n\t" \ + "rep\n\t" \ + "movsl\n\t" \ + :: "g" (src), "g" (dst), "g" (wlen) + : "esi", "edi", "ecx" + ); + } + asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high)); + + /* Compute the elapsed time */ + asm __volatile__ ( + "subl %2,%0\n\t" + "sbbl %3,%1" + :"=a" (end_low), "=d" (end_high) + :"g" (st_low), "g" (st_high), + "0" (end_low), "1" (end_high) + ); + /* Subtract the overhead time */ + asm __volatile__ ( + "subl %2,%0\n\t" + "sbbl %3,%1" + :"=a" (end_low), "=d" (end_high) + :"g" (cal_low), "g" (cal_high), + "0" (end_low), "1" (end_high) + ); + + /* Make sure that the result fits in 32 bits */ + //hprint(11,40,end_high); + if (end_high) { + return(-3); + } + end_low /= 2; + + /* Convert to clocks/KB */ + end_low /= len; + end_low *= 1024; + end_low /= iter; + if (end_low == 0) { + return(-4); + } + + /* Convert to kbytes/sec */ + + if (tsc_invariable) end_low = correct_tsc(end_low); + + return((vv->clks_msec)/end_low); +} + +#define rdmsr(msr,val1,val2) \ + __asm__ __volatile__("rdmsr" \ + : "=a" (val1), "=d" (val2) \ + : "c" (msr)) + + +ulong correct_tsc(ulong el_org) +{ + float coef_now, coef_max; + int msr_lo, msr_hi, is_xe; + + rdmsr(0x198, msr_lo, msr_hi); + is_xe = (msr_lo >> 31) & 0x1; + + if(is_xe){ + rdmsr(0x198, msr_lo, msr_hi); + coef_max = ((msr_hi >> 8) & 0x1F); + if ((msr_hi >> 14) & 0x1) { coef_max = coef_max + 0.5f; } + } else { + rdmsr(0x17, msr_lo, msr_hi); + coef_max = ((msr_lo >> 8) & 0x1F); + if ((msr_lo >> 14) & 0x1) { coef_max = coef_max + 0.5f; } + } + + if(cpu_id.fid.bits.eist) { + rdmsr(0x198, msr_lo, msr_hi); + coef_now = ((msr_lo >> 8) & 0x1F); + if ((msr_lo >> 14) & 0x1) { coef_now = coef_now + 0.5f; } + } else { + rdmsr(0x2A, msr_lo, msr_hi); + coef_now = (msr_lo >> 22) & 0x1F; + } + if(coef_max && coef_now) { + el_org = (ulong)(el_org * coef_now / coef_max); + } + return el_org; +} + diff --git a/memtestEDK/Memtest/SingleComponents/io.h b/memtestEDK/Memtest/SingleComponents/io.h new file mode 100644 index 0000000..ae70dcf --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/io.h @@ -0,0 +1,133 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +/* + * This file contains the definitions for the x86 IO instructions + * inb/inw/inl/outb/outw/outl and the "string versions" of the same + * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" + * versions of the single-IO instructions (inb_p/inw_p/..). + * + * This file is not meant to be obfuscating: it's just complicated + * to (a) handle it all in a way that makes gcc able to optimize it + * as well as possible and (b) trying to avoid writing the same thing + * over and over again with slight variations and possibly making a + * mistake somewhere. + */ + +#ifdef SLOW_IO_BY_JUMPING +#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") +#else +#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") +#endif + +#ifdef REALLY_SLOW_IO +#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } +#else +#define SLOW_DOWN_IO __SLOW_DOWN_IO +#endif + +/* + * Talk about misusing macros.. + */ + +#define __OUT1(s,x) \ +static inline void __out##s(unsigned x value, unsigned short port) { + +#define __OUT2(s,s1,s2) \ +__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" + +#define __OUT(s,s1,x) \ +__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \ +__OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \ +__OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \ +__OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; } + +#define __IN1(s) \ +static inline RETURN_TYPE __in##s(unsigned short port) { RETURN_TYPE _v; + +#define __IN2(s,s1,s2) \ +__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" + +#define __IN(s,s1,i...) \ +__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \ +__IN1(s##c) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \ +__IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \ +__IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; } + +#define __OUTS(s) \ +static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ +{ __asm__ __volatile__ ("cld ; rep ; outs" #s \ +: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } + +#define RETURN_TYPE unsigned char +/* __IN(b,"b","0" (0)) */ +__IN(b,"") +#undef RETURN_TYPE +#define RETURN_TYPE unsigned short +/* __IN(w,"w","0" (0)) */ +__IN(w,"") +#undef RETURN_TYPE +#define RETURN_TYPE unsigned int +__IN(l,"") +#undef RETURN_TYPE + +__OUT(b,"b",char) +__OUT(w,"w",short) +__OUT(l,,int) + +__OUTS(b) +__OUTS(w) +__OUTS(l) + +/* + * Note that due to the way __builtin_constant_p() works, you + * - can't use it inside a inline function (it will never be true) + * - you don't have to worry about side effects within the __builtin.. + */ +#define outb(val,port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __outbc((val),(port)) : \ + __outb((val),(port))) + +#define inb(port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __inbc(port) : \ + __inb(port)) + + +#define outw(val,port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __outwc((val),(port)) : \ + __outw((val),(port))) + +#define inw(port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __inwc(port) : \ + __inw(port)) + + +#define outl(val,port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __outlc((val),(port)) : \ + __outl((val),(port))) + +#define inl(port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __inlc(port) : \ + __inl(port)) +#endif + +static __inline void +outb_p (unsigned char __value, unsigned short int __port ) +{ + __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (__value), + "Nd" (__port)); +} + +static __inline unsigned char +inb_p (unsigned short int __port) +{ + unsigned char _v; + __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); + return _v; +}
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/jedec_id.h b/memtestEDK/Memtest/SingleComponents/jedec_id.h new file mode 100644 index 0000000..240876c --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/jedec_id.h @@ -0,0 +1,985 @@ +/* MemTest86+ V5 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + * ------------------------------------------------ + * Based on JEDEC JEP106-AG - January 2012 + */ + +struct spd_jedec_manufacturer { + unsigned cont_code; + unsigned hex_byte; + char *name; +}; + +static struct spd_jedec_manufacturer jep106[] = + { + { 0, 0x01, "AMD"}, + { 0, 0x02, "AMI"}, + { 0, 0x83, "Fairchild"}, + { 0, 0x04, "Fujitsu"}, + // { 0, 0x85, "GTE"}, + { 0, 0x86, "Harris"}, + { 0, 0x07, "Hitachi"}, + { 0, 0x08, "Inmos"}, + { 0, 0x89, "Intel"}, + { 0, 0x8a, "I.T.T."}, + { 0, 0x0b, "Intersil"}, + { 0, 0x8c, "Monolithic Memories"}, + { 0, 0x0d, "Mostek"}, + { 0, 0x0e, "Freescale"}, + { 0, 0x8f, "National"}, + { 0, 0x10, "NEC"}, + { 0, 0x91, "RCA"}, + { 0, 0x92, "Raytheon"}, + { 0, 0x13, "Conexant"}, + // { 0, 0x94, "Seeq"}, + { 0, 0x15, "NXP"}, + { 0, 0x16, "Synertek"}, + { 0, 0x97, "Texas Instruments"}, + { 0, 0x98, "Toshiba"}, + { 0, 0x19, "Xicor"}, + { 0, 0x1a, "Zilog"}, + // { 0, 0x9b, "Eurotechnique"}, + { 0, 0x1c, "Mitsubishi"}, + { 0, 0x9d, "Lucent (AT&T)"}, + // { 0, 0x9e, "Exel"}, + { 0, 0x1f, "Atmel"}, + { 0, 0x20, "SGS/Thomson"}, + // { 0, 0xa1, "Lattice Semi."}, + { 0, 0xa2, "NCR"}, + // { 0, 0x23, "Wafer Scale Integration"}, + { 0, 0xa4, "IBM"}, + { 0, 0x25, "Tristar"}, + // { 0, 0x26, "Visic"}, + { 0, 0xa7, "Intl. CMOS Technology"}, + // { 0, 0xa8, "SSSI"}, + { 0, 0x29, "MicrochipTechnology"}, + // { 0, 0x2a, "Ricoh"}, + // { 0, 0xab, "VLSI"}, + { 0, 0x2c, "Micron"}, + { 0, 0xad, "Hynix"}, + { 0, 0xae, "OKI Semiconductor"}, + // { 0, 0x2f, "ACTEL"}, + { 0, 0xb0, "Sharp"}, + { 0, 0x31, "Catalyst"}, + { 0, 0x32, "Panasonic"}, + { 0, 0xb3, "IDT"}, + { 0, 0x34, "Cypress"}, + { 0, 0xb5, "DEC"}, + { 0, 0xb6, "LSI Logic"}, + // { 0, 0x37, "Zarlink (Plessey)"}, + { 0, 0x38, "UTMC"}, + // { 0, 0xb9, "Thinking Machine"}, + { 0, 0xba, "Thomson CSF"}, + // { 0, 0x3b, "Integrated CMOS (Vertex)"}, + // { 0, 0xbc, "Honeywell"}, + { 0, 0x3d, "Tektronix"}, + // { 0, 0x3e, "Oracle"}, + // { 0, 0xbf, "Silicon Storage Technology"}, + { 0, 0x40, "ProMos/Mosel"}, + { 0, 0xc1, "Infineon"}, + // { 0, 0xc2, "Macronix"}, + { 0, 0x43, "Xerox"}, + // { 0, 0xc4, "Plus Logic"}, + { 0, 0x45, "SanDisk"}, + // { 0, 0x46, "Elan Circuit Tech."}, + // { 0, 0xc7, "European Silicon Str."}, + { 0, 0xc8, "Apple Computer"}, + { 0, 0x49, "Xilinx"}, + { 0, 0x4a, "Compaq"}, + // { 0, 0xcb, "Protocol Engines"}, + // { 0, 0x4c, "SCI"}, + { 0, 0xcd, "Seiko Instruments"}, + { 0, 0xce, "Samsung"}, + // { 0, 0x4f, "I3 Design System"}, + // { 0, 0xd0, "Klic"}, + // { 0, 0x51, "Crosspoint Solutions"}, + // { 0, 0x52, "Alliance Semiconductor"}, + // { 0, 0xd3, "Tandem"}, + { 0, 0x54, "Hewlett-Packard"}, + { 0, 0xd5, "Integrated Silicon Solutions"}, + // { 0, 0xd6, "Brooktree"}, + // { 0, 0x57, "New Media"}, + // { 0, 0x58, "MHS Electronic"}, + // { 0, 0xd9, "Performance Semi."}, + { 0, 0xda, "Winbond Electronic"}, + // { 0, 0x5b, "Kawasaki Steel"}, + // { 0, 0xdc, "Bright Micro"}, + // { 0, 0x5d, "TECMAR"}, + { 0, 0x5e, "Exar"}, + // { 0, 0xdf, "PCMCIA"}, + { 0, 0xe0, "LG"}, + // { 0, 0x61, "Northern Telecom"}, + { 0, 0x62, "Sanyo"}, + // { 0, 0xe3, "Array Microsystems"}, + // { 0, 0x64, "Crystal Semiconductor"}, + { 0, 0xe5, "Analog Devices"}, + // { 0, 0xe6, "PMC-Sierra"}, + // { 0, 0x67, "Asparix"}, + // { 0, 0x68, "Convex Computer"}, + // { 0, 0xe9, "Quality Semiconductor"}, + // { 0, 0xea, "Nimbus Technology"}, + // { 0, 0x6b, "Transwitch"}, + // { 0, 0xec, "Micronas (ITT Intermetall)"}, + { 0, 0x6d, "Cannon"}, + // { 0, 0x6e, "Altera"}, + // { 0, 0xef, "NEXCOM"}, + // { 0, 0x70, "QUALCOMM"}, + { 0, 0xf1, "Sony"}, + // { 0, 0xf2, "Cray Research"}, + // { 0, 0x73, "AMS(Austria Micro)"}, + // { 0, 0xf4, "Vitesse"}, + // { 0, 0x75, "Aster Electronics"}, + // { 0, 0x76, "Bay Networks (Synoptic)"}, + // { 0, 0xf7, "Zentrum/ZMD"}, + // { 0, 0xf8, "TRW"}, + // { 0, 0x79, "Thesys"}, + // { 0, 0x7a, "Solbourne Computer"}, + { 0, 0xfb, "Allied-Signal"}, + { 0, 0x7c, "Dialog"}, + { 0, 0xfd, "Media Vision"}, + // { 0, 0xfe, "Numonyx"}, + { 1, 0x01, "Cirrus Logic"}, + { 1, 0x02, "National Instruments"}, + // { 1, 0x83, "ILC Data Device"}, + // { 1, 0x04, "Alcatel Mietec"}, + // { 1, 0x85, "Micro Linear"}, + // { 1, 0x86, "Univ. of NC"}, + // { 1, 0x07, "JTAG Technologies"}, + // { 1, 0x08, "BAE Systems (Loral)"}, + // { 1, 0x89, "Nchip"}, + // { 1, 0x8a, "Galileo Tech"}, + // { 1, 0x0b, "Bestlink Systems"}, + // { 1, 0x8c, "Graychip"}, + // { 1, 0x0d, "GENNUM"}, + // { 1, 0x0e, "VideoLogic"}, + // { 1, 0x8f, "Robert Bosch"}, + // { 1, 0x10, "Chip Express"}, + { 1, 0x91, "DATARAM"}, + // { 1, 0x92, "United Microelectronics Corp."}, + // { 1, 0x13, "TCSI"}, + { 1, 0x94, "Smart Modular"}, + // { 1, 0x15, "Hughes Aircraft"}, + // { 1, 0x16, "Lanstar Semiconductor"}, + // { 1, 0x97, "Qlogic"}, + { 1, 0x98, "Kingston"}, + // { 1, 0x19, "Music Semi"}, + // { 1, 0x1a, "Ericsson Components"}, + // { 1, 0x9b, "SpaSE"}, + // { 1, 0x1c, "Eon Silicon Devices"}, + // { 1, 0x9d, "Programmable Micro Corp"}, + // { 1, 0x9e, "DoD"}, + // { 1, 0x1f, "Integ. Memories Tech."}, + // { 1, 0x20, "Corollary"}, + // { 1, 0xa1, "Dallas Semiconductor"}, + // { 1, 0xa2, "Omnivision"}, + // { 1, 0x23, "EIV(Switzerland)"}, + // { 1, 0xa4, "Novatel Wireless"}, + // { 1, 0x25, "Zarlink (Mitel)"}, + // { 1, 0x26, "Clearpoint"}, + // { 1, 0xa7, "Cabletron"}, + // { 1, 0xa8, "STEC (Silicon Tech)"}, + // { 1, 0x29, "Vanguard"}, + // { 1, 0x2a, "Hagiwara Sys-Com"}, + // { 1, 0xab, "Vantis"}, + // { 1, 0x2c, "Celestica"}, + // { 1, 0xad, "Century"}, + // { 1, 0xae, "Hal Computers"}, + // { 1, 0x2f, "Rohm Company"}, + // { 1, 0xb0, "Juniper Networks"}, + // { 1, 0x31, "Libit Signal Processing"}, + { 1, 0x32, "Mushkin"}, + // { 1, 0xb3, "Tundra Semiconductor"}, + { 1, 0x34, "Adaptec"}, + // { 1, 0xb5, "LightSpeed Semi."}, + // { 1, 0xb6, "ZSP Corp."}, + // { 1, 0x37, "AMIC Technology"}, + // { 1, 0x38, "Adobe Systems"}, + // { 1, 0xb9, "Dynachip"}, + { 1, 0xba, "PNY"}, + // { 1, 0x3b, "Newport Digital"}, + // { 1, 0xbc, "MMC Networks"}, + // { 1, 0x3d, "T Square"}, + // { 1, 0x3e, "Seiko Epson"}, + // { 1, 0xbf, "Broadcom"}, + // { 1, 0x40, "Viking Components"}, + // { 1, 0xc1, "V3 Semiconductor"}, + // { 1, 0xc2, "Flextronics (Orbit Semiconductor)"}, + // { 1, 0x43, "Suwa Electronics"}, + { 1, 0xc4, "Transmeta"}, + { 1, 0x45, "Micron CMS"}, + // { 1, 0x46, "American Computer & Digital Components"}, + // { 1, 0xc7, "Enhance 3000"}, + { 1, 0xc8, "Tower Semiconductor"}, + // { 1, 0x49, "CPU Design"}, + // { 1, 0x4a, "Price Point"}, + { 1, 0xcb, "Maxim Integrated Product"}, + // { 1, 0x4c, "Tellabs"}, + // { 1, 0xcd, "Centaur Technology"}, + { 1, 0xce, "Unigen"}, + { 1, 0x4f, "Transcend"}, + { 1, 0xd0, "Memory Card"}, + // { 1, 0x51, "CKD"}, + // { 1, 0x52, "Capital Instruments"}, + // { 1, 0xd3, "Aica Kogyo"}, + // { 1, 0x54, "Linvex Technology"}, + { 1, 0xd5, "MSC"}, + // { 1, 0xd6, "AKM Company"}, + // { 1, 0x57, "Dynamem"}, + // { 1, 0x58, "NERA ASA"}, + // { 1, 0xd9, "GSI Technology"}, + { 1, 0xda, "Dane-Elec"}, + // { 1, 0x5b, "Acorn Computers"}, + // { 1, 0xdc, "Lara Technology"}, + // { 1, 0x5d, "Oak Technology"}, + { 1, 0x5e, "Itec Memory"}, + // { 1, 0xdf, "Tanisys Technology"}, + // { 1, 0xe0, "Truevision"}, + { 1, 0x61, "Wintec"}, + // { 1, 0x62, "Super PC Memory"}, + // { 1, 0xe3, "MGV Memory"}, + // { 1, 0x64, "Galvantech"}, + // { 1, 0xe5, "Gadzoox Networks"}, + // { 1, 0xe6, "Multi Dimensional Cons."}, + // { 1, 0x67, "GateField"}, + { 1, 0x68, "Integrated Memory System"}, + // { 1, 0xe9, "Triscend"}, + // { 1, 0xea, "XaQti"}, + // { 1, 0x6b, "Goldenram"}, + // { 1, 0xec, "Clear Logic"}, + // { 1, 0x6d, "Cimaron Communications"}, + // { 1, 0x6e, "Nippon Steel Semi. Corp."}, + // { 1, 0xef, "Advantage Memory"}, + // { 1, 0x70, "AMCC"}, + { 1, 0xf1, "LeCroy"}, + // { 1, 0xf2, "Yamaha"}, + // { 1, 0x73, "Digital Microwave"}, + // { 1, 0xf4, "NetLogic Microsystems"}, + // { 1, 0x75, "MIMOS Semiconductor"}, + // { 1, 0x76, "Advanced Fibre"}, + // { 1, 0xf7, "BF Goodrich Data."}, + // { 1, 0xf8, "Epigram"}, + // { 1, 0x79, "Acbel Polytech"}, + { 1, 0x7a, "Apacer Technology"}, + // { 1, 0xfb, "Admor Memory"}, + { 1, 0x7c, "FOXCONN"}, + // { 1, 0xfd, "Quadratics Superconductor"}, + // { 1, 0xfe, "3COM"}, + // { 2, 0x01, "Camintonn"}, + // { 2, 0x02, "ISOA"}, + // { 2, 0x83, "Agate Semiconductor"}, + // { 2, 0x04, "ADMtek"}, + // { 2, 0x85, "HYPERTEC"}, + // { 2, 0x86, "Adhoc Technologies"}, + // { 2, 0x07, "MOSAID Technologies"}, + // { 2, 0x08, "Ardent Technologies"}, + // { 2, 0x89, "Switchcore"}, + // { 2, 0x8a, "Cisco Systems"}, + // { 2, 0x0b, "Allayer Technologies"}, + // { 2, 0x8c, "WorkX AG (Wichman)"}, + // { 2, 0x0d, "Oasis Semiconductor"}, + // { 2, 0x0e, "Novanet Semiconductor"}, + // { 2, 0x8f, "E-M Solutions"}, + // { 2, 0x10, "Power General"}, + // { 2, 0x91, "Advanced Hardware Arch."}, + // { 2, 0x92, "Inova Semiconductors"}, + // { 2, 0x13, "Telocity"}, + // { 2, 0x94, "Delkin Devices"}, + // { 2, 0x15, "Symagery Microsystems"}, + // { 2, 0x16, "C-Port"}, + // { 2, 0x97, "SiberCore Technologies"}, + // { 2, 0x98, "Southland Microsystems"}, + // { 2, 0x19, "Malleable Technologies"}, + // { 2, 0x1a, "Kendin Communications"}, + // { 2, 0x9b, "Great Technology Microcomputer"}, + // { 2, 0x1c, "Sanmina"}, + // { 2, 0x9d, "HADCO"}, + { 2, 0x9e, "Corsair"}, + // { 2, 0x1f, "Actrans System"}, + // { 2, 0x20, "ALPHA Technologies"}, + // { 2, 0xa1, "Silicon Laboratories (Cygnal)"}, + // { 2, 0xa2, "Artesyn Technologies"}, + // { 2, 0x23, "Align Manufacturing"}, + // { 2, 0xa4, "Peregrine Semiconductor"}, + // { 2, 0x25, "Chameleon Systems"}, + // { 2, 0x26, "Aplus Flash Technology"}, + { 2, 0xa7, "MIPS Technologies"}, + // { 2, 0xa8, "Chrysalis ITS"}, + // { 2, 0x29, "ADTEC"}, + { 2, 0x2a, "Kentron Technologies"}, + // { 2, 0xab, "Win Technologies"}, + // { 2, 0x2c, "Tachyon Semiconductor (ASIC)"}, + // { 2, 0xad, "Extreme Packet Devices"}, + // { 2, 0xae, "RF Micro Devices"}, + { 2, 0x2f, "Siemens AG"}, + // { 2, 0xb0, "Sarnoff"}, + // { 2, 0x31, "Itautec SA"}, + // { 2, 0x32, "Radiata"}, + // { 2, 0xb3, "Benchmark Elect. (AVEX)"}, + // { 2, 0x34, "Legend"}, + { 2, 0xb5, "SpecTek"}, + // { 2, 0xb6, "Hi/fn"}, + // { 2, 0x37, "Enikia"}, + // { 2, 0x38, "SwitchOn Networks"}, + // { 2, 0xb9, "AANetcom"}, + // { 2, 0xba, "Micro Memory Bank"}, + { 2, 0x3b, "ESS Technology"}, + // { 2, 0xbc, "Virata"}, + // { 2, 0x3d, "Excess Bandwidth"}, + // { 2, 0x3e, "West Bay Semiconductor"}, + // { 2, 0xbf, "DSP Group"}, + // { 2, 0x40, "Newport Communications"}, + // { 2, 0xc1, "Chip2Chip"}, + // { 2, 0xc2, "Phobos"}, + // { 2, 0x43, "Intellitech"}, + // { 2, 0xc4, "Nordic VLSI ASA"}, + // { 2, 0x45, "Ishoni Networks"}, + // { 2, 0x46, "Silicon Spice"}, + // { 2, 0xc7, "Alchemy Semiconductor"}, + { 2, 0xc8, "Agilent Technologies"}, + // { 2, 0x49, "Centillium Communications"}, + // { 2, 0x4a, "W.L. Gore"}, + // { 2, 0xcb, "HanBit Electronics"}, + // { 2, 0x4c, "GlobeSpan"}, + // { 2, 0xcd, "Element 14"}, + // { 2, 0xce, "Pycon"}, + // { 2, 0x4f, "Saifun Semiconductors"}, + // { 2, 0xd0, "Sibyte,"}, + // { 2, 0x51, "MetaLink Technologies"}, + // { 2, 0x52, "Feiya Technology"}, + // { 2, 0xd3, "I & C Technology"}, + // { 2, 0x54, "Shikatronics"}, + // { 2, 0xd5, "Elektrobit"}, + // { 2, 0xd6, "Megic"}, + // { 2, 0x57, "Com-Tier"}, + // { 2, 0x58, "Malaysia Micro Solutions"}, + // { 2, 0xd9, "Hyperchip"}, + // { 2, 0xda, "Gemstone Communications"}, + // { 2, 0x5b, "Anadigm (Anadyne)"}, + // { 2, 0xdc, "3ParData"}, + // { 2, 0x5d, "Mellanox Technologies"}, + // { 2, 0x5e, "Tenx Technologies"}, + // { 2, 0xdf, "Helix AG"}, + // { 2, 0xe0, "Domosys"}, + // { 2, 0x61, "Skyup Technology"}, + // { 2, 0x62, "HiNT"}, + // { 2, 0xe3, "Chiaro"}, + { 2, 0x64, "MDT"}, + // { 2, 0xe5, "Exbit Technology A/S"}, + // { 2, 0xe6, "Integrated Technology Express"}, + // { 2, 0x67, "AVED Memory"}, + // { 2, 0x68, "Legerity"}, + // { 2, 0xe9, "Jasmine Networks"}, + // { 2, 0xea, "Caspian Networks"}, + // { 2, 0x6b, "nCUBE"}, + // { 2, 0xec, "Silicon Access Networks"}, + // { 2, 0x6d, "FDK"}, + // { 2, 0x6e, "High Bandwidth Access"}, + // { 2, 0xef, "MultiLink Technology"}, + // { 2, 0x70, "BRECIS"}, + // { 2, 0xf1, "World Wide Packets"}, + // { 2, 0xf2, "APW"}, + // { 2, 0x73, "Chicory Systems"}, + // { 2, 0xf4, "Xstream Logic"}, + // { 2, 0x75, "Fast-Chip"}, + // { 2, 0x76, "Zucotto Wireless"}, + // { 2, 0xf7, "Realchip"}, + // { 2, 0xf8, "Galaxy Power"}, + // { 2, 0x79, "eSilicon"}, + // { 2, 0x7a, "Morphics Technology"}, + // { 2, 0xfb, "Accelerant Networks"}, + // { 2, 0x7c, "Silicon Wave"}, + // { 2, 0xfd, "SandCraft"}, + { 2, 0xfe, "Elpida"}, + // { 3, 0x01, "Solectron"}, + { 3, 0x02, "Optosys Technologies"}, + { 3, 0x83, "Buffalo"}, + // { 3, 0x04, "TriMedia Technologies"}, + // { 3, 0x85, "Cyan Technologies"}, + // { 3, 0x86, "Global Locate"}, + // { 3, 0x07, "Optillion"}, + // { 3, 0x08, "Terago Communications"}, + // { 3, 0x89, "Ikanos Communications"}, + { 3, 0x8a, "Princeton"}, + { 3, 0x0b, "Nanya"}, + // { 3, 0x8c, "Elite Flash Storage"}, + // { 3, 0x0d, "Mysticom"}, + // { 3, 0x0e, "LightSand Communications"}, + { 3, 0x8f, "ATI"}, + // { 3, 0x10, "Agere Systems"}, + // { 3, 0x91, "NeoMagic"}, + // { 3, 0x92, "AuroraNetics"}, + // { 3, 0x13, "Golden Empire"}, + { 3, 0x94, "Mushkin"}, + // { 3, 0x15, "Tioga Technologies"}, + { 3, 0x16, "Netlist"}, + // { 3, 0x97, "TeraLogic"}, + // { 3, 0x98, "Cicada Semiconductor"}, + { 3, 0x19, "Centon"}, + { 3, 0x1a, "Tyco Electronics"}, + // { 3, 0x9b, "Magis Works"}, + // { 3, 0x1c, "Zettacom"}, + // { 3, 0x9d, "Cogency Semiconductor"}, + // { 3, 0x9e, "Chipcon AS"}, + // { 3, 0x1f, "Aspex Technology"}, + // { 3, 0x20, "F5 Networks"}, + // { 3, 0xa1, "Programmable Silicon Solutions"}, + // { 3, 0xa2, "ChipWrights"}, + // { 3, 0x23, "Acorn Networks"}, + // { 3, 0xa4, "Quicklogic"}, + { 3, 0x25, "Kingmax"}, + // { 3, 0x26, "BOPS"}, + // { 3, 0xa7, "Flasys"}, + // { 3, 0xa8, "BitBlitz Communications"}, + { 3, 0x29, "eMemory Technology"}, + // { 3, 0x2a, "Procket Networks"}, + // { 3, 0xab, "Purple Ray"}, + // { 3, 0x2c, "Trebia Networks"}, + // { 3, 0xad, "Delta Electronics"}, + // { 3, 0xae, "Onex Communications"}, + // { 3, 0x2f, "Ample Communications"}, + { 3, 0xb0, "Memory Experts"}, + // { 3, 0x31, "Astute Networks"}, + // { 3, 0x32, "Azanda Network Devices"}, + // { 3, 0xb3, "Dibcom"}, + // { 3, 0x34, "Tekmos"}, + // { 3, 0xb5, "API NetWorks"}, + // { 3, 0xb6, "Bay Microsystems"}, + // { 3, 0x37, "Firecron"}, + // { 3, 0x38, "Resonext Communications"}, + // { 3, 0xb9, "Tachys Technologies"}, + // { 3, 0xba, "Equator Technology"}, + // { 3, 0x3b, "Concept Computer"}, + // { 3, 0xbc, "SILCOM"}, + // { 3, 0x3d, "3Dlabs"}, + // { 3, 0x3e, "c’t Magazine"}, + // { 3, 0xbf, "Sanera Systems"}, + // { 3, 0x40, "Silicon Packets"}, + { 3, 0xc1, "Viasystems Group"}, + { 3, 0xc2, "Simtek"}, + // { 3, 0x43, "Semicon Devices Singapore"}, + // { 3, 0xc4, "Satron Handelsges"}, + // { 3, 0x45, "Improv Systems"}, + // { 3, 0x46, "INDUSYS"}, + // { 3, 0xc7, "Corrent"}, + // { 3, 0xc8, "Infrant Technologies"}, + // { 3, 0x49, "Ritek Corp"}, + // { 3, 0x4a, "empowerTel Networks"}, + // { 3, 0xcb, "Hypertec"}, + // { 3, 0x4c, "Cavium Networks"}, + { 3, 0xcd, "PLX Technology"}, + // { 3, 0xce, "Massana Design"}, + // { 3, 0x4f, "Intrinsity"}, + // { 3, 0xd0, "Valence Semiconductor"}, + // { 3, 0x51, "Terawave Communications"}, + // { 3, 0x52, "IceFyre Semiconductor"}, + // { 3, 0xd3, "Primarion"}, + // { 3, 0x54, "Picochip Designs"}, + // { 3, 0xd5, "Silverback Systems"}, + { 3, 0xd6, "Jade Star"}, + // { 3, 0x57, "Pijnenburg Securealink"}, + { 3, 0x58, "takeMS"}, + // { 3, 0xd9, "Cambridge Silicon Radio"}, + { 3, 0xda, "Swissbit"}, + // { 3, 0x5b, "Nazomi Communications"}, + // { 3, 0xdc, "eWave System"}, + // { 3, 0x5d, "Rockwell Collins"}, + // { 3, 0x5e, "Picocel (Paion)"}, + // { 3, 0xdf, "Alphamosaic"}, + // { 3, 0xe0, "Sandburst"}, + // { 3, 0x61, "SiCon Video"}, + // { 3, 0x62, "NanoAmp Solutions"}, + // { 3, 0xe3, "Ericsson Technology"}, + // { 3, 0x64, "PrairieComm"}, + { 3, 0xe5, "Mitac International"}, + // { 3, 0xe6, "Layer N Networks"}, + // { 3, 0x67, "MtekVision (Atsana)"}, + // { 3, 0x68, "Allegro Networks"}, + // { 3, 0xe9, "Marvell Semiconductors"}, + // { 3, 0xea, "Netergy Microelectronic"}, + { 3, 0x6b, "nVidia"}, + // { 3, 0xec, "Internet Machines"}, + // { 3, 0x6d, "Peak Electronics"}, + // { 3, 0x6e, "Litchfield Communication"}, + { 3, 0xef, "Accton"}, + // { 3, 0x70, "Teradiant Networks"}, + // { 3, 0xf1, "Scaleo Chip"}, + // { 3, 0xf2, "Cortina Systems"}, + { 3, 0x73, "RAM Components"}, + // { 3, 0xf4, "Raqia Networks"}, + // { 3, 0x75, "ClearSpeed"}, + // { 3, 0x76, "Matsushita Battery"}, + // { 3, 0xf7, "Xelerated"}, + // { 3, 0xf8, "SimpleTech"}, + { 3, 0x79, "Utron"}, + // { 3, 0x7a, "Astec International"}, + // { 3, 0xfb, "AVM"}, + // { 3, 0x7c, "Redux Communications"}, + // { 3, 0xfd, "Dot Hill Systems"}, + { 3, 0xfe, "TeraChip"}, + { 4, 0x01, "T-RAM"}, + // { 4, 0x02, "Innovics Wireless"}, + // { 4, 0x83, "Teknovus"}, + // { 4, 0x04, "KeyEye Communications"}, + // { 4, 0x85, "Runcom Technologies"}, + // { 4, 0x86, "RedSwitch"}, + // { 4, 0x07, "Dotcast"}, + { 4, 0x08, "Silicon Mountain Memory"}, + // { 4, 0x89, "Signia Technologies"}, + // { 4, 0x8a, "Pixim"}, + // { 4, 0x0b, "Galazar Networks"}, + // { 4, 0x8c, "White Electronic Designs"}, + // { 4, 0x0d, "Patriot Scientific"}, + // { 4, 0x0e, "Neoaxiom"}, + // { 4, 0x8f, "3Y Power Technology"}, + { 4, 0x10, "Scaleo Chip"}, + // { 4, 0x91, "Potentia Power Systems"}, + // { 4, 0x92, "C-guys"}, + // { 4, 0x13, "Digital Communications Technology"}, + // { 4, 0x94, "Silicon-Based Technology"}, + // { 4, 0x15, "Fulcrum Microsystems"}, + // { 4, 0x16, "Positivo Informatica"}, + // { 4, 0x97, "XIOtech"}, + // { 4, 0x98, "PortalPlayer"}, + // { 4, 0x19, "Zhiying Software"}, + // { 4, 0x1a, "ParkerVision"}, + // { 4, 0x9b, "Phonex Broadband"}, + // { 4, 0x1c, "Skyworks Solutions"}, + // { 4, 0x9d, "Entropic Communications"}, + // { 4, 0x9e, "Pacific Force Technology"}, + // { 4, 0x1f, "Zensys A/S"}, + // { 4, 0x20, "Legend Silicon Corp."}, + // { 4, 0xa1, "Sci-worx"}, + // { 4, 0xa2, "SMSC (Standard Microsystems)"}, + { 4, 0x23, "Renesas"}, + // { 4, 0xa4, "Raza Microelectronics"}, + // { 4, 0x25, "Phyworks"}, + // { 4, 0x26, "MediaTek"}, + // { 4, 0xa7, "Non-cents Productions"}, + // { 4, 0xa8, "US Modular"}, + // { 4, 0x29, "Wintegra"}, + // { 4, 0x2a, "Mathstar"}, + // { 4, 0xab, "StarCore"}, + // { 4, 0x2c, "Oplus Technologies"}, + // { 4, 0xad, "Mindspeed"}, + // { 4, 0xae, "Just Young Computer"}, + // { 4, 0x2f, "Radia Communications"}, + { 4, 0xb0, "OCZ"}, + // { 4, 0x31, "Emuzed"}, + // { 4, 0x32, "LOGIC Devices"}, + // { 4, 0xb3, "Inphi"}, + // { 4, 0x34, "Quake Technologies"}, + // { 4, 0xb5, "Vixel"}, + // { 4, 0xb6, "SolusTek"}, + // { 4, 0x37, "Kongsberg Maritime"}, + // { 4, 0x38, "Faraday Technology"}, + { 4, 0xb9, "Altium"}, + // { 4, 0xba, "Insyte"}, + { 4, 0x3b, "ARM"}, + // { 4, 0xbc, "DigiVision"}, + // { 4, 0x3d, "Vativ Technologies"}, + // { 4, 0x3e, "Endicott Interconnect Technologies"}, + { 4, 0xbf, "Pericom"}, + // { 4, 0x40, "Bandspeed"}, + // { 4, 0xc1, "LeWiz Communications"}, + // { 4, 0xc2, "CPU Technology"}, + { 4, 0x43, "Ramaxel"}, + // { 4, 0xc4, "DSP Group"}, + // { 4, 0x45, "Axis Communications"}, + { 4, 0x46, "Legacy Electronics"}, + // { 4, 0xc7, "Chrontel"}, + // { 4, 0xc8, "Powerchip Semiconductor"}, + // { 4, 0x49, "MobilEye Technologies"}, + { 4, 0x4a, "Excel Semiconductor"}, + { 4, 0xcb, "A-DATA"}, + // { 4, 0x4c, "VirtualDigm"}, + { 4, 0xcd, "G.Skill"}, + // { 4, 0xce, "Quanta Computer"}, + // { 4, 0x4f, "Yield Microelectronics"}, + // { 4, 0xd0, "Afa Technologies"}, + { 4, 0x51, "Kingbox"}, + // { 4, 0x52, "Ceva"}, + // { 4, 0xd3, "iStor Networks"}, + // { 4, 0x54, "Advance Modules"}, + { 4, 0xd5, "Microsoft"}, + // { 4, 0xd6, "Open-Silicon"}, + // { 4, 0x57, "Goal Semiconductor"}, + // { 4, 0x58, "ARC International"}, + { 4, 0xd9, "Simmtec"}, + // { 4, 0xda, "Metanoia"}, + // { 4, 0x5b, "Key Stream"}, + // { 4, 0xdc, "Lowrance Electronics"}, + // { 4, 0x5d, "Adimos"}, + // { 4, 0x5e, "SiGe Semiconductor"}, + // { 4, 0xdf, "Fodus Communications"}, + // { 4, 0xe0, "Credence Systems Corp."}, + // { 4, 0x61, "Genesis Microchip"}, + // { 4, 0x62, "Vihana"}, + // { 4, 0xe3, "WIS Technologies"}, + // { 4, 0x64, "GateChange Technologies"}, + // { 4, 0xe5, "High Density Devices AS"}, + // { 4, 0xe6, "Synopsys"}, + // { 4, 0x67, "Gigaram"}, + // { 4, 0x68, "Enigma Semiconductor"}, + // { 4, 0xe9, "Century Micro"}, + // { 4, 0xea, "Icera Semiconductor"}, + // { 4, 0x6b, "Mediaworks Integrated Systems"}, + // { 4, 0xec, "O’Neil Product Development"}, + // { 4, 0x6d, "Supreme Top Technology"}, + // { 4, 0x6e, "MicroDisplay"}, + { 4, 0xef, "Team Group"}, + // { 4, 0x70, "Sinett"}, + { 4, 0xf1, "Toshiba"}, + // { 4, 0xf2, "Tensilica"}, + // { 4, 0x73, "SiRF Technology"}, + // { 4, 0xf4, "Bacoc"}, + // { 4, 0x75, "SMaL Camera Technologies"}, + { 4, 0x76, "Thomson SC"}, + // { 4, 0xf7, "Airgo Networks"}, + // { 4, 0xf8, "Wisair"}, + // { 4, 0x79, "SigmaTel"}, + // { 4, 0x7a, "Arkados"}, + // { 4, 0xfb, "Compete IT KG"}, + // { 4, 0x7c, "Eudar Technology"}, + // { 4, 0xfd, "Focus Enhancements"}, + // { 4, 0xfe, "Xyratex"}, + // { 5, 0x01, "Specular Networks"}, + { 5, 0x02, "Patriot Memory"}, + // { 5, 0x83, "U-Chip Technology Corp."}, + // { 5, 0x04, "Silicon Optix"}, + // { 5, 0x85, "Greenfield Networks"}, + { 5, 0x86, "CompuRAM"}, + // { 5, 0x07, "Stargen"}, + // { 5, 0x08, "NetCell"}, + // { 5, 0x89, "Excalibrus Technologies"}, + // { 5, 0x8a, "SCM Microsystems"}, + // { 5, 0x0b, "Xsigo Systems"}, + // { 5, 0x8c, "CHIPS & Systems"}, + // { 5, 0x0d, "Tier"}, + // { 5, 0x0e, "CWRL Labs"}, + // { 5, 0x8f, "Teradici"}, + // { 5, 0x10, "Gigaram"}, + // { 5, 0x91, "g2 Microsystems"}, + // { 5, 0x92, "PowerFlash Semiconductor"}, + // { 5, 0x13, "P.A. Semi"}, + { 5, 0x94, "NovaTech"}, + // { 5, 0x15, "c2 Microsystems"}, + // { 5, 0x16, "Level5 Networks"}, + { 5, 0x97, "COS Memory"}, + // { 5, 0x98, "Innovasic Semiconductor"}, + // { 5, 0x19, "02IC"}, + // { 5, 0x1a, "Tabula"}, + { 5, 0x9b, "Crucial"}, + // { 5, 0x1c, "Chelsio Communications"}, + // { 5, 0x9d, "Solarflare Communications"}, + // { 5, 0x9e, "Xambala"}, + // { 5, 0x1f, "EADS Astrium"}, + // { 5, 0x20, "Terra Semiconductor"}, + // { 5, 0xa1, "Imaging Works"}, + // { 5, 0xa2, "Astute Networks"}, + // { 5, 0x23, "Tzero"}, + // { 5, 0xa4, "Emulex"}, + // { 5, 0x25, "Power-One"}, + // { 5, 0x26, "Pulse~LINK"}, + // { 5, 0xa7, "Hon Hai Precision Industry"}, + // { 5, 0xa8, "White Rock Networks"}, + // { 5, 0x29, "Telegent Systems USA"}, + // { 5, 0x2a, "Atrua Technologies"}, + // { 5, 0xab, "Acbel Polytech"}, + // { 5, 0x2c, "eRide"}, + { 5, 0xad, "ULi"}, + // { 5, 0xae, "Magnum Semiconductor"}, + // { 5, 0x2f, "neoOne Technology"}, + // { 5, 0xb0, "Connex Technology"}, + // { 5, 0x31, "Stream Processors"}, + // { 5, 0x32, "Focus Enhancements"}, + // { 5, 0xb3, "Telecis Wireless"}, + // { 5, 0x34, "uNav Microelectronics"}, + // { 5, 0xb5, "Tarari"}, + // { 5, 0xb6, "Ambric"}, + // { 5, 0x37, "Newport Media"}, + // { 5, 0x38, "VMTS"}, + // { 5, 0xb9, "Enuclia Semiconductor"}, + // { 5, 0xba, "Virtium Technology"}, + // { 5, 0x3b, "Solid State System"}, + // { 5, 0xbc, "Kian Tech LLC"}, + // { 5, 0x3d, "Artimi"}, + { 5, 0x3e, "PQI"}, + // { 5, 0xbf, "Avago Technologies"}, + // { 5, 0x40, "ADTechnology"}, + { 5, 0xc1, "Sigma Designs"}, + // { 5, 0xc2, "SiCortex"}, + // { 5, 0x43, "Ventura Technology Group"}, + // { 5, 0xc4, "eASIC"}, + // { 5, 0x45, "M.H.S. SAS"}, + { 5, 0x46, "MSI"}, + // { 5, 0xc7, "Rapport"}, + // { 5, 0xc8, "Makway International"}, + // { 5, 0x49, "Broad Reach Engineering"}, + // { 5, 0x4a, "Semiconductor Mfg Intl Corp"}, + // { 5, 0xcb, "SiConnect"}, + // { 5, 0x4c, "FCI USA"}, + // { 5, 0xcd, "Validity Sensors"}, + // { 5, 0xce, "Coney Technology"}, + // { 5, 0x4f, "Spans Logic"}, + // { 5, 0xd0, "Neterion"}, + { 5, 0x51, "Qimonda"}, + // { 5, 0x52, "New Japan Radio"}, + // { 5, 0xd3, "Velogix"}, + // { 5, 0x54, "Montalvo Systems"}, + // { 5, 0xd5, "iVivity"}, + { 5, 0xd6, "Walton Chaintech"}, + { 5, 0x57, "AENEON"}, + // { 5, 0x58, "Lorom Industrial"}, + // { 5, 0xd9, "Radiospire Networks"}, + // { 5, 0xda, "Sensio Technologies"}, + // { 5, 0x5b, "Nethra Imaging"}, + { 5, 0xdc, "Hexon"}, + // { 5, 0x5d, "CompuStocx (CSX)"}, + // { 5, 0x5e, "Methode Electronics"}, + // { 5, 0xdf, "Connect One"}, + // { 5, 0xe0, "Opulan Technologies"}, + // { 5, 0x61, "Septentrio NV"}, + { 5, 0x62, "Goldenmars"}, + { 5, 0xe3, "Kreton"}, + // { 5, 0x64, "Cochlear"}, + // { 5, 0xe5, "Altair Semiconductor"}, + // { 5, 0xe6, "NetEffect"}, + // { 5, 0x67, "Spansion"}, + // { 5, 0x68, "Taiwan Semiconductor Mfg"}, + // { 5, 0xe9, "Emphany Systems"}, + // { 5, 0xea, "ApaceWave Technologies"}, + // { 5, 0x6b, "Mobilygen"}, + // { 5, 0xec, "Tego"}, + // { 5, 0x6d, "Cswitch"}, + // { 5, 0x6e, "Haier (Beijing) IC Design"}, + // { 5, 0xef, "MetaRAM"}, + // { 5, 0x70, "Axel Electronics"}, + // { 5, 0xf1, "Tilera"}, + // { 5, 0xf2, "Aquantia"}, + // { 5, 0x73, "Vivace Semiconductor"}, + // { 5, 0xf4, "Redpine Signals"}, + // { 5, 0x75, "Octalica"}, + // { 5, 0x76, "InterDigital Communications"}, + { 5, 0xf7, "Avant Technology"}, + { 5, 0xf8, "Asrock"}, + // { 5, 0x79, "Availink"}, + // { 5, 0x7a, "Quartics"}, + // { 5, 0xfb, "Element CXI"}, + // { 5, 0x7c, "Innovaciones Microelectronicas"}, + // { 5, 0xfd, "VeriSilicon Microelectronics"}, + // { 5, 0xfe, "W5 Networks"}, + // { 6, 0x01, "MOVEKING"}, + // { 6, 0x02, "Mavrix Technology"}, + // { 6, 0x83, "CellGuide"}, + // { 6, 0x04, "Faraday Technology"}, + // { 6, 0x85, "Diablo Technologies"}, + // { 6, 0x86, "Jennic"}, + // { 6, 0x07, "Octasic"}, + { 6, 0x08, "Molex"}, + // { 6, 0x89, "3Leaf Networks"}, + // { 6, 0x8a, "Bright Micron Technology"}, + // { 6, 0x0b, "Netxen"}, + // { 6, 0x8c, "NextWave Broadband"}, + // { 6, 0x0d, "DisplayLink"}, + // { 6, 0x0e, "ZMOS Technology"}, + // { 6, 0x8f, "Tec-Hill"}, + // { 6, 0x10, "Multigig"}, + // { 6, 0x91, "Amimon"}, + // { 6, 0x92, "Euphonic Technologies"}, + // { 6, 0x13, "BRN Phoenix"}, + // { 6, 0x94, "InSilica"}, + // { 6, 0x15, "Ember"}, + { 6, 0x16, "Avexir"}, + // { 6, 0x97, "Echelon"}, + // { 6, 0x98, "Edgewater Computer Systems"}, + // { 6, 0x19, "XMOS Semiconductor"}, + // { 6, 0x1a, "GENUSION"}, + { 6, 0x9b, "Memory Corp NV"}, + // { 6, 0x1c, "SiliconBlue Technologies"}, + // { 6, 0x9d, "Rambus"}, + // { 6, 0x9e, "Andes Technology"}, + // { 6, 0x1f, "Coronis Systems"}, + // { 6, 0x20, "Achronix Semiconductor"}, + // { 6, 0xa1, "Siano Mobile Silicon"}, + // { 6, 0xa2, "Semtech"}, + // { 6, 0x23, "Pixelworks"}, + // { 6, 0xa4, "Gaisler Research AB"}, + // { 6, 0x25, "Teranetics"}, + // { 6, 0x26, "Toppan Printing"}, + // { 6, 0xa7, "Kingxcon"}, + { 6, 0xa8, "SiS"}, + // { 6, 0x29, "I-O Data Device"}, + // { 6, 0x2a, "NDS Americas"}, + // { 6, 0xab, "Solomon Systech Limited"}, + // { 6, 0x2c, "On Demand Microelectronics"}, + // { 6, 0xad, "Amicus Wireless"}, + // { 6, 0xae, "SMARDTV SNC"}, + // { 6, 0x2f, "Comsys Communication"}, + // { 6, 0xb0, "Movidia"}, + // { 6, 0x31, "Javad GNSS"}, + // { 6, 0x32, "Montage Technology Group"}, + { 6, 0xb3, "Trident"}, + { 6, 0x34, "Super Talent"}, + // { 6, 0xb5, "Optichron"}, + // { 6, 0xb6, "Future Waves UK"}, + // { 6, 0x37, "SiBEAM"}, + // { 6, 0x38, "Inicore,"}, + // { 6, 0xb9, "Virident Systems"}, + // { 6, 0xba, "M2000"}, + // { 6, 0x3b, "ZeroG Wireless"}, + { 6, 0xbc, "Gingle"}, + // { 6, 0x3d, "Space Micro"}, + // { 6, 0x3e, "Wilocity"}, + // { 6, 0xbf, "Novafora, Ic."}, + // { 6, 0x40, "iKoa"}, + { 6, 0xc1, "ASint"}, + { 6, 0xc2, "Ramtron"}, + // { 6, 0x43, "Plato Networks"}, + // { 6, 0xc4, "IPtronics AS"}, + // { 6, 0x45, "Infinite-Memories"}, + // { 6, 0x46, "Parade Technologies"}, + // { 6, 0xc7, "Dune Networks"}, + // { 6, 0xc8, "GigaDevice Semiconductor"}, + // { 6, 0x49, "Modu"}, + // { 6, 0x4a, "CEITEC"}, + // { 6, 0xcb, "Northrop Grumman"}, + // { 6, 0x4c, "XRONET"}, + // { 6, 0xcd, "Sicon Semiconductor AB"}, + // { 6, 0xce, "Atla Electronics"}, + { 6, 0x4f, "TOPRAM"}, + // { 6, 0xd0, "Silego Technology"}, + { 6, 0x51, "Kinglife"}, + // { 6, 0x52, "Ability Industries"}, + // { 6, 0xd3, "Silicon Power Computer & Communications"}, + // { 6, 0x54, "Augusta Technology"}, + // { 6, 0xd5, "Nantronics Semiconductors"}, + // { 6, 0xd6, "Hilscher Gesellschaft"}, + // { 6, 0x57, "Quixant"}, + // { 6, 0x58, "Percello"}, + // { 6, 0xd9, "NextIO"}, + // { 6, 0xda, "Scanimetrics"}, + // { 6, 0x5b, "FS-Semi Company"}, + // { 6, 0xdc, "Infinera"}, + { 6, 0x5d, "SandForce"}, + { 6, 0x5e, "Lexar Media"}, + // { 6, 0xdf, "Teradyne"}, + { 6, 0xe0, "Memory Exchange Corp."}, + // { 6, 0x61, "Suzhou Smartek Electronics"}, + { 6, 0x62, "Avantium"}, + // { 6, 0xe3, "ATP Electronics"}, + // { 6, 0x64, "Valens Semiconductor"}, + // { 6, 0xe5, "Agate Logic"}, + // { 6, 0xe6, "Netronome"}, + // { 6, 0x67, "Zenverge"}, + // { 6, 0x68, "N-trig"}, + // { 6, 0xe9, "SanMax Technologies"}, + // { 6, 0xea, "Contour Semiconductor"}, + { 6, 0x6b, "TwinMOS"}, + { 6, 0xec, "Silicon Systems"}, + // { 6, 0x6d, "V-Color Technology"}, + // { 6, 0x6e, "Certicom"}, + // { 6, 0xef, "JSC ICC Milandr"}, + // { 6, 0x70, "PhotoFast Global"}, + { 6, 0xf1, "InnoDisk"}, + { 6, 0xf2, "Muscle Power"}, + // { 6, 0x73, "Energy Micro"}, + // { 6, 0xf4, "Innofidei"}, + // { 6, 0x75, "CopperGate Communications"}, + // { 6, 0x76, "Holtek Semiconductor"}, + // { 6, 0xf7, "Myson Century"}, + // { 6, 0xf8, "FIDELIX"}, + // { 6, 0x79, "Red Digital Cinema"}, + // { 6, 0x7a, "Densbits Technology"}, + // { 6, 0xfb, "Zempro"}, + // { 6, 0x7c, "MoSys"}, + // { 6, 0xfd, "Provigent"}, + // { 6, 0xfe, "Triad Semiconductor"}, + // { 8, 0x01, "Siklu Communication"}, + // { 8, 0x02, "A Force Manufacturing"}, + { 8, 0x83, "Strontium"}, + // { 8, 0x04, "Abilis Systems"}, + // { 8, 0x85, "Siglead"}, + // { 8, 0x86, "Ubicom"}, + // { 8, 0x07, "Unifosa"}, + // { 8, 0x08, "Stretch"}, + // { 8, 0x89, "Lantiq Deutschland"}, + // { 8, 0x8a, "Visipro."}, + { 8, 0x0b, "EKMemory"}, + // { 8, 0x8c, "Microelectronics Institute ZTE"}, + // { 8, 0x0d, "Cognovo"}, + // { 8, 0x0e, "Carry Technology"}, + { 8, 0x8f, "Nokia"}, + { 8, 0x10, "King Tiger"}, + // { 8, 0x91, "Sierra Wireless"}, + { 8, 0x92, "HT Micron"}, + { 8, 0x13, "Albatron"}, + // { 8, 0x94, "Leica Geosystems AG"}, + // { 8, 0x15, "BroadLight"}, + // { 8, 0x16, "AEXEA"}, + // { 8, 0x97, "ClariPhy Communications"}, + // { 8, 0x98, "Green Plug"}, + // { 8, 0x19, "Design Art Networks"}, + // { 8, 0x1a, "Mach Xtreme Technology"}, + // { 8, 0x9b, "ATO Solutions"}, + // { 8, 0x1c, "Ramsta"}, + // { 8, 0x9d, "Greenliant Systems"}, + // { 8, 0x9e, "Teikon"}, + // { 8, 0x1f, "Antec Hadron"}, + // { 8, 0x20, "NavCom Technology"}, + // { 8, 0xa1, "Shanghai Fudan Microelectronics"}, + // { 8, 0xa2, "Calxeda"}, + // { 8, 0x23, "JSC EDC Electronics"}, + // { 8, 0xa4, "Kandit Technology"}, + // { 8, 0x25, "Ramos Technology"}, + // { 8, 0x26, "Goldenmars Technology"}, + // { 8, 0xa7, "XeL Technology"}, + // { 8, 0xa8, "Newzone"}, + { 8, 0x29, "MercyPower"}, + // { 8, 0x2a, "Nanjing Yihuo Technology."}, + // { 8, 0xab, "Nethra Imaging"}, + // { 8, 0x2c, "SiTel Semiconductor BV"}, + // { 8, 0xad, "SolidGear"}, + { 8, 0xae, "Topower"}, + // { 8, 0x2f, "Wilocity"}, + // { 8, 0xb0, "Profichip"}, + // { 8, 0x31, "Gerad Technologies"}, + { 8, 0x32, "Ritek"}, + // { 8, 0xb3, "Gomos Technology Limited"}, + { 8, 0x34, "Memoright"}, + // { 8, 0xb5, "D-Broad"}, + // { 8, 0xb6, "HiSilicon Technologies"}, + // { 8, 0x37, "Syndiant ."}, + // { 8, 0x38, "Enverv"}, + // { 8, 0xb9, "Cognex"}, + // { 8, 0xba, "Xinnova Technology"}, + { 8, 0x3b, "Ultron"}, + // { 8, 0xbc, "Concord Idea"}, + // { 8, 0x3d, "AIM"}, + // { 8, 0x3e, "Lifetime Memory Products"}, + // { 8, 0xbf, "Ramsway"}, + // { 8, 0x40, "Recore Systems B.V."}, + // { 8, 0xc1, "Haotian Jinshibo Science Tech"}, + // { 8, 0xc2, "Being Advanced Memory"}, + // { 8, 0x43, "Adesto Technologies"}, + // { 8, 0xc4, "Giantec Semiconductor"}, + // { 8, 0x45, "HMD Electronics AG"}, + // { 8, 0x46, "Gloway International (HK)"}, + // { 8, 0xc7, "Kingcore"}, + // { 8, 0xc8, "Anucell Technology Holding"}, + // { 8, 0x49, "Accord Software & Systems Pvt."}, + // { 8, 0x4a, "Active-Semi"}, + // { 8, 0xcb, "Denso"}, + // { 8, 0x4c, "TLSI"}, + // { 8, 0xcd, "Shenzhen Daling Electronic"}, + // { 8, 0xce, "Mustang"}, + // { 8, 0x4f, "Orca Systems"}, + // { 8, 0xd0, "Passif Semiconductor"}, + // { 8, 0x51, "GigaDevice Semiconductor (Beijing)"}, + // { 8, 0x52, "Memphis Electronic"}, + // { 8, 0xd3, "Beckhoff Automation"}, + // { 8, 0x54, "Harmony Semiconductor Corp"}, + // { 8, 0xd5, "Air Computers SRL"}, + { 8, 0xd6, "TMT Memory"}, + { 9, 0xff, ""} + }; diff --git a/memtestEDK/Memtest/SingleComponents/lib.c b/memtestEDK/Memtest/SingleComponents/lib.c new file mode 100644 index 0000000..8d3ff04 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/lib.c @@ -0,0 +1,1208 @@ +/* lib.c - MemTest-86 Version 3.4 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + */ +#include "io.h" +#include "serial.h" +#include "test.h" +#include "config.h" +#include "screen_buffer.h" +#include "stdint.h" +#include "cpuid.h" +#include "smp.h" + +#include "environment.h" +#include <Library/UefiLib.h> + + +int slock = 0, lsr = 0; +short serial_cons = SERIAL_CONSOLE_DEFAULT; +#if SERIAL_TTY != 0 && SERIAL_TTY != 1 +#error Bad SERIAL_TTY. Only ttyS0 and ttyS1 are supported. +#endif +short serial_tty = SERIAL_TTY; +const short serial_base_ports[] = {0x3f8, 0x2f8}; + +#if ((115200%SERIAL_BAUD_RATE) != 0) +#error Bad default baud rate +#endif +int serial_baud_rate = SERIAL_BAUD_RATE; +unsigned char serial_parity = 0; +unsigned char serial_bits = 8; + +struct ascii_map_str { + int ascii; + int keycode; +}; + +void reboot(void) +{ + + /* tell the BIOS to do a cold start */ + *((unsigned short *)0x472) = 0x0; + + while(1) + { + outb(0xFE, 0x64); + outb(0x02, 0xcf9); /* reset that doesn't rely on the keyboard controller */ + outb(0x04, 0xcf9); + outb(0x0E, 0xcf9); + } +} + +int mt86_strlen(char * string){ + int i=0; + while(*string++){i++;}; + return i; +} + +int mt86_strstr(char *haystack, char * needle) +{ + int i=0,j=0; + int here=0; + while(1){ + if(needle[i]==haystack[j]) + { + if(here==0) + here=j; + i++;j++; + if(i>=mt86_strlen(needle)) + { + return here; + } + if(j>=mt86_strlen(haystack)) + { + return -1; + } + } else { + j++;i=0;here=0; + } + } +} + +int mt86_memcmp(const void *s1, const void *s2, ulong count) +{ + const unsigned char *src1 = s1, *src2 = s2; + int i; + for(i = 0; i < count; i++) { + if (src1[i] != src2[i]) { + return (int)src1[i] - (int)src2[i]; + } + } + return 0; +} + +int mt86_strncmp(const char *s1, const char *s2, ulong n) { + signed char res = 0; + while (n) { + res = *s1 - *s2; + if (res != 0) + return res; + if (*s1 == '\0') + return 0; + ++s1, ++s2; + --n; + } + return res; +} + +void *mt86_memmove(void *dest, const void *src, ulong n) +{ + long i; + char *d = (char *)dest, *s = (char *)src; + + /* If src == dest do nothing */ + if (dest < src) { + for(i = 0; i < n; i++) { + d[i] = s[i]; + } + } + else if (dest > src) { + for(i = n -1; i >= 0; i--) { + d[i] = s[i]; + } + } + return dest; +} + +char toupper(char c) +{ + if (c >= 'a' && c <= 'z') + return c + 'A' -'a'; + else + return c; +} + +int mt86_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +int isxdigit(char c) +{ + return mt86_isdigit(c) || (toupper(c) >= 'A' && toupper(c) <= 'F'); } + +unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) { + unsigned long result = 0, value; + + if (!base) { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if (toupper(*cp) == 'X' && isxdigit(cp[1])) { + cp++; + base = 16; + } + } + } else if (base == 16) { + if (cp[0] == '0' && toupper(cp[1]) == 'X') + cp += 2; + } + while (isxdigit(*cp) && + (value = mt86_isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +/* + * Scroll the error message area of the screen as needed + * Starts at line LINE_SCROLL and ends at line 23 + */ +void scroll(void) +{ + int i, j; + char *s, tmp; + + /* Only scroll if at the bottom of the screen */ + if (vv->msg_line < 23) { + vv->msg_line++; + } else { + /* If scroll lock is on, loop till it is cleared */ + while (slock) { + check_input(); + } + for (i=LINE_SCROLL; i<23; i++) { + s = (char *) (MAX_BLOCK_SIZE) (SCREEN_ADR + ((i+1) * 160)); + for (j=0; j<160; j+=2, s+=2) { + *(s-160) = *s; + tmp = get_scrn_buf(i+1, j/2); + set_scrn_buf(i, j/2, tmp); + } + } + /* Clear the newly opened line */ + s = (char *)(SCREEN_ADR + (23 * 160)); + for (j=0; j<80; j++) { + *s = ' '; + set_scrn_buf(23, j, ' '); + s += 2; + } + tty_print_region(LINE_SCROLL, 0, 23, 79); + } +} + +/* + * Clear scroll region + */ +void clear_scroll(void) +{ + int i; + char *s; + + s = (char*)(SCREEN_ADR+LINE_HEADER*160); + for(i=0; i<80*(24-LINE_HEADER); i++) { + *s++ = ' '; + *s++ = 0x17; + } +} + +/* + * Place a single character on screen + */ +void cplace(int y, int x, const char c) +{ + char *dptr; + + dptr = (char *) (MAX_BLOCK_SIZE) (SCREEN_ADR + (160*y) + (2*x)); + *dptr = c; +} + +/* + * Print characters on screen + */ +void cprint(int y, int x, const char *text) +{ + register int i; + char *dptr; + + dptr = (char *) (MAX_BLOCK_SIZE) (SCREEN_ADR + (160*y) + (2*x)); + for (i=0; text[i]; i++) { + *dptr = text[i]; + dptr += 2; + } + tty_print_line(y, x, text); +} + +void itoa(char s[], int n) +{ + Print(L"start itoa\n"); + int i, sign; + + if((sign = n) < 0) + n = -n; + i=0; + do { + s[i++] = n % 10 + '0'; + } while ((n /= 10) > 0); + if(sign < 0) + s[i++] = '-'; + s[i] = '\0'; + reverse(s); + Print(L"end itoa\n"); +} + +void reverse(char s[]) +{ + int c, i, j; + for(j = 0; s[j] != 0; j++) + ; + + for(i=0, j = j - 1; i < j; i++, j--) { + c = s[i]; + s[i] = s[j]; + s[j] = c; + } +} +void memcpy (void *dst, void *src, int len) +{ + char *s = (char*)src; + char *d = (char*)dst; + int i; + + if (len <= 0) { + return; + } + for (i = 0 ; i < len; i++) { + *d++ = *s++; + } +} + +/* + * Print a people friendly address + */ +void aprint(int y, int x, ulong page) +{ + /* page is in multiples of 4K */ + if ((page << 2) < 9999) { + dprint(y, x, page << 2, 4, 0); + cprint(y, x+4, "K"); + } + else if ((page >>8) < 9999) { + dprint(y, x, (page + (1 << 7)) >> 8, 4, 0); + cprint(y, x+4, "M"); + } + else if ((page >>18) < 9999) { + dprint(y, x, (page + (1 << 17)) >> 18, 4, 0); + cprint(y, x+4, "G"); + } + else { + dprint(y, x, (page + (1 << 27)) >> 28, 4, 0); + cprint(y, x+4, "T"); + } +} + +/* + * Print a decimal number on screen + */ +void dprint(int y, int x, ulong val, int len, int right) +{ + ulong j, k; + int i, flag=0; + char buf[18]; + + if (val > 999999999 || len > 9) { + return; + } + for(i=0, j=1; i<len-1; i++) { + j *= 10; + } + if (!right) { + for (i=0; j>0; j/=10) { + k = val/j; + if (k > 9) { + j *= 100; + continue; + } + if (flag || k || j == 1) { + buf[i++] = k + '0'; + flag++; + } else { + buf[i++] = ' '; + } + val -= k * j; + } + } else { + for(i=0; i<len; j/=10) { + if (j) { + k = val/j; + if (k > 9) { + j *= 100; + len++; + continue; + } + if (k == 0 && flag == 0) { + continue; + } + buf[i++] = k + '0'; + val -= k * j; + } else { + if (flag == 0 && i < len-1) { + buf[i++] = '0'; + } else { + buf[i++] = ' '; + } + } + flag++; + } + } + buf[i] = 0; + cprint(y,x,buf); +} + +/* + * Print a hex number on screen at least digits long + */ +void hprint2(int y,int x, unsigned long val, int digits) +{ + unsigned long j; + int i, idx, flag = 0; + char buf[18]; + + for (i=0, idx=0; i<8; i++) { + j = val >> (28 - (4 * i)); + j &= 0xf; + if (j < 10) { + if (flag || j || i == 7) { + buf[idx++] = j + '0'; + flag++; + } else { + buf[idx++] = '0'; + } + } else { + buf[idx++] = j + 'a' - 10; + flag++; + } + } + if (digits > 8) { + digits = 8; + } + if (flag > digits) { + digits = flag; + } + buf[idx] = 0; + cprint(y,x,buf + (idx - digits)); +} + +/* + * Print a hex number on screen exactly digits long + */ +void hprint3(int y,int x, unsigned long val, int digits) +{ + unsigned long j; + int i, idx, flag = 0; + char buf[18]; + + for (i=0, idx=0; i<digits; i++) { + j = 0xf & val; + val /= 16; + + if (j < 10) { + if (flag || j || i == 7) { + buf[digits - ++idx] = j + '0'; + flag++; + } else { + buf[digits - ++idx] = '0'; + } + } else { + buf[digits - ++idx] = j + 'a' - 10; + flag++; + } + } + buf[idx] = 0; + cprint(y,x,buf); +} + +/* + * Print a hex number on screen + */ +void hprint(int y, int x, unsigned long val) +{ + return hprint2(y, x, val, 8); +} + +/* + * Print an address in 0000m0000k0000 notation + */ +void xprint(int y,int x, ulong val) +{ + ulong j; + + j = (val & 0xffc00000) >> 20; + dprint(y, x, j, 4, 0); + cprint(y, x+4, "m"); + j = (val & 0xffc00) >> 10; + dprint(y, x+5, j, 4, 0); + cprint(y, x+9, "k"); + j = val & 0x3ff; + dprint(y, x+10, j, 4, 0); +} + +char *codes[] = { + " Divide", + " Debug", + " NMI", + " Brkpnt", + "Overflow", + " Bound", + " Inv_Op", + " No_Math", + "Double_Fault", + "Seg_Over", + " Inv_TSS", + " Seg_NP", + "Stack_Fault", + "Gen_Prot", + "Page_Fault", + " Resvd", + " FPE", + "Alignment", + " Mch_Chk", + "SIMD FPE" +}; + +struct eregs { + ulong ss; + ulong ds; + ulong esp; + ulong ebp; + ulong esi; + ulong edi; + ulong edx; + ulong ecx; + ulong ebx; + ulong eax; + ulong vect; + ulong code; + ulong eip; + ulong cs; + ulong eflag; +}; + +/* Handle an interrupt */ +void inter(struct eregs *trap_regs) +{ + int i, line; + unsigned char *pp; + ulong address = 0; + int my_cpu_num = smp_my_cpu_num(); + + /* Get the page fault address */ + if (trap_regs->vect == 14) { + __asm__("movl %%cr2,%0":"=r" (address)); + } +#ifdef PARITY_MEM + + /* Check for a parity error */ + if (trap_regs->vect == 2) { + parity_err(trap_regs->edi, trap_regs->esi); + return; + } +#endif + + /* clear scrolling region */ + pp=(unsigned char *)(SCREEN_ADR+(2*80*(LINE_SCROLL-2))); + for(i=0; i<2*80*(24-LINE_SCROLL-2); i++, pp+=2) { + *pp = ' '; + } + line = LINE_SCROLL-2; + + cprint(line, 0, "Unexpected Interrupt - Halting CPU"); + dprint(line, COL_MID + 4, my_cpu_num, 2, 1); + cprint(line+2, 0, " Type: "); + if (trap_regs->vect <= 19) { + cprint(line+2, 7, codes[trap_regs->vect]); + } else { + hprint(line+2, 7, trap_regs->vect); + } + cprint(line+3, 0, " PC: "); + hprint(line+3, 7, trap_regs->eip); + cprint(line+4, 0, " CS: "); + hprint(line+4, 7, trap_regs->cs); + cprint(line+5, 0, "Eflag: "); + hprint(line+5, 7, trap_regs->eflag); + cprint(line+6, 0, " Code: "); + hprint(line+6, 7, trap_regs->code); + cprint(line+7, 0, " DS: "); + hprint(line+7, 7, trap_regs->ds); + cprint(line+8, 0, " SS: "); + hprint(line+8, 7, trap_regs->ss); + if (trap_regs->vect == 14) { + /* Page fault address */ + cprint(line+7, 0, " Addr: "); + hprint(line+7, 7, address); + } + + cprint(line+2, 20, "eax: "); + hprint(line+2, 25, trap_regs->eax); + cprint(line+3, 20, "ebx: "); + hprint(line+3, 25, trap_regs->ebx); + cprint(line+4, 20, "ecx: "); + hprint(line+4, 25, trap_regs->ecx); + cprint(line+5, 20, "edx: "); + hprint(line+5, 25, trap_regs->edx); + cprint(line+6, 20, "edi: "); + hprint(line+6, 25, trap_regs->edi); + cprint(line+7, 20, "esi: "); + hprint(line+7, 25, trap_regs->esi); + cprint(line+8, 20, "ebp: "); + hprint(line+8, 25, trap_regs->ebp); + cprint(line+9, 20, "esp: "); + hprint(line+9, 25, trap_regs->esp); + + cprint(line+1, 38, "Stack:"); + for (i=0; i<10; i++) { + hprint(line+2+i, 38, trap_regs->esp+(4*i)); + hprint(line+2+i, 47, *(ulong*)(trap_regs->esp+(4*i))); + hprint(line+2+i, 57, trap_regs->esp+(4*(i+10))); + hprint(line+2+i, 66, *(ulong*)(trap_regs->esp+(4*(i+10)))); + } + + cprint(line+11, 0, "CS:EIP: "); + pp = (unsigned char *)trap_regs->eip; + for(i = 0; i < 9; i++) { + hprint2(line+11, 8+(3*i), pp[i], 2); + } + + while(1) { + check_input(); + } +} + +void set_cache(int val) +{ + switch(val) { + case 0: + cache_off(); + break; + case 1: + cache_on(); + break; + } +} + +int get_key() { + int c; + + c = inb(0x64); + if ((c & 1) == 0) { + if (serial_cons) { + int comstat; + comstat = serial_echo_inb(UART_LSR); + if (comstat & UART_LSR_DR) { + c = serial_echo_inb(UART_RX); + /* Pressing '.' has same effect as 'c' + on a keyboard. + Oct 056 Dec 46 Hex 2E Ascii . + */ + return (ascii_to_keycode(c)); + } + } + return(0); + } + c = inb(0x60); + return((c)); +} + +void check_input(void) +{ + unsigned char c; + + if ((c = get_key())) { + switch(c & 0x7f) { + case 1: + /* "ESC" key was pressed, bail out. */ + cprint(LINE_RANGE, COL_MID+23, "Halting... "); + reboot(); + break; + case 46: + /* c - Configure */ + get_config(); + break; + case 28: + /* CR - clear scroll lock */ + slock = 0; + footer(); + break; + case 57: + /* SP - set scroll lock */ + slock = 1; + footer(); + break; + case 0x26: + /* ^L/L - redraw the display */ + tty_print_screen(); + break; + } + } +} + +void footer() +{ + cprint(24, 0, "(ESC)exit (c)configuration (SP)scroll_lock (CR)scroll_unlock"); + if (slock) { + cprint(24, 74, "Locked"); + } else { + cprint(24, 74, " "); + } +} + +ulong getval(int x, int y, int result_shift) +{ + unsigned long val; + int done; + int c; + int i, n; + int base; + int shift; + char buf[16]; + + for(i = 0; i < sizeof(buf)/sizeof(buf[0]); i++ ) { + buf[i] = ' '; + } + buf[sizeof(buf)/sizeof(buf[0]) -1] = '\0'; + + wait_keyup(); + done = 0; + n = 0; + base = 10; + while(!done) { + /* Read a new character and process it */ + c = get_key(); + switch(c) { + case 0x26: /* ^L/L - redraw the display */ + tty_print_screen(); + break; + case 0x1c: /* CR */ + /* If something has been entered we are done */ + if(n) done = 1; + break; + case 0x19: /* p */ buf[n] = 'p'; break; + case 0x22: /* g */ buf[n] = 'g'; break; + case 0x32: /* m */ buf[n] = 'm'; break; + case 0x25: /* k */ buf[n] = 'k'; break; + case 0x2d: /* x */ + /* Only allow 'x' after an initial 0 */ + if (n == 1 && (buf[0] == '0')) { + buf[n] = 'x'; + } + break; + case 0x0e: /* BS */ + if (n > 0) { + n -= 1; + buf[n] = ' '; + } + break; + /* Don't allow entering a number not in our current base */ + case 0x0B: if (base >= 1) buf[n] = '0'; break; + case 0x02: if (base >= 2) buf[n] = '1'; break; + case 0x03: if (base >= 3) buf[n] = '2'; break; + case 0x04: if (base >= 4) buf[n] = '3'; break; + case 0x05: if (base >= 5) buf[n] = '4'; break; + case 0x06: if (base >= 6) buf[n] = '5'; break; + case 0x07: if (base >= 7) buf[n] = '6'; break; + case 0x08: if (base >= 8) buf[n] = '7'; break; + case 0x09: if (base >= 9) buf[n] = '8'; break; + case 0x0A: if (base >= 10) buf[n] = '9'; break; + case 0x1e: if (base >= 11) buf[n] = 'a'; break; + case 0x30: if (base >= 12) buf[n] = 'b'; break; + case 0x2e: if (base >= 13) buf[n] = 'c'; break; + case 0x20: if (base >= 14) buf[n] = 'd'; break; + case 0x12: if (base >= 15) buf[n] = 'e'; break; + case 0x21: if (base >= 16) buf[n] = 'f'; break; + default: + break; + } + /* Don't allow anything to be entered after a suffix */ + if (n > 0 && ( + (buf[n-1] == 'p') || (buf[n-1] == 'g') || + (buf[n-1] == 'm') || (buf[n-1] == 'k'))) { + buf[n] = ' '; + } + /* If we have entered a character increment n */ + if (buf[n] != ' ') { + n++; + } + buf[n] = ' '; + /* Print the current number */ + cprint(x, y, buf); + + /* Find the base we are entering numbers in */ + base = 10; + if ((buf[0] == '0') && (buf[1] == 'x')) { + base = 16; + } + else if (buf[0] == '0') { + base = 8; + } + } + /* Compute our current shift */ + shift = 0; + switch(buf[n-1]) { + case 'g': /* gig */ shift = 30; break; + case 'm': /* meg */ shift = 20; break; + case 'p': /* page */ shift = 12; break; + case 'k': /* kilo */ shift = 10; break; + } + shift -= result_shift; + + /* Compute our current value */ + val = simple_strtoul(buf, 0, base); + if (shift > 0) { + if (shift >= 32) { + val = 0xffffffff; + } else { + val <<= shift; + } + } else { + if (-shift >= 32) { + val = 0; + } + else { + val >>= -shift; + } + } + return val; +} + +void ttyprint(int y, int x, const char *p) +{ + Print(L"start ttyprint\n"); + static char sx[3]; + static char sy[3]; + + sx[0]='\0'; + sy[0]='\0'; + x++; y++; + itoa(sx, x); + itoa(sy, y); + serial_echo_print("["); + serial_echo_print(sy); + serial_echo_print(";"); + serial_echo_print(sx); + serial_echo_print("H"); + serial_echo_print(p); + Print(L"end ttyprint\n"); +} + +void serial_echo_init(void) +{ + int comstat, serial_div; + unsigned char lcr; + + /* read the Divisor Latch */ + comstat = serial_echo_inb(UART_LCR); + serial_echo_outb(comstat | UART_LCR_DLAB, UART_LCR); + /*hi =*/ serial_echo_inb(UART_DLM); + /*lo =*/ serial_echo_inb(UART_DLL); + serial_echo_outb(comstat, UART_LCR); + + /* now do hardwired init */ + lcr = serial_parity | (serial_bits - 5); + serial_echo_outb(lcr, UART_LCR); /* No parity, 8 data bits, 1 stop */ + serial_div = 115200 / serial_baud_rate; + serial_echo_outb(0x80|lcr, UART_LCR); /* Access divisor latch */ + serial_echo_outb(serial_div & 0xff, UART_DLL); /* baud rate divisor */ + serial_echo_outb((serial_div >> 8) & 0xff, UART_DLM); + serial_echo_outb(lcr, UART_LCR); /* Done with divisor */ + + /* Prior to disabling interrupts, read the LSR and RBR + * registers */ + comstat = serial_echo_inb(UART_LSR); /* COM? LSR */ + comstat = serial_echo_inb(UART_RX); /* COM? RBR */ + serial_echo_outb(0x00, UART_IER); /* Disable all interrupts */ + + clear_screen_buf(); + + return; +} + +/* + * Get_number of digits + */ +int getnum(ulong val) +{ + int len = 0; + int i = 1; + + while(i <= val) + { + len++; + i *= 10; + } + + return len; + +} + + +void serial_echo_print(const char *p) +{ + Print(L"start serial_echo_print\n"); + if (!serial_cons) { + return; + } + /* Now, do each character */ + while (*p) { + WAIT_FOR_XMITR; + + /* Send the character out. */ + serial_echo_outb(*p, UART_TX); + if(*p==10) { + WAIT_FOR_XMITR; + serial_echo_outb(13, UART_TX); + } + p++; + } + Print(L"end serial echo print\n"); +} + +/* Except for multi-character key sequences this mapping + * table is complete. So it should not need to be updated + * when new keys are searched for. However the key handling + * should really be turned around and only in get_key should + * we worry about the exact keycode that was pressed. Everywhere + * else we should switch on the character... + */ +struct ascii_map_str ser_map[] = + /*ascii keycode ascii keycode*/ + { + /* Special cases come first so I can leave + * their ``normal'' mapping in the table, + * without it being activated. + */ + { 27, 0x01}, /* ^[/ESC -> ESC */ + { 127, 0x0e}, /* DEL -> BS */ + { 8, 0x0e}, /* ^H/BS -> BS */ + { 10, 0x1c}, /* ^L/NL -> CR */ + { 13, 0x1c}, /* ^M/CR -> CR */ + { 9, 0x0f}, /* ^I/TAB -> TAB */ + { 19, 0x39}, /* ^S -> SP */ + { 17, 28}, /* ^Q -> CR */ + + { ' ', 0x39}, /* SP -> SP */ + { 'a', 0x1e}, + { 'A', 0x1e}, + { 1, 0x1e}, /* ^A -> A */ + { 'b', 0x30}, + { 'B', 0x30}, + { 2, 0x30}, /* ^B -> B */ + { 'c', 0x2e}, + { 'C', 0x2e}, + { 3, 0x2e}, /* ^C -> C */ + { 'd', 0x20}, + { 'D', 0x20}, + { 4, 0x20}, /* ^D -> D */ + { 'e', 0x12}, + { 'E', 0x12}, + { 5, 0x12}, /* ^E -> E */ + { 'f', 0x21}, + { 'F', 0x21}, + { 6, 0x21}, /* ^F -> F */ + { 'g', 0x22}, + { 'G', 0x22}, + { 7, 0x22}, /* ^G -> G */ + { 'h', 0x23}, + { 'H', 0x23}, + { 8, 0x23}, /* ^H -> H */ + { 'i', 0x17}, + { 'I', 0x17}, + { 9, 0x17}, /* ^I -> I */ + { 'j', 0x24}, + { 'J', 0x24}, + { 10, 0x24}, /* ^J -> J */ + { 'k', 0x25}, + { 'K', 0x25}, + { 11, 0x25}, /* ^K -> K */ + { 'l', 0x26}, + { 'L', 0x26}, + { 12, 0x26}, /* ^L -> L */ + { 'm', 0x32}, + { 'M', 0x32}, + { 13, 0x32}, /* ^M -> M */ + { 'n', 0x31}, + { 'N', 0x31}, + { 14, 0x31}, /* ^N -> N */ + { 'o', 0x18}, + { 'O', 0x18}, + { 15, 0x18}, /* ^O -> O */ + { 'p', 0x19}, + { 'P', 0x19}, + { 16, 0x19}, /* ^P -> P */ + { 'q', 0x10}, + { 'Q', 0x10}, + { 17, 0x10}, /* ^Q -> Q */ + { 'r', 0x13}, + { 'R', 0x13}, + { 18, 0x13}, /* ^R -> R */ + { 's', 0x1f}, + { 'S', 0x1f}, + { 19, 0x1f}, /* ^S -> S */ + { 't', 0x14}, + { 'T', 0x14}, + { 20, 0x14}, /* ^T -> T */ + { 'u', 0x16}, + { 'U', 0x16}, + { 21, 0x16}, /* ^U -> U */ + { 'v', 0x2f}, + { 'V', 0x2f}, + { 22, 0x2f}, /* ^V -> V */ + { 'w', 0x11}, + { 'W', 0x11}, + { 23, 0x11}, /* ^W -> W */ + { 'x', 0x2d}, + { 'X', 0x2d}, + { 24, 0x2d}, /* ^X -> X */ + { 'y', 0x15}, + { 'Y', 0x15}, + { 25, 0x15}, /* ^Y -> Y */ + { 'z', 0x2c}, + { 'Z', 0x2c}, + { 26, 0x2c}, /* ^Z -> Z */ + { '-', 0x0c}, + { '_', 0x0c}, + { 31, 0x0c}, /* ^_ -> _ */ + { '=', 0x0c}, + { '+', 0x0c}, + { '[', 0x1a}, + { '{', 0x1a}, + { 27, 0x1a}, /* ^[ -> [ */ + { ']', 0x1b}, + { '}', 0x1b}, + { 29, 0x1b}, /* ^] -> ] */ + { ';', 0x27}, + { ':', 0x27}, + { '\'', 0x28}, + { '"', 0x28}, + { '`', 0x29}, + { '~', 0x29}, + { '\\', 0x2b}, + { '|', 0x2b}, + { 28, 0x2b}, /* ^\ -> \ */ + { ',', 0x33}, + { '<', 0x33}, + { '.', 0x34}, + { '>', 0x34}, + { '/', 0x35}, + { '?', 0x35}, + { '1', 0x02}, + { '!', 0x02}, + { '2', 0x03}, + { '@', 0x03}, + { '3', 0x04}, + { '#', 0x04}, + { '4', 0x05}, + { '$', 0x05}, + { '5', 0x06}, + { '%', 0x06}, + { '6', 0x07}, + { '^', 0x07}, + { 30, 0x07}, /* ^^ -> 6 */ + { '7', 0x08}, + { '&', 0x08}, + { '8', 0x09}, + { '*', 0x09}, + { '9', 0x0a}, + { '(', 0x0a}, + { '0', 0x0b}, + { ')', 0x0b}, + { 0, 0} + }; + +/* + * Given an ascii character, return the keycode + * + * Uses ser_map definition above. + * + * It would be more efficient to use an array of 255 characters + * and directly index into it. + */ +int ascii_to_keycode (int in) +{ + struct ascii_map_str *p; + for (p = ser_map; p->ascii; p++) { + if (in ==p->ascii) + return p->keycode; + } + return 0; +} + +/* + * Call this when you want to wait for the user to lift the + * finger off of a key. It is a noop if you are using a + * serial console. + */ +void wait_keyup( void ) { + /* Check to see if someone lifted the keyboard key */ + while (1) { + if ((get_key() & 0x80) != 0) { + return; + } + /* Trying to simulate waiting for a key release with + * the serial port is to nasty to let live. + * In particular some menus don't even display until + * you release the key that caused to to get there. + * With the serial port this results in double pressing + * or something worse for just about every key. + */ + if (serial_cons) { + return; + } + } +} + +/* + * Handles "console=<param>" command line option + * + * Examples of accepted params: + * ttyS0 + * ttyS1 + * ttyS0,115200 + * ttyS0,9600e8 + */ +void serial_console_setup(char *param) +{ + char *option, *end; + unsigned long tty; + unsigned long baud_rate; + unsigned char parity, bits; + + if (mt86_strncmp(param, "ttyS", 4)) + return; /* not a serial port */ + + param += 4; + + tty = simple_strtoul(param, &option, 10); + + if (option == param) + return; /* there were no digits */ + + if (tty > 1) + return; /* only ttyS0 and ttyS1 supported */ + + if (*option == '\0' || *option == ' ') + goto save_tty; /* no options given, just ttyS? */ + + if (*option != ',') + return; /* missing the comma separator */ + + /* baud rate must follow */ + option++; + baud_rate = simple_strtoul(option, &end, 10); + + if (end == option) + return; /* no baudrate after comma */ + + if (baud_rate == 0 || (115200 % baud_rate) != 0) + return; /* wrong baud rate */ + + if (*end == '\0' || *end == ' ') + goto save_baud_rate; /* no more options given */ + + switch (toupper(*end)) { + case 'N': + parity = 0; + break; + case 'O': + parity = UART_LCR_PARITY; + break; + case 'E': + parity = UART_LCR_PARITY | UART_LCR_EPAR; + break; + default: + /* Unknown parity */ + return; + } + + end++; + if (*end == '\0' || *end == ' ') + goto save_parity; + + /* word length (bits) */ + if (*end < '7' || *end > '8') + return; /* invalid number of bits */ + + bits = *end - '0'; + + end++; + + if (*end != '\0' || *end != ' ') + return; /* garbage at the end */ + + serial_bits = bits; + save_parity: + serial_parity = parity; + save_baud_rate: + serial_baud_rate = (int) baud_rate; + save_tty: + serial_tty = (short) tty; + serial_cons = 1; +} + +/* Get a comma seperated list of numbers */ +void get_list(int x, int y, int len, char *buf) +{ + int c, n = 0; + + len--; + wait_keyup(); + while(1) { + /* Read a new character and process it */ + c = get_key(); + switch(c) { + case 0x1c: /* CR */ + /* If something has been entered we are done */ + if(n) { + buf[n] = 0; + return; + } + break; + case 0x0e: /* BS */ + if (n > 0) { + n -= 1; + buf[n] = ' '; + } + break; + case 0x0B: buf[n++] = '0'; break; + case 0x02: buf[n++] = '1'; break; + case 0x03: buf[n++] = '2'; break; + case 0x04: buf[n++] = '3'; break; + case 0x05: buf[n++] = '4'; break; + case 0x06: buf[n++] = '5'; break; + case 0x07: buf[n++] = '6'; break; + case 0x08: buf[n++] = '7'; break; + case 0x09: buf[n++] = '8'; break; + case 0x0a: buf[n++] = '9'; break; + case 0x33: buf[n++] = ','; break; + } + cprint(x, y, buf); + if (n >= len) { + buf[n] = 0; + return; + } + } +} diff --git a/memtestEDK/Memtest/SingleComponents/linuxbios.c b/memtestEDK/Memtest/SingleComponents/linuxbios.c new file mode 100644 index 0000000..4804b31 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/linuxbios.c @@ -0,0 +1,165 @@ +#include "linuxbios_tables.h" +#include "test.h" + +static unsigned long ip_compute_csum(void *addr, unsigned long length) +{ + uint16_t *ptr; + unsigned long sum; + unsigned long len; + unsigned long laddr; + /* compute an ip style checksum */ + laddr = (unsigned long )addr; + sum = 0; + if (laddr & 1) { + uint16_t buffer; + unsigned char *ptr; + /* copy the first byte into a 2 byte buffer. + * This way automatically handles the endian question + * of which byte (low or high) the last byte goes in. + */ + buffer = 0; + ptr = addr; + mt86_memmove(&buffer, ptr, 1); + sum += buffer; + if (sum > 0xFFFF) + sum -= 0xFFFF; + length -= 1; + addr = ptr +1; + + } + len = length >> 1; + ptr = addr; + while (len--) { + sum += *(ptr++); + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + addr = ptr; + if (length & 1) { + uint16_t buffer; + unsigned char *ptr; + /* copy the last byte into a 2 byte buffer. + * This way automatically handles the endian question + * of which byte (low or high) the last byte goes in. + */ + buffer = 0; + ptr = addr; + mt86_memmove(&buffer, ptr, 1); + sum += buffer; + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + return (~sum) & 0xFFFF; + +} + +#define for_each_lbrec(head, rec) \ + for(rec = (struct lb_record *)(((char *)head) + sizeof(*head)); \ + (((char *)rec) < (((char *)head) + sizeof(*head) + head->table_bytes)) && \ + (rec->size >= 1) && \ + ((((char *)rec) + rec->size) <= (((char *)head) + sizeof(*head) + head->table_bytes)); \ + rec = (struct lb_record *)(((char *)rec) + rec->size)) + + +static int count_lb_records(struct lb_header *head) +{ + struct lb_record *rec; + int count; + count = 0; + for_each_lbrec(head, rec) { + count++; + } + return count; +} + +static struct lb_header * __find_lb_table(unsigned long start, unsigned long end) +{ + unsigned long addr; + /* For now be stupid.... */ + for(addr = start; addr < end; addr += 16) { + struct lb_header *head = (struct lb_header *)addr; + struct lb_record *recs = (struct lb_record *)(addr + sizeof(*head)); + if (mt86_memcmp(head->signature, "LBIO", 4) != 0) + continue; + if (head->header_bytes != sizeof(*head)) + continue; + if (ip_compute_csum((unsigned char *)head, sizeof(*head)) != 0) + continue; + if (ip_compute_csum((unsigned char *)recs, head->table_bytes) + != head->table_checksum) + continue; + if (count_lb_records(head) != head->table_entries) + continue; + return head; + }; + return 0; +} + +static struct lb_header * find_lb_table(void) +{ + struct lb_header *head; + head = 0; + if (!head) { + /* First try at address 0 */ + head = __find_lb_table(0x00000, 0x1000); + } + if (!head) { + /* Then try at address 0xf0000 */ + head = __find_lb_table(0xf0000, 0x100000); + } + return head; +} + +int query_linuxbios(void) +{ + struct lb_header *head; + struct lb_record *rec; + struct lb_memory *mem; + struct lb_forward *forward; + int i, entries; + + head = find_lb_table(); + if (!head) { + return 0; + } + + /* coreboot also can forward the table to the high tables area. */ + rec = (struct lb_record *)(((char *)head) + sizeof(*head)); + if (rec->tag == LB_TAG_FORWARD) { + forward = (struct lb_forward *)rec; + head = (struct lb_header *)(unsigned long)(forward->forward); + if (!head) { return 0; } + } + + mem = 0; + for_each_lbrec(head, rec) { + if (rec->tag == LB_TAG_MEMORY) { + mem = (struct lb_memory *)rec; + break; + } + } + if (!mem) { + return 1; + } + entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); + if (entries == 0) + return 1; + mem_info.e820_nr = 0; + for(i = 0; i < entries; i++) { + unsigned long long start; + unsigned long long size; + unsigned long type; + if (i >= E820MAX) { + break; + } + start = mem->map[i].start; + size = mem->map[i].size; + type = (mem->map[i].type == LB_MEM_RAM)?E820_RAM: E820_RESERVED; + mem_info.e820[mem_info.e820_nr].addr = start; + mem_info.e820[mem_info.e820_nr].size = size; + mem_info.e820[mem_info.e820_nr].type = type; + mem_info.e820_nr++; + } + return 1; +} + diff --git a/memtestEDK/Memtest/SingleComponents/linuxbios_tables.h b/memtestEDK/Memtest/SingleComponents/linuxbios_tables.h new file mode 100644 index 0000000..38f2038 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/linuxbios_tables.h @@ -0,0 +1,89 @@ +#ifndef LINUXBIOS_TABLES_H +#define LINUXBIOS_TABLES_H + +#include "stdint.h" + +/* The linuxbios table information is for conveying information + * from the firmware to the loaded OS image. Primarily this + * is expected to be information that cannot be discovered by + * other means, such as quering the hardware directly. + * + * All of the information should be Position Independent Data. + * That is it should be safe to relocated any of the information + * without it's meaning/correctnes changing. For table that + * can reasonably be used on multiple architectures the data + * size should be fixed. This should ease the transition between + * 32 bit and 64 bit architectures etc. + * + * The completeness test for the information in this table is: + * - Can all of the hardware be detected? + * - Are the per motherboard constants available? + * - Is there enough to allow a kernel to run that was written before + * a particular motherboard is constructed? (Assuming the kernel + * has drivers for all of the hardware but it does not have + * assumptions on how the hardware is connected together). + * + * With this test it should be straight forward to determine if a + * table entry is required or not. This should remove much of the + * long term compatibility burden as table entries which are + * irrelevant or have been replaced by better alternatives may be + * dropped. Of course it is polite and expidite to include extra + * table entries and be backwards compatible, but it is not required. + */ + + +struct lb_header +{ + uint8_t signature[4]; /* LBIO */ + uint32_t header_bytes; + uint32_t header_checksum; + uint32_t table_bytes; + uint32_t table_checksum; + uint32_t table_entries; +}; + +/* Every entry in the boot enviroment list will correspond to a boot + * info record. Encoding both type and size. The type is obviously + * so you can tell what it is. The size allows you to skip that + * boot enviroment record if you don't know what it easy. This allows + * forward compatibility with records not yet defined. + */ +struct lb_record { + uint32_t tag; /* tag ID */ + uint32_t size; /* size of record (in bytes) */ +}; + +#define LB_TAG_UNUSED 0x0000 + +#define LB_TAG_MEMORY 0x0001 +#define LB_TAG_FORWARD 0x0011 + +struct lb_memory_range { + uint64_t start; + uint64_t size; + uint32_t type; +#define LB_MEM_RAM 1 +#define LB_MEM_RESERVED 2 + +}; + +struct lb_memory { + uint32_t tag; + uint32_t size; + struct lb_memory_range map[0]; +}; + +#define LB_TAG_HWRPB 0x0002 +struct lb_hwrpb { + uint32_t tag; + uint32_t size; + uint64_t hwrpb; +}; + +struct lb_forward { + uint32_t tag; + uint32_t size; + uint64_t forward; +}; + +#endif /* LINUXBIOS_TABLES_H */ diff --git a/memtestEDK/Memtest/SingleComponents/main.c b/memtestEDK/Memtest/SingleComponents/main.c new file mode 100644 index 0000000..d0c9289 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/main.c @@ -0,0 +1,1299 @@ +/* + * MemTest86+ V5 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + * ------------------------------------------------ + * main.c - MemTest-86 Version 3.5 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + */ + +#include "stdint.h" +#include "stddef.h" +#include "test.h" +#include "defs.h" +#include "cpuid.h" +#include "smp.h" +#include "config.h" +#undef TEST_TIMES +#define DEFTESTS 9 +#define FIRST_DIVISER 3 + +/* The main stack is allocated during boot time. The stack size should + * preferably be a multiple of page size(4Kbytes) + */ + +extern struct cpu_ident cpu_id; +extern char toupper(char c); +extern int isxdigit(char c); +extern void reboot(); +extern void bzero(); +extern void smp_set_ordinal(int me, int ord); +extern int smp_my_ord_num(int me); +extern int smp_ord_to_cpu(int me); +extern void get_cpuid(); +extern void initialise_cpus(); +extern ulong rand(int cpu); +extern void get_mem_speed(int cpu, int ncpus); +extern void rand_seed(unsigned int seed1, unsigned int seed2, int cpu); +extern struct barrier_s *barr; +extern int num_cpus; +extern int act_cpus; + +static int find_ticks_for_test(int test); +void find_ticks_for_pass(void); +int find_chunks(int test); +static void test_setup(void); +static int compute_segments(struct pmap map, int cpu); +int do_test(int ord); +struct tseq tseq[] = + { + {1, -1, 0, 6, 0, "[Address test, walking ones, no cache] "}, + {1, -1, 1, 6, 0, "[Address test, own address Sequential] "}, + {1, 32, 2, 6, 0, "[Address test, own address Parallel] "}, + {1, 32, 3, 6, 0, "[Moving inversions, 1s & 0s Parallel] "}, + {1, 32, 5, 3, 0, "[Moving inversions, 8 bit pattern] "}, + {1, 32, 6, 30, 0, "[Moving inversions, random pattern] "}, + {1, 32, 7, 81, 0, "[Block move] "}, + {1, 1, 8, 3, 0, "[Moving inversions, 32 bit pattern] "}, + {1, 32, 9, 48, 0, "[Random number sequence] "}, + {1, 32, 10, 6, 0, "[Modulo 20, Random pattern] "}, + {1, 1, 11, 240, 0, "[Bit fade test, 2 patterns] "}, + {1, 0, 0, 0, 0, NULL} +}; + +volatile int mstr_cpu; +volatile int run_cpus; +volatile int cpu_ord=0; +int maxcpus=MAX_CPUS; +volatile short cpu_sel; +volatile short cpu_mode; +char cpu_mask[MAX_CPUS]; +long bin_mask=0xffffffff; +short onepass; +volatile short btflag = 0; +volatile int test; +short restart_flag; +uint8_t volatile stacks[MAX_CPUS][STACKSIZE_BYTES]; +int bitf_seq = 0; +char cmdline_parsed = 0; +struct vars variables = {}; +struct vars * const vv = &variables; +volatile int bail; +int nticks; +int test_ticks; +volatile int segs; /* number of entries in vv->map[] + (Why not be a member of vars then?) */ +static int ltest; +static int pass_flag = 0; +volatile short start_seq = 0; +static int c_iter; +ulong high_test_adr; +volatile static int window; +volatile static unsigned long win_next; +volatile static ulong win0_start; /* Start test address for window 0 */ +volatile static ulong win1_end; /* End address for relocation */ +volatile static struct pmap winx; /* Window struct for mapping windows */ + +/* Find the next selected test to run */ +void next_test() +{ + test++; + while (tseq[test].sel == 0 && tseq[test].cpu_sel != 0) { + test++; + } + + if (tseq[test].cpu_sel == 0) { + /* We hit the end of the list so we completed a pass */ + pass_flag++; + /* Find the next test to run, start searching from 0 */ + test = 0; + while (tseq[test].sel == 0 && tseq[test].cpu_sel != 0) { + test++; + } + } +} + +/* Set default values for all parameters */ +void set_defaults() +{ + int i; + + if (start_seq == 2) { + /* This is a restart so we reset everything */ + onepass = 0; + i = 0; + while (tseq[i].cpu_sel) { + tseq[i].sel = 1; + i++; + } + test = 0; + if (tseq[0].sel == 0) { + next_test(); + } + } + ltest = -1; + win_next = 0; + window = 0; + bail = 0; + cpu_mode = CPM_ALL; + cpu_sel = 0; + vv->printmode=PRINTMODE_ADDRESSES; + vv->numpatn=0; + vv->plim_lower = 0; + vv->plim_upper = vv->pmap[vv->msegs-1].end; + vv->pass = 0; + vv->msg_line = 0; + vv->ecount = 0; + vv->ecc_ecount = 0; + vv->msg_line = LINE_SCROLL-1; + vv->scroll_start = vv->msg_line * 160; + vv->debugging = 0; + vv->erri.low_addr.page = 0x7fffffff; + vv->erri.low_addr.offset = 0xfff; + vv->erri.high_addr.page = 0; + vv->erri.high_addr.offset = 0; + vv->erri.min_bits = 32; + vv->erri.max_bits = 0; + vv->erri.min_bits = 32; + vv->erri.max_bits = 0; + vv->erri.maxl = 0; + vv->erri.cor_err = 0; + vv->erri.ebits = 0; + vv->erri.hdr_flag = 0; + vv->erri.tbits = 0; + for (i=0; tseq[i].msg != NULL; i++) { + tseq[i].errors = 0; + } + restart_flag = 0; + tseq[10].sel = 0; +} + +/* Boot trace function */ +short tidx = 25; +void btrace(int me, int line, char *msg, int wait, long v1, long v2) +{ + int y, x; + + /* Is tracing turned on? */ + if (btflag == 0) return; + + spin_lock(&barr->mutex); + y = tidx%13; + x = tidx/13*40; + cplace(y+11, x+1, ' '); + if (++tidx > 25) { + tidx = 0; + } + y = tidx%13; + x = tidx/13*40; + + cplace(y+11, x+1, '>'); + dprint(y+11, x+2, me, 2, 0); + dprint(y+11, x+5, line, 4, 0); + cprint(y+11, x+10, msg); + hprint(y+11, x+22, v1); + hprint(y+11, x+31, v2); + if (wait) { + wait_keyup(); + } + spin_unlock(&barr->mutex); +} + +/* Relocate the test to a new address. Be careful to not overlap! */ +static void run_at(unsigned long addr, int cpu) +{ + ulong *ja = (ulong *)(addr + startup_32 - _start); + + /* CPU 0, Copy memtest86+ code */ + if (cpu == 0) { + mt86_memmove((void *)addr, &_start, _end - _start); + } + + /* Wait for the copy */ + barrier(); + + /* We use a lock to insure that only one CPU at a time jumps to + * the new code. Some of the startup stuff is not thread safe! */ + spin_lock(&barr->mutex); + + /* Jump to the start address */ + goto *ja; +} + +/* Switch from the boot stack to the main stack. First the main stack + * is allocated, then the contents of the boot stack are copied, then + * ESP is adjusted to point to the new stack. + */ +static void +switch_to_main_stack(unsigned cpu_num) +{ + extern uintptr_t boot_stack; + extern uintptr_t boot_stack_top; + uintptr_t *src, *dst; + int offs; + uint8_t * stackAddr, *stackTop; + + stackAddr = (uint8_t *) &stacks[cpu_num][0]; + + stackTop = stackAddr + STACKSIZE_BYTES; + + src = (uintptr_t*)&boot_stack_top; + dst = (uintptr_t*)stackTop; + do { + src--; dst--; + *dst = *src; + } while ((uintptr_t *)src > (uintptr_t *)&boot_stack); + + offs = (uint8_t *)&boot_stack_top - stackTop; + __asm__ __volatile__ ( + "subl %%eax, %%esp" + : /*no output*/ + : "a" (offs) : "memory" + ); +} + +/* command line passing using the 'old' boot protocol */ +#define MK_PTR(seg,off) ((void*)(((unsigned long)(seg) << 4) + (off))) +#define OLD_CL_MAGIC_ADDR ((unsigned short*) MK_PTR(INITSEG,0x20)) +#define OLD_CL_MAGIC 0xA33F +#define OLD_CL_OFFSET_ADDR ((unsigned short*) MK_PTR(INITSEG,0x22)) + +static void parse_command_line(void) +{ + long simple_strtoul(char *cmd, char *ptr, int base); + char *cp, dummy; + int i, j, k; + + if (cmdline_parsed) + return; + + /* Fill in the cpu mask array with the default */ + for (i=0; i<MAX_CPUS; i++) { + cpu_mask[i] = 1; + } + + if (*OLD_CL_MAGIC_ADDR != OLD_CL_MAGIC) + return; + + unsigned short offset = *OLD_CL_OFFSET_ADDR; + cp = MK_PTR(INITSEG, offset); + + /* skip leading spaces */ + while (*cp == ' ') + cp++; + + while (*cp) { + if (!mt86_strncmp(cp, "console=", 8)) { + cp += 8; + serial_console_setup(cp); + } + /* Enable boot trace? */ + if (!mt86_strncmp(cp, "btrace", 6)) { + cp += 6; + btflag++; + } + /* Limit number of CPUs */ + if (!mt86_strncmp(cp, "maxcpus=", 8)) { + cp += 8; + maxcpus=(int)simple_strtoul(cp, &dummy, 10); + } + /* Run one pass and exit if there are no errors */ + if (!mt86_strncmp(cp, "onepass", 7)) { + cp += 7; + onepass++; + } + /* Setup a list of tests to run */ + if (!mt86_strncmp(cp, "tstlist=", 8)) { + cp += 8; + /* Clear all of the tests first */ + k = 0; + while (tseq[k].cpu_sel) { + tseq[k].sel = 0; + k++; + } + + /* Now enable all of the tests in the list */ + j = 0; + while(*cp && mt86_isdigit(*cp)) { + i = *cp-'0'; + j = j*10 + i; + cp++; + if (*cp == ',' || !mt86_isdigit(*cp)) { + if (j < k) { + tseq[j].sel = 1; + } + if (*cp != ',') break; + j = 0; + cp++; + } + } + } + /* Set a CPU mask to select CPU's to use for testing */ + if (!mt86_strncmp(cp, "cpumask=", 8)) { + cp += 8; + if (cp[0] == '0' && toupper(cp[1]) == 'X') cp += 2; + while (*cp && *cp != ' ' && isxdigit(*cp)) { + i = mt86_isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10; + bin_mask = bin_mask * 16 + i; + cp++; + } + /* Force CPU zero to always be selected */ + bin_mask |= 1; + for (i=0; i<32; i++) { + if (((bin_mask>>i) & 1) == 0) { + cpu_mask[i] = 0; + } + } + } + /* go to the next parameter */ + while (*cp && *cp != ' ') cp++; + while (*cp == ' ') cp++; + } + + cmdline_parsed = 1; +} + +void clear_screen() +{ + int i; + char *pp; + + /* Clear screen & set background to blue */ + for(i=0, pp=(char *)(SCREEN_ADR); i<80*25; i++) { + *pp++ = ' '; + *pp++ = 0x17; + } + if (btflag) { + cprint(1, 0, "Boot Trace Enabled"); + cprint(1, 0, "Press any key to advance to next trace point"); + cprint(9, 1,"CPU Line Message Param #1 Param #2 CPU Line Message Param #1 Param #2"); + cprint(10,1,"--- ---- ----------- -------- -------- --- ---- ----------- -------- --------"); + } + +} + +/* Test entry point. We get here on startup and also whenever + * we relocate. */ +void test_start(void) +{ + int my_cpu_num, my_cpu_ord, run; + + /* If this is the first time here we are CPU 0 */ + if (start_seq == 0) { + my_cpu_num = 0; + } else { + my_cpu_num = smp_my_cpu_num(); + } + /* First thing, switch to main stack */ + switch_to_main_stack(my_cpu_num); + + /* First time (for this CPU) initialization */ + if (start_seq < 2) { + + /* These steps are only done by the boot cpu */ + if (my_cpu_num == 0) { + my_cpu_ord = cpu_ord++; + smp_set_ordinal(my_cpu_num, my_cpu_ord); + parse_command_line(); + clear_screen(); + /* Initialize the barrier so the lock in btrace will work. + * Will get redone later when we know how many CPUs we have */ + barrier_init(1); + btrace(my_cpu_num, __LINE__, "Begin ", 1, 0, 0); + /* Find memory size */ + mem_size(); /* must be called before initialise_cpus(); */ + /* Fill in the CPUID table */ + get_cpuid(); + /* Startup the other CPUs */ + start_seq = 1; + //initialise_cpus(); + btrace(my_cpu_num, __LINE__, "BeforeInit", 1, 0, 0); + /* Draw the screen and get system information */ + init(); + + /* Set defaults and initialize variables */ + set_defaults(); + + /* Setup base address for testing, 1 MB */ + win0_start = 0x100; + + /* Set relocation address to 32Mb if there is enough + * memory. Otherwise set it to 3Mb */ + /* Large reloc addr allows for more testing overlap */ + if ((ulong)vv->pmap[vv->msegs-1].end > 0x2f00) { + high_test_adr = 0x2000000; + } else { + high_test_adr = 0x300000; + } + win1_end = (high_test_adr >> 12); + + /* Adjust the map to not test the page at 939k, + * reserved for locks */ + vv->pmap[0].end--; + + find_ticks_for_pass(); + } else { + /* APs only, Register the APs */ + btrace(my_cpu_num, __LINE__, "AP_Start ", 0, my_cpu_num, + cpu_ord); + smp_ap_booted(my_cpu_num); + /* Asign a sequential CPU ordinal to each active cpu */ + spin_lock(&barr->mutex); + my_cpu_ord = cpu_ord++; + smp_set_ordinal(my_cpu_num, my_cpu_ord); + spin_unlock(&barr->mutex); + btrace(my_cpu_num, __LINE__, "AP_Done ", 0, my_cpu_num, + my_cpu_ord); + } + + } else { + /* Unlock after a relocation */ + spin_unlock(&barr->mutex); + /* Get the CPU ordinal since it is lost during relocation */ + my_cpu_ord = smp_my_ord_num(my_cpu_num); + btrace(my_cpu_num, __LINE__, "Reloc_Done",0,my_cpu_num,my_cpu_ord); + } + + /* A barrier to insure that all of the CPUs are done with startup */ + barrier(); + btrace(my_cpu_num, __LINE__, "1st Barr ", 1, my_cpu_num, my_cpu_ord); + + + /* Setup Memory Management and measure memory speed, we do it here + * because we need all of the available CPUs */ + if (start_seq < 2) { + + /* Enable floating point processing */ + if (cpu_id.fid.bits.fpu) + __asm__ __volatile__ + ( + "movl %%cr0, %%eax\n\t" + "andl $0x7, %%eax\n\t" + "movl %%eax, %%cr0\n\t" + : : + : "ax" + ); + if (cpu_id.fid.bits.sse) + __asm__ __volatile__ + ( + "movl %%cr4, %%eax\n\t" + "orl $0x00000200, %%eax\n\t" + "movl %%eax, %%cr4\n\t" + : : + : "ax" + ); + + btrace(my_cpu_num, __LINE__, "Mem Mgmnt ", + 1, cpu_id.fid.bits.pae, cpu_id.fid.bits.lm); + /* Setup memory management modes */ + /* If we have PAE, turn it on */ + if (cpu_id.fid.bits.pae == 1) { + __asm__ __volatile__ + ( + "movl %%cr4, %%eax\n\t" + "orl $0x00000020, %%eax\n\t" + "movl %%eax, %%cr4\n\t" + : : + : "ax" + ); + cprint(LINE_TITLE+1, COL_MODE, "(PAE Mode)"); + } + /* If this is a 64 CPU enable long mode */ + if (cpu_id.fid.bits.lm == 1) { + __asm__ __volatile__ + ( + "movl $0xc0000080, %%ecx\n\t" + "rdmsr\n\t" + "orl $0x00000100, %%eax\n\t" + "wrmsr\n\t" + : : + : "ax", "cx" + ); + cprint(LINE_TITLE+1, COL_MODE, "(X64 Mode)"); + } + /* Get the memory Speed with all CPUs */ + get_mem_speed(my_cpu_num, num_cpus); + } + + /* Set the initialized flag only after all of the CPU's have + * Reached the barrier. This insures that relocation has + * been completed for each CPU. */ + btrace(my_cpu_num, __LINE__, "Start Done", 1, 0, 0); + start_seq = 2; + + /* Loop through all tests */ + while (1) { + /* If the restart flag is set all initial params */ + if (restart_flag) { + set_defaults(); + continue; + } + /* Skip single CPU tests if we are using only one CPU */ + if (tseq[test].cpu_sel == -1 && + (num_cpus == 1 || cpu_mode != CPM_ALL)) { + test++; + continue; + } + + test_setup(); + + /* Loop through all possible windows */ + while (win_next <= ((ulong)vv->pmap[vv->msegs-1].end + WIN_SZ_PAGES)) { + + /* Main scheduling barrier */ + cprint(8, my_cpu_num+7, "W"); + btrace(my_cpu_num, __LINE__, "Sched_Barr", 1,window,win_next); + barrier(); + + /* Don't go over the 8TB PAE limit */ + if (win_next > MAX_MEM_PAGES) { + break; + } + + /* For the bit fade test, #11, we cannot relocate so bump the + * window to 1 */ + if (tseq[test].pat == 11 && window == 0) { + window = 1; + } + + /* Relocate if required */ + if (window != 0 && (ulong)&_start != LOW_TEST_ADR) { + btrace(my_cpu_num, __LINE__, "Sched_RelL", 1,0,0); + run_at(LOW_TEST_ADR, my_cpu_num); + } + if (window == 0 && vv->plim_lower >= win0_start) { + window++; + } + if (window == 0 && (ulong)&_start == LOW_TEST_ADR) { + btrace(my_cpu_num, __LINE__, "Sched_RelH", 1,0,0); + run_at(high_test_adr, my_cpu_num); + } + + /* Decide which CPU(s) to use */ + btrace(my_cpu_num, __LINE__, "Sched_CPU0",1,cpu_sel, + tseq[test].cpu_sel); + run = 1; + switch(cpu_mode) { + case CPM_RROBIN: + case CPM_SEQ: + /* Select a single CPU */ + if (my_cpu_ord == cpu_sel) { + mstr_cpu = cpu_sel; + run_cpus = 1; + } else { + run = 0; + } + break; + case CPM_ALL: + /* Use all CPUs */ + if (tseq[test].cpu_sel == -1) { + /* Round robin through all of the CPUs */ + if (my_cpu_ord == cpu_sel) { + mstr_cpu = cpu_sel; + run_cpus = 1; + } else { + run = 0; + } + } else { + /* Use the number of CPUs specified by the test, + * Starting with zero */ + if (my_cpu_ord >= tseq[test].cpu_sel) { + run = 0; + } + /* Set the master CPU to the highest CPU number + * that has been selected */ + if (act_cpus < tseq[test].cpu_sel) { + mstr_cpu = act_cpus-1; + run_cpus = act_cpus; + } else { + mstr_cpu = tseq[test].cpu_sel-1; + run_cpus = tseq[test].cpu_sel; + } + } + } + btrace(my_cpu_num, __LINE__, "Sched_CPU1",1,run_cpus,run); + barrier(); + dprint(9, 7, run_cpus, 2, 0); + + /* Setup a sub barrier for only the selected CPUs */ + if (my_cpu_ord == mstr_cpu) { + s_barrier_init(run_cpus); + } + + /* Make sure the the sub barrier is ready before proceeding */ + barrier(); + + /* Not selected CPUs go back to the scheduling barrier */ + if (run == 0 ) { + continue; + } + cprint(8, my_cpu_num+7, "-"); + btrace(my_cpu_num, __LINE__, "Sched_Win0",1,window,win_next); + + if (my_cpu_ord == mstr_cpu) { + switch (window) { + /* Special case for relocation */ + case 0: + winx.start = 0; + winx.end = win1_end; + window++; + break; + /* Special case for first segment */ + case 1: + winx.start = win0_start; + winx.end = WIN_SZ_PAGES; + win_next += WIN_SZ_PAGES; + window++; + break; + /* For all other windows */ + default: + winx.start = win_next; + win_next += WIN_SZ_PAGES; + winx.end = win_next; + } + btrace(my_cpu_num,__LINE__,"Sched_Win1",1,winx.start, + winx.end); + + /* Find the memory areas to test */ + segs = compute_segments(winx, my_cpu_num); + } + s_barrier(); + btrace(my_cpu_num,__LINE__,"Sched_Win2",1,segs, + vv->map[0].pbase_addr); + + if (segs == 0) { + /* No memory in this window so skip it */ + continue; + } + + /* map in the window... */ + if (map_page(vv->map[0].pbase_addr) < 0) { + /* Either there is no PAE or we are at the PAE limit */ + break; + } + + btrace(my_cpu_num, __LINE__, "Strt_Test ",1,my_cpu_num, + my_cpu_ord); + do_test(my_cpu_ord); + btrace(my_cpu_num, __LINE__, "End_Test ",1,my_cpu_num, + my_cpu_ord); + + paging_off(); + + } /* End of window loop */ + + s_barrier(); + btrace(my_cpu_num, __LINE__, "End_Win ",1,test, window); + + /* Setup for the next set of windows */ + win_next = 0; + window = 0; + bail = 0; + + /* Only the master CPU does the end of test housekeeping */ + if (my_cpu_ord != mstr_cpu) { + continue; + } + + /* Special handling for the bit fade test #11 */ + if (tseq[test].pat == 11 && bitf_seq != 6) { + /* Keep going until the sequence is complete. */ + bitf_seq++; + continue; + } else { + bitf_seq = 0; + } + + /* Select advancement of CPUs and next test */ + switch(cpu_mode) { + case CPM_RROBIN: + if (++cpu_sel >= act_cpus) { + cpu_sel = 0; + } + next_test(); + break; + case CPM_SEQ: + if (++cpu_sel >= act_cpus) { + cpu_sel = 0; + next_test(); + } + break; + case CPM_ALL: + if (tseq[test].cpu_sel == -1) + { + /* Do the same test for each CPU */ + if (++cpu_sel >= act_cpus) + { + cpu_sel = 0; + next_test(); + } else { + continue; + } + } else { + next_test(); + } + } //???? + btrace(my_cpu_num, __LINE__, "Next_CPU ",1,cpu_sel,test); + + /* If this was the last test then we finished a pass */ + if (pass_flag) + { + pass_flag = 0; + + vv->pass++; + + dprint(LINE_INFO, 49, vv->pass, 5, 0); + find_ticks_for_pass(); + ltest = -1; + + if (vv->ecount == 0) + { + /* If onepass is enabled and we did not get any errors + * reboot to exit the test */ + if (onepass) { reboot(); } + if (!btflag) + cprint(LINE_MSG, COL_MSG-8, + "** Pass complete, no errors, press Esc to exit **"); + if(BEEP_END_NO_ERROR) + { + beep(1000); + beep(2000); + beep(1000); + beep(2000); + } + } + } + + bail=0; + } /* End test loop */ +} + +void test_setup() +{ + static int ltest = -1; + + /* See if a specific test has been selected */ + if (vv->testsel >= 0) { + test = vv->testsel; + } + + /* Only do the setup if this is a new test */ + if (test == ltest) { + return; + } + ltest = test; + + /* Now setup the test parameters based on the current test number */ + if (vv->pass == 0) { + /* Reduce iterations for first pass */ + c_iter = tseq[test].iter/FIRST_DIVISER; + } else { + c_iter = tseq[test].iter; + } + + /* Set the number of iterations. We only do half of the iterations */ + /* on the first pass */ + //dprint(LINE_INFO, 28, c_iter, 3, 0); + test_ticks = find_ticks_for_test(test); + nticks = 0; + vv->tptr = 0; + + cprint(LINE_PAT, COL_PAT, " "); + cprint(LINE_PAT, COL_PAT-3, " "); + dprint(LINE_TST, COL_MID+6, tseq[test].pat, 2, 1); + cprint(LINE_TST, COL_MID+9, tseq[test].msg); + cprint(2, COL_MID+8, " "); +} + +/* A couple static variables for when all cpus share the same pattern */ +static ulong sp1, sp2; + +int do_test(int my_ord) +{ + int i=0, j=0; + static int bitf_sleep; + unsigned long p0=0, p1=0, p2=0; + + if (my_ord == mstr_cpu) { + if ((ulong)&_start > LOW_TEST_ADR) { + /* Relocated so we need to test all selected lower memory */ + vv->map[0].start = mapping(vv->plim_lower); + + /* Good 'ol Legacy USB_WAR */ + if (vv->map[0].start < (ulong*)0x500) + { + vv->map[0].start = (ulong*)0x500; + } + + cprint(LINE_PAT, COL_MID+25, " R"); + } else { + cprint(LINE_PAT, COL_MID+25, " "); + } + + /* Update display of memory segments being tested */ + p0 = page_of(vv->map[0].start); + p1 = page_of(vv->map[segs-1].end); + aprint(LINE_RANGE, COL_MID+9, p0); + cprint(LINE_RANGE, COL_MID+14, " - "); + aprint(LINE_RANGE, COL_MID+17, p1); + aprint(LINE_RANGE, COL_MID+25, p1-p0); + cprint(LINE_RANGE, COL_MID+30, " of "); + aprint(LINE_RANGE, COL_MID+34, vv->selected_pages); + } + + switch(tseq[test].pat) { + + /* do the testing according to the selected pattern */ + + case 0: /* Address test, walking ones (test #0) */ + /* Run with cache turned off */ + set_cache(0); + addr_tst1(my_ord); + set_cache(1); + BAILOUT; + break; + + case 1: + case 2: /* Address test, own address (test #1, 2) */ + addr_tst2(my_ord); + BAILOUT; + break; + + case 3: + case 4: /* Moving inversions, all ones and zeros (tests #3, 4) */ + p1 = 0; + p2 = ~p1; + s_barrier(); + movinv1(c_iter,p1,p2,my_ord); + BAILOUT; + + /* Switch patterns */ + s_barrier(); + movinv1(c_iter,p2,p1,my_ord); + BAILOUT; + break; + + case 5: /* Moving inversions, 8 bit walking ones and zeros (test #5) */ + p0 = 0x80; + for (i=0; i<8; i++, p0=p0>>1) { + p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24); + p2 = ~p1; + s_barrier(); + movinv1(c_iter,p1,p2, my_ord); + BAILOUT; + + /* Switch patterns */ + s_barrier(); + movinv1(c_iter,p2,p1, my_ord); + BAILOUT; + } + break; + + case 6: /* Random Data (test #6) */ + /* Seed the random number generator */ + if (my_ord == mstr_cpu) { + if (cpu_id.fid.bits.rdtsc) { + asm __volatile__ ("rdtsc":"=a" (sp1),"=d" (sp2)); + } else { + sp1 = 521288629 + vv->pass; + sp2 = 362436069 - vv->pass; + } + rand_seed(sp1, sp2, 0); + } + + s_barrier(); + for (i=0; i < c_iter; i++) { + if (my_ord == mstr_cpu) { + sp1 = rand(0); + sp2 = ~p1; + } + s_barrier(); + movinv1(2,sp1,sp2, my_ord); + BAILOUT; + } + break; + + + case 7: /* Block move (test #7) */ + block_move(c_iter, my_ord); + BAILOUT; + break; + + case 8: /* Moving inversions, 32 bit shifting pattern (test #8) */ + for (i=0, p1=1; p1; p1=p1<<1, i++) { + s_barrier(); + movinv32(c_iter,p1, 1, 0x80000000, 0, i, my_ord); + { BAILOUT } + s_barrier(); + movinv32(c_iter,~p1, 0xfffffffe, + 0x7fffffff, 1, i, my_ord); + { BAILOUT } + } + break; + + case 9: /* Random Data Sequence (test #9) */ + for (i=0; i < c_iter; i++) { + s_barrier(); + movinvr(my_ord); + BAILOUT; + } + break; + + case 10: /* Modulo 20 check, Random pattern (test #10) */ + for (j=0; j<c_iter; j++) { + p1 = rand(0); + for (i=0; i<MOD_SZ; i++) { + p2 = ~p1; + s_barrier(); + modtst(i, 2, p1, p2, my_ord); + BAILOUT; + + /* Switch patterns */ + s_barrier(); + modtst(i, 2, p2, p1, my_ord); + BAILOUT; + } + } + break; + + case 11: /* Bit fade test, fill (test #11) */ + /* Use a sequence to process all windows for each stage */ + switch(bitf_seq) { + case 0: /* Fill all of memory 0's */ + bit_fade_fill(0, my_ord); + bitf_sleep = 1; + break; + case 1: /* Sleep for the specified time */ + /* Only sleep once */ + if (bitf_sleep) { + sleep(c_iter, 1, my_ord, 0); + bitf_sleep = 0; + } + break; + case 2: /* Now check all of memory for changes */ + bit_fade_chk(0, my_ord); + break; + case 3: /* Fill all of memory 1's */ + bit_fade_fill(-1, my_ord); + bitf_sleep = 1; + break; + case 4: /* Sleep for the specified time */ + /* Only sleep once */ + if (bitf_sleep) { + sleep(c_iter, 1, my_ord, 0); + bitf_sleep = 0; + } + break; + case 5: /* Now check all of memory for changes */ + bit_fade_chk(-1, my_ord); + break; + } + BAILOUT; + break; + + case 90: /* Modulo 20 check, all ones and zeros (unused) */ + p1=0; + for (i=0; i<MOD_SZ; i++) { + p2 = ~p1; + modtst(i, c_iter, p1, p2, my_ord); + BAILOUT; + + /* Switch patterns */ + p2 = p1; + p1 = ~p2; + modtst(i, c_iter, p1,p2, my_ord); + BAILOUT; + } + break; + + case 91: /* Modulo 20 check, 8 bit pattern (unused) */ + p0 = 0x80; + for (j=0; j<8; j++, p0=p0>>1) { + p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24); + for (i=0; i<MOD_SZ; i++) { + p2 = ~p1; + modtst(i, c_iter, p1, p2, my_ord); + BAILOUT; + + /* Switch patterns */ + p2 = p1; + p1 = ~p2; + modtst(i, c_iter, p1, p2, my_ord); + BAILOUT; + } + } + break; + } + return(0); +} + +/* Compute number of SPINSZ_DWORDS chunks being tested */ +int find_chunks(int tst) +{ + int i, j, sg, wmax, ch; + struct pmap twin={0,0}; + unsigned long wnxt = WIN_SZ_PAGES; + unsigned long len; + + wmax = MAX_MEM_PAGES/WIN_SZ_PAGES+2; /* The number of 2 GB segments +2 */ + /* Compute the number of SPINSZ_DWORDS memory segments */ + ch = 0; + for(j = 0; j < wmax; j++) { + /* special case for relocation */ + if (j == 0) { + twin.start = 0; + twin.end = win1_end; + } + + /* special case for first 2 GB */ + if (j == 1) { + twin.start = win0_start; + twin.end = WIN_SZ_PAGES; + } + + /* For all other windows */ + if (j > 1) { + twin.start = wnxt; + wnxt += WIN_SZ_PAGES; + twin.end = wnxt; + } + + /* Find the memory areas I am going to test */ + sg = compute_segments(twin, -1); + for(i = 0; i < sg; i++) { + len = vv->map[i].end - vv->map[i].start; + + if (cpu_mode == CPM_ALL && num_cpus > 1) { + switch(tseq[tst].pat) { + case 2: + case 4: + case 5: + case 6: + case 9: + case 10: + len /= act_cpus; + break; + case 7: + case 8: + len /= act_cpus; + break; + } + } + ch += (len + SPINSZ_DWORDS -1)/SPINSZ_DWORDS; + } + } + return(ch); +} + +/* Compute the total number of ticks per pass */ +void find_ticks_for_pass(void) +{ + int i; + + vv->pptr = 0; + vv->pass_ticks = 0; + vv->total_ticks = 0; + cprint(1, COL_MID+8, " "); + i = 0; + while (tseq[i].cpu_sel != 0) { + /* Skip tests 2 and 4 if we are using 1 cpu */ + if (act_cpus == 1 && (i == 2 || i == 4)) { + i++; + continue; + } + vv->pass_ticks += find_ticks_for_test(i); + i++; + } +} + +static int find_ticks_for_test(int tst) +{ + int ticks=0, iter, ch; + + if (tseq[tst].sel == 0) { + return(0); + } + + /* Determine the number of SPINSZ chunks for this test */ + ch = find_chunks(tst); + + /* Set the number of iterations. We only do 1/2 of the iterations */ + /* on the first pass */ + if (vv->pass == 0) { + iter = tseq[tst].iter/FIRST_DIVISER; + } else { + iter = tseq[tst].iter; + } + + switch(tseq[tst].pat) { + case 0: /* Address test, walking ones */ + ticks = ch; + break; + case 1: /* Address test, own address */ + case 2: + ticks = ch * 2; + break; + case 3: /* Moving inversions, all ones and zeros */ + case 4: { + const int each_movinv1 = ch * (1 + 2 * iter); // each movinv1() + ticks = 2 * each_movinv1; // which we call twice + break; + } + case 5: { /* Moving inversions, 8 bit walking ones and zeros */ + const int each_movinv1 = ch * (1 + 2 * iter); // same as above + ticks = 16 * each_movinv1; // but here we call it 16x + break; + } + case 6: { /* Random Data */ + const int each_movinv1 = ch * 5; // movinv1() does only 5 ticks here + ticks = iter * each_movinv1; // and we call it 'iter' times. + break; + } + case 7: /* Block move */ + ticks = ch * (2 + iter); + break; + case 8: { /* Moving inversions, 32 bit shifting pattern */ + const int each_movinv32 = ch * (1 + 2 * iter); // Each movinv32() + ticks = each_movinv32 * 64; // We call it 64x + break; + } + case 9: { /* Random Data Sequence */ + const int each_movinvr = 3 * ch; // Each movinvr() ticks 3*ch times + ticks = each_movinvr * iter; // We call it iter times + break; + } + case 10: { /* Modulo 20 check, Random pattern */ + const int each_modtst = ch * 4; + ticks = iter * MOD_SZ * each_modtst; + break; + } + case 11: { /* Bit fade test */ + // Each call to bit_fade_fill() and bit_fade_chk() ticks ch times. + const int each_bit_fade_fill = ch; + const int each_bit_fade_chk = ch; + // We call each twice: fill 0s, check, fill 1s, check. + const int loop_ticks = 2 * each_bit_fade_chk + 2 * each_bit_fade_fill; + // We also sleep for '2*iter' seconds and tick once per second + const int sleep_ticks = iter * 2; + ticks = loop_ticks + sleep_ticks; + break; + } + case 90: { /* Modulo 20 check, all ones and zeros (unused) */ + const int each_modtst = ch * (2 + iter); + ticks = each_modtst * 2 * MOD_SZ; + break; + } + case 91: { /* Modulo 20 check, 8 bit pattern (unused) */ + const int each_modtst = ch * (2 + iter); + ticks = each_modtst * 2 * MOD_SZ * 8; + break; + } + default: + ASSERT(0); + break; + } + if (cpu_mode == CPM_SEQ || tseq[tst].cpu_sel == -1) { + ticks *= act_cpus; + } + return ticks; +} + +static int compute_segments(struct pmap win, int me) +{ + unsigned long wstart, wend; + int i, sg; + + /* Compute the window I am testing memory in */ + wstart = win.start; + wend = win.end; + sg = 0; + + /* Now reduce my window to the area of memory I want to test */ + if (wstart < vv->plim_lower) { + wstart = vv->plim_lower; + } + if (wend > vv->plim_upper) { + wend = vv->plim_upper; + } + if (wstart >= wend) { + return(0); + } + /* List the segments being tested */ + for (i=0; i< vv->msegs; i++) { + unsigned long start, end; + start = vv->pmap[i].start; + end = vv->pmap[i].end; + if (start <= wstart) { + start = wstart; + } + if (end >= wend) { + end = wend; + } +#if 0 + cprint(LINE_SCROLL+(2*i), 0, " ("); + hprint(LINE_SCROLL+(2*i), 2, start); + cprint(LINE_SCROLL+(2*i), 10, ", "); + hprint(LINE_SCROLL+(2*i), 12, end); + cprint(LINE_SCROLL+(2*i), 20, ") "); + + cprint(LINE_SCROLL+(2*i), 22, "r("); + hprint(LINE_SCROLL+(2*i), 24, wstart); + cprint(LINE_SCROLL+(2*i), 32, ", "); + hprint(LINE_SCROLL+(2*i), 34, wend); + cprint(LINE_SCROLL+(2*i), 42, ") "); + + cprint(LINE_SCROLL+(2*i), 44, "p("); + hprint(LINE_SCROLL+(2*i), 46, vv->plim_lower); + cprint(LINE_SCROLL+(2*i), 54, ", "); + hprint(LINE_SCROLL+(2*i), 56, vv->plim_upper); + cprint(LINE_SCROLL+(2*i), 64, ") "); + + cprint(LINE_SCROLL+(2*i+1), 0, "w("); + hprint(LINE_SCROLL+(2*i+1), 2, win.start); + cprint(LINE_SCROLL+(2*i+1), 10, ", "); + hprint(LINE_SCROLL+(2*i+1), 12, win.end); + cprint(LINE_SCROLL+(2*i+1), 20, ") "); + + cprint(LINE_SCROLL+(2*i+1), 22, "m("); + hprint(LINE_SCROLL+(2*i+1), 24, vv->pmap[i].start); + cprint(LINE_SCROLL+(2*i+1), 32, ", "); + hprint(LINE_SCROLL+(2*i+1), 34, vv->pmap[i].end); + cprint(LINE_SCROLL+(2*i+1), 42, ") "); + + cprint(LINE_SCROLL+(2*i+1), 44, "i="); + hprint(LINE_SCROLL+(2*i+1), 46, i); + + cprint(LINE_SCROLL+(2*i+2), 0, + " " + " "); + cprint(LINE_SCROLL+(2*i+3), 0, + " " + " "); +#endif + if ((start < end) && (start < wend) && (end > wstart)) { + vv->map[sg].pbase_addr = start; + vv->map[sg].start = mapping(start); + vv->map[sg].end = emapping(end); +#if 0 + hprint(LINE_SCROLL+(sg+1), 0, sg); + hprint(LINE_SCROLL+(sg+1), 12, vv->map[sg].pbase_addr); + hprint(LINE_SCROLL+(sg+1), 22, start); + hprint(LINE_SCROLL+(sg+1), 32, end); + hprint(LINE_SCROLL+(sg+1), 42, mapping(start)); + hprint(LINE_SCROLL+(sg+1), 52, emapping(end)); + cprint(LINE_SCROLL+(sg+2), 0, + " " + " "); +#endif +#if 0 + cprint(LINE_SCROLL+(2*i+1), 54, ", sg="); + hprint(LINE_SCROLL+(2*i+1), 59, sg); +#endif + sg++; + } + } + return (sg); +} + diff --git a/memtestEDK/Memtest/SingleComponents/memsize.c b/memtestEDK/Memtest/SingleComponents/memsize.c new file mode 100644 index 0000000..84230d5 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/memsize.c @@ -0,0 +1,346 @@ +/* memsize.c - MemTest-86 Version 3.3 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + */ + +#include "test.h" +#include "defs.h" +#include "config.h" + +short e820_nr = 0; +short memsz_mode = SZ_MODE_BIOS; + +static ulong alt_mem_k = 0; +static ulong ext_mem_k = 0; +static struct e820entry e820[E820MAX]; + +static void sort_pmap(void); +static void memsize_820(void); +static void memsize_801(void); +static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios, short old_nr); +static void memsize_linuxbios(); + +/* + * Find out how much memory there is. + */ +#pragma GCC push_options +#pragma GCC optimize ("O0") +void mem_size(void) +{ + int i = 0, flag = 0; + vv->test_pages = 0; + + /* Get the memory size from the BIOS */ + /* Determine the memory map */ + + if (query_linuxbios()) { + flag = 1; + } else if (query_pcbios()) { + flag = 2; + } + + /* On the first time thru only */ + /* Make a copy of the memory info table so that we can re-evaluate */ + /* The memory map later */ + if (e820_nr == 0 && alt_mem_k == 0 && ext_mem_k == 0) { + ext_mem_k = mem_info.e88_mem_k; + alt_mem_k = mem_info.e801_mem_k; + e820_nr = mem_info.e820_nr; + for (i=0; i< mem_info.e820_nr; i++) { + e820[i].addr = mem_info.e820[i].addr; + e820[i].size = mem_info.e820[i].size; + e820[i].type = mem_info.e820[i].type; + } + } + if (flag == 1) { + memsize_linuxbios(); + } else if (flag == 2) { + memsize_820(); + } + + /* Guarantee that pmap entries are in ascending order */ + sort_pmap(); + vv->plim_lower = 0; + vv->plim_upper = vv->pmap[vv->msegs-1].end; + + adj_mem(); +} +#pragma GCC pop_options + +static void sort_pmap(void) +{ + int i, j; + /* Do an insertion sort on the pmap, on an already sorted + * list this should be a O(1) algorithm. + */ + for(i = 0; i < vv->msegs; i++) { + /* Find where to insert the current element */ + for(j = i -1; j >= 0; j--) { + if (vv->pmap[i].start > vv->pmap[j].start) { + j++; + break; + } + } + /* Insert the current element */ + if (i != j) { + struct pmap temp; + temp = vv->pmap[i]; + mt86_memmove(&vv->pmap[j], &vv->pmap[j+1], + (i -j)* sizeof(temp)); + vv->pmap[j] = temp; + } + } +} +static void memsize_linuxbios(void) +{ + int i, n; + /* Build the memory map for testing */ + n = 0; + for (i=0; i < e820_nr; i++) { + unsigned long long end; + + if (e820[i].type != E820_RAM) { + continue; + } + end = e820[i].addr; + end += e820[i].size; + vv->pmap[n].start = (e820[i].addr + 4095) >> 12; + vv->pmap[n].end = end >> 12; + vv->test_pages += vv->pmap[n].end - vv->pmap[n].start; + n++; + } + vv->msegs = n; +} +static void memsize_820() +{ + int i, n, nr; + struct e820entry nm[E820MAX]; + unsigned long long start; + unsigned long long end; + + /* Clean up, adjust and copy the BIOS-supplied E820-map. */ + nr = sanitize_e820_map(e820, nm, e820_nr); + + /* If there is not a good 820 map use the BIOS 801/88 info */ + if (nr < 1 || nr > E820MAX) { + memsize_801(); + return; + } + + /* Build the memory map for testing */ + n = 0; + for (i=0; i<nr; i++) { + if (nm[i].type == E820_RAM || nm[i].type == E820_ACPI) { + start = nm[i].addr; + end = start + nm[i].size; + + /* Don't ever use memory between 640 and 1024k */ + if (start > RES_START && start < RES_END) { + if (end < RES_END) { + continue; + } + start = RES_END; + } + if (end > RES_START && end < RES_END) { + end = RES_START; + } + vv->pmap[n].start = (start + 4095) >> 12; + vv->pmap[n].end = end >> 12; + vv->test_pages += vv->pmap[n].end - vv->pmap[n].start; + n++; +#if 0 + int epmap = 0; + int lpmap = 0; + if(n > 12) { epmap = 34; lpmap = -12; } + hprint (11+n+lpmap,0+epmap,vv->pmap[n-1].start); + hprint (11+n+lpmap,10+epmap,vv->pmap[n-1].end); + hprint (11+n+lpmap,20+epmap,vv->pmap[n-1].end - vv->pmap[n-1].start); + dprint (11+n+lpmap,30+epmap,nm[i].type,0,0); +#endif + } + } + vv->msegs = n; +} + +static void memsize_801(void) +{ + ulong mem_size; + + /* compare results from 88 and 801 methods and take the greater */ + /* These sizes are for extended memory in 1k units. */ + + if (alt_mem_k < ext_mem_k) { + mem_size = ext_mem_k; + } else { + mem_size = alt_mem_k; + } + /* First we map in the first 640k */ + vv->pmap[0].start = 0; + vv->pmap[0].end = RES_START >> 12; + vv->test_pages = RES_START >> 12; + + /* Now the extended memory */ + vv->pmap[1].start = (RES_END + 4095) >> 12; + vv->pmap[1].end = (mem_size + 1024) >> 2; + vv->test_pages += mem_size >> 2; + vv->msegs = 2; +} + +/* + * Sanitize the BIOS e820 map. + * + * Some e820 responses include overlapping entries. The following + * replaces the original e820 map with a new one, removing overlaps. + * + */ +static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios, + short old_nr) +{ + struct change_member { + struct e820entry *pbios; /* pointer to original bios entry */ + unsigned long long addr; /* address for this change point */ + }; + struct change_member change_point_list[2*E820MAX]; + struct change_member *change_point[2*E820MAX]; + struct e820entry *overlap_list[E820MAX]; + struct e820entry biosmap[E820MAX]; + struct change_member *change_tmp; + ulong current_type, last_type; + unsigned long long last_addr; + int chgidx, still_changing; + int overlap_entries; + int new_bios_entry; + int i; + + /* + Visually we're performing the following (1,2,3,4 = memory types)... + Sample memory map (w/overlaps): + ____22__________________ + ______________________4_ + ____1111________________ + _44_____________________ + 11111111________________ + ____________________33__ + ___________44___________ + __________33333_________ + ______________22________ + ___________________2222_ + _________111111111______ + _____________________11_ + _________________4______ + + Sanitized equivalent (no overlap): + 1_______________________ + _44_____________________ + ___1____________________ + ____22__________________ + ______11________________ + _________1______________ + __________3_____________ + ___________44___________ + _____________33_________ + _______________2________ + ________________1_______ + _________________4______ + ___________________2____ + ____________________33__ + ______________________4_ + */ + /* First make a copy of the map */ + for (i=0; i<old_nr; i++) { + biosmap[i].addr = orig_map[i].addr; + biosmap[i].size = orig_map[i].size; + biosmap[i].type = orig_map[i].type; + } + + /* bail out if we find any unreasonable addresses in bios map */ + for (i=0; i<old_nr; i++) { + if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) + return 0; + } + + /* create pointers for initial change-point information (for sorting) */ + for (i=0; i < 2*old_nr; i++) + change_point[i] = &change_point_list[i]; + + /* record all known change-points (starting and ending addresses) */ + chgidx = 0; + for (i=0; i < old_nr; i++) { + change_point[chgidx]->addr = biosmap[i].addr; + change_point[chgidx++]->pbios = &biosmap[i]; + change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size; + change_point[chgidx++]->pbios = &biosmap[i]; + } + + /* sort change-point list by memory addresses (low -> high) */ + still_changing = 1; + while (still_changing) { + still_changing = 0; + for (i=1; i < 2*old_nr; i++) { + /* if <current_addr> > <last_addr>, swap */ + /* or, if current=<start_addr> & last=<end_addr>, swap */ + if ((change_point[i]->addr < change_point[i-1]->addr) || + ((change_point[i]->addr == change_point[i-1]->addr) && + (change_point[i]->addr == change_point[i]->pbios->addr) && + (change_point[i-1]->addr != change_point[i-1]->pbios->addr)) + ) + { + change_tmp = change_point[i]; + change_point[i] = change_point[i-1]; + change_point[i-1] = change_tmp; + still_changing=1; + } + } + } + + /* create a new bios memory map, removing overlaps */ + overlap_entries=0; /* number of entries in the overlap table */ + new_bios_entry=0; /* index for creating new bios map entries */ + last_type = 0; /* start with undefined memory type */ + last_addr = 0; /* start with 0 as last starting address */ + /* loop through change-points, determining affect on the new bios map */ + for (chgidx=0; chgidx < 2*old_nr; chgidx++) + { + /* keep track of all overlapping bios entries */ + if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr) + { + /* add map entry to overlap list (> 1 entry implies an overlap) */ + overlap_list[overlap_entries++]=change_point[chgidx]->pbios; + } + else + { + /* remove entry from list (order independent, so swap with last) */ + for (i=0; i<overlap_entries; i++) + { + if (overlap_list[i] == change_point[chgidx]->pbios) + overlap_list[i] = overlap_list[overlap_entries-1]; + } + overlap_entries--; + } + /* if there are overlapping entries, decide which "type" to use */ + /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */ + current_type = 0; + for (i=0; i<overlap_entries; i++) + if (overlap_list[i]->type > current_type) + current_type = overlap_list[i]->type; + /* continue building up new bios map based on this information */ + if (current_type != last_type) { + if (last_type != 0) { + new_bios[new_bios_entry].size = + change_point[chgidx]->addr - last_addr; + /* move forward only if the new size was non-zero */ + if (new_bios[new_bios_entry].size != 0) + if (++new_bios_entry >= E820MAX) + break; /* no more space left for new bios entries */ + } + if (current_type != 0) { + new_bios[new_bios_entry].addr = change_point[chgidx]->addr; + new_bios[new_bios_entry].type = current_type; + last_addr=change_point[chgidx]->addr; + } + last_type = current_type; + } + } + return(new_bios_entry); +} diff --git a/memtestEDK/Memtest/SingleComponents/msr.h b/memtestEDK/Memtest/SingleComponents/msr.h new file mode 100644 index 0000000..af873a0 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/msr.h @@ -0,0 +1,145 @@ +#ifndef __ASM_MSR_H +#define __ASM_MSR_H + +/* + * Access to machine-specific registers (available on 586 and better only) + * Note: the rd* operations modify the parameters directly (without using + * pointer indirection), this allows gcc to optimize better + */ + +#define __FIXUP_ALIGN ".align 8" +#define __FIXUP_WORD ".quad" +#define EFAULT 14 /* Bad address */ + +#define rdmsr(msr,val1,val2) \ + __asm__ __volatile__("rdmsr" \ + : "=a" (val1), "=d" (val2) \ + : "c" (msr) : "edi") + +/* +#define rdmsr_safe(msr,val1,val2) ({\ + int _rc; \ + __asm__ __volatile__( \ + "1: rdmsr\n2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl %5,%2\n; jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " "__FIXUP_ALIGN"\n" \ + ".previous\n" \ + : "=a" (val1), "=d" (val2), "=&r" (_rc) \ + : "c" (msr), "2" (0), "i" (-EFAULT)); \ + _rc; }) +*/ + +#define wrmsr(msr,val1,val2) \ + __asm__ __volatile__("wrmsr" \ + : /* no outputs */ \ + : "c" (msr), "a" (val1), "d" (val2)) + +#define rdtsc(low,high) \ + __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) + +#define rdtscl(low) \ + __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx") + +#define rdtscll(val) \ + __asm__ __volatile__("rdtsc" : "=A" (val)) + +#define write_tsc(val1,val2) wrmsr(0x10, val1, val2) + +#define rdpmc(counter,low,high) \ + __asm__ __volatile__("rdpmc" \ + : "=a" (low), "=d" (high) \ + : "c" (counter)) + +/* symbolic names for some interesting MSRs */ +/* Intel defined MSRs. */ +#define MSR_IA32_P5_MC_ADDR 0 +#define MSR_IA32_P5_MC_TYPE 1 +#define MSR_IA32_PLATFORM_ID 0x17 +#define MSR_IA32_EBL_CR_POWERON 0x2a + +#define MSR_IA32_APICBASE 0x1b +#define MSR_IA32_APICBASE_BSP (1<<8) +#define MSR_IA32_APICBASE_ENABLE (1<<11) +#define MSR_IA32_APICBASE_BASE (0xfffff<<12) + +#define MSR_IA32_UCODE_WRITE 0x79 +#define MSR_IA32_UCODE_REV 0x8b + +#define MSR_IA32_BBL_CR_CTL 0x119 + +#define MSR_IA32_MCG_CAP 0x179 +#define MSR_IA32_MCG_STATUS 0x17a +#define MSR_IA32_MCG_CTL 0x17b + +#define MSR_IA32_THERM_CONTROL 0x19a +#define MSR_IA32_THERM_INTERRUPT 0x19b +#define MSR_IA32_THERM_STATUS 0x19c +#define MSR_IA32_MISC_ENABLE 0x1a0 +#define MSR_IA32_TEMPERATURE_TARGET 0x1a2 + +#define MSR_IA32_DEBUGCTLMSR 0x1d9 +#define MSR_IA32_LASTBRANCHFROMIP 0x1db +#define MSR_IA32_LASTBRANCHTOIP 0x1dc +#define MSR_IA32_LASTINTFROMIP 0x1dd +#define MSR_IA32_LASTINTTOIP 0x1de + +#define MSR_IA32_MC0_CTL 0x400 +#define MSR_IA32_MC0_STATUS 0x401 +#define MSR_IA32_MC0_ADDR 0x402 +#define MSR_IA32_MC0_MISC 0x403 + +#define MSR_P6_PERFCTR0 0xc1 +#define MSR_P6_PERFCTR1 0xc2 +#define MSR_P6_EVNTSEL0 0x186 +#define MSR_P6_EVNTSEL1 0x187 + +#define MSR_IA32_PERF_STATUS 0x198 +#define MSR_IA32_PERF_CTL 0x199 + +/* AMD Defined MSRs */ +#define MSR_K6_EFER 0xC0000080 +#define MSR_K6_STAR 0xC0000081 +#define MSR_K6_WHCR 0xC0000082 +#define MSR_K6_UWCCR 0xC0000085 +#define MSR_K6_EPMR 0xC0000086 +#define MSR_K6_PSOR 0xC0000087 +#define MSR_K6_PFIR 0xC0000088 + +#define MSR_K7_EVNTSEL0 0xC0010000 +#define MSR_K7_PERFCTR0 0xC0010004 +#define MSR_K7_HWCR 0xC0010015 +#define MSR_K7_CLK_CTL 0xC001001b +#define MSR_K7_FID_VID_CTL 0xC0010041 +#define MSR_K7_VID_STATUS 0xC0010042 + +/* Centaur-Hauls/IDT defined MSRs. */ +#define MSR_IDT_FCR1 0x107 +#define MSR_IDT_FCR2 0x108 +#define MSR_IDT_FCR3 0x109 +#define MSR_IDT_FCR4 0x10a + +#define MSR_IDT_MCR0 0x110 +#define MSR_IDT_MCR1 0x111 +#define MSR_IDT_MCR2 0x112 +#define MSR_IDT_MCR3 0x113 +#define MSR_IDT_MCR4 0x114 +#define MSR_IDT_MCR5 0x115 +#define MSR_IDT_MCR6 0x116 +#define MSR_IDT_MCR7 0x117 +#define MSR_IDT_MCR_CTRL 0x120 + +/* VIA Cyrix defined MSRs*/ +#define MSR_VIA_FCR 0x1107 +#define MSR_VIA_LONGHAUL 0x110a +#define MSR_VIA_BCR2 0x1147 + +/* Transmeta defined MSRs */ +#define MSR_TMTA_LONGRUN_CTRL 0x80868010 +#define MSR_TMTA_LONGRUN_FLAGS 0x80868011 +#define MSR_TMTA_LRTI_READOUT 0x80868018 +#define MSR_TMTA_LRTI_VOLT_MHZ 0x8086801a + +#endif /* __ASM_MSR_H */ diff --git a/memtestEDK/Memtest/SingleComponents/mt86+_loader.asm b/memtestEDK/Memtest/SingleComponents/mt86+_loader.asm new file mode 100644 index 0000000..8472262 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/mt86+_loader.asm @@ -0,0 +1,231 @@ +; A loader for www.memtest.org images, by Eric Auer 2003. +; This assumes that the image starts with the boot sector, +; which has the size of setup.S in sectors in a byte at offset +; 1f1h (497). Further, I assume setup.S directly after the boot +; sector and the actual memtest head.S after setup.S ... + +; This version is derived from memtestL loader, which loads +; memtest.bin from a separate file. This version is meant to +; be used like (DOS / Unix variants): +; copy /b memteste.bin + memtest.bin memtest.exe +; cat memteste.bin memtest.bin > memtest.exe +; The good thing is that you get a single file which can be +; compressed, for example with http://upx.sf.net/ (UPX). + +%define fullsize (150024 + buffer - exeh) + ; 150024 is the size of memtest86+ V5.01, adjust as needed! + +%define stacksize 2048 +%define stackpara ((stacksize + 15) / 16) + + ; the trick is that NASM believes the header would be part + ; of the loaded image, so we "org 20h bytes too early" to fix: + org 0e0h ; NASM thinks after header we have 100h + ; which is what we want it to think. + +exeh: db "MZ" + dw fullsize % 512 ; how much to load from + dw (fullsize + 511) / 512 ; .exe to RAM + dw 0 ; no relocations used + dw 2 ; header size is 2 * 16 bytes + dw stackpara ; minimum heap is 128 * 16 bytes, for stack + dw stackpara ; we do not need more heap either + dw (fullsize + 15) / 16 ; SS is after file + ; segment offsets are relative to PSPseg+10h + ; initial DS and ES point to PSPseg, and file + ; except headers is loaded to PSPseg+10h. + + dw stacksize-4 ; initial SP value + dw 0 ; no checksum + dw 100h ; initial IP + dw -10h ; initial CS relative to PSPseg+10h + dw 0 ; no relocation table, "offset 0 in file" + dw 0 ; this is not an overlay + db "MEMT" ; padding to a multiple of 16 bytes + + ; loaded part begins here (set CS so that IP is 100h here) + +start: ; entry point ; if you use obj + linker, use "..start:" + mov ah, 01h + mov bh, 00h + mov cx, 2000h + int 10h + + mov ax,cs ; *** + mov ds,ax ; *** + mov es,ax ; *** + + ; test if we have 386 or better: + pushf ; save flags + xor ax,ax + push ax + popf ; try to clear all bits + pushf + pop ax + and ax,0f000h + cmp ax,0f000h + jz noinst1 ; 4 msb stuck to 1: 808x or 80186 + mov ax,0f000h + push ax + popf ; try to set 4 msb + pushf + pop ax + test ax,0f000h + jz noinst1 ; 4 msb stuck to 0: 80286 + popf ; restore flags + jmp short found386 + +noinst1: + popf ; restore flags + mov dx,need386 + jmp generror + + +found386: ; now test if the system is in real mode: + smsw ax ; MSW is the low half of CR0 + ; (smsw is not priv'd, unlike mov eax,cr0) + test al,1 ; if the PE (protected mode) flag on? +%ifndef DEBUG ; ignore findings in debug mode + jnz foundprotected +%endif + jmp foundreal + +foundprotected: + mov dx,noreal + jmp generror + +; ------------ + +need386 db "Sorry, you need at least a 386 CPU to use Memtest86+." + db 13,10,"$" +noreal db "You cannot run Memtest86+ if the system already is in" + db " protected mode.",13,10,"$" + +; ------------ + +generror: ; generic error exit + push cs + pop ds + push cs + pop es + mov ah,9 + int 21h + mov ax,4c01h + int 21h + +; ------------ + +foundreal: + mov cx,buffer+15 + shr cx,4 ; buffer offset in paragraphs + mov ax,cs + add ax,cx ; buffer offset in paragraphs + ; now AX is the buffer segment + mov [cs:bufsetup+2],ax ; far pointer to boot sector now + mov cx,20h ; size of boot sector in paragraphs + add [cs:bufsetup+2],cx ; far pointer to setup now + movzx eax,ax + shl eax,4 ; linear buffer offset + mov [cs:buflinear],eax + +findpoint: ; now patch the loader! + mov al,[buffer+1f1h] ; size of setup.S in sectors + ; should be 4 ... + inc al ; the boot sector itself + movzx eax,al + shl eax,9 ; log 2 of sector size + add [cs:buflinear],eax ; linear address of head.S now + mov ax,[buffer+251h] ; should be jmp far dword (ofs, seg) + cmp ax,0ea66h + jz foundpatch +patchbug: ; could not patch the jump + mov dx,nopatch + jmp generror + +gdtbug: + mov dx,nogdt + jmp generror + +foundpatch: + mov eax,[cs:buflinear] + mov [buffer+253h],eax ; patch the protected mode entry jump + ; (offset only - segment selector unchanged: flat linear CS) + +findgdt: + mov eax,[cs:buffer+20ch] ; should be lgdt offset + and eax,00ffffffh + cmp eax,0016010fh ; lgdt ... + jnz gdtbug + + mov ax,[cs:buffer+20fh] ; GDTR contents pointer + mov bx,ax + mov eax,[cs:buffer+200h+bx+2] ; GDT linear offset + and eax,1ffh ; assume GDT in first sector of setup.S + ; *** WARNING: this is needed because setup.S contains + ; *** HARDCODED offset of setup.S on linear 90200h, which + ; *** is 90000h + bootsect.S ... flaw in Memtest86! + + mov cx,[cs:bufsetup+2] ; setup.S segment + movzx ecx,cx + shl ecx,4 ; linear setup.S address + add eax,ecx ; fixed GDT linear offset + mov [cs:buffer+200h+bx+2],eax ; patch it + + ;mov dx,trying + ;mov ah,9 + ;int 21h + + ;xor ax,ax + ;int 16h ; wait for a keypress from the user + + mov ax,[cs:bufsetup+2] ; setup segment + mov ds,ax ; set nice data segments for setup.S ... + mov es,ax + xor ax,ax + mov fs,ax + mov gs,ax + + cli + lss sp,[cs:newstack] ; stack in first 64k now! + movzx esp,sp ; ensure 16bit stack pointer + ; Memtest86 head.S assumes that it can just turn SS to + ; linear. This would put the stack at 0:200h or so for us + ; if we fail to move the stack around ... + +%ifdef DEBUG + mov ebp,[cs:buflinear] ; will show up in debugging logs + mov esi,[cs:bufsetup] ; will show up in debugging logs +%endif + + jmp far [cs:bufsetup] + ; setup.S will enable the A20 (ignoring HIMEM, just using + ; the classic 8042 programming trick) and turn on protected + ; mode. Then it will jump to head.S, which luckily can run + ; from any offset inside the linear 4 GB CS ... + +; ------------ + +buflinear dd 0 ; linear address of head.S entry point +bufsetup dw 0,0 ; far pointer to setup.S entry point + +newstack dw 03fch,0 ; beware, stack will overwrite IDT. + +; ------------ + +nopatch db "jmp far dword not found at setup.S offset 37h,",13,10 + db "(file offset 237h is not 66h, 0eah)",13,10 + db "please adjust and recompile memtestl...",13,10,"$" + +nogdt db "lgdt [...] not found at setup.S offset 0ch,",13,10 + db "(file offset 20ch is not 0fh, 01h, 16h)",13,10 + db "please adjust and recompile memtestl...",13,10,"$" + +trying db "Now trying to start Memtest86...",13,10 + db "You have to reboot to leave Memtest86 again.",13,10 + db "Press a key to go on.",13,10,"$" + +; ------------ + + align 16 +buffer: ; a label pointing to where in the file memtest.bin will be. + diff --git a/memtestEDK/Memtest/SingleComponents/patn.c b/memtestEDK/Memtest/SingleComponents/patn.c new file mode 100644 index 0000000..fabd2ea --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/patn.c @@ -0,0 +1,144 @@ +/* Pattern extension for memtest86 + * + * Generates patterns for the Linux kernel's BadRAM extension that avoids + * allocation of faulty pages. + * + * Released under version 2 of the Gnu Public License. + * + * By Rick van Rein, vanrein@zonnet.nl + * ---------------------------------------------------- + * MemTest86+ V1.60 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.x86-secret.com - http://www.memtest.org + */ + + +#include "test.h" + + +/* + * DEFAULT_MASK covers a longword, since that is the testing granularity. + */ +#define DEFAULT_MASK ((~0L) << 2) + + +/* extern struct vars *v; */ + + +/* What it does: + * - Keep track of a number of BadRAM patterns in an array; + * - Combine new faulty addresses with it whenever possible; + * - Keep masks as selective as possible by minimising resulting faults; + * - Print a new pattern only when the pattern array is changed. + */ + +#define COMBINE_MASK(a,b,c,d) ((a & b & c & d) | (~a & b & ~c & d)) + +/* Combine two adr/mask pairs to one adr/mask pair. + */ +void combine (ulong adr1, ulong mask1, ulong adr2, ulong mask2, + ulong *adr, ulong *mask) { + + *mask = COMBINE_MASK (adr1, mask1, adr2, mask2); + + *adr = adr1 | adr2; + *adr &= *mask; // Normalise, no fundamental need for this +} + +/* Count the number of addresses covered with a mask. + */ +ulong addresses (ulong mask) { + ulong ctr=1; + int i=32; + while (i-- > 0) { + if (! (mask & 1)) { + ctr += ctr; + } + mask >>= 1; + } + return ctr; +} + +/* Count how much more addresses would be covered by adr1/mask1 when combined + * with adr2/mask2. + */ +ulong combicost (ulong adr1, ulong mask1, ulong adr2, ulong mask2) { + ulong cost1=addresses (mask1); + ulong tmp, mask; + combine (adr1, mask1, adr2, mask2, &tmp, &mask); + return addresses (mask) - cost1; +} + +/* Find the cheapest array index to extend with the given adr/mask pair. + * Return -1 if nothing below the given minimum cost can be found. + */ +int cheapindex (ulong adr1, ulong mask1, ulong mincost) { + int i=vv->numpatn; + int idx=-1; + while (i-- > 0) { + ulong tmpcost=combicost(vv->patn[i].adr, vv->patn[i].mask, adr1, mask1); + if (tmpcost < mincost) { + mincost=tmpcost; + idx=i; + } + } + return idx; +} + +/* Try to find a relocation index for idx if it costs nothing. + * Return -1 if no such index exists. + */ +int relocateidx (int idx) { + ulong adr =vv->patn[idx].adr; + ulong mask=vv->patn[idx].mask; + int new; + vv->patn[idx].adr ^= ~0L; // Never select idx + new=cheapindex (adr, mask, 1+addresses (mask)); + vv->patn[idx].adr = adr; + return new; +} + +/* Relocate the given index idx only if free of charge. + * This is useful to combine to `neighbouring' sections to integrate. + * Inspired on the Buddy memalloc principle in the Linux kernel. + */ +void relocateiffree (int idx) { + int newidx=relocateidx (idx); + if (newidx>=0) { + ulong cadr, cmask; + combine (vv->patn [newidx].adr, vv->patn[newidx].mask, + vv->patn [ idx].adr, vv->patn[ idx].mask, + &cadr, &cmask); + vv->patn[newidx].adr =cadr; + vv->patn[newidx].mask=cmask; + if (idx < --vv->numpatn) { + vv->patn[idx].adr =vv->patn[vv->numpatn].adr; + vv->patn[idx].mask=vv->patn[vv->numpatn].mask; + } + relocateiffree (newidx); + } +} + +/* Insert a single faulty address in the pattern array. + * Return 1 only if the array was changed. + */ +int insertaddress (ulong adr) { + if (cheapindex (adr, DEFAULT_MASK, 1L) != -1) + return 0; + + if (vv->numpatn < BADRAM_MAXPATNS) { + vv->patn[vv->numpatn].adr =adr; + vv->patn[vv->numpatn].mask=DEFAULT_MASK; + vv->numpatn++; + relocateiffree (vv->numpatn-1); + } else { + int idx=cheapindex (adr, DEFAULT_MASK, ~0L); + ulong cadr, cmask; + combine (vv->patn [idx].adr, vv->patn[idx].mask, + adr, DEFAULT_MASK, &cadr, &cmask); + vv->patn[idx].adr =cadr; + vv->patn[idx].mask=cmask; + relocateiffree (idx); + } + return 1; +} diff --git a/memtestEDK/Memtest/SingleComponents/pci.c b/memtestEDK/Memtest/SingleComponents/pci.c new file mode 100644 index 0000000..075a07f --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/pci.c @@ -0,0 +1,177 @@ +/* pci.c - MemTest-86 Version 3.2 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + * ---------------------------------------------------- + * MemTest86+ V5.00 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.x86-secret.com - http://www.memtest.org + */ + +#include "io.h" +#include "pci.h" +#include "test.h" +#include "stdint.h" +#include "cpuid.h" + +#define PCI_CONF_TYPE_NONE 0 +#define PCI_CONF_TYPE_1 1 +#define PCI_CONF_TYPE_2 2 + +extern struct cpu_ident cpu_id; + +static unsigned char pci_conf_type = PCI_CONF_TYPE_NONE; + +#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \ + (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) + +#define PCI_CONF2_ADDRESS(dev, reg) (unsigned short)(0xC000 | (dev << 8) | reg) + +#define PCI_CONF3_ADDRESS(bus, dev, fn, reg) \ + (0x80000000 | (((reg >> 8) & 0xF) << 24) | (bus << 16) | ((dev & 0x1F) << 11) | (fn << 8) | (reg & 0xFF)) + +int pci_conf_read(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsigned len, unsigned long *value) +{ + int result; + + if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255 && pci_conf_type != PCI_CONF_TYPE_1)) + return -1; + + result = -1; + switch(pci_conf_type) { + case PCI_CONF_TYPE_1: + if(reg < 256){ + outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8); + }else{ + outl(PCI_CONF3_ADDRESS(bus, dev, fn, reg), 0xCF8); + } + switch(len) { + case 1: *value = inb(0xCFC + (reg & 3)); result = 0; break; + case 2: *value = inw(0xCFC + (reg & 2)); result = 0; break; + case 4: *value = inl(0xCFC); result = 0; break; + } + break; + case PCI_CONF_TYPE_2: + outb(0xF0 | (fn << 1), 0xCF8); + outb(bus, 0xCFA); + + switch(len) { + case 1: *value = inb(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break; + case 2: *value = inw(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break; + case 4: *value = inl(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break; + } + outb(0, 0xCF8); + break; + } + return result; +} + +int pci_conf_write(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsigned len, unsigned long value) +{ + int result; + + if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255 && pci_conf_type != PCI_CONF_TYPE_1)) + return -1; + + result = -1; + + switch(pci_conf_type) + { + case PCI_CONF_TYPE_1: + if(reg < 256){ + outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8); + }else{ + outl(PCI_CONF3_ADDRESS(bus, dev, fn, reg), 0xCF8); + } + switch(len) { + case 1: outb(value, 0xCFC + (reg & 3)); result = 0; break; + case 2: outw(value, 0xCFC + (reg & 2)); result = 0; break; + case 4: outl(value, 0xCFC); result = 0; break; + } + break; + case PCI_CONF_TYPE_2: + outb(0xF0 | (fn << 1), 0xCF8); + outb(bus, 0xCFA); + + switch(len) { + case 1: outb(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break; + case 2: outw(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break; + case 4: outl(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break; + } + outb(0, 0xCF8); + break; + } + return result; +} + +static int pci_sanity_check(void) +{ + unsigned long value; + int result; + /* Do a trivial check to make certain we can see a host bridge. + * There are reportedly some buggy chipsets from intel and + * compaq where this test does not work, I will worry about + * that when we support them. + */ + result = pci_conf_read(0, 0, 0, PCI_CLASS_DEVICE, 2, &value); + if (result == 0) { + result = -1; + if (value == PCI_CLASS_BRIDGE_HOST) { + result = 0; + } + } + return result; +} + +static int pci_check_direct(void) +{ + unsigned char tmpCFB; + unsigned int tmpCF8; + + if (cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.family == 0xF) { + pci_conf_type = PCI_CONF_TYPE_1; + return 0; + } else { + /* Check if configuration type 1 works. */ + pci_conf_type = PCI_CONF_TYPE_1; + tmpCFB = inb(0xCFB); + outb(0x01, 0xCFB); + tmpCF8 = inl(0xCF8); + outl(0x80000000, 0xCF8); + if ((inl(0xCF8) == 0x80000000) && (pci_sanity_check() == 0)) { + outl(tmpCF8, 0xCF8); + outb(tmpCFB, 0xCFB); + return 0; + } + outl(tmpCF8, 0xCF8); + + /* Check if configuration type 2 works. */ + + pci_conf_type = PCI_CONF_TYPE_2; + outb(0x00, 0xCFB); + outb(0x00, 0xCF8); + outb(0x00, 0xCFA); + if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 && (pci_sanity_check() == 0)) { + outb(tmpCFB, 0xCFB); + return 0; + + } + + outb(tmpCFB, 0xCFB); + + /* Nothing worked return an error */ + pci_conf_type = PCI_CONF_TYPE_NONE; + return -1; + + } +} + +int pci_init(void) +{ + int result; + /* For now just make certain we can directly + * use the pci functions. + */ + result = pci_check_direct(); + return result; +} diff --git a/memtestEDK/Memtest/SingleComponents/pci.h b/memtestEDK/Memtest/SingleComponents/pci.h new file mode 100644 index 0000000..f21c478 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/pci.h @@ -0,0 +1,96 @@ +#ifndef MEMTEST_PCI_H +#define MEMTEST_PCI_H + +int pci_conf_read(unsigned bus, unsigned dev, unsigned fn, unsigned reg, + unsigned len, unsigned long *value); +int pci_conf_write(unsigned bus, unsigned dev, unsigned fn, unsigned reg, + unsigned len, unsigned long value); +int pci_init(void); + +#define MAKE_PCIE_ADDRESS(bus, device, function) (((bus) & 0xFF)<<20) | (((device) & 0x1F)<<15) | (((function) & 0x7)<<12) + +/* + * Under PCI, each device has 256 bytes of configuration address space, + * of which the first 64 bytes are standardized as follows: + */ +#define PCI_VENDOR_ID 0x00 /* 16 bits */ +#define PCI_DEVICE_ID 0x02 /* 16 bits */ +#define PCI_COMMAND 0x04 /* 16 bits */ +#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ +#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ +#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ +#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ +#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ +#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ +#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ +#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ +#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ +#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ + +#define PCI_STATUS 0x06 /* 16 bits */ +#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ +#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ +#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */ +#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ +#define PCI_STATUS_PARITY 0x100 /* Detected parity error */ +#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ +#define PCI_STATUS_DEVSEL_FAST 0x000 +#define PCI_STATUS_DEVSEL_MEDIUM 0x200 +#define PCI_STATUS_DEVSEL_SLOW 0x400 +#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ +#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ +#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ +#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ +#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ + +#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 + revision */ +#define PCI_REVISION_ID 0x08 /* Revision ID */ +#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ +#define PCI_CLASS_DEVICE 0x0a /* Device class */ + +#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ +#define PCI_LATENCY_TIMER 0x0d /* 8 bits */ +#define PCI_HEADER_TYPE 0x0e /* 8 bits */ +#define PCI_HEADER_TYPE_NORMAL 0 +#define PCI_HEADER_TYPE_BRIDGE 1 +#define PCI_HEADER_TYPE_CARDBUS 2 + +#define PCI_BIST 0x0f /* 8 bits */ +#define PCI_BIST_CODE_MASK 0x0f /* Return result */ +#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ +#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ + +/* + * Base addresses specify locations in memory or I/O space. + * Decoded size can be determined by writing a value of + * 0xffffffff to the register, and reading it back. Only + * 1 bits are decoded. + */ +#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ +#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */ +#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */ +#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ +#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ +#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ +#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ +#define PCI_BASE_ADDRESS_SPACE_IO 0x01 +#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 +#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 +#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ +#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */ +#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ +#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ +#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) +#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL) +/* bit 1 is reserved if address_space = 1 */ + + +/* Device classes and subclasses */ +#define PCI_CLASS_NOT_DEFINED 0x0000 +#define PCI_CLASS_NOT_DEFINED_VGA 0x0001 + +#define PCI_BASE_CLASS_BRIDGE 0x06 +#define PCI_CLASS_BRIDGE_HOST 0x0600 + +#endif /* MEMTEST_PCI_H */ diff --git a/memtestEDK/Memtest/SingleComponents/precomp.bin b/memtestEDK/Memtest/SingleComponents/precomp.bin Binary files differnew file mode 100755 index 0000000..5738e08 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/precomp.bin diff --git a/memtestEDK/Memtest/SingleComponents/random.c b/memtestEDK/Memtest/SingleComponents/random.c new file mode 100644 index 0000000..69dd140 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/random.c @@ -0,0 +1,38 @@ +/******************************************************************/ +/* Random number generator */ +/* concatenation of following two 16-bit multiply with carry generators */ +/* x(n)=a*x(n-1)+carry mod 2^16 and y(n)=b*y(n-1)+carry mod 2^16, */ +/* number and carry packed within the same 32 bit integer. */ +/******************************************************************/ +#include "stdint.h" +#include "cpuid.h" +#include "smp.h" + +/* Keep a separate seed for each CPU */ +/* Space the seeds by at least a cache line or performance suffers big time! */ +static unsigned int SEED_X[MAX_CPUS*16]; +static unsigned int SEED_Y[MAX_CPUS*16]; + +unsigned long rand (int cpu) +{ + static unsigned int a = 18000, b = 30903; + int me; + + me = cpu*16; + + SEED_X[me] = a*(SEED_X[me]&65535) + (SEED_X[me]>>16); + SEED_Y[me] = b*(SEED_Y[me]&65535) + (SEED_Y[me]>>16); + + return ((SEED_X[me]<<16) + (SEED_Y[me]&65535)); +} + + +void rand_seed( unsigned int seed1, unsigned int seed2, int cpu) +{ + int me; + + me = cpu*16; + SEED_X[me] = seed1; + SEED_Y[me] = seed2; +} + diff --git a/memtestEDK/Memtest/SingleComponents/reloc.c b/memtestEDK/Memtest/SingleComponents/reloc.c new file mode 100644 index 0000000..bde268f --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/reloc.c @@ -0,0 +1,268 @@ +/* reloc.c - MemTest-86 Version 3.3 + * + * Released under version 2 of the Gnu Public License. + * By Eric Biederman + */ + +#include "stddef.h" +#include "stdint.h" +#include "elf.h" + +#define __ELF_NATIVE_CLASS 32 +#define ELF_MACHINE_NO_RELA 1 + +/* We use this macro to refer to ELF types independent of the native wordsize. + `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ +#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type) +#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t) +#define _ElfW_1(e,w,t) e##w##t +#define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type) + +static inline void __attribute__ ((unused)) +fail_assert(unsigned line_num, unsigned code) { + // Put line num in low bits of %edx and a sentinel in the high bits. + line_num |= 0xEEEC0000; // eek! + asm __volatile__ ("movl %%edx, %%edx" + : "=d"(line_num), "=c" (code) + : "d" (line_num), "c" (code)); + + // Now observe %edx in a virtual machine's debugger. + // Have a nice day. + while(1) {} +} + +// TODO(jcoiner): It would be nice to try to print a message here, +// even though we don't have function calls yet, maybe we can write +// to the screen before going into our infinite loop. +#define assert(expr, code) do { \ + if (!(expr)) { fail_assert(__LINE__, code); } \ + } while(0) + +/* This #define produces dynamic linking inline functions for + bootstrap relocation instead of general-purpose relocation. */ +#define RTLD_BOOTSTRAP + +struct link_map { + ElfW(Addr) l_addr; /* Current load address */ + ElfW(Addr) ll_addr; /* Last load address */ + ElfW(Dyn) *l_ld; + /* Indexed pointers to dynamic section. + [0,DT_NUM) are indexed by the processor-independent tags. + [DT_NUM,DT_NUM+DT_PROCNUM) are indexed by the tag minus DT_LOPROC. + [DT_NUM+DT_PROCNUM, + DT_NUM+DT_PROCNUM+DT_EXTRANUM) + are indexed by DT_EXTRATAGIDX(tagvalue) (see <elf.h>). */ + ElfW(Dyn) *l_info[DT_NUM + DT_PROCNUM + DT_EXTRANUM]; +}; + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static inline Elf32_Addr __attribute__ ((unused)) +elf_machine_dynamic(void) { + register Elf32_Addr *got asm ("%ebx"); + return *got; +} + +/* Return the run-time load address of the shared object. */ +static inline Elf32_Addr __attribute__ ((unused)) +elf_machine_load_address(void) { + Elf32_Addr addr; + asm volatile ("leal _start@GOTOFF(%%ebx), %0\n" + : "=r" (addr) : : "cc"); + return addr; +} + +/* Perform the relocation specified by RELOC and SYM (which is fully resolved). + MAP is the object containing the reloc. */ +static inline void +elf_machine_rel(struct link_map *map, const Elf32_Rel *reloc, + const Elf32_Sym *sym, Elf32_Addr *const reloc_addr) { + Elf32_Addr ls_addr, s_addr; + Elf32_Addr value; + if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE) + { + *reloc_addr += map->l_addr - map->ll_addr; + return; + } + if (ELF32_R_TYPE(reloc->r_info) == R_386_NONE) { + return; + } + value = sym->st_value; + /* Every section except the undefined section has a base of map->l_addr */ + ls_addr = sym->st_shndx == SHN_UNDEF ? 0 : map->ll_addr; + s_addr = sym->st_shndx == SHN_UNDEF ? 0 : map->l_addr; + + switch (ELF32_R_TYPE (reloc->r_info)) + { + case R_386_COPY: { + /* Roll memcpy by hand as we don't have function calls yet. */ + unsigned char *dest, *src; + long i; + dest = (unsigned char *)reloc_addr; + src = (unsigned char *)(value + s_addr); + for(i = 0; i < sym->st_size; i++) { + dest[i] = src[i]; + } + break; + } + case R_386_GLOB_DAT: + *reloc_addr = s_addr + value; + break; + case R_386_JMP_SLOT: + *reloc_addr = s_addr + value; + break; + case R_386_32: + if (map->ll_addr == 0) { + *reloc_addr += value; + } + *reloc_addr += s_addr - ls_addr; + break; + case R_386_PC32: + if (map->ll_addr == 0) { + *reloc_addr += value - reloc->r_offset; + } + *reloc_addr += (s_addr - map->l_addr) - (ls_addr - map->ll_addr); + break; + default: + assert (! "unexpected dynamic reloc type", 0); + break; + } +} + +/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */ + +static inline void __attribute__ ((unused)) +elf_get_dynamic_info(ElfW(Dyn) *dyn, ElfW(Addr) l_addr, + ElfW(Dyn) *info[DT_NUM + DT_PROCNUM + DT_EXTRANUM]) { + if (! dyn) + return; + + while (dyn->d_tag != DT_NULL) { + if (dyn->d_tag < DT_NUM) + info[dyn->d_tag] = dyn; + else if (dyn->d_tag >= DT_LOPROC && + dyn->d_tag < DT_LOPROC + DT_PROCNUM) + info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn; + else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM) + info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_PROCNUM] = dyn; +#if 0 + else { + // JPC this is failing, BOZO! + // Not surprising, there are a bunch of sections we don't + // handle and which modern ELF relocation code in glibc + // will handle and relocate. Bah. + assert (! "bad dynamic tag", dyn->d_tag); + } +#endif + ++dyn; + } + + if (info[DT_PLTGOT] != NULL) + info[DT_PLTGOT]->d_un.d_ptr += l_addr; + if (info[DT_STRTAB] != NULL) + info[DT_STRTAB]->d_un.d_ptr += l_addr; + if (info[DT_SYMTAB] != NULL) + info[DT_SYMTAB]->d_un.d_ptr += l_addr; +#if ! ELF_MACHINE_NO_RELA + if (info[DT_RELA] != NULL) { + assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)), 0); + info[DT_RELA]->d_un.d_ptr += l_addr; + } +#endif +#if ! ELF_MACHINE_NO_REL + if (info[DT_REL] != NULL) { + assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)), 0); + info[DT_REL]->d_un.d_ptr += l_addr; + } +#endif + if (info[DT_PLTREL] != NULL) { +#if ELF_MACHINE_NO_RELA + assert (info[DT_PLTREL]->d_un.d_val == DT_REL, 0); +#elif ELF_MACHINE_NO_REL + assert (info[DT_PLTREL]->d_un.d_val == DT_RELA, 0); +#else + assert (info[DT_PLTREL]->d_un.d_val == DT_REL + || info[DT_PLTREL]->d_un.d_val == DT_RELA, 0); +#endif + } + if (info[DT_JMPREL] != NULL) + info[DT_JMPREL]->d_un.d_ptr += l_addr; +} + +/* Perform the relocations in MAP on the running program image as specified + by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT + relocations; they should be set up to call _dl_runtime_resolve, rather + than fully resolved now. */ + +static inline void +elf_dynamic_do_rel(struct link_map *map, + ElfW(Addr) reladdr, ElfW(Addr) relsize) { + const ElfW(Rel) *r = (const void *) reladdr; + const ElfW(Rel) *end = (const void *) (reladdr + relsize); + + const ElfW(Sym) *const symtab = + (const void *) map->l_info[DT_SYMTAB]->d_un.d_ptr; + + for (; r < end; ++r) { + elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], + (void *) (map->l_addr + r->r_offset)); + } +} + +void _dl_start(void) { + static Elf32_Addr last_load_address = 0; + struct link_map map; + size_t cnt; + + /* Partly clean the `map' structure up. Don't use `memset' + since it might nor be built in or inlined and we cannot make function + calls at this point. */ + for (cnt = 0; cnt < sizeof(map.l_info) / sizeof(map.l_info[0]); ++cnt) { + map.l_info[cnt] = 0; + } + + /* Get the last load address */ + map.ll_addr = last_load_address; + + /* Figure out the run-time load address of the dynamic linker itself. */ + last_load_address = map.l_addr = elf_machine_load_address(); + + /* Read our own dynamic section and fill in the info array. */ + map.l_ld = (void *)map.l_addr + elf_machine_dynamic(); + + elf_get_dynamic_info (map.l_ld, map.l_addr - map.ll_addr, map.l_info); + + /* Relocate ourselves so we can do normal function calls and + * data access using the global offset table. + */ +#if !ELF_MACHINE_NO_REL + elf_dynamic_do_rel(&map, + map.l_info[DT_REL]->d_un.d_ptr, + map.l_info[DT_RELSZ]->d_un.d_val); + if (map.l_info[DT_PLTREL]->d_un.d_val == DT_REL) { + elf_dynamic_do_rel(&map, + map.l_info[DT_JMPREL]->d_un.d_ptr, + map.l_info[DT_PLTRELSZ]->d_un.d_val); + } +#endif + +#if !ELF_MACHINE_NO_RELA + elf_dynamic_do_rela(&map, + map.l_info[DT_RELA]->d_un.d_ptr, + map.l_info[DT_RELASZ]->d_un.d_val); + if (map.l_info[DT_PLTREL]->d_un.d_val == DT_RELA) { + elf_dynamic_do_rela(&map, + map.l_info[DT_JMPREL]->d_un.d_ptr, + map.l_info[DT_PLTRELSZ]->d_un.d_val); + } +#endif + + /* Now life is sane; we can call functions and access global data. + Set up to use the operating system facilities, and find out from + the operating system's program loader where to find the program + header table in core. Put the rest of _dl_start into a separate + function, that way the compiler cannot put accesses to the GOT + before ELF_DYNAMIC_RELOCATE. */ + return; +} diff --git a/memtestEDK/Memtest/SingleComponents/screen_buffer.c b/memtestEDK/Memtest/SingleComponents/screen_buffer.c new file mode 100644 index 0000000..2a8e77d --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/screen_buffer.c @@ -0,0 +1,133 @@ +/* screen_buffer.c - MemTest-86 Version 3.3 + * + * Released under version 2 of the Gnu Public License. + * By Jani Averbach, Jaa@iki.fi, 2001 + */ + +// #include "test.h" +#include "screen_buffer.h" +#include "lib.c" + + +#include <Library/UefiLib.h> + +#define SCREEN_X 80 +#define SCREEN_Y 25 +#define Y_SIZE SCREEN_Y +/* + * X-size should by one of by screen size, + * so that there is room for ending '\0' + */ +#define X_SIZE SCREEN_X+1 + +static char screen_buf[Y_SIZE][X_SIZE]; + +#ifdef SCRN_DEBUG + +char *padding = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; + +#define CHECK_BOUNDS(y,x) do {if (y < 0 || Y_SIZE <= y || x < 0 || X_SIZE <= x) print_error("out of index");}while(0) + +#else /* ! SCRN_DEBUG */ + +#define CHECK_BOUNDS(y,x) + +#endif /* SCRN_DEBUG */ + +char +get_scrn_buf(const int y, + const int x) +{ + CHECK_BOUNDS(y,x); + return screen_buf[y][x]; +} + + +void +set_scrn_buf(const int y, + const int x, + const char val) +{ + CHECK_BOUNDS(y,x); + screen_buf[y][x] = val; +} + +void clear_screen_buf() +{ + int y, x; + + for (y=0; y < SCREEN_Y; ++y){ + for (x=0; x < SCREEN_X; ++x){ + CHECK_BOUNDS(y,x); + screen_buf[y][x] = ' '; + } + CHECK_BOUNDS(y,SCREEN_X); + screen_buf[y][SCREEN_X] = '\0'; + } +} + +void tty_print_region(const int pi_top, + const int pi_left, + const int pi_bottom, + const int pi_right) +{ + Print(L"Start tty_print_region\n"); + int y; + char tmp; + + for (y=pi_top; y < pi_bottom; ++y){ + CHECK_BOUNDS(y, pi_right); + + tmp = screen_buf[y][pi_right]; + screen_buf[y][pi_right] = '\0'; + + CHECK_BOUNDS(y, pi_left); + ttyprint(y, pi_left, &(screen_buf[y][pi_left])); + + screen_buf[y][pi_right] = tmp; + } + Print(L"end tty_print_region\n"); +} + +void tty_print_line( + int y, int x, const char *text) +{ + for(; *text && (x < SCREEN_X); x++, text++) { + if (*text != screen_buf[y][x]) { + break; + } + } + /* If there is nothing to do return */ + if (*text == '\0') { + return; + } + // ttyprint(y, x, text); + for(; *text && (x < SCREEN_X); x++, text++) { + screen_buf[y][x] = *text; + } +} + + +void tty_print_screen(void) +{ +#ifdef SCRN_DEBUG + int i; + + for (i=0; i < SCREEN_Y; ++i) + // ttyprint(i,0, padding); +#endif /* SCRN_DEBUG */ + + // tty_print_region(0, 0, SCREEN_Y, SCREEN_X); +} + +void print_error(char *pstr) +{ + +#ifdef SCRN_DEBUG + // ttyprint(0,0, padding); +#endif /* SCRN_DEBUG */ + + // ttyprint(0,35, pstr); + + while(1); +} diff --git a/memtestEDK/Memtest/SingleComponents/screen_buffer.h b/memtestEDK/Memtest/SingleComponents/screen_buffer.h new file mode 100644 index 0000000..37949a0 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/screen_buffer.h @@ -0,0 +1,20 @@ +/* --*- C -*-- + * + * By Jani Averbach, Jaa@iki.fi, 2001 + * + * Released under version 2 of the Gnu Public License. + * + */ +#ifndef SCREEN_BUFFER_H_1D10F83B_INCLUDED +#define SCREEN_BUFFER_H_1D10F83B_INCLUDED + +// #include "config.h" + +char get_scrn_buf(const int y, const int x); +void set_scrn_buf(const int y, const int x, const char val); +void clear_screen_buf(void); +void tty_print_region(const int pi_top,const int pi_left, const int pi_bottom,const int pi_right); +void tty_print_line(int y, int x, const char *text); +void tty_print_screen(void); +void print_error(char *pstr); +#endif /* SCREEN_BUFFER_H_1D10F83B_INCLUDED */ diff --git a/memtestEDK/Memtest/SingleComponents/self_test.c b/memtestEDK/Memtest/SingleComponents/self_test.c new file mode 100644 index 0000000..975ec40 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/self_test.c @@ -0,0 +1,209 @@ +/* Usermode self-test. + * + * This is a unit test for memtest86+ itself, + * not a standalone usermode memory tester. Sorry. + * + * It covers the main test routines in test.c, allows running them + * in a debugger or adding printfs as needed. + * + * It does not cover: + * - SMP functionality. There's no fundamental obstacle + * to this, it's just not here yet. + * - Every .c file. Some of them do things that will be + * difficult to test in user mode (eg set page tables) + * without some refactoring. + */ + +#ifdef NDEBUG + #error "Someone disabled asserts, but we want asserts for the self test." +#endif +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "stdint.h" +#include "cpuid.h" +#include "test.h" + +/* Provide alternate versions of the globals */ +volatile int run_cpus = 1; +volatile int bail = 0; +volatile int segs = 0; +struct vars variables; +struct vars* const vv = &variables; +// Self-test only supports single CPU (ordinal 0) for now: +volatile int mstr_cpu = 0; + +void assert_fail(const char* file, int line_no) { + printf("Failing assert at %s:%d\n", file, line_no); + assert(0); +} + +void do_tick(int me) {} +void hprint(int y, int x, ulong val) {} +void cprint(int y,int x, const char *s) {} +void dprint(int y,int x,ulong val,int len, int right) {} +void s_barrier() {} // No SMP support in selftest yet + +// Selftest doesn't have error injection yet, and thus, we +// never expect to detect any error. Fail an assert in these +// error-reporting routines: +void ad_err1(ulong *adr1, ulong *adr2, ulong good, ulong bad) { + assert(0); +} +void ad_err2(ulong *adr, ulong bad) { + assert(0); +} +void mt86_error(ulong* adr, ulong good, ulong bad) { + assert(0); +} + +typedef struct { + ulong* va; + ulong len_dw; +} foreach_chunk; + +#define MAX_CHUNK 16 + +typedef struct { + foreach_chunk chunks[MAX_CHUNK]; + int index; +} foreach_ctx; + +void record_chunks(ulong* va, ulong len_dw, const void* vctx) { + foreach_ctx* ctx = (foreach_ctx*)vctx; + + ctx->chunks[ctx->index].va = va; + ctx->chunks[ctx->index].len_dw = len_dw; + ctx->index++; +} + +void foreach_tests() { + foreach_ctx ctx; + const int me = 0; + + // mapped segment is 3G to 4G exact + memset(&ctx, 0, sizeof(ctx)); + foreach_segment((ulong*)0xc0000000, + (ulong*)0xfffffffc, me, &ctx, record_chunks); + + assert(ctx.index == 4); + assert(ctx.chunks[0].va == (ulong*)0xc0000000); + assert(ctx.chunks[0].len_dw == SPINSZ_DWORDS); + assert(ctx.chunks[1].va == (ulong*)0xd0000000); + assert(ctx.chunks[1].len_dw == SPINSZ_DWORDS); + assert(ctx.chunks[2].va == (ulong*)0xe0000000); + assert(ctx.chunks[2].len_dw == SPINSZ_DWORDS); + assert(ctx.chunks[3].va == (ulong*)0xf0000000); + assert(ctx.chunks[3].len_dw == SPINSZ_DWORDS); + + // mapped segment is 256 bytes, 128 byte aligned + memset(&ctx, 0, sizeof(ctx)); + foreach_segment((ulong*)0xc0000080, + (ulong*)0xc000017c, me, &ctx, record_chunks); + assert(ctx.index == 1); + assert(ctx.chunks[0].va == (ulong*)0xc0000080); + assert(ctx.chunks[0].len_dw == 64); + + // mapped segment starts a bit below 3.75G + // and goes up to the 4G boundary + memset(&ctx, 0, sizeof(ctx)); + foreach_segment((ulong*)0xeffff800, + (ulong*)0xfffffffc, me, &ctx, record_chunks); + assert(ctx.index == 2); + assert(ctx.chunks[0].va == (ulong*)0xeffff800); + assert(ctx.chunks[0].len_dw == SPINSZ_DWORDS); + assert(ctx.chunks[1].va == (ulong*)0xfffff800); + assert(ctx.chunks[1].len_dw == 0x200); + + // mapped segment is 0 to 32M + memset(&ctx, 0, sizeof(ctx)); + foreach_segment((ulong*)0x0, + (ulong*)0x1fffffc, me, &ctx, record_chunks); + assert(ctx.index == 1); + assert(ctx.chunks[0].va == (ulong*)0x0); + assert(ctx.chunks[0].len_dw == 0x800000); +} + +int main() { + memset(&variables, 0, sizeof(variables)); + vv->debugging = 1; + + get_cpuid(); + + // add a non-power-of-2 pad to the size, so things don't line + // up too nicely. Chose 508 because it's not 512. + const int kTestSizeDwords = SPINSZ_DWORDS * 2 + 508; + + // Allocate an extra cache line on each end, where we'll + // write a sentinel pattern to detect overflow or underflow: + const int kRawBufSizeDwords = kTestSizeDwords + 32; + + segs = 1; + ulong raw_start = (ulong)malloc(kRawBufSizeDwords * sizeof(ulong)); + ulong raw_end = raw_start + kRawBufSizeDwords * sizeof(ulong); + + // align to a cache line: + if (raw_start & 0x3f) { + raw_start &= ~0x3f; + raw_start += 0x40; + } + // align to a cache line: + if (raw_end & 0x3f) { + raw_end &= ~0x3f; + } + + const int kSentinelBytes = 48; + ulong start = raw_start + kSentinelBytes; // exclude low sentinel + ulong end = raw_end - kSentinelBytes; // exclude high sentinel + + // setup sentinels + memset((ulong*)raw_start, 'z', kSentinelBytes); + memset((ulong*)end, 'z', kSentinelBytes); + + vv->map[0].start = (ulong*)start; + vv->map[0].end = ((ulong*)end) - 1; // map.end points to xxxxxfc + + const int iter = 2; + const int me = 0; // cpu ordinal + + foreach_tests(); + + // TEST 0 + addr_tst1(me); + + // TEST 1, 2 + addr_tst2(me); + + // TEST 3, 4, 5, 6 + const ulong pat = 0x112211ee; + movinv1(iter, pat, ~pat, 0); + + // TEST 7 + block_move(iter, me); + + // TEST 8 + movinv32(iter, 0x2, 0x1, 0x80000000, 0, 1, me); + + // TEST 9 + movinvr(me); + + // TEST 10 + modtst(2, 1, 0x5555aaaa, 0xaaaa5555, me); + + // TEST 11 + bit_fade_fill(0xdeadbeef, me); + bit_fade_chk(0xdeadbeef, me); + + + // Check sentinels, they should not have been overwritten. Do this last. + for (int j=0; j<kSentinelBytes; j++) { + assert(((char*)raw_start)[j] == 'z'); + assert(((char*)end)[j] == 'z'); + } + + printf("All self-tests PASS.\n"); + + return 0; +} diff --git a/memtestEDK/Memtest/SingleComponents/serial.h b/memtestEDK/Memtest/SingleComponents/serial.h new file mode 100644 index 0000000..bbdfa9c --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/serial.h @@ -0,0 +1,162 @@ +/* + * include/linux/serial.h + * + * Copyright (C) 1992, 1994 by Theodore Ts'o. + * + * Redistribution of this file is permitted under the terms of the GNU + * Public License (GPL) + * + * These are the UART port assignments, expressed as offsets from the base + * register. These assignments should hold for any serial port based on + * a 8250, 16450, or 16550(A). + */ + +#ifndef _LINUX_SERIAL_REG_H +#define _LINUX_SERIAL_REG_H + +#define UART_RX 0 /* In: Receive buffer (DLAB=0) */ +#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ +#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ +#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ +#define UART_IER 1 /* Out: Interrupt Enable Register */ +#define UART_IIR 2 /* In: Interrupt ID Register */ +#define UART_FCR 2 /* Out: FIFO Control Register */ +#define UART_EFR 2 /* I/O: Extended Features Register */ + /* (DLAB=1, 16C660 only) */ +#define UART_LCR 3 /* Out: Line Control Register */ +#define UART_MCR 4 /* Out: Modem Control Register */ +#define UART_LSR 5 /* In: Line Status Register */ +#define UART_MSR 6 /* In: Modem Status Register */ +#define UART_SCR 7 /* I/O: Scratch Register */ + + + +/* + * These are the definitions for the FIFO Control Register + * (16650 only) + */ +#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ +#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ +#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ +#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */ +#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */ +#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */ +#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ +#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ +#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ +/* 16650 redefinitions */ +#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */ +#define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */ +#define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */ +#define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */ +#define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */ +#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */ +#define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */ +#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */ + +/* + * These are the definitions for the Line Control Register + * + * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting + * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits. + */ +#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ +#define UART_LCR_SBC 0x40 /* Set break control */ +#define UART_LCR_SPAR 0x20 /* Stick parity (?) */ +#define UART_LCR_EPAR 0x10 /* Even parity select */ +#define UART_LCR_PARITY 0x08 /* Parity Enable */ +#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */ +#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */ +#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */ +#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */ +#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ + +/* + * These are the definitions for the Line Status Register + */ +#define UART_LSR_TEMT 0x40 /* Transmitter empty */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define UART_LSR_BI 0x10 /* Break interrupt indicator */ +#define UART_LSR_FE 0x08 /* Frame error indicator */ +#define UART_LSR_PE 0x04 /* Parity error indicator */ +#define UART_LSR_OE 0x02 /* Overrun error indicator */ +#define UART_LSR_DR 0x01 /* Receiver data ready */ + +/* + * These are the definitions for the Interrupt Identification Register + */ +#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ +#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ + +#define UART_IIR_MSI 0x00 /* Modem status interrupt */ +#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ +#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ +#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ + +/* + * These are the definitions for the Interrupt Enable Register + */ +#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ +#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ +#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ +#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ + +/* + * These are the definitions for the Modem Control Register + */ +#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ +#define UART_MCR_OUT2 0x08 /* Out2 complement */ +#define UART_MCR_OUT1 0x04 /* Out1 complement */ +#define UART_MCR_RTS 0x02 /* RTS complement */ +#define UART_MCR_DTR 0x01 /* DTR complement */ + +/* + * These are the definitions for the Modem Status Register + */ +#define UART_MSR_DCD 0x80 /* Data Carrier Detect */ +#define UART_MSR_RI 0x40 /* Ring Indicator */ +#define UART_MSR_DSR 0x20 /* Data Set Ready */ +#define UART_MSR_CTS 0x10 /* Clear to Send */ +#define UART_MSR_DDCD 0x08 /* Delta DCD */ +#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ +#define UART_MSR_DDSR 0x02 /* Delta DSR */ +#define UART_MSR_DCTS 0x01 /* Delta CTS */ +#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ + +/* + * These are the definitions for the Extended Features Register + * (StarTech 16C660 only, when DLAB=1) + */ +#define UART_EFR_CTS 0x80 /* CTS flow control */ +#define UART_EFR_RTS 0x40 /* RTS flow control */ +#define UART_EFR_SCD 0x20 /* Special character detect */ +#define UART_EFR_ENI 0x10 /* Enhanced Interrupt */ +/* + * the low four bits control software flow control + */ + +#define serial_echo_outb(v,a) outb((v),(a)+serial_base_ports[serial_tty]) +#define serial_echo_inb(a) inb((a)+serial_base_ports[serial_tty]) +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) +/* Wait for transmitter & holding register to empty */ +#define WAIT_FOR_XMITR \ + do { \ + lsr = serial_echo_inb(UART_LSR); \ + } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY) + +#if 0 +static inline void serial_echo(int ch) +{ + int lsr; + WAIT_FOR_XMITR; + serial_echo_outb(ch, UART_TX); +} +static inline void serial_debug(int ch) +{ + serial_echo(ch); + serial_echo('\r'); + serial_echo('\n'); +} +#endif +#endif /* _LINUX_SERIAL_REG_H */ + diff --git a/memtestEDK/Memtest/SingleComponents/setup.S b/memtestEDK/Memtest/SingleComponents/setup.S new file mode 100644 index 0000000..f80875b --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/setup.S @@ -0,0 +1,154 @@ +/* + * setup.s is responsible for getting the system data from the BIOS, + * and putting them into the appropriate places in system memory. + * both setup.s and system has been loaded by the bootblock. + * + * 1-Jan-96 Modified by Chris Brady for use as a boot/loader for memtest-86. + */ + +#define __ASSEMBLY__ +#include "defs.h" + +.code16 +.section ".setup", "ax", @progbits +.globl start +start: +# ok, the read went well +# now we want to move to protected mode ... + + + cli # no interrupts allowed # + movb $0x80, %al # disable NMI for the bootup sequence + outb %al, $0x70 + +# The system will move itself to its rightful place. +# reload the segment registers and the stack since the +# APs also execute this code +#ljmp $INITSEG, $(reload - start + 0x200) +reload: + movw $INITSEG, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %ss # reset the stack to INITSEG:0x4000-12. + movw %dx, %sp + push %cs + pop %ds + lidt idt_48 - start # load idt with 0,0 + lgdt gdt_48 - start # load gdt with whatever appropriate + +# that was painless, now we enable A20 +# start from grub-a20.patch + /* + * try to switch gateA20 using PORT92, the "Fast A20 and Init" + * register + */ + mov $0x92, %dx + inb %dx, %al + /* skip the port92 code if it's unimplemented (read returns 0xff) */ + cmpb $0xff, %al + jz alt_a20_done + + /* set or clear bit1, the ALT_A20_GATE bit */ + movb 4(%esp), %ah + testb %ah, %ah + jz alt_a20_cont1 + orb $2, %al + jmp alt_a20_cont2 +alt_a20_cont1: + and $0xfd, %al + + /* clear the INIT_NOW bit; don't accidently reset the machine */ +alt_a20_cont2: + and $0xfe, %al + outb %al, %dx + +alt_a20_done: +# end from grub-a20.patch + + call empty_8042 + + movb $0xD1, %al # command write + outb %al, $0x64 + call empty_8042 + + movb $0xDF, %al # A20 on + outb %al, $0x60 + call empty_8042 + +/* + * Note that the short jump isn't strictly needed, althought there are + * reasons why it might be a good idea. It won't hurt in any case. + */ + movw $0x0001, %ax # protected mode (PE) bit + lmsw %ax # This is it# + jmp flush_instr +flush_instr: + movw $KERNEL_DS, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + +data32 ljmp $KERNEL_CS, $(TSTLOAD <<4) # jmp offset 2000 of segment 0x10 (cs) + +/* + * This routine checks that the keyboard command queue is empty + * (after emptying the output buffers) + * + * No timeout is used - if this hangs there is something wrong with + * the machine, and we probably couldn't proceed anyway. + */ +empty_8042: + call delay + inb $0x64, %al # 8042 status port + cmpb $0xff, %al # from grub-a20-patch, skip if not impl + jz empty_8042_ret + testb $1, %al # output buffer? + jz no_output + call delay + inb $0x60, %al # read it + jmp empty_8042 + +no_output: + testb $2, %al # is input buffer full? + jnz empty_8042 # yes - loop +empty_8042_ret: + ret +# +# Delay is needed after doing i/o +# +delay: + .word 0x00eb # jmp $+2 + ret + +gdt: + .word 0,0,0,0 # dummy + + .word 0,0,0,0 # unused + + .word 0x7FFF # limit 128mb + .word 0x0000 # base address=0 + .word 0x9A00 # code read/exec + .word 0x00C0 # granularity=4096, 386 + + .word 0x7FFF # limit 128mb + .word 0x0000 # base address=0 + .word 0x9200 # data read/write + .word 0x00C0 # granularity=4096, 386 + +idt_48: + .word 0 # idt limit=0 + .long 0 # idt base=0L + +gdt_48: + .word 0x800 # gdt limit=2048, 256 GDT entries + .word 512+gdt - start,0x9 # gdt base = 0X9xxxx + +msg1: + .asciz "Setup.S\r\n" + + /* Pad setup to the proper size */ + .org (SETUPSECS*512) + diff --git a/memtestEDK/Memtest/SingleComponents/smp.c b/memtestEDK/Memtest/SingleComponents/smp.c new file mode 100644 index 0000000..aecefc1 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/smp.c @@ -0,0 +1,700 @@ +/* + * MemTest86+ V5 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + * ------------------------------------------------ + * smp.c - MemTest-86 Version 3.5 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + */ + +#include <Library/UefiLib.h> + + +#include "stddef.h" +#include "stdint.h" +#include "cpuid.h" +#include "smp.h" +#include "test.h" +#include "environment.h" + +#define DELAY_FACTOR 1 +unsigned num_cpus = 1; // There is at least one cpu, the BSP +int act_cpus; +unsigned found_cpus = 0; + +extern void memcpy(void *dst, void *src , int len); +extern void test_start(void); +extern int run_cpus; +extern int maxcpus; +extern char cpu_mask[]; +extern struct cpu_ident cpu_id; + +struct barrier_s *barr; + +void smp_find_cpus(); + +void barrier_init(int max) +{ + /* Set the adddress of the barrier structure */ + barr = (struct barrier_s *)0x9ff00; + barr->lck.slock = 1; + barr->mutex.slock = 1; + barr->maxproc = max; + barr->count = max; + barr->st1.slock = 1; + barr->st2.slock = 0; +} + +void s_barrier_init(int max) +{ + barr->s_lck.slock = 1; + barr->s_maxproc = max; + barr->s_count = max; + barr->s_st1.slock = 1; + barr->s_st2.slock = 0; +} + +void barrier() +{ + if (num_cpus == 1 || vv->fail_safe & 3) { + return; + } + spin_wait(&barr->st1); /* Wait if the barrier is active */ + spin_lock(&barr->lck); /* Get lock for barr struct */ + if (--barr->count == 0) { /* Last process? */ + barr->st1.slock = 0; /* Hold up any processes re-entering */ + barr->st2.slock = 1; /* Release the other processes */ + barr->count++; + spin_unlock(&barr->lck); + } else { + spin_unlock(&barr->lck); + spin_wait(&barr->st2); /* wait for peers to arrive */ + spin_lock(&barr->lck); + if (++barr->count == barr->maxproc) { + barr->st1.slock = 1; + barr->st2.slock = 0; + } + spin_unlock(&barr->lck); + } +} + +void s_barrier() +{ + if (run_cpus == 1 || vv->fail_safe & 3) { + return; + } + spin_wait(&barr->s_st1); /* Wait if the barrier is active */ + spin_lock(&barr->s_lck); /* Get lock for barr struct */ + if (--barr->s_count == 0) { /* Last process? */ + barr->s_st1.slock = 0; /* Hold up any processes re-entering */ + barr->s_st2.slock = 1; /* Release the other processes */ + barr->s_count++; + spin_unlock(&barr->s_lck); + } else { + spin_unlock(&barr->s_lck); + spin_wait(&barr->s_st2); /* wait for peers to arrive */ + spin_lock(&barr->s_lck); + if (++barr->s_count == barr->s_maxproc) { + barr->s_st1.slock = 1; + barr->s_st2.slock = 0; + } + spin_unlock(&barr->s_lck); + } +} + +typedef struct { + bool started; +} ap_info_t; + +volatile apic_register_t *APIC = NULL; +/* CPU number to APIC ID mapping table. CPU 0 is the BSP. */ +static unsigned cpu_num_to_apic_id[MAX_CPUS]; +volatile ap_info_t AP[MAX_CPUS]; + +void PUT_MEM16(uintptr_t addr, uint16_t val) +{ + *((volatile uint16_t *)(MAX_BLOCK_SIZE)addr) = val; +} + +void PUT_MEM32(uintptr_t addr, uint32_t val) +{ + *((volatile uint32_t *)(MAX_BLOCK_SIZE)addr) = val; +} + +static void inline +APIC_WRITE(unsigned reg, uint32_t val) +{ + APIC[reg][0] = val; +} + +static inline uint32_t +APIC_READ(unsigned reg) +{ + return APIC[reg][0]; +} + + +static void +SEND_IPI(unsigned apic_id, unsigned trigger, unsigned level, unsigned mode, + uint8_t vector) +{ + uint32_t v; + + v = APIC_READ(APICR_ICRHI) & 0x00ffffff; + APIC_WRITE(APICR_ICRHI, v | (apic_id << 24)); + + v = APIC_READ(APICR_ICRLO) & ~0xcdfff; + v |= (APIC_DEST_DEST << APIC_ICRLO_DEST_OFFSET) + | (trigger << APIC_ICRLO_TRIGGER_OFFSET) + | (level << APIC_ICRLO_LEVEL_OFFSET) + | (mode << APIC_ICRLO_DELMODE_OFFSET) + | (vector); + APIC_WRITE(APICR_ICRLO, v); +} + + +// Silly way of busywaiting, but we don't have a timer +void delay(unsigned us) +{ + unsigned freq = 1000; // in MHz, assume 1GHz CPU speed + uint64_t cycles = us * freq; + uint64_t t0 = RDTSC(); + uint64_t t1; + volatile unsigned k; + + do { + for (k = 0; k < 1000; k++) continue; + t1 = RDTSC(); + } while (t1 - t0 < cycles); +} + +static inline void +memset (volatile void *dst, + char value, + int len) +{ + int i; + for (i = 0 ; i < len ; i++ ) { + *((char *) dst + i) = value; + } +} +void initialise_cpus(void) +{ + int i; + + act_cpus = 0; + + if (maxcpus > 1) { + smp_find_cpus(); + /* The total number of CPUs may be limited */ + if (num_cpus > maxcpus) { + num_cpus = maxcpus; + } + /* Determine how many cpus have been selected */ + for(i = 0; i < num_cpus; i++) { + if (cpu_mask[i]) { + act_cpus++; + } + } + } else { + act_cpus = found_cpus = num_cpus = 1; + } + + /* Initialize the barrier before starting AP's */ + barrier_init(act_cpus); + + /* let the BSP initialise the APs. */ + for(i = 1; i < num_cpus; i++) { + /* Only start this CPU if it is selected by the mask */ + if (cpu_mask[i]) { + smp_boot_ap(i); + } + } + +} +void kick_cpu(unsigned cpu_num) +{ + unsigned num_sipi, apic_id; + apic_id = cpu_num_to_apic_id[cpu_num]; + + // clear the APIC ESR register + APIC_WRITE(APICR_ESR, 0); + APIC_READ(APICR_ESR); + + // asserting the INIT IPI + SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 1, APIC_DELMODE_INIT, 0); + delay(100000 / DELAY_FACTOR); + + // de-assert the INIT IPI + SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 0, APIC_DELMODE_INIT, 0); + + for (num_sipi = 0; num_sipi < 2; num_sipi++) { + unsigned timeout; + bool send_pending; + unsigned err; + + APIC_WRITE(APICR_ESR, 0); + + SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, (unsigned)(MAX_BLOCK_SIZE)startup_32 >> 12); + + timeout = 0; + do { + delay(10); + timeout++; + send_pending = (APIC_READ(APICR_ICRLO) & APIC_ICRLO_STATUS_MASK) != 0; + } while (send_pending && timeout < 1000); + + if (send_pending) { + cprint(LINE_STATUS+3, 0, "SMP: STARTUP IPI was never sent"); + } + + delay(100000 / DELAY_FACTOR); + + err = APIC_READ(APICR_ESR) & 0xef; + if (err) { + cprint(LINE_STATUS+3, 0, "SMP: After STARTUP IPI: err = 0x"); + hprint(LINE_STATUS+3, COL_MID, err); + } + } +} + +// These memory locations are used for the trampoline code and data. + +#define BOOTCODESTART 0x9000 +#define GDTPOINTERADDR 0x9100 +#define GDTADDR 0x9110 + +void boot_ap(unsigned cpu_num) +{ + unsigned num_sipi, apic_id; + extern uint8_t gdt; + extern uint8_t _ap_trampoline_start; + extern uint8_t _ap_trampoline_protmode; + unsigned len = &_ap_trampoline_protmode - &_ap_trampoline_start; + apic_id = cpu_num_to_apic_id[cpu_num]; + + + memcpy((uint8_t*)BOOTCODESTART, &_ap_trampoline_start, len); + + // Fixup the LGDT instruction to point to GDT pointer. + PUT_MEM16(BOOTCODESTART + 3, GDTPOINTERADDR); + + // Copy a pointer to the temporary GDT to addr GDTPOINTERADDR. + // The temporary gdt is at addr GDTADDR + PUT_MEM16(GDTPOINTERADDR, 4 * 8); + PUT_MEM32(GDTPOINTERADDR + 2, GDTADDR); + + // Copy the first 4 gdt entries from the currently used GDT to the + // temporary GDT. + memcpy((uint8_t *)GDTADDR, &gdt, 32); + + // clear the APIC ESR register + APIC_WRITE(APICR_ESR, 0); + APIC_READ(APICR_ESR); + + // asserting the INIT IPI + SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 1, APIC_DELMODE_INIT, 0); + delay(100000 / DELAY_FACTOR); + + // de-assert the INIT IPI + SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 0, APIC_DELMODE_INIT, 0); + + for (num_sipi = 0; num_sipi < 2; num_sipi++) { + unsigned timeout; + bool send_pending; + unsigned err; + + APIC_WRITE(APICR_ESR, 0); + + SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, BOOTCODESTART >> 12); + + timeout = 0; + do { + delay(10); + timeout++; + send_pending = (APIC_READ(APICR_ICRLO) & APIC_ICRLO_STATUS_MASK) != 0; + } while (send_pending && timeout < 1000); + + if (send_pending) { + cprint(LINE_STATUS+3, 0, "SMP: STARTUP IPI was never sent"); + } + + delay(100000 / DELAY_FACTOR); + + err = APIC_READ(APICR_ESR) & 0xef; + if (err) { + cprint(LINE_STATUS+3, 0, "SMP: After STARTUP IPI: err = 0x"); + hprint(LINE_STATUS+3, COL_MID, err); + } + } +} + +static int checksum(unsigned char *mp, int len) +{ + int sum = 0; + + while (len--) { + sum += *mp++; + } + return (sum & 0xFF); +} + +/* Parse an MP config table for CPU information */ +bool read_mp_config_table(uintptr_t addr) +{ + mp_config_table_header_t *mpc = (mp_config_table_header_t*)(MAX_BLOCK_SIZE)addr; + uint8_t *tab_entry_ptr; + uint8_t *mpc_table_end; + + if (mpc->signature != MPCSignature) { + return FALSE; + } + if (checksum((unsigned char*)mpc, mpc->length) != 0) { + return FALSE; + } + + /* FIXME: the uintptr_t cast here works around a compilation problem on + * AMD64, but it ignores the real problem, which is that lapic_addr + * is only 32 bits. Maybe that's OK, but it should be investigated. + */ + APIC = (volatile apic_register_t*)(MAX_BLOCK_SIZE)(uintptr_t)mpc->lapic_addr; + + tab_entry_ptr = ((uint8_t*)mpc) + sizeof(mp_config_table_header_t); + mpc_table_end = ((uint8_t*)mpc) + mpc->length; + + while (tab_entry_ptr < mpc_table_end) { + switch (*tab_entry_ptr) { + case MP_PROCESSOR: { + mp_processor_entry_t *pe = (mp_processor_entry_t*)tab_entry_ptr; + + if (pe->cpu_flag & CPU_BOOTPROCESSOR) { + // BSP is CPU 0 + cpu_num_to_apic_id[0] = pe->apic_id; + } else if (num_cpus < MAX_CPUS) { + cpu_num_to_apic_id[num_cpus] = pe->apic_id; + num_cpus++; + } + found_cpus++; + + // we cannot handle non-local 82489DX apics + if ((pe->apic_ver & 0xf0) != 0x10) { + return 0; + } + + tab_entry_ptr += sizeof(mp_processor_entry_t); + break; + } + case MP_BUS: { + tab_entry_ptr += sizeof(mp_bus_entry_t); + break; + } + case MP_IOAPIC: { + tab_entry_ptr += sizeof(mp_io_apic_entry_t); + break; + } + case MP_INTSRC: + tab_entry_ptr += sizeof(mp_interrupt_entry_t); + break; + case MP_LINTSRC: + tab_entry_ptr += sizeof(mp_local_interrupt_entry_t); + break; + default: + return FALSE; + } + } + return TRUE; +} + +/* Search for a Floating Pointer structure */ +floating_pointer_struct_t * +scan_for_floating_ptr_struct(uintptr_t addr, uint32_t length) +{ + floating_pointer_struct_t *fp; + uintptr_t end = addr + length; + + + while ((uintptr_t)addr < end) { + fp = (floating_pointer_struct_t*)(MAX_BLOCK_SIZE)addr; + if (*(unsigned int *)(MAX_BLOCK_SIZE)addr == FPSignature && fp->length == 1 + && checksum((unsigned char*)(MAX_BLOCK_SIZE)addr, 16) == 0 + && ((fp->spec_rev == 1) || (fp->spec_rev == 4))) { + return fp; + } + addr += 4; + } + return NULL; +} + +/* Search for a Root System Descriptor Pointer */ +rsdp_t *scan_for_rsdp(uintptr_t addr, uint32_t length) +{ + rsdp_t *rp; + uintptr_t end = addr + length; + + + while ((uintptr_t)addr < end) { + rp = (rsdp_t*)(MAX_BLOCK_SIZE)addr; + if (*(unsigned int *)(MAX_BLOCK_SIZE)addr == RSDPSignature && + checksum((unsigned char*)(MAX_BLOCK_SIZE)addr, rp->length) == 0) { + return rp; + } + addr += 4; + } + return NULL; +} + +/* Parse a MADT table for processor entries */ +int parse_madt(uintptr_t addr) { + + mp_config_table_header_t *mpc = (mp_config_table_header_t*)(MAX_BLOCK_SIZE)addr; + uint8_t *tab_entry_ptr; + uint8_t *mpc_table_end; + + if (checksum((unsigned char*)mpc, mpc->length) != 0) { + return FALSE; + } + + APIC = (volatile apic_register_t*)(MAX_BLOCK_SIZE)(uintptr_t)mpc->lapic_addr; + + tab_entry_ptr = ((uint8_t*)mpc) + sizeof(mp_config_table_header_t); + mpc_table_end = ((uint8_t*)mpc) + mpc->length; + while (tab_entry_ptr < mpc_table_end) { + + madt_processor_entry_t *pe = (madt_processor_entry_t*)tab_entry_ptr; + if (pe->type == MP_PROCESSOR) { + if (pe->enabled) { + if (num_cpus < MAX_CPUS) { + cpu_num_to_apic_id[num_cpus] = pe->apic_id; + + /* the first CPU is the BSP, don't increment */ + if (found_cpus) { + num_cpus++; + } + } + found_cpus++; + } + } + tab_entry_ptr += pe->length; + } + return TRUE; +} + +/* This is where we search for SMP information in the following order + * look for a floating MP pointer + * found: + * check for a default configuration + * found: + * setup config, return + * check for a MP config table + * found: + * validate: + * good: + * parse the MP config table + * good: + * setup config, return + * + * find & validate ACPI RSDP (Root System Descriptor Pointer) + * found: + * find & validate RSDT (Root System Descriptor Table) + * found: + * find & validate MSDT + * found: + * parse the MADT table + * good: + * setup config, return + */ +void smp_find_cpus() +{ + floating_pointer_struct_t *fp; + rsdp_t *rp; + rsdt_t *rt; + uint8_t *tab_ptr, *tab_end; + unsigned int *ptr; + unsigned int uiptr; + + Print(L"fail_safe: %d\n", vv->fail_safe); + + if(vv->fail_safe & 3) { return; } + + memset(&AP, 0, sizeof AP); + + if(vv->fail_safe & 8) + { + // Search for the Floating MP structure pointer + fp = scan_for_floating_ptr_struct(0x0, 0x400); + if (fp == NULL) { + fp = scan_for_floating_ptr_struct(639*0x400, 0x400); + } + if (fp == NULL) { + fp = scan_for_floating_ptr_struct(0xf0000, 0x10000); + } + if (fp == NULL) { + // Search the BIOS ESDS area + unsigned int address = *(unsigned short *)0x40E; + address <<= 4; + if (address) { + fp = scan_for_floating_ptr_struct(address, 0x400); + } + } + + if (fp != NULL) { + // We have a floating MP pointer + // Is this a default configuration? + + if (fp->feature[0] > 0 && fp->feature[0] <=7) { + // This is a default config so plug in the numbers + num_cpus = 2; + APIC = (volatile apic_register_t*)0xFEE00000; + cpu_num_to_apic_id[0] = 0; + cpu_num_to_apic_id[1] = 1; + return; + } + + // Do we have a pointer to a MP configuration table? + if ( fp->phys_addr != 0) { + if (read_mp_config_table(fp->phys_addr)) { + // Found a good MP table, done + return; + } + } + } + } + + + /* No MP table so far, try to find an ACPI MADT table + * We try to use the MP table first since there is no way to distinguish + * real cores from hyper-threads in the MADT */ + + /* Search for the RSDP */ + rp = scan_for_rsdp(0xE0000, 0x20000); + if (rp == NULL) { + /* Search the BIOS ESDS area */ + unsigned int address = *(unsigned short *)0x40E; + address <<= 4; + if (address) { + rp = scan_for_rsdp(address, 0x400); + } + } + + if (rp == NULL) { + /* RSDP not found, give up */ + return; + } + + /* Found the RSDP, now get either the RSDT or XSDT */ + if (rp->revision >= 2) { + rt = (rsdt_t *)(MAX_BLOCK_SIZE)rp->xrsdt[0]; + + if (rt == 0) { + return; + } + // Validate the XSDT + if (*(unsigned int *)rt != XSDTSignature) { + return; + } + if ( checksum((unsigned char*)rt, rt->length) != 0) { + return; + } + + } else { + rt = (rsdt_t *)(MAX_BLOCK_SIZE)rp->rsdt; + if (rt == 0) { + return; + } + /* Validate the RSDT */ + if (*(unsigned int *)rt != RSDTSignature) { + return; + } + if ( checksum((unsigned char*)rt, rt->length) != 0) { + return; + } + } + + /* Scan the RSDT or XSDT for a pointer to the MADT */ + tab_ptr = ((uint8_t*)rt) + sizeof(rsdt_t); + tab_end = ((uint8_t*)rt) + rt->length; + + while (tab_ptr < tab_end) { + + uiptr = *((unsigned int *)tab_ptr); + ptr = (unsigned int *)(MAX_BLOCK_SIZE)uiptr; + + /* Check for the MADT signature */ + if (ptr && *ptr == MADTSignature) { + /* Found it, now parse it */ + if (parse_madt((uintptr_t)(MAX_BLOCK_SIZE)ptr)) { + return; + } + } + tab_ptr += 4; + } +} + +unsigned my_apic_id() +{ + return (APIC[APICR_ID][0]) >> 24; +} + +void smp_ap_booted(unsigned cpu_num) +{ + AP[cpu_num].started = TRUE; +} + +void smp_boot_ap(unsigned cpu_num) +{ + unsigned timeout; + + boot_ap(cpu_num); + timeout = 0; + do { + delay(1000 / DELAY_FACTOR); + timeout++; + } while (!AP[cpu_num].started && timeout < 100000 / DELAY_FACTOR); + + if (!AP[cpu_num].started) { + cprint(LINE_STATUS+3, 0, "SMP: Boot timeout for"); + dprint(LINE_STATUS+3, COL_MID, cpu_num,2,1); + cprint(LINE_STATUS+3, 26, "Turning off SMP"); + } +} + +unsigned smp_my_cpu_num() +{ + unsigned apicid = my_apic_id(); + unsigned i; + + for (i = 0; i < MAX_CPUS; i++) { + if (apicid == cpu_num_to_apic_id[i]) { + break; + } + } + if (i == MAX_CPUS) { + i = 0; + } + return i; +} + +/* A set of simple functions used to preserve assigned CPU ordinals since + * they are lost after relocation (the stack is reloaded). + */ +int num_to_ord[MAX_CPUS]; +void smp_set_ordinal(int me, int ord) +{ + num_to_ord[me] = ord; +} + +int smp_my_ord_num(int me) +{ + return num_to_ord[me]; +} + +int smp_ord_to_cpu(int me) +{ + int i; + for (i=0; i<MAX_CPUS; i++) { + if (num_to_ord[i] == me) return i; + } + return -1; +} diff --git a/memtestEDK/Memtest/SingleComponents/smp.h b/memtestEDK/Memtest/SingleComponents/smp.h new file mode 100644 index 0000000..5d07ce7 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/smp.h @@ -0,0 +1,366 @@ +/* ********************************************************** + * Copyright 2002 VMware, Inc. All rights reserved. -- VMware Confidential + * **********************************************************/ + + +#ifndef _SMP_H_ +#define _SMP_H_ +#include "stdint.h" +#include "defs.h" +#define MAX_CPUS 32 + +#define FPSignature ('_' | ('M' << 8) | ('P' << 16) | ('_' << 24)) + +typedef struct { + uint32_t signature; // "_MP_" + uint32_t phys_addr; + uint8_t length; + uint8_t spec_rev; + uint8_t checksum; + uint8_t feature[5]; +} floating_pointer_struct_t; + +#define MPCSignature ('P' | ('C' << 8) | ('M' << 16) | ('P' << 24)) +typedef struct { + uint32_t signature; // "PCMP" + uint16_t length; + uint8_t spec_rev; + uint8_t checksum; + char oem[8]; + char productid[12]; + uint32_t oem_ptr; + uint16_t oem_size; + uint16_t oem_count; + uint32_t lapic_addr; + uint32_t reserved; +} mp_config_table_header_t; + +/* Followed by entries */ + +#define MP_PROCESSOR 0 +#define MP_BUS 1 +#define MP_IOAPIC 2 +#define MP_INTSRC 3 +#define MP_LINTSRC 4 + +typedef struct { + uint8_t type; /* MP_PROCESSOR */ + uint8_t apic_id; /* Local APIC number */ + uint8_t apic_ver; /* Its versions */ + uint8_t cpu_flag; +#define CPU_ENABLED 1 /* Processor is available */ +#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */ + uint32_t cpu_signature; +#define CPU_STEPPING_MASK 0x0F +#define CPU_MODEL_MASK 0xF0 +#define CPU_FAMILY_MASK 0xF00 + uint32_t featureflag; /* CPUID feature value */ + uint32_t reserved[2]; +} mp_processor_entry_t; + +typedef struct { + uint8_t type; // has value MP_BUS + uint8_t busid; + char bustype[6]; +} mp_bus_entry_t; + +/* We don't understand the others */ + +typedef struct { + uint8_t type; // set to MP_IOAPIC + uint8_t apicid; + uint8_t apicver; + uint8_t flags; +#define MPC_APIC_USABLE 0x01 + uint32_t apicaddr; +} mp_io_apic_entry_t; + + +typedef struct { + uint8_t type; + uint8_t irqtype; + uint16_t irqflag; + uint8_t srcbus; + uint8_t srcbusirq; + uint8_t dstapic; + uint8_t dstirq; +} mp_interrupt_entry_t; + +#define MP_INT_VECTORED 0 +#define MP_INT_NMI 1 +#define MP_INT_SMI 2 +#define MP_INT_EXTINT 3 + +#define MP_IRQDIR_DEFAULT 0 +#define MP_IRQDIR_HIGH 1 +#define MP_IRQDIR_LOW 3 + + +typedef struct { + uint8_t type; + uint8_t irqtype; + uint16_t irqflag; + uint8_t srcbusid; + uint8_t srcbusirq; + uint8_t destapic; +#define MP_APIC_ALL 0xFF + uint8_t destapiclint; +} mp_local_interrupt_entry_t; + +#define RSDPSignature ('R' | ('S' << 8) | ('D' << 16) | (' ' << 24)) +typedef struct { + char signature[8]; // "RSD " + uint8_t checksum; + char oemid[6]; + uint8_t revision; + uint32_t rsdt; + uint32_t length; + uint32_t xrsdt[2]; + uint8_t xsum; +} rsdp_t; + +#define RSDTSignature ('R' | ('S' << 8) | ('D' << 16) | ('T' << 24)) +#define XSDTSignature ('X' | ('S' << 8) | ('D' << 16) | ('T' << 24)) +typedef struct { + char signature[4]; // "RSDT" + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oemid[18]; + char cid[4]; + char cver[4]; +} rsdt_t; + +#define MADTSignature ('A' | ('P' << 8) | ('I' << 16) | ('C' << 24)) +typedef struct { + uint8_t type; + uint8_t length; + uint8_t acpi_id; + uint8_t apic_id; /* Local APIC number */ + uint32_t enabled; +} madt_processor_entry_t; + +/* APIC definitions */ +/* + * APIC registers + */ +#define APICR_ID 0x02 +#define APICR_ESR 0x28 +#define APICR_ICRLO 0x30 +#define APICR_ICRHI 0x31 + +/* APIC destination shorthands */ +#define APIC_DEST_DEST 0 +#define APIC_DEST_LOCAL 1 +#define APIC_DEST_ALL_INC 2 +#define APIC_DEST_ALL_EXC 3 + +/* APIC IPI Command Register format */ +#define APIC_ICRHI_RESERVED 0x00ffffff +#define APIC_ICRHI_DEST_MASK 0xff000000 +#define APIC_ICRHI_DEST_OFFSET 24 + +#define APIC_ICRLO_RESERVED 0xfff32000 +#define APIC_ICRLO_DEST_MASK 0x000c0000 +#define APIC_ICRLO_DEST_OFFSET 18 +#define APIC_ICRLO_TRIGGER_MASK 0x00008000 +#define APIC_ICRLO_TRIGGER_OFFSET 15 +#define APIC_ICRLO_LEVEL_MASK 0x00004000 +#define APIC_ICRLO_LEVEL_OFFSET 14 +#define APIC_ICRLO_STATUS_MASK 0x00001000 +#define APIC_ICRLO_STATUS_OFFSET 12 +#define APIC_ICRLO_DESTMODE_MASK 0x00000800 +#define APIC_ICRLO_DESTMODE_OFFSET 11 +#define APIC_ICRLO_DELMODE_MASK 0x00000700 +#define APIC_ICRLO_DELMODE_OFFSET 8 +#define APIC_ICRLO_VECTOR_MASK 0x000000ff +#define APIC_ICRLO_VECTOR_OFFSET 0 + +/* APIC trigger types (edge/level) */ +#define APIC_TRIGGER_EDGE 0 +#define APIC_TRIGGER_LEVEL 1 + +/* APIC delivery modes */ +#define APIC_DELMODE_FIXED 0 +#define APIC_DELMODE_LOWEST 1 +#define APIC_DELMODE_SMI 2 +#define APIC_DELMODE_NMI 4 +#define APIC_DELMODE_INIT 5 +#define APIC_DELMODE_STARTUP 6 +#define APIC_DELMODE_EXTINT 7 +typedef uint32_t apic_register_t[4]; + +extern volatile apic_register_t *APIC; + +unsigned smp_my_cpu_num(); + +void smp_init_bsp(void); +void smp_init_aps(void); + +void smp_boot_ap(unsigned cpu_num); +void smp_ap_booted(unsigned cpu_num); + +typedef struct { + unsigned int slock; +} spinlock_t; + +struct barrier_s +{ + spinlock_t mutex; + spinlock_t lck; + int maxproc; + volatile int count; + spinlock_t st1; + spinlock_t st2; + spinlock_t s_lck; + int s_maxproc; + volatile int s_count; + spinlock_t s_st1; + spinlock_t s_st2; +}; + +void barrier(); +void s_barrier(); +void barrier_init(int max); +void s_barrier_init(int max); + +static inline void +__GET_CPUID(int ax, uint32_t *regs) +{ + __asm__ __volatile__("\t" + /* save ebx in case -fPIC is being used */ + "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" + : "=a" (regs[0]), "=D" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) + : "a" (ax) + : "memory" + ); +} + +#define GET_CPUID(_ax,_bx,_cx,_dx) { \ + uint32_t regs[4]; \ + __GET_CPUID(_ax,regs); \ + _ax = regs[0]; \ + _bx = regs[1]; \ + _cx = regs[2]; \ + _dx = regs[3]; \ +} + +/* + * Checked against the Intel manual and GCC --hpreg + * + * volatile because the tsc always changes without the compiler knowing it. + */ +static inline uint64_t +RDTSC(void) +{ + uint64_t tim; + + __asm__ __volatile__( + "rdtsc" + : "=A" (tim) + ); + + return tim; +} + +static inline uint64_t __GET_MSR(int cx) +{ + uint64_t msr; + + __asm__ __volatile__( + "rdmsr" + : "=A" (msr) + : "c" (cx) + ); + + return msr; +} + +#define __GCC_OUT(s, s2, port, val) do { \ + __asm__( \ + "out" #s " %" #s2 "1, %w0" \ + : \ + : "Nd" (port), "a" (val) \ + ); \ +} while (0) +#define OUTB(port, val) __GCC_OUT(b, b, port, val) + +static inline void spin_wait(spinlock_t *lck) +{ + if (cpu_id.fid.bits.mon) { + /* Use monitor/mwait for a low power, low contention spin */ + asm volatile( + "movl $0,%%ecx\n\t" + "movl %%ecx, %%edx\n\t" + "1:\n\t" + "movl %%edi,%%eax\n\t" + "monitor\n\t" + "cmpb $0,(%%edi)\n\t" + "jne 2f\n\t" + "movl %%ecx, %%eax\n\t" + "mwait\n\t" + "jmp 1b\n" + "2:" + : : "D" (lck): "%eax", "%ecx", "%edx" + ); + } else { + /* No monitor/mwait so just spin with a lot of nop's */ + int inc = 0x400; + asm volatile( + "1:\t" + "cmpb $0,%1\n\t" + "jne 2f\n\t" + "rep ; nop\n\t" + "jmp 1b\n" + "2:" + : : "c" (inc), "m" (lck->slock): "memory" + ); + } +} + +static inline void spin_lock(spinlock_t *lck) +{ + if (cpu_id.fid.bits.mon) { + /* Use monitor/mwait for a low power, low contention spin */ + asm volatile( + "\n1:\t" + " ; lock;decb (%%edi)\n\t" + "jns 3f\n" + "movl $0,%%ecx\n\t" + "movl %%ecx, %%edx\n\t" + "2:\t" + "movl %%edi,%%eax\n\t" + "monitor\n\t" + "movl %%ecx, %%eax\n\t" + "mwait\n\t" + "cmpb $0,(%%edi)\n\t" + "jle 2b\n\t" + "jmp 1b\n" + "3:\n\t" + : : "D" (lck): "%eax", "%ecx", "%edx" + ); + } else { + /* No monitor/mwait so just spin with a lot of nop's */ + int inc = 0x400; + asm volatile( + "\n1:\t" + " ; lock;decb %0\n\t" + "jns 3f\n" + "2:\t" + "rep;nop\n\t" + "cmpb $0,%0\n\t" + "jle 2b\n\t" + "jmp 1b\n" + "3:\n\t" + : "+m" (lck->slock) : "c" (inc) : "memory" + ); + } +} + +static inline void spin_unlock(spinlock_t *lock) +{ + asm volatile("movb $1,%0" : "+m" (lock->slock) :: "memory"); +} + + +#endif /* _SMP_H_ */ diff --git a/memtestEDK/Memtest/SingleComponents/spd.c b/memtestEDK/Memtest/SingleComponents/spd.c new file mode 100644 index 0000000..197db56 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/spd.c @@ -0,0 +1,541 @@ +/* + * MemTest86+ V5 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + */ + + +#include "test.h" +#include "io.h" +#include "pci.h" +#include "msr.h" +#include "spd.h" +#include "screen_buffer.h" +#include "jedec_id.h" + +#define NULL 0 + +#define SMBHSTSTS smbusbase +#define SMBHSTCNT smbusbase + 2 +#define SMBHSTCMD smbusbase + 3 +#define SMBHSTADD smbusbase + 4 +#define SMBHSTDAT smbusbase + 5 + +extern void wait_keyup(); + +int smbdev, smbfun; +unsigned short smbusbase; +unsigned char spd_raw[256]; +char s[] = {'/', 0, '-', 0, '\\', 0, '|', 0}; + +static void ich5_get_smb(void) +{ + unsigned long x; + int result; + result = pci_conf_read(0, smbdev, smbfun, 0x20, 2, &x); + if (result == 0) smbusbase = (unsigned short) x & 0xFFFE; +} + +static void piix4_get_smb(void) +{ + unsigned long x; + int result; + + result = pci_conf_read(0, smbdev, smbfun, 0x08, 1, &x); + + if(x < 0x40){ + // SB600/700 + result = pci_conf_read(0, smbdev, smbfun, 0x90, 2, &x); + if (result == 0) smbusbase = (unsigned short) x & 0xFFFE; + } else { + // SB800 + sb800_get_smb(); + } +} + +void sb800_get_smb(void) +{ + int lbyte, hbyte; + + __outb(AMD_SMBUS_BASE_REG + 1, AMD_INDEX_IO_PORT); + lbyte = __inb(AMD_DATA_IO_PORT); + __outb(AMD_SMBUS_BASE_REG, AMD_INDEX_IO_PORT); + hbyte = __inb(AMD_DATA_IO_PORT); + + smbusbase = lbyte; + smbusbase <<= 8; + smbusbase += hbyte; + smbusbase &= 0xFFE0; + + if (smbusbase == 0xFFE0) { smbusbase = 0; } +} + +unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd) +{ + int l1, h1, l2, h2; + unsigned long long t; + __outb(0x1f, SMBHSTSTS); // reset SMBus Controller + __outb(0xff, SMBHSTDAT); + while(__inb(SMBHSTSTS) & 0x01); // wait until ready + __outb(cmd, SMBHSTCMD); + __outb((adr << 1) | 0x01, SMBHSTADD); + __outb(0x48, SMBHSTCNT); + rdtsc(l1, h1); + //cprint(POP2_Y, POP2_X + 16, s + cmd % 8); // progress bar + while (!(__inb(SMBHSTSTS) & 0x02)) { // wait til command finished + rdtsc(l2, h2); + t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / vv->clks_msec; + if (t > 10) break; // break after 10ms + } + return __inb(SMBHSTDAT); +} + +static int ich5_read_spd(int dimmadr) +{ + int x; + spd_raw[0] = ich5_smb_read_byte(0x50 + dimmadr, 0); + if (spd_raw[0] == 0xff) return -1; // no spd here + for (x = 1; x < 256; x++) { + spd_raw[x] = ich5_smb_read_byte(0x50 + dimmadr, (unsigned char) x); + } + return 0; +} + +static void us15w_get_smb(void) +{ + unsigned long x; + int result; + result = pci_conf_read(0, 0x1f, 0, 0x40, 2, &x); + if (result == 0) smbusbase = (unsigned short) x & 0xFFC0; +} + +unsigned char us15w_smb_read_byte(unsigned char adr, unsigned char cmd) +{ + int l1, h1, l2, h2; + unsigned long long t; + //__outb(0x00, smbusbase + 1); // reset SMBus Controller + //__outb(0x00, smbusbase + 6); + //while((__inb(smbusbase + 1) & 0x08) != 0); // wait until ready + __outb(0x02, smbusbase + 0); // Byte read + __outb(cmd, smbusbase + 5); // Command + __outb(0x07, smbusbase + 1); // Clear status + __outb((adr << 1) | 0x01, smbusbase + 4); // DIMM address + __outb(0x12, smbusbase + 0); // Start + //while (((__inb(smbusbase + 1) & 0x08) == 0)) {} // wait til busy + rdtsc(l1, h1); + cprint(POP2_Y, POP2_X + 16, s + cmd % 8); // progress bar + while (((__inb(smbusbase + 1) & 0x01) == 0) || + ((__inb(smbusbase + 1) & 0x08) != 0)) { // wait til command finished + rdtsc(l2, h2); + t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / vv->clks_msec; + if (t > 10) break; // break after 10ms + } + return __inb(smbusbase + 6); +} + +static int us15w_read_spd(int dimmadr) +{ + int x; + spd_raw[0] = us15w_smb_read_byte(0x50 + dimmadr, 0); + if (spd_raw[0] == 0xff) return -1; // no spd here + for (x = 1; x < 256; x++) { + spd_raw[x] = us15w_smb_read_byte(0x50 + dimmadr, (unsigned char) x); + } + return 0; +} + +struct pci_smbus_controller { + unsigned vendor; + unsigned device; + char *name; + void (*get_adr)(void); + int (*read_spd)(int dimmadr); +}; + +static struct pci_smbus_controller smbcontrollers[] = + { + // Intel SMBUS + {0x8086, 0x9C22, "Intel HSW-ULT", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x8C22, "Intel HSW", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x1E22, "Intel Z77", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x1C22, "Intel P67", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x3B30, "Intel P55", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x3A60, "Intel ICH10B", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x3A30, "Intel ICH10R", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x2930, "Intel ICH9", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x283E, "Intel ICH8", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x27DA, "Intel ICH7", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x266A, "Intel ICH6", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x24D3, "Intel ICH5", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x24C3, "Intel ICH4", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x25A4, "Intel 6300ESB", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x269B, "Intel ESB2", ich5_get_smb, ich5_read_spd}, + {0x8086, 0x8119, "Intel US15W", us15w_get_smb, us15w_read_spd}, + {0x8086, 0x5032, "Intel EP80579", ich5_get_smb, ich5_read_spd}, + + // AMD SMBUS + {0x1002, 0x4385, "AMD SB600/700", piix4_get_smb, ich5_read_spd}, + {0x1022, 0x780B, "AMD SB800/900", sb800_get_smb, ich5_read_spd}, + {0, 0, "", NULL, NULL} + }; + +int find_smb_controller(void) +{ + int i = 0; + unsigned long valuev, valued; + + for (smbdev = 0; smbdev < 32; smbdev++) { + for (smbfun = 0; smbfun < 8; smbfun++) { + pci_conf_read(0, smbdev, smbfun, 0, 2, &valuev); + if (valuev != 0xFFFF) { // if there is something look what's it.. + for (i = 0; smbcontrollers[i].vendor > 0; i++) { // check if this is a known smbus controller + if (valuev == smbcontrollers[i].vendor) { + pci_conf_read(0, smbdev, smbfun, 2, 2, &valued); // read the device id + if (valued == smbcontrollers[i].device) { + return i; + } + } + } + } + } + } + return -1; +} + +void get_spd_spec(void) +{ + int index; + int h, i, j, z; + int k = 0; + int module_size; + int curcol; + int temp_nbd; + int tck; + + index = find_smb_controller(); + + if (index == -1) + { + // Unknown SMBUS Controller, exit + return; + } + + smbcontrollers[index].get_adr(); + cprint(LINE_SPD-2, 0, "Memory SPD Informations"); + cprint(LINE_SPD-1, 0, "--------------------------"); + + for (j = 0; j < 8; j++) { + if (smbcontrollers[index].read_spd(j) == 0) { + curcol = 1; + if(spd_raw[2] == 0x0b){ + // We are here if DDR3 present + + // First print slot#, module capacity + cprint(LINE_SPD+k, curcol, " - Slot :"); + dprint(LINE_SPD+k, curcol+8, k, 1, 0); + + module_size = get_ddr3_module_size(spd_raw[4] & 0xF, spd_raw[8] & 0x7, spd_raw[7] & 0x7, spd_raw[7] >> 3); + temp_nbd = getnum(module_size); curcol += 12; + dprint(LINE_SPD+k, curcol, module_size, temp_nbd, 0); curcol += temp_nbd; + cprint(LINE_SPD+k, curcol, " MB"); curcol += 4; + + // If XMP is supported, check Tck in XMP reg + if(spd_raw[176] == 0x0C && spd_raw[177] == 0x4A && spd_raw[12]) + { + tck = spd_raw[186]; + } else { + tck = spd_raw[12]; + } + + // Then module jedec speed + switch(tck) + { + default: + cprint(LINE_SPD+k, curcol, "DDR3-????"); + break; + case 20: + cprint(LINE_SPD+k, curcol, "DDR3-800"); + curcol--; + break; + case 15: + cprint(LINE_SPD+k, curcol, "DDR3-1066"); + break; + case 12: + cprint(LINE_SPD+k, curcol, "DDR3-1333"); + break; + case 10: + cprint(LINE_SPD+k, curcol, "DDR3-1600"); + break; + case 9: + cprint(LINE_SPD+k, curcol, "DDR3-1866"); + break; + case 8: + cprint(LINE_SPD+k, curcol, "DDR3-2133"); + break; + case 7: + cprint(LINE_SPD+k, curcol, "DDR3-2400"); + break; + case 6: + cprint(LINE_SPD+k, curcol, "DDR3-2533"); + break; + case 5: + cprint(LINE_SPD+k, curcol, "DDR3-2666"); + break; + } + + curcol += 10; + + if((spd_raw[8] >> 3) == 1) { cprint(LINE_SPD+k, curcol, "ECC"); curcol += 4; } + + // Then print module infos (manufacturer & part number) + spd_raw[117] &= 0x0F; // Parity odd or even + for (i = 0; jep106[i].cont_code < 9; i++) { + if (spd_raw[117] == jep106[i].cont_code && spd_raw[118] == jep106[i].hex_byte) { + // We are here if a Jedec manufacturer is detected + cprint(LINE_SPD+k, curcol, "-"); curcol += 2; + cprint(LINE_SPD+k, curcol, jep106[i].name); + for(z = 0; jep106[i].name[z] != '\0'; z++) { curcol++; } + curcol++; + // Display module serial number + for (h = 128; h < 146; h++) { + cprint(LINE_SPD+k, curcol, convert_hex_to_char(spd_raw[h])); + curcol++; + } + + // Detect Week and Year of Manufacturing (Think to upgrade after 2015 !!!) + if(curcol <= 72 && spd_raw[120] > 3 && spd_raw[120] < 16 && spd_raw[121] < 55) + { + cprint(LINE_SPD+k, curcol, "(W"); + dprint(LINE_SPD+k, curcol+2, spd_raw[121], 2, 0); + if(spd_raw[121] < 10) { cprint(LINE_SPD+k, curcol+2, "0"); } + cprint(LINE_SPD+k, curcol+4, "'"); + dprint(LINE_SPD+k, curcol+5, spd_raw[120], 2, 0); + if(spd_raw[120] < 10) { cprint(LINE_SPD+k, curcol+5, "0"); } + cprint(LINE_SPD+k, curcol+7, ")"); + curcol += 9; + } + + // Detect XMP Memory + if(spd_raw[176] == 0x0C && spd_raw[177] == 0x4A) + { + cprint(LINE_SPD+k, curcol, "*XMP*"); + } + } + } + } + // We enter this function if DDR2 is detected + if(spd_raw[2] == 0x08){ + // First print slot#, module capacity + cprint(LINE_SPD+k, curcol, " - Slot :"); + dprint(LINE_SPD+k, curcol+8, k, 1, 0); + + module_size = get_ddr2_module_size(spd_raw[31], spd_raw[5]); + temp_nbd = getnum(module_size); curcol += 12; + dprint(LINE_SPD+k, curcol, module_size, temp_nbd, 0); curcol += temp_nbd; + cprint(LINE_SPD+k, curcol, " MB"); curcol += 4; + + // Then module jedec speed + float ddr2_speed, byte1, byte2; + + byte1 = (spd_raw[9] >> 4) * 10; + byte2 = spd_raw[9] & 0xF; + + ddr2_speed = 1 / (byte1 + byte2) * 10000 * 2; + + temp_nbd = getnum(ddr2_speed); + cprint(LINE_SPD+k, curcol, "DDR2-"); curcol += 5; + dprint(LINE_SPD+k, curcol, ddr2_speed, temp_nbd, 0); curcol += temp_nbd; + + if((spd_raw[11] >> 1) == 1) { cprint(LINE_SPD+k, curcol+1, "ECC"); curcol += 4; } + + // Then print module infos (manufacturer & part number) + int ccode = 0; + + for(i = 64; i < 72; i++) + { + if(spd_raw[i] == 0x7F) { ccode++; } + } + + curcol++; + + for (i = 0; jep106[i].cont_code < 9; i++) { + if (ccode == jep106[i].cont_code && spd_raw[64+ccode] == jep106[i].hex_byte) { + // We are here if a Jedec manufacturer is detected + cprint(LINE_SPD+k, curcol, "-"); curcol += 2; + cprint(LINE_SPD+k, curcol, jep106[i].name); + for(z = 0; jep106[i].name[z] != '\0'; z++) { curcol++; } + curcol++; + // Display module serial number + for (h = 73; h < 91; h++) { + cprint(LINE_SPD+k, curcol, convert_hex_to_char(spd_raw[h])); + curcol++; + } + } + } + } + k++; + } + } +} + +void show_spd(void) +{ + int index; + int i, j; + int flag = 0; + pop2up(); + wait_keyup(); + index = find_smb_controller(); + if (index == -1) { + cprint(POP2_Y, POP2_X+1, "SMBus Controller not known"); + while (!get_key()); + wait_keyup(); + pop2down(); + return; + } + else cprint(POP2_Y, POP2_X+1, "SPD Data: Slot"); + smbcontrollers[index].get_adr(); + for (j = 0; j < 16; j++) { + if (smbcontrollers[index].read_spd(j) == 0) { + dprint(POP2_Y, POP2_X + 15, j, 2, 0); + for (i = 0; i < 256; i++) { + hprint2(2 + POP2_Y + i / 16, 3 + POP2_X + (i % 16) * 3, spd_raw[i], 2); + } + flag = 0; + while(!flag) { + if (get_key()) flag++; + } + wait_keyup(); + } + } + pop2down(); +} + +int get_ddr3_module_size(int sdram_capacity, int prim_bus_width, int sdram_width, int ranks) +{ + int module_size; + + switch(sdram_capacity) + { + case 0: + module_size = 256; + break; + case 1: + module_size = 512; + break; + default: + case 2: + module_size = 1024; + break; + case 3: + module_size = 2048; + break; + case 4: + module_size = 4096; + break; + case 5: + module_size = 8192; + break; + case 6: + module_size = 16384; + break; + } + + module_size /= 8; + + switch(prim_bus_width) + { + case 0: + module_size *= 8; + break; + case 1: + module_size *= 16; + break; + case 2: + module_size *= 32; + break; + case 3: + module_size *= 64; + break; + } + + switch(sdram_width) + { + case 0: + module_size /= 4; + break; + case 1: + module_size /= 8; + break; + case 2: + module_size /= 16; + break; + case 3: + module_size /= 32; + break; + + } + + module_size *= (ranks + 1); + + return module_size; +} + + +int get_ddr2_module_size(int rank_density_byte, int rank_num_byte) +{ + int module_size; + + switch(rank_density_byte) + { + case 1: + module_size = 1024; + break; + case 2: + module_size = 2048; + break; + case 4: + module_size = 4096; + break; + case 8: + module_size = 8192; + break; + case 16: + module_size = 16384; + break; + case 32: + module_size = 128; + break; + case 64: + module_size = 256; + break; + default: + case 128: + module_size = 512; + break; + } + + module_size *= (rank_num_byte & 7) + 1; + + return module_size; + +} + + +struct ascii_map { + unsigned hex_code; + char *name; +}; + + +char* convert_hex_to_char(unsigned hex_org) { + static char buf[2] = " "; + if (hex_org >= 0x20 && hex_org < 0x80) { + buf[0] = hex_org; + } else { + //buf[0] = '\0'; + buf[0] = ' '; + } + + return buf; +} diff --git a/memtestEDK/Memtest/SingleComponents/spd.h b/memtestEDK/Memtest/SingleComponents/spd.h new file mode 100644 index 0000000..55f164f --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/spd.h @@ -0,0 +1,17 @@ +/* + * MemTest86+ V5.00 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + */ + +#define AMD_INDEX_IO_PORT 0xCD6 +#define AMD_DATA_IO_PORT 0xCD7 +#define AMD_SMBUS_BASE_REG 0x2C + +void get_spd_spec(void); +int get_ddr2_module_size(int rank_density_byte, int rank_num_byte); +int get_ddr3_module_size(int sdram_capacity, int prim_bus_width, int sdram_width, int ranks); +char* convert_hex_to_char(unsigned hex_org); +void sb800_get_smb(void); + + diff --git a/memtestEDK/Memtest/SingleComponents/stddef.h b/memtestEDK/Memtest/SingleComponents/stddef.h new file mode 100644 index 0000000..e835dc8 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/stddef.h @@ -0,0 +1,10 @@ +#ifndef I386_STDDEF_H +#define I386_STDDEF_H +/* +#ifndef UEFI +#define NULL ((void *)0) +#endif*/ + +typedef unsigned long size_t; + +#endif /* I386_STDDEF_H */ diff --git a/memtestEDK/Memtest/SingleComponents/stdin.h b/memtestEDK/Memtest/SingleComponents/stdin.h new file mode 100644 index 0000000..e3a08e1 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/stdin.h @@ -0,0 +1,52 @@ +#ifndef I386_STDINT_H +#define I386_STDINT_H + +/* Exact integral types */ +typedef unsigned char uint8_t; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned long long uint64_t; +typedef signed long long int64_t; + +/* Small types */ +typedef unsigned char uint_least8_t; +typedef signed char int_least8_t; + +typedef unsigned short uint_least16_t; +typedef signed short int_least16_t; + +typedef unsigned int uint_least32_t; +typedef signed int int_least32_t; + +typedef unsigned long long uint_least64_t; +typedef signed long long int_least64_t; + +/* Fast Types */ +typedef unsigned char uint_fast8_t; +typedef signed char int_fast8_t; + +typedef unsigned int uint_fast16_t; +typedef signed int int_fast16_t; + +typedef unsigned int uint_fast32_t; +typedef signed int int_fast32_t; + +typedef unsigned long long uint_fast64_t; +typedef signed long long int_fast64_t; + +/* Types for `void *' pointers. */ +typedef int intptr_t; +typedef unsigned int uintptr_t; + +/* Largest integral types */ +typedef long long int intmax_t; +typedef unsigned long long uintmax_t; + + +#endif /* I386_STDINT_H */
\ No newline at end of file diff --git a/memtestEDK/Memtest/SingleComponents/stdint.h b/memtestEDK/Memtest/SingleComponents/stdint.h new file mode 100644 index 0000000..1c136e0 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/stdint.h @@ -0,0 +1,60 @@ +#ifndef I386_STDINT_H +#define I386_STDINT_H + +/* Exact integral types */ +typedef unsigned char uint8_t; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned long long uint64_t; +typedef signed long long int64_t; + +/* Small types */ +typedef unsigned char uint_least8_t; +typedef signed char int_least8_t; + +typedef unsigned short uint_least16_t; +typedef signed short int_least16_t; + +typedef unsigned int uint_least32_t; +typedef signed int int_least32_t; + +typedef unsigned long long uint_least64_t; +typedef signed long long int_least64_t; + +/* Fast Types */ +typedef unsigned char uint_fast8_t; +typedef signed char int_fast8_t; + +typedef unsigned int uint_fast16_t; +typedef signed int int_fast16_t; + +typedef unsigned int uint_fast32_t; +typedef signed int int_fast32_t; + +typedef unsigned long long uint_fast64_t; +typedef signed long long int_fast64_t; + +/* Types for `void *' pointers. */ +typedef int intptr_t; +typedef unsigned int uintptr_t; + +/* Largest integral types */ +typedef long long int intmax_t; +typedef unsigned long long uintmax_t; + +typedef char bool; +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#endif /* I386_STDINT_H */ diff --git a/memtestEDK/Memtest/SingleComponents/test.c b/memtestEDK/Memtest/SingleComponents/test.c new file mode 100644 index 0000000..864dfcc --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/test.c @@ -0,0 +1,1549 @@ +/* test.c - MemTest-86 Version 3.4 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + * ---------------------------------------------------- + * MemTest86+ V5 Specific code (GPL V2.0) + * By Samuel DEMEULEMEESTER, sdemeule@memtest.org + * http://www.canardpc.com - http://www.memtest.org + * Thanks to Passmark for calculate_chunk() and various comments ! + */ + +#include "test.h" +#include "config.h" +#include "stdint.h" +#include "cpuid.h" +#include "smp.h" +#include "io.h" + +extern struct cpu_ident cpu_id; +extern volatile int mstr_cpu; +extern volatile int run_cpus; +extern volatile int test; +extern volatile int segs, bail; +extern int test_ticks, nticks; +extern struct tseq tseq[]; +extern void update_err_counts(void); +extern void print_err_counts(void); +void rand_seed( unsigned int seed1, unsigned int seed2, int me); +ulong rand(int me); +void poll_errors(); + +// NOTE(jcoiner): +// Defining 'STATIC' to empty string results in crashes. (It should +// work fine, of course.) I suspect relocation problems in reloc.c. +// When we declare these routines static, we use relative addresses +// for them instead of looking up their addresses in (supposedly +// relocated) global elf tables, which avoids the crashes. + +#define STATIC static +//#define STATIC + +#define PREFER_C 0 + +static const void* const nullptr = 0x0; + +// Writes *start and *end with the VA range to test. +// +// me - this threads CPU number +// j - index into v->map for current segment we are testing +// align - number of bytes to align each block to +STATIC void calculate_chunk(ulong** start, ulong** end, int me, + int j, int makeMultipleOf) { + ulong chunk; + + // If we are only running 1 CPU then test the whole block + if (run_cpus == 1) { + *start = vv->map[j].start; + *end = vv->map[j].end; + } else { + + // Divide the current segment by the number of CPUs + chunk = (ulong)vv->map[j].end-(ulong)vv->map[j].start; + chunk /= run_cpus; + + // Round down to the nearest desired bitlength multiple + chunk = (chunk + (makeMultipleOf-1)) & ~(makeMultipleOf-1); + + // Figure out chunk boundaries + *start = (ulong*)((ulong)vv->map[j].start+(chunk*me)); + /* Set end addrs for the highest CPU num to the + * end of the segment for rounding errors */ + /* Also rounds down to boundary if needed, may miss some ram but + better than crashing or producing false errors. */ + /* This rounding probably will never happen as the segments should + be in 4096 bytes pages if I understand correctly. */ + if (me == mstr_cpu) { + *end = (ulong*)(vv->map[j].end); + } else { + *end = (ulong*)((ulong)(*start) + chunk); + (*end)--; + } + } +} + +/* Call segment_fn() for each up-to-SPINSZ segment between + * 'start' and 'end'. + */ +void foreach_segment +(ulong* start, ulong* end, + int me, const void* ctx, segment_fn func) { + + ASSERT(start < end); + + // Confirm 'start' points to an even dword, and 'end' + // should point to an odd dword + ASSERT(0 == (((ulong)start) & 0x7)); + ASSERT(0x4 == (((ulong)end) & 0x7)); + + // 'end' may be exactly 0xfffffffc, right at the 4GB boundary. + // + // To avoid overflow in our loop tests and length calculations, + // use dword indices (the '_dw' vars) to avoid overflows. + ulong start_dw = ((ulong)start) >> 2; + ulong end_dw = ((ulong) end) >> 2; + + // end is always xxxxxffc, but increment end_dw to an + // address beyond the segment for easier boundary calculations. + ++end_dw; + + ulong seg_dw = start_dw; + ulong seg_end_dw = start_dw; + + int done = 0; + do { + do_tick(me); + { BAILR } + + // ensure no overflow + ASSERT((seg_end_dw + SPINSZ_DWORDS) > seg_end_dw); + seg_end_dw += SPINSZ_DWORDS; + + if (seg_end_dw >= end_dw) { + seg_end_dw = end_dw; + done++; + } + if (seg_dw == seg_end_dw) { + break; + } + + ASSERT(((ulong)seg_end_dw) <= 0x40000000); + ASSERT(seg_end_dw > seg_dw); + ulong seg_len_dw = seg_end_dw - seg_dw; + + func((ulong*)(seg_dw << 2), seg_len_dw, ctx); + + seg_dw = seg_end_dw; + } while (!done); +} + +/* Calls segment_fn() for each segment in vv->map. + * + * Does not slice by CPU number, so it covers the entire memory. + * Contrast to sliced_foreach_segment(). + */ +STATIC void unsliced_foreach_segment +(const void* ctx, int me, segment_fn func) { + int j; + for (j=0; j<segs; j++) { + foreach_segment(vv->map[j].start, + vv->map[j].end, + me, ctx, func); + } +} + +/* Calls segment_fn() for each segment to be tested by CPU 'me'. + * + * In multicore mode, slices the segments by 'me' (the CPU ordinal + * number) so that each call will cover only 1/Nth of memory. + */ +STATIC void sliced_foreach_segment +(const void *ctx, int me, segment_fn func) { + int j; + ulong *start, *end; // VAs + ulong* prev_end = 0; + for (j=0; j<segs; j++) { + calculate_chunk(&start, &end, me, j, 64); + + // Ensure no overlap among chunks + ASSERT(end > start); + if (prev_end > 0) { + ASSERT(prev_end < start); + } + prev_end = end; + + foreach_segment(start, end, me, ctx, func); + } +} + +STATIC void addr_tst1_seg(ulong* restrict buf, + ulong len_dw, const void* unused) { + // Within each segment: + // - choose a low dword offset 'off' + // - write pat to *off + // - write ~pat to addresses that are above off by + // 1, 2, 4, ... dwords up to the top of the segment. None + // should alias to the original dword. + // - write ~pat to addresses that are below off by + // 1, 2, 4, etc dwords, down to the start of the segment. None + // should alias to the original dword. If adding a given offset + // doesn't produce a single bit address flip (because it produced + // a carry) subtracting the same offset should give a single bit flip. + // - repeat this, moving off ahead in increments of 1MB; + // this covers address bits within physical memory banks, we hope? + + ulong pat; + int k; + + for (pat=0x5555aaaa, k=0; k<2; k++) { + hprint(LINE_PAT, COL_PAT, pat); + + for (ulong off_dw = 0; off_dw < len_dw; off_dw += (1 << 18)) { + buf[off_dw] = pat; + pat = ~pat; + + for (ulong more_off_dw = 1; off_dw + more_off_dw < len_dw; + more_off_dw = more_off_dw << 1) { + ASSERT(more_off_dw); // it should never get to zero + buf[off_dw + more_off_dw] = pat; + ulong bad; + if ((bad = buf[off_dw]) != ~pat) { + ad_err1(buf + off_dw, + buf + off_dw + more_off_dw, + bad, ~pat); + break; + } + } + for (ulong more_off_dw = 1; off_dw > more_off_dw; + more_off_dw = more_off_dw << 1) { + ASSERT(more_off_dw); // it should never get to zero + buf[off_dw - more_off_dw] = pat; + ulong bad; + if ((bad = buf[off_dw]) != ~pat) { + ad_err1(buf + off_dw, + buf + off_dw - more_off_dw, + bad, ~pat); + break; + } + } + } + } +} + +/* + * Memory address test, walking ones + */ +void addr_tst1(int me) +{ + unsliced_foreach_segment(nullptr, me, addr_tst1_seg); +} + +STATIC void addr_tst2_init_segment(ulong* p, + ulong len_dw, const void* unused) { + ulong* pe = p + (len_dw - 1); + + /* Original C code replaced with hand tuned assembly code + * for (; p <= pe; p++) { + * *p = (ulong)p; + * } + */ + asm __volatile__ ( + "jmp L91\n\t" + ".p2align 4,,7\n\t" + "L90:\n\t" + "addl $4,%%edi\n\t" + "L91:\n\t" + "movl %%edi,(%%edi)\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L90\n\t" + : : "D" (p), "d" (pe) + ); +} + +STATIC void addr_tst2_check_segment(ulong* p, + ulong len_dw, const void* unused) { + ulong* pe = p + (len_dw - 1); + + /* Original C code replaced with hand tuned assembly code + * for (; p <= pe; p++) { + * if((bad = *p) != (ulong)p) { + * ad_err2((ulong)p, bad); + * } + * } + */ + asm __volatile__ + ( + "jmp L95\n\t" + ".p2align 4,,7\n\t" + "L99:\n\t" + "addl $4,%%edi\n\t" + "L95:\n\t" + "movl (%%edi),%%ecx\n\t" + "cmpl %%edi,%%ecx\n\t" + "jne L97\n\t" + "L96:\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L99\n\t" + "jmp L98\n\t" + + "L97:\n\t" + "pushl %%edx\n\t" + "pushl %%ecx\n\t" + "pushl %%edi\n\t" + "call ad_err2\n\t" + "popl %%edi\n\t" + "popl %%ecx\n\t" + "popl %%edx\n\t" + "jmp L96\n\t" + + "L98:\n\t" + : : "D" (p), "d" (pe) + : "ecx" + ); +} + +/* + * Memory address test, own address + */ +void addr_tst2(int me) +{ + cprint(LINE_PAT, COL_PAT, "address "); + + /* Write each address with its own address */ + unsliced_foreach_segment(nullptr, me, addr_tst2_init_segment); + { BAILR } + + /* Each address should have its own address */ + unsliced_foreach_segment(nullptr, me, addr_tst2_check_segment); +} + +typedef struct { + int me; + ulong xorVal; +} movinvr_ctx; + +STATIC void movinvr_init(ulong* p, + ulong len_dw, const void* vctx) { + ulong* pe = p + (len_dw - 1); + const movinvr_ctx* ctx = (const movinvr_ctx*)vctx; + /* Original C code replaced with hand tuned assembly code */ + /* + for (; p <= pe; p++) { + *p = rand(me); + } + */ + + asm __volatile__ + ( + "jmp L200\n\t" + ".p2align 4,,7\n\t" + "L201:\n\t" + "addl $4,%%edi\n\t" + "L200:\n\t" + "pushl %%ecx\n\t" + "call rand\n\t" + "popl %%ecx\n\t" + "movl %%eax,(%%edi)\n\t" + "cmpl %%ebx,%%edi\n\t" + "jb L201\n\t" + : : "D" (p), "b" (pe), "c" (ctx->me) + : "eax" + ); +} + +STATIC void movinvr_body(ulong* p, ulong len_dw, const void* vctx) { + ulong* pe = p + (len_dw - 1); + const movinvr_ctx* ctx = (const movinvr_ctx*)vctx; + + /* Original C code replaced with hand tuned assembly code */ + + /*for (; p <= pe; p++) { + num = rand(me); + if (i) { + num = ~num; + } + if ((bad=*p) != num) { + mt86_error((ulong*)p, num, bad); + } + *p = ~num; + }*/ + + asm __volatile__ + ( + "pushl %%ebp\n\t" + + // Skip first increment + "jmp L26\n\t" + ".p2align 4,,7\n\t" + + // increment 4 bytes (32-bits) + "L27:\n\t" + "addl $4,%%edi\n\t" + + // Check this byte + "L26:\n\t" + + // Get next random number, pass in me(edx), random value returned in num(eax) + // num = rand(me); + // cdecl call maintains all registers except eax, ecx, and edx + // We maintain edx with a push and pop here using it also as an input + // we don't need the current eax value and want it to change to the return value + // we overwrite ecx shortly after this discarding its current value + "pushl %%edx\n\t" // Push function inputs onto stack + "call rand\n\t" + "popl %%edx\n\t" // Remove function inputs from stack + + // XOR the random number with xorVal(ebx), which is either 0xffffffff or 0 depending on the outer loop + // if (i) { num = ~num; } + "xorl %%ebx,%%eax\n\t" + + // Move the current value of the current position p(edi) into bad(ecx) + // (bad=*p) + "movl (%%edi),%%ecx\n\t" + + // Compare bad(ecx) to num(eax) + "cmpl %%eax,%%ecx\n\t" + + // If not equal jump the error case + "jne L23\n\t" + + // Set a new value or not num(eax) at the current position p(edi) + // *p = ~num; + "L25:\n\t" + "movl $0xffffffff,%%ebp\n\t" + "xorl %%ebp,%%eax\n\t" + "movl %%eax,(%%edi)\n\t" + + // Loop until current position p(edi) equals the end position pe(esi) + "cmpl %%esi,%%edi\n\t" + "jb L27\n\t" + "jmp L24\n" + + // Error case + "L23:\n\t" + // Must manually maintain eax, ecx, and edx as part of cdecl call convention + "pushl %%edx\n\t" + "pushl %%ecx\n\t" // Next three pushes are functions input + "pushl %%eax\n\t" + "pushl %%edi\n\t" + "call mt86_error\n\t" + "popl %%edi\n\t" // Remove function inputs from stack and restore register values + "popl %%eax\n\t" + "popl %%ecx\n\t" + "popl %%edx\n\t" + "jmp L25\n" + + "L24:\n\t" + "popl %%ebp\n\t" + :: "D" (p), "S" (pe), "b" (ctx->xorVal), + "d" (ctx->me) + : "eax", "ecx" + ); +} + +/* + * Test all of memory using a "half moving inversions" algorithm using random + * numbers and their complement as the data pattern. Since we are not able to + * produce random numbers in reverse order testing is only done in the forward + * direction. + */ +void movinvr(int me) +{ + int i, seed1, seed2; + + movinvr_ctx ctx; + ctx.me = me; + ctx.xorVal = 0; + + /* Initialize memory with initial sequence of random numbers. */ + if (cpu_id.fid.bits.rdtsc) { + asm __volatile__ ("rdtsc":"=a" (seed1),"=d" (seed2)); + } else { + seed1 = 521288629 + vv->pass; + seed2 = 362436069 - vv->pass; + } + + /* Display the current seed */ + if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, seed1); + rand_seed(seed1, seed2, me); + + sliced_foreach_segment(&ctx, me, movinvr_init); + { BAILR } + + /* Do moving inversions test. Check for initial pattern and then + * write the complement for each memory location. + */ + for (i=0; i<2; i++) { + rand_seed(seed1, seed2, me); + + if (i) { + ctx.xorVal = 0xffffffff; + } else { + ctx.xorVal = 0; + } + + sliced_foreach_segment(&ctx, me, movinvr_body); + { BAILR } + } +} + +typedef struct { + ulong p1; + ulong p2; +} movinv1_ctx; + +STATIC void movinv1_init(ulong* start, + ulong len_dw, const void* vctx) { + const movinv1_ctx* ctx = (const movinv1_ctx*)vctx; + + ulong p1 = ctx->p1; + ulong* p = start; + + asm __volatile__ + ( + "rep\n\t" + "stosl\n\t" + : : "c" (len_dw), "D" (p), "a" (p1) + ); +} + +STATIC void movinv1_bottom_up(ulong* start, + ulong len_dw, const void* vctx) { + const movinv1_ctx* ctx = (const movinv1_ctx*)vctx; + ulong p1 = ctx->p1; + ulong p2 = ctx->p2; + ulong* p = start; + ulong* pe = p + (len_dw - 1); + + // Original C code replaced with hand tuned assembly code + // seems broken + /*for (; p <= pe; p++) { + if ((bad=*p) != p1) { + mt86_error((ulong*)p, p1, bad); + } + *p = p2; + }*/ + + asm __volatile__ + ( + "jmp L2\n\t" + ".p2align 4,,7\n\t" + "L0:\n\t" + "addl $4,%%edi\n\t" + "L2:\n\t" + "movl (%%edi),%%ecx\n\t" + "cmpl %%eax,%%ecx\n\t" + "jne L3\n\t" + "L5:\n\t" + "movl %%ebx,(%%edi)\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L0\n\t" + "jmp L4\n" + + "L3:\n\t" + "pushl %%edx\n\t" + "pushl %%ebx\n\t" + "pushl %%ecx\n\t" + "pushl %%eax\n\t" + "pushl %%edi\n\t" + "call mt86_error\n\t" + "popl %%edi\n\t" + "popl %%eax\n\t" + "popl %%ecx\n\t" + "popl %%ebx\n\t" + "popl %%edx\n\t" + "jmp L5\n" + + "L4:\n\t" + :: "a" (p1), "D" (p), "d" (pe), "b" (p2) + : "ecx" + ); +} + +STATIC void movinv1_top_down(ulong* start, + ulong len_dw, const void* vctx) { + const movinv1_ctx* ctx = (const movinv1_ctx*)vctx; + ulong p1 = ctx->p1; + ulong p2 = ctx->p2; + ulong* p = start + (len_dw - 1); + ulong* pe = start; + + //Original C code replaced with hand tuned assembly code + // seems broken + /*do { + if ((bad=*p) != p2) { + mt86_error((ulong*)p, p2, bad); + } + *p = p1; + } while (--p >= pe);*/ + + asm __volatile__ + ( + "jmp L9\n\t" + ".p2align 4,,7\n\t" + "L11:\n\t" + "subl $4, %%edi\n\t" + "L9:\n\t" + "movl (%%edi),%%ecx\n\t" + "cmpl %%ebx,%%ecx\n\t" + "jne L6\n\t" + "L10:\n\t" + "movl %%eax,(%%edi)\n\t" + "cmpl %%edi, %%edx\n\t" + "jne L11\n\t" + "jmp L7\n\t" + + "L6:\n\t" + "pushl %%edx\n\t" + "pushl %%eax\n\t" + "pushl %%ecx\n\t" + "pushl %%ebx\n\t" + "pushl %%edi\n\t" + "call mt86_error\n\t" + "popl %%edi\n\t" + "popl %%ebx\n\t" + "popl %%ecx\n\t" + "popl %%eax\n\t" + "popl %%edx\n\t" + "jmp L10\n" + + "L7:\n\t" + :: "a" (p1), "D" (p), "d" (pe), "b" (p2) + : "ecx" + ); +} + +/* + * Test all of memory using a "moving inversions" algorithm using the + * pattern in p1 and its complement in p2. + */ +void movinv1 (int iter, ulong p1, ulong p2, int me) +{ + int i; + + /* Display the current pattern */ + if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, p1); + + movinv1_ctx ctx; + ctx.p1 = p1; + ctx.p2 = p2; + sliced_foreach_segment(&ctx, me, movinv1_init); + { BAILR } + + /* Do moving inversions test. Check for initial pattern and then + * write the complement for each memory location. Test from bottom + * up and then from the top down. */ + for (i=0; i<iter; i++) { + sliced_foreach_segment(&ctx, me, movinv1_bottom_up); + { BAILR } + + // NOTE(jcoiner): + // For the top-down pass, the original 5.01 code iterated over + // 'segs' in from n-1 down to 0, and then within each mapped segment, + // it would form the SPINSZ windows from the top down -- thus forming + // a different set of windows than the bottom-up pass, when the segment + // is not an integer number of windows. + // + // My guess is that this buys us very little additional coverage, that + // the value in going top-down happens at the word or cache-line level + // and that there's little to be gained from reversing the direction of + // the outer loops. So I'm leaving a 'direction' bit off of the + // foreach_segment() routines for now. + sliced_foreach_segment(&ctx, me, movinv1_top_down); + { BAILR } + } +} + +typedef struct { + ulong p1; + ulong lb; + ulong hb; + int sval; + int off; +} movinv32_ctx; + +STATIC void movinv32_init(ulong* restrict buf, + ulong len_dw, const void* vctx) { + const movinv32_ctx* restrict ctx = (const movinv32_ctx*)vctx; + + ulong* p = buf; + ulong* pe = buf + (len_dw - 1); + + int k = ctx->off; + ulong pat = ctx->p1; + ulong lb = ctx->lb; + int sval = ctx->sval; + + /* Original C code replaced with hand tuned assembly code + * while (p <= pe) { + * *p = pat; + * if (++k >= 32) { + * pat = lb; + * k = 0; + * } else { + * pat = pat << 1; + * pat |= sval; + * } + * p++; + * } + */ + asm __volatile__ + ( + "jmp L20\n\t" + ".p2align 4,,7\n\t" + "L923:\n\t" + "addl $4,%%edi\n\t" + "L20:\n\t" + "movl %%ecx,(%%edi)\n\t" + "addl $1,%%ebx\n\t" + "cmpl $32,%%ebx\n\t" + "jne L21\n\t" + "movl %%esi,%%ecx\n\t" + "xorl %%ebx,%%ebx\n\t" + "jmp L22\n" + "L21:\n\t" + "shll $1,%%ecx\n\t" + "orl %%eax,%%ecx\n\t" + "L22:\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L923\n\t" + :: "D" (p),"d" (pe),"b" (k),"c" (pat), + "a" (sval), "S" (lb) + ); +} + +STATIC void movinv32_bottom_up(ulong* restrict buf, ulong len_dw, + const void* vctx) { + const movinv32_ctx* restrict ctx = (const movinv32_ctx*)vctx; + + ulong* p = buf; + ulong* pe = buf + (len_dw - 1); + + int k = ctx->off; + ulong pat = ctx->p1; + ulong lb = ctx->lb; + int sval = ctx->sval; + + /* Original C code replaced with hand tuned assembly code + * while (1) { + * if ((bad=*p) != pat) { + * mt86_error((ulong*)p, pat, bad); + * } + * *p = ~pat; + * if (p >= pe) break; + * p++; + * + * if (++k >= 32) { + * pat = lb; + * k = 0; + * } else { + * pat = pat << 1; + * pat |= sval; + * } + * } + */ + asm __volatile__ + ( + "pushl %%ebp\n\t" + "jmp L30\n\t" + ".p2align 4,,7\n\t" + "L930:\n\t" + "addl $4,%%edi\n\t" + "L30:\n\t" + "movl (%%edi),%%ebp\n\t" + "cmpl %%ecx,%%ebp\n\t" + "jne L34\n\t" + + "L35:\n\t" + "notl %%ecx\n\t" + "movl %%ecx,(%%edi)\n\t" + "notl %%ecx\n\t" + "incl %%ebx\n\t" + "cmpl $32,%%ebx\n\t" + "jne L31\n\t" + "movl %%esi,%%ecx\n\t" + "xorl %%ebx,%%ebx\n\t" + "jmp L32\n" + "L31:\n\t" + "shll $1,%%ecx\n\t" + "orl %%eax,%%ecx\n\t" + "L32:\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L930\n\t" + "jmp L33\n\t" + + "L34:\n\t" + "pushl %%esi\n\t" + "pushl %%eax\n\t" + "pushl %%ebx\n\t" + "pushl %%edx\n\t" + "pushl %%ebp\n\t" + "pushl %%ecx\n\t" + "pushl %%edi\n\t" + "call mt86_error\n\t" + "popl %%edi\n\t" + "popl %%ecx\n\t" + "popl %%ebp\n\t" + "popl %%edx\n\t" + "popl %%ebx\n\t" + "popl %%eax\n\t" + "popl %%esi\n\t" + "jmp L35\n" + + "L33:\n\t" + "popl %%ebp\n\t" + : "=b" (k),"=c" (pat) + : "D" (p),"d" (pe),"b" (k),"c" (pat), + "a" (sval), "S" (lb) + ); +} + +STATIC void movinv32_top_down(ulong* restrict buf, + ulong len_dw, const void* vctx) { + const movinv32_ctx* restrict ctx = (const movinv32_ctx*)vctx; + + ulong* pe = buf; + ulong* p = buf + (len_dw - 1); + + int k = ctx->off; + ulong pat = ctx->p1; + ulong hb = ctx->hb; + int sval = ctx->sval; + ulong p3 = (ulong)sval << 31; + + // Advance 'k' and 'pat' to where they would have been + // at the end of the corresponding bottom_up segment. + // + // The '-1' is because we didn't advance 'k' or 'pat' + // on the final bottom_up loop, so they're off by one... + ulong mod_len = (len_dw - 1) % 32; + for (int i = 0; i < mod_len; i++) { + if (++k >= 32) { + pat = ctx->lb; + k = 0; + } else { + pat = pat << 1; + pat |= sval; + } + } + + // Increment 'k' only because the code below has an off-by-one + // interpretation of 'k' relative to the bottom_up routine. + // There it ranges from 0:31, and here it ranges from 1:32. + k++; + + /* Original C code replaced with hand tuned assembly code */ +#if PREFER_C + ulong bad; + while(1) { + if ((bad=*p) != ~pat) { + mt86_error((ulong*)p, ~pat, bad); + } + *p = pat; + if (p <= pe) break; + p--; + + if (--k <= 0) { + k = 32; + pat = hb; + } else { + pat = pat >> 1; + pat |= p3; + } + }; +#else + asm __volatile__ + ( + "pushl %%ebp\n\t" + "jmp L40\n\t" + ".p2align 4,,7\n\t" + "L49:\n\t" + "subl $4,%%edi\n\t" + "L40:\n\t" + "movl (%%edi),%%ebp\n\t" + "notl %%ecx\n\t" + "cmpl %%ecx,%%ebp\n\t" + "jne L44\n\t" + + "L45:\n\t" + "notl %%ecx\n\t" + "movl %%ecx,(%%edi)\n\t" + "decl %%ebx\n\t" + "cmpl $0,%%ebx\n\t" + "jg L41\n\t" + "movl %%esi,%%ecx\n\t" + "movl $32,%%ebx\n\t" + "jmp L42\n" + "L41:\n\t" + "shrl $1,%%ecx\n\t" + "orl %%eax,%%ecx\n\t" + "L42:\n\t" + "cmpl %%edx,%%edi\n\t" + "ja L49\n\t" + "jmp L43\n\t" + + "L44:\n\t" + "pushl %%esi\n\t" + "pushl %%eax\n\t" + "pushl %%ebx\n\t" + "pushl %%edx\n\t" + "pushl %%ebp\n\t" + "pushl %%ecx\n\t" + "pushl %%edi\n\t" + "call mt86_error\n\t" + "popl %%edi\n\t" + "popl %%ecx\n\t" + "popl %%ebp\n\t" + "popl %%edx\n\t" + "popl %%ebx\n\t" + "popl %%eax\n\t" + "popl %%esi\n\t" + "jmp L45\n" + + "L43:\n\t" + "popl %%ebp\n\t" + : : "D" (p),"d" (pe),"b" (k),"c" (pat), + "a" (p3), "S" (hb) + ); +#endif +} + +void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off,int me) +{ + // First callsite: + // - p1 has 1 bit set (somewhere) + // - lb = 1 ("low bit") + // - hb = 0x80000000 ("high bit") + // - sval = 0 + // - 'off' indicates the position of the set bit in p1 + // + // Second callsite is the same, but inverted: + // - p1 has 1 bit clear (somewhere) + // - lb = 0xfffffffe + // - hb = 0x7fffffff + // - sval = 1 + // - 'off' indicates the position of the cleared bit in p1 + + movinv32_ctx ctx; + ctx.p1 = p1; + ctx.lb = lb; + ctx.hb = hb; + ctx.sval = sval; + ctx.off = off; + + /* Display the current pattern */ + if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, p1); + + sliced_foreach_segment(&ctx, me, movinv32_init); + { BAILR } + + /* Do moving inversions test. Check for initial pattern and then + * write the complement for each memory location. Test from bottom + * up and then from the top down. */ + for (int i=0; i<iter; i++) { + sliced_foreach_segment(&ctx, me, movinv32_bottom_up); + { BAILR } + + sliced_foreach_segment(&ctx, me, movinv32_top_down); + { BAILR } + } +} + +typedef struct { + int offset; + ulong p1; + ulong p2; +} modtst_ctx; + +STATIC void modtst_sparse_writes(ulong* restrict start, + ulong len_dw, const void* vctx) { + const modtst_ctx* restrict ctx = (const modtst_ctx*)vctx; + ulong p1 = ctx->p1; + ulong offset = ctx->offset; + +#if PREFER_C + for (ulong i = offset; i < len_dw; i += MOD_SZ) { + start[i] = p1; + } +#else + ulong* p = start + offset; + ulong* pe = start + len_dw; + asm __volatile__ + ( + "jmp L60\n\t" + ".p2align 4,,7\n\t" + + "L60:\n\t" + "movl %%eax,(%%edi)\n\t" + "addl $80,%%edi\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L60\n\t" + :: "D" (p), "d" (pe), "a" (p1) + ); +#endif +} + +STATIC void modtst_dense_writes(ulong* restrict start, ulong len_dw, + const void* vctx) { + const modtst_ctx* restrict ctx = (const modtst_ctx*)vctx; + ulong p2 = ctx->p2; + ulong offset = ctx->offset; + + ASSERT(offset < MOD_SZ); + + ulong k = 0; +#if PREFER_C + for (ulong i = 0; i < len_dw; i++) { + if (k != offset) { + start[i] = p2; + } + if (++k >= MOD_SZ) { + k = 0; + } + } +#else + ulong* pe = start + (len_dw - 1); + asm __volatile__ + ( + "jmp L50\n\t" + ".p2align 4,,7\n\t" + + "L54:\n\t" + "addl $4,%%edi\n\t" + "L50:\n\t" + "cmpl %%ebx,%%ecx\n\t" + "je L52\n\t" + "movl %%eax,(%%edi)\n\t" + "L52:\n\t" + "incl %%ebx\n\t" + "cmpl $19,%%ebx\n\t" + "jle L53\n\t" + "xorl %%ebx,%%ebx\n\t" + "L53:\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L54\n\t" + : : "D" (start), "d" (pe), "a" (p2), + "b" (k), "c" (offset) + ); +#endif +} + +STATIC void modtst_check(ulong* restrict start, + ulong len_dw, const void* vctx) { + const modtst_ctx* restrict ctx = (const modtst_ctx*)vctx; + ulong p1 = ctx->p1; + ulong offset = ctx->offset; + + ASSERT(offset < MOD_SZ); + +#if PREFER_C + ulong bad; + for (ulong i = offset; i < len_dw; i += MOD_SZ) { + if ((bad = start[i]) != p1) + mt86_error(start + i, p1, bad); + } +#else + ulong* p = start + offset; + ulong* pe = start + len_dw; + asm __volatile__ + ( + "jmp L70\n\t" + ".p2align 4,,7\n\t" + + "L70:\n\t" + "movl (%%edi),%%ecx\n\t" + "cmpl %%eax,%%ecx\n\t" + "jne L71\n\t" + "L72:\n\t" + "addl $80,%%edi\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L70\n\t" + "jmp L73\n\t" + + "L71:\n\t" + "pushl %%edx\n\t" + "pushl %%ecx\n\t" + "pushl %%eax\n\t" + "pushl %%edi\n\t" + "call mt86_error\n\t" + "popl %%edi\n\t" + "popl %%eax\n\t" + "popl %%ecx\n\t" + "popl %%edx\n\t" + "jmp L72\n" + + "L73:\n\t" + : : "D" (p), "d" (pe), "a" (p1) + : "ecx" + ); +#endif +} + +/* + * Test all of memory using modulo X access pattern. + */ +void modtst(int offset, int iter, ulong p1, ulong p2, int me) +{ + modtst_ctx ctx; + ctx.offset = offset; + ctx.p1 = p1; + ctx.p2 = p2; + + /* Display the current pattern */ + if (mstr_cpu == me) { + hprint(LINE_PAT, COL_PAT-2, p1); + cprint(LINE_PAT, COL_PAT+6, "-"); + dprint(LINE_PAT, COL_PAT+7, offset, 2, 1); + } + + /* Write every nth location with pattern */ + sliced_foreach_segment(&ctx, me, modtst_sparse_writes); + { BAILR } + + /* Write the rest of memory "iter" times with the pattern complement */ + for (ulong i=0; i<iter; i++) { + sliced_foreach_segment(&ctx, me, modtst_dense_writes); + { BAILR } + } + + /* Now check every nth location */ + sliced_foreach_segment(&ctx, me, modtst_check); +} + +#if PREFER_C + +STATIC void movsl(ulong* dest, + ulong* src, + ulong size_in_dwords) { + /* Logically equivalent to: + + for (ulong i = 0; i < size_in_dwords; i++) + dest[i] = src[i]; + + However: the movsl instruction does the entire loop + in one instruction -- this is probably how 'memcpy' + is implemented -- so hardware makes it very fast. + + Even in PREFER_C mode, we want the brute force of movsl! + */ + asm __volatile__ + ( + "cld\n" + "jmp L1189\n\t" + + ".p2align 4,,7\n\t" + "L1189:\n\t" + + "movl %1,%%edi\n\t" // dest + "movl %0,%%esi\n\t" // src + "movl %2,%%ecx\n\t" // len in dwords + "rep\n\t" + "movsl\n\t" + + :: "g" (src), "g" (dest), "g" (size_in_dwords) + : "edi", "esi", "ecx" + ); +} +#endif // PREFER_C + +STATIC ulong block_move_normalize_len_dw(ulong len_dw) { + // The block_move test works with sets of 64-byte blocks, + // so ensure our total length is a multiple of 64. + // + // In fact, since we divide the region in half, and each half-region + // is a set of 64-byte blocks, the full region should be a multiple of 128 + // bytes. + // + // Note that there's no requirement for the start address of the region to + // be 64-byte aligned, it can be any dword. + ulong result = (len_dw >> 5) << 5; + ASSERT(result > 0); + return result; +} + +STATIC void block_move_init(ulong* restrict buf, + ulong len_dw, const void* unused_ctx) { + len_dw = block_move_normalize_len_dw(len_dw); + + // Compute 'len' in units of 64-byte chunks: + ulong len = len_dw >> 4; + + // We only need to initialize len/2, since we'll just copy + // the first half onto the second half in the move step. + len = len >> 1; + + ulong base_val = 1; +#if PREFER_C + while(len > 0) { + ulong neg_val = ~base_val; + + // Set a block of 64 bytes // first block DWORDS are: + buf[0] = base_val; // 0x00000001 + buf[1] = base_val; // 0x00000001 + buf[2] = base_val; // 0x00000001 + buf[3] = base_val; // 0x00000001 + buf[4] = neg_val; // 0xfffffffe + buf[5] = neg_val; // 0xfffffffe + buf[6] = base_val; // 0x00000001 + buf[7] = base_val; // 0x00000001 + buf[8] = base_val; // 0x00000001 + buf[9] = base_val; // 0x00000001 + buf[10] = neg_val; // 0xfffffffe + buf[11] = neg_val; // 0xfffffffe + buf[12] = base_val; // 0x00000001 + buf[13] = base_val; // 0x00000001 + buf[14] = neg_val; // 0xfffffffe + buf[15] = neg_val; // 0xfffffffe + + buf += 16; // advance to next 64-byte block + len--; + + // Rotate the bit left, including an all-zero state. + // It can't hurt to have a periodicity of 33 instead of + // a power of two. + if (base_val == 0) { + base_val = 1; + } else if (base_val & 0x80000000) { + base_val = 0; + } else { + base_val = base_val << 1; + } + } +#else + asm __volatile__ + ( + "jmp L100\n\t" + + ".p2align 4,,7\n\t" + "L100:\n\t" + + // First loop eax is 0x00000001, edx is 0xfffffffe + "movl %%eax, %%edx\n\t" + "notl %%edx\n\t" + + // Set a block of 64-bytes // First loop DWORDS are + "movl %%eax,0(%%edi)\n\t" // 0x00000001 + "movl %%eax,4(%%edi)\n\t" // 0x00000001 + "movl %%eax,8(%%edi)\n\t" // 0x00000001 + "movl %%eax,12(%%edi)\n\t" // 0x00000001 + "movl %%edx,16(%%edi)\n\t" // 0xfffffffe + "movl %%edx,20(%%edi)\n\t" // 0xfffffffe + "movl %%eax,24(%%edi)\n\t" // 0x00000001 + "movl %%eax,28(%%edi)\n\t" // 0x00000001 + "movl %%eax,32(%%edi)\n\t" // 0x00000001 + "movl %%eax,36(%%edi)\n\t" // 0x00000001 + "movl %%edx,40(%%edi)\n\t" // 0xfffffffe + "movl %%edx,44(%%edi)\n\t" // 0xfffffffe + "movl %%eax,48(%%edi)\n\t" // 0x00000001 + "movl %%eax,52(%%edi)\n\t" // 0x00000001 + "movl %%edx,56(%%edi)\n\t" // 0xfffffffe + "movl %%edx,60(%%edi)\n\t" // 0xfffffffe + + // rotate left with carry, + // second loop eax is 0x00000002 + // second loop edx is (~eax) 0xfffffffd + "rcll $1, %%eax\n\t" + + // Move current position forward 64-bytes (to start of next block) + "leal 64(%%edi), %%edi\n\t" + + // Loop until end + "decl %%ecx\n\t" + "jnz L100\n\t" + + : : "D" (buf), "c" (len), "a" (base_val) + : "edx" + ); +#endif +} + +typedef struct { + int iter; + int me; +} block_move_ctx; + +STATIC void block_move_move(ulong* restrict buf, + ulong len_dw, const void* vctx) { + const block_move_ctx* restrict ctx = (const block_move_ctx*)vctx; + ulong iter = ctx->iter; + int me = ctx->me; + + len_dw = block_move_normalize_len_dw(len_dw); + + /* Now move the data around + * First move the data up half of the segment size we are testing + * Then move the data to the original location + 32 bytes + */ + ulong half_len_dw = len_dw / 2; // Half the size of this block in DWORDS + ASSERT(half_len_dw > 8); + + ulong* mid = buf + half_len_dw; // VA at mid-point of this block. + for (int i=0; i<iter; i++) { + if (i > 0) { + // foreach_segment() called this before the 0th iteration, + // so don't tick twice in quick succession. + do_tick(me); + } + { BAILR } + +#if PREFER_C + // Move first half to 2nd half: + movsl(/*dest=*/ mid, /*src=*/ buf, half_len_dw); + + // Move the second half, less the last 8 dwords + // to the first half plus an offset of 8 dwords. + movsl(/*dest=*/ buf + 8, /*src=*/ mid, half_len_dw - 8); + + // Finally, move the last 8 dwords of the 2nd half + // to the first 8 dwords of the first half. + movsl(/*dest=*/ mid + half_len_dw - 8, /*src=*/ buf, 8); +#else + asm __volatile__ + ( + "cld\n" + "jmp L110\n\t" + + ".p2align 4,,7\n\t" + "L110:\n\t" + + // + // At the end of all this + // - the second half equals the inital value of the first half + // - the first half is right shifted 32-bytes (with wrapping) + // + + // Move first half to second half + "movl %1,%%edi\n\t" // Destination 'mid' (mid point) + "movl %0,%%esi\n\t" // Source, 'buf' (start point) + "movl %2,%%ecx\n\t" // Length, 'half_len_dw' (size of a half in DWORDS) + "rep\n\t" + "movsl\n\t" + + // Move the second half, less the last 32-bytes. To the first half, offset plus 32-bytes + "movl %0,%%edi\n\t" + "addl $32,%%edi\n\t" // Destination 'buf' plus 32 bytes + "movl %1,%%esi\n\t" // Source, 'mid' + "movl %2,%%ecx\n\t" + "subl $8,%%ecx\n\t" // Length, 'half_len_dw' + "rep\n\t" + "movsl\n\t" + + // Move last 8 DWORDS (32-bytes) of the second half to the start of the first half + "movl %0,%%edi\n\t" // Destination 'buf' + // Source, 8 DWORDS from the end of the second half, left over by the last rep/movsl + "movl $8,%%ecx\n\t" // Length, 8 DWORDS (32-bytes) + "rep\n\t" + "movsl\n\t" + + :: "g" (buf), "g" (mid), "g" (half_len_dw) + : "edi", "esi", "ecx" + ); +#endif + } +} + +STATIC void block_move_check(ulong* restrict buf, + ulong len_dw, const void* unused_ctx) { + len_dw = block_move_normalize_len_dw(len_dw); + + /* Now check the data. + * This is rather crude, we just check that the + * adjacent words are the same. + */ +#if PREFER_C + for (ulong i = 0; i < len_dw; i = i + 2) { + if (buf[i] != buf[i+1]) { + mt86_error(buf+i, buf[i], buf[i+1]); + } + } +#else + ulong* pe = buf + (len_dw - 2); + asm __volatile__ + ( + "jmp L120\n\t" + + ".p2align 4,,7\n\t" + "L124:\n\t" + "addl $8,%%edi\n\t" // Next QWORD + "L120:\n\t" + + // Compare adjacent DWORDS + "movl (%%edi),%%ecx\n\t" + "cmpl 4(%%edi),%%ecx\n\t" + "jnz L121\n\t" // Print error if they don't match + + // Loop until end of block + "L122:\n\t" + "cmpl %%edx,%%edi\n\t" + "jb L124\n" + "jmp L123\n\t" + + "L121:\n\t" + // eax not used so we don't need to save it as per cdecl + // ecx is used but not restored, however we don't need it's value anymore after this point + "pushl %%edx\n\t" + "pushl 4(%%edi)\n\t" + "pushl %%ecx\n\t" + "pushl %%edi\n\t" + "call mt86_error\n\t" + "popl %%edi\n\t" + "addl $8,%%esp\n\t" + "popl %%edx\n\t" + "jmp L122\n" + "L123:\n\t" + :: "D" (buf), "d" (pe) + : "ecx" + ); +#endif +} + +/* + * Test memory using block moves + * Adapted from Robert Redelmeier's burnBX test + */ +void block_move(int iter, int me) +{ + cprint(LINE_PAT, COL_PAT-2, " "); + + block_move_ctx ctx; + ctx.iter = iter; + ctx.me = me; + + /* Initialize memory with the initial pattern. */ + sliced_foreach_segment(&ctx, me, block_move_init); + { BAILR } + s_barrier(); + + /* Now move the data around */ + sliced_foreach_segment(&ctx, me, block_move_move); + { BAILR } + s_barrier(); + + /* And check it. */ + sliced_foreach_segment(&ctx, me, block_move_check); +} + +typedef struct { + ulong pat; +} bit_fade_ctx; + +STATIC void bit_fade_fill_seg(ulong* restrict p, + ulong len_dw, const void* vctx) { + const bit_fade_ctx* restrict ctx = (const bit_fade_ctx*)vctx; + ulong pat = ctx->pat; + + for (ulong i = 0; i < len_dw; i++) { + p[i] = pat; + } +} + +/* + * Test memory for bit fade, fill memory with pattern. + */ +void bit_fade_fill(ulong p1, int me) +{ + /* Display the current pattern */ + hprint(LINE_PAT, COL_PAT, p1); + + /* Initialize memory with the initial pattern. */ + bit_fade_ctx ctx; + ctx.pat = p1; + unsliced_foreach_segment(&ctx, me, bit_fade_fill_seg); +} + +STATIC void bit_fade_chk_seg(ulong* restrict p, + ulong len_dw, const void* vctx) { + const bit_fade_ctx* restrict ctx = (const bit_fade_ctx*)vctx; + ulong pat = ctx->pat; + + for (ulong i = 0; i < len_dw; i++) { + ulong bad; + if ((bad=p[i]) != pat) { + mt86_error(p+i, pat, bad); + } + } +} + +void bit_fade_chk(ulong p1, int me) +{ + bit_fade_ctx ctx; + ctx.pat = p1; + + /* Make sure that nothing changed while sleeping */ + unsliced_foreach_segment(&ctx, me, bit_fade_chk_seg); +} + +/* Sleep for N seconds */ +void sleep(long n, int flag, int me, + int sms /* interpret 'n' as milliseconds instead */) +{ + ulong sh, sl, l, h, t, ip=0; + + /* save the starting time */ + asm __volatile__( + "rdtsc":"=a" (sl),"=d" (sh)); + + /* loop for n seconds */ + while (1) { + asm __volatile__( + "rep ; nop\n\t" + "rdtsc":"=a" (l),"=d" (h)); + asm __volatile__ ( + "subl %2,%0\n\t" + "sbbl %3,%1" + :"=a" (l), "=d" (h) + :"g" (sl), "g" (sh), + "0" (l), "1" (h)); + + if (sms != 0) { + t = h * ((unsigned)0xffffffff / vv->clks_msec); + t += (l / vv->clks_msec); + } else { + t = h * ((unsigned)0xffffffff / vv->clks_msec) / 1000; + t += (l / vv->clks_msec) / 1000; + } + + /* Is the time up? */ + if (t >= n) { + break; + } + + /* Only display elapsed time if flag is set */ + if (flag == 0) { + continue; + } + + if (t != ip) { + do_tick(me); + { BAILR } + ip = t; + } + } +} + +void beep(unsigned int frequency) +{ +#if 0 + // BOZO(jcoiner) + // Removed this, we need to define outb_p() and inb_p() + // before reintroducing it. +#else + unsigned int count = 1193180 / frequency; + + // Switch on the speaker + outb_p(inb_p(0x61)|3, 0x61); + + // Set command for counter 2, 2 byte write + outb_p(0xB6, 0x43); + + // Select desired Hz + outb_p(count & 0xff, 0x42); + outb((count >> 8) & 0xff, 0x42); + + // Block for 100 microseconds + sleep(100, 0, 0, 1); + + // Switch off the speaker + outb(inb_p(0x61)&0xFC, 0x61); +#endif +} diff --git a/memtestEDK/Memtest/SingleComponents/test.h b/memtestEDK/Memtest/SingleComponents/test.h new file mode 100644 index 0000000..8b2e924 --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/test.h @@ -0,0 +1,346 @@ +/* test.h - MemTest-86 Version 3.4 + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + */ + +#ifndef _TEST_H_ +#define _TEST_H_ +#define E88 0x00 +#define E801 0x04 +#define E820NR 0x08 /* # entries in E820MAP */ +#define E820MAP 0x0c /* our map */ +#define E820MAX 127 /* number of entries in E820MAP */ +#define E820ENTRY_SIZE 20 +#define MEMINFO_SIZE (E820MAP + E820MAX * E820ENTRY_SIZE) + +#ifndef __ASSEMBLY__ + +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ +#define E820_NVS 4 + +struct e820entry { + unsigned long long addr; /* start of memory segment */ + unsigned long long size; /* size of memory segment */ + unsigned long type; /* type of memory segment */ +}; + +struct mem_info_t { + unsigned long e88_mem_k; /* 0x00 */ + unsigned long e801_mem_k; /* 0x04 */ + unsigned long e820_nr; /* 0x08 */ + struct e820entry e820[E820MAX]; /* 0x0c */ + /* 0x28c */ +}; + +typedef unsigned long ulong; +#define STACKSIZE_BYTES (8*1024) +#define MAX_MEM_PAGES 0x7FF00000 /* 8 TB; units are 4K pages */ +#define WIN_SZ_PAGES 0x80000 /* 2 GB; units are 4K pages */ +#define UNMAP_SZ_PAGES (0x100000-WIN_SZ_PAGES) /* Size of unmapped first segment */ + +#define SPINSZ_DWORDS 0x4000000 /* 256 MB; units are dwords (32-bit words) */ +#define MOD_SZ 20 +#define BAILOUT if (bail) return(1); +#define BAILR if (bail) return; + +#define RES_START 0xa0000 +#define RES_END 0x100000 +#define SCREEN_ADR 0xb8000 +#define SCREEN_END_ADR (SCREEN_ADR + 80*25*2) + +#define DMI_SEARCH_START 0x0000F000 +#define DMI_SEARCH_LENGTH 0x000F0FFF +#define MAX_DMI_MEMDEVS 16 + +#define TITLE_WIDTH 28 +#define LINE_TITLE 0 +#define LINE_TST 3 +#define LINE_RANGE 4 +#define LINE_PAT 5 +#define LINE_TIME 5 +#define LINE_STATUS 8 +#define LINE_INFO 9 +#define LINE_HEADER 12 +#define LINE_SCROLL 14 +#define LINE_SPD 14 +#define LINE_MSG 22 +#define LINE_CPU 7 +#define LINE_RAM 8 +#define LINE_DMI 23 +#define COL_INF1 15 +#define COL_INF2 32 +#define COL_INF3 51 +#define COL_INF4 70 +#define COL_MODE 15 +#define COL_MID 30 +#define COL_PAT 41 +#define BAR_SIZE (78-COL_MID-9) +#define COL_MSG 23 +#define COL_TIME 67 +#define COL_SPEC 41 + +#define POP_W 34 +#define POP_H 15 +#define POP_X 11 +#define POP_Y 8 +#define POP2_W 74 +#define POP2_H 21 +#define POP2_X 3 +#define POP2_Y 2 + +/* CPU mode types */ +#define CPM_ALL 1 +#define CPM_RROBIN 2 +#define CPM_SEQ 3 + +/* memspeed operations */ +#define MS_COPY 1 +#define MS_WRITE 2 +#define MS_READ 3 + +#define SZ_MODE_BIOS 1 +#define SZ_MODE_PROBE 2 + +#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); }) + +int mt86_memcmp(const void *s1, const void *s2, ulong count); +void *mt86_memmove(void *dest, const void *src, ulong n); +int mt86_strncmp(const char *s1, const char *s2, ulong n); +int mt86_strstr(char *str1, char *str2); +int mt86_strlen(char *string); +int query_linuxbios(void); +int query_pcbios(void); +int insertaddress(ulong); +void printpatn(void); +void printpatn(void); +void itoa(char s[], int n); +void reverse(char *p); +void serial_console_setup(char *param); +void serial_echo_init(void); +void serial_echo_print(const char *s); +void ttyprint(int y, int x, const char *s); +void ttyprintc(int y, int x, char c); +void cprint(int y,int x, const char *s); +void cplace(int y,int x, const char s); +void hprint(int y,int x, ulong val); +void hprint2(int y,int x, ulong val, int len); +void hprint3(int y,int x, ulong val, int len); +void xprint(int y,int x,ulong val); +void aprint(int y,int x,ulong page); +void dprint(int y,int x,ulong val,int len, int right); +void movinv1(int iter, ulong p1, ulong p2, int cpu); +void movinvr(int cpu); +void movinv32(int iter, ulong p1, ulong lb, ulong mb, int sval, int off, + int cpu); +void modtst(int off, int iter, ulong p1, ulong p2, int cpu); +#define ASSERT(n) do { \ + if (!(n)) { \ + assert_fail(__FILE__, __LINE__); \ + } } while(0) +void assert_fail(const char* file, int line_no); +void mt86_error(ulong* adr, ulong good, ulong bad); +void ad_err1(ulong *adr1, ulong *adr2, ulong good, ulong bad); +void ad_err2(ulong *adr, ulong bad); +void do_tick(); +void init(void); +struct eregs; +void inter(struct eregs *trap_regs); +void set_cache(int val); +void check_input(void); +void footer(void); +void scroll(void); +void clear_scroll(void); +void popup(void); +void popdown(void); +void popclear(void); +void pop2up(void); +void pop2down(void); +void pop2clear(void); +void get_config(void); +void get_menu(void); +void get_printmode(void); +void addr_tst1(int cpu); +void addr_tst2(int cpu); +int getnum(ulong val); +void sleep(long sec, int flag, int cpu, int sms); +void block_move(int iter, int cpu); +void find_ticks(void); +void print_err(ulong *adr, ulong good, ulong bad, ulong xor); +void print_ecc_err(ulong page, ulong offset, int corrected, + unsigned short syndrome, int channel); +void mem_size(void); +void adj_mem(void); +ulong getval(int x, int y, int result_shift); +int get_key(void); +int ascii_to_keycode(int in); +void wait_keyup(void); +void print_hdr(void); +void restart(void); +void parity_err(ulong edi, ulong esi); +void start_config(void); +void clear_screen(void); +void paging_off(void); +void show_spd(void); +int map_page(unsigned long page); +void *mapping(unsigned long phys_page); // get VA for a physical page +void *emapping(unsigned long phys_page); +int mt86_isdigit(char c); +ulong memspeed(ulong src, ulong len, int iter); +unsigned long page_of(void *ptr); +ulong correct_tsc(ulong el_org); +void bit_fade_fill(unsigned long n, int cpu); +void bit_fade_chk(unsigned long n, int cpu); +void find_ticks_for_pass(void); +void beep(unsigned int frequency); + +// Expose foreach_segment here for self_test, otherwise +// it would be local to test.c: +typedef void(*segment_fn)(ulong* start, // start address + ulong len_dw, // length of segment in dwords + const void* ctx); // any context data needed +void foreach_segment(ulong* start, ulong* end, + int me, const void* ctx, segment_fn func); + + +// In self-test, DEBUGF wraps libc's printf. +// In memtest standalone, printf will be a stub +// and 'vv->debugging' is false to avoid call overhead. +int printf(const char *format, ...); +#define DEBUGF(...) { \ + if (vv->debugging) { \ + printf(__VA_ARGS__); \ + } \ + } + +#define PRINTMODE_SUMMARY 0 +#define PRINTMODE_ADDRESSES 1 +#define PRINTMODE_PATTERNS 2 +#define PRINTMODE_NONE 3 + +#define BADRAM_MAXPATNS 10 + +struct pair { + ulong adr; + ulong mask; +}; + +static inline void cache_off(void) +{ + asm( + "push %eax\n\t" + "movl %cr0,%eax\n\t" + "orl $0x40000000,%eax\n\t" /* Set CD */ + "movl %eax,%cr0\n\t" + "wbinvd\n\t" + "pop %eax\n\t"); +} + +static inline void cache_on(void) +{ + asm( + "push %eax\n\t" + "movl %cr0,%eax\n\t" + "andl $0x9fffffff,%eax\n\t" /* Clear CD and NW */ + "movl %eax,%cr0\n\t" + "pop %eax\n\t"); +} + +struct mmap { + ulong pbase_addr; + ulong *start; // VA of segment start + ulong *end; // VA of the last dword within the segment. +}; + +struct pmap { + ulong start; /* phys page number of RAM segment start, + in 4K pages. */ + ulong end; // phys page number (past the end? or inclusive?) +}; + +struct tseq { + short sel; // enabled + short cpu_sel; // cpu_sel == 0 indicates end of tseq[] array + short pat; // the test # + short iter; // # of iterations to run + short errors; // error count, updated as tests run + char *msg; +}; + +struct xadr { + ulong page; + ulong offset; +}; + +struct err_info { + struct xadr low_addr; + struct xadr high_addr; + unsigned long ebits; + long tbits; + short min_bits; + short max_bits; + unsigned long maxl; + unsigned long eadr; + unsigned long exor; + unsigned long cor_err; + short hdr_flag; +}; + + + +#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ + +#define MAX_MEM_SEGMENTS E820MAX + +/* Define common variables across relocations of memtest86 */ +struct vars { + int pass; + int msg_line; + int ecount; + int ecc_ecount; + int msegs; // number of entries in pmap[] + int testsel; + int scroll_start; + int pass_ticks; + int total_ticks; + int pptr; + int tptr; + struct err_info erri; + // PA ranges from e820 table: + struct pmap pmap[MAX_MEM_SEGMENTS]; + // VA mappings: + volatile struct mmap map[MAX_MEM_SEGMENTS]; + ulong plim_lower; // phys page number + ulong plim_upper; // phys page number + ulong clks_msec; + ulong starth; + ulong startl; + ulong snaph; + ulong snapl; + int printmode; + int numpatn; + struct pair patn [BADRAM_MAXPATNS]; + ulong test_pages; + ulong selected_pages; + ulong reserved_pages; + int check_temp; + int fail_safe; + int each_sec; + int beepmode; + int debugging; // Set in selftest only +}; + +#define FIRMWARE_UNKNOWN 0 +#define FIRMWARE_PCBIOS 1 +#define FIRMWARE_LINUXBIOS 2 + +extern struct vars * const vv; +extern unsigned char _start[], _end[], startup_32[]; +extern unsigned char _size, _pages; + +extern struct mem_info_t mem_info; + +#endif /* __ASSEMBLY__ */ +#endif /* _TEST_H_ */ diff --git a/memtestEDK/Memtest/SingleComponents/vmem.c b/memtestEDK/Memtest/SingleComponents/vmem.c new file mode 100644 index 0000000..6125e0d --- /dev/null +++ b/memtestEDK/Memtest/SingleComponents/vmem.c @@ -0,0 +1,159 @@ +/* vmem.c - MemTest-86 + * + * Virtual memory handling (PAE) + * + * Released under version 2 of the Gnu Public License. + * By Chris Brady + */ +#include "stdint.h" +#include "test.h" +#include "cpuid.h" + +extern struct cpu_ident cpu_id; + +static unsigned long mapped_win = 1; +void paging_off(void) +{ + if (!cpu_id.fid.bits.pae) + return; + __asm__ __volatile__ + ( + /* Disable paging */ + "movl %%cr0, %%eax\n\t" + "andl $0x7FFFFFFF, %%eax\n\t" + "movl %%eax, %%cr0\n\t" + : : + : "ax" + ); +} + +static void paging_on(void *pdp) +{ + if (!cpu_id.fid.bits.pae) + return; + __asm__ __volatile__ + ( + /* Load the page table address */ + "movl %0, %%cr3\n\t" + /* Enable paging */ + "movl %%cr0, %%eax\n\t" + "orl $0x80000000, %%eax\n\t" + "movl %%eax, %%cr0\n\t" + : + : "r" (pdp) + : "ax" + ); +} + +static void paging_on_lm(void *pml) +{ + if (!cpu_id.fid.bits.pae) + return; + __asm__ __volatile__ + ( + /* Load the page table address */ + "movl %0, %%cr3\n\t" + /* Enable paging */ + "movl %%cr0, %%eax\n\t" + "orl $0x80000000, %%eax\n\t" + "movl %%eax, %%cr0\n\t" + : + : "r" (pml) + : "ax" + ); +} + +int map_page(unsigned long page) +{ + unsigned long i; + struct pde { + unsigned long addr_lo; + unsigned long addr_hi; + }; + extern unsigned char pdp[]; + extern unsigned char pml4[]; + extern struct pde pd2[]; + unsigned long win = page >> 19; + + /* Less than 2 GB so no mapping is required */ + if (win == 0) { + return 0; + } + if (cpu_id.fid.bits.pae == 0) { + /* Fail, we don't have PAE */ + return -1; + } + if (cpu_id.fid.bits.lm == 0 && (page > 0x1000000)) { + /* Fail, we want an address that is out of bounds (> 64GB) + * for PAE and no long mode (ie. 32 bit CPU). + */ + return -1; + } + /* Compute the page table entries... */ + for(i = 0; i < 1024; i++) { + /*-----------------10/30/2004 12:37PM--------------- + * 0xE3 -- + * Bit 0 = Present bit. 1 = PDE is present + * Bit 1 = Read/Write. 1 = memory is writable + * Bit 2 = Supervisor/User. 0 = Supervisor only (CPL 0-2) + * Bit 3 = Writethrough. 0 = writeback cache policy + * Bit 4 = Cache Disable. 0 = page level cache enabled + * Bit 5 = Accessed. 1 = memory has been accessed. + * Bit 6 = Dirty. 1 = memory has been written to. + * Bit 7 = Page Size. 1 = page size is 2 MBytes + * --------------------------------------------------*/ + pd2[i].addr_lo = ((win & 1) << 31) + ((i & 0x3ff) << 21) + 0xE3; + pd2[i].addr_hi = (win >> 1); + } + paging_off(); + if (cpu_id.fid.bits.lm == 1) { + paging_on_lm(pml4); + } else { + paging_on(pdp); + } + mapped_win = win; + return 0; +} + +void *mapping(unsigned long phys_page) +{ + void *result; + if (phys_page < WIN_SZ_PAGES) { + /* If the page is below 2GB, address it directly */ + result = (void *)(phys_page << 12); + } + else { + // Higher physical pages map to a virtual address + // in the 2G-4G range. + unsigned long alias; + alias = phys_page & 0x7FFFF; + alias += 0x80000; + result = (void *)(alias << 12); + } + return result; +} + +void *emapping(unsigned long phys_page) +{ + void *result; + result = mapping(phys_page - 1); + /* Fill in the low address bits */ + result = ((unsigned char *)result) + 0xffc; + return result; +} + +unsigned long page_of(void *addr) +{ + unsigned long page; + page = ((unsigned long)addr) >> 12; + if (page >= 0x80000) { + page &= 0x7FFFF; + page += mapped_win << 19; + } +#if 0 + cprint(LINE_SCROLL -2, 0, "page_of( )-> "); + hprint(LINE_SCROLL -2, 8, ((unsigned long)addr)); + hprint(LINE_SCROLL -2, 20, page); +#endif + return page; +} diff --git a/memtestEDK/Memtest/run.sh b/memtestEDK/Memtest/run.sh new file mode 100755 index 0000000..f9a3f01 --- /dev/null +++ b/memtestEDK/Memtest/run.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +(cd ..;. edksetup.sh BaseTools; build -a X64 -p MdeModulePkg/MdeModulePkg.dsc) + +if [ $? -ne 0 ]; then exit 1; fi +(cd ..; cp Build/MdeModule/DEBUG_GCC5/X64/GetRootSystemDescriptionPointer.efi ../../git/working_dir/memtest86/test_code/hda-contents/) + +if [ $? -ne 0 ]; then exit 1; fi +(cd ../../../git/working_dir/memtest86/test_code; sudo ./run.sh ) + diff --git a/memtestEDK/README b/memtestEDK/README new file mode 100644 index 0000000..92190eb --- /dev/null +++ b/memtestEDK/README @@ -0,0 +1,16 @@ +####### +# HOW TO BUILD/RUN MEMTEST APPLICATION +####### + + +1. Build +============ +1.0 Create *.c and *.h file inside edk2/Memtest +1.1 Add Application to [Components] Section of edk2/MdeModulePkg/MdeModulePkg.dsc +1.2 Run ./run.sh from edk2/Memtest + + +2. Run from UEFI Shell +========================= +2.0 Choose filesystem where the application is placed +2.1 Start the application by typing its name |