[coreboot-gerrit] New patch to review for coreboot: Profile memory scrambling and enable memory dumps from CAR.

Anonymous Coward gerrit at coreboot.org
Thu Mar 2 12:45:40 CET 2017


Anonymous Coward just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18539

-gerrit

commit 1bf34c8d51f9139be74b1903d37c4fdec34a3aee
Author: Nico van Heijningen <nico.heijningen at gmail.com>
Date:   Thu Mar 2 12:34:06 2017 +0100

    Profile memory scrambling and enable memory dumps from CAR.
    
    The code is very experimental and only applicable to the Gigabyte
    GA-B75M-D3V motherboard, hence the inclusion of the config files.
    I have made no effort to optimize or clean-up any debug code,
    as this could be useful to understand the concepts. I do not expect
    this patch to be merged into Coreboot, but merely to serve as a
    public backup. An effort to make my work on Ivy Bridge reproducible.
    The accompanying work should be available soon under the name:
    "Professionalizing hardware-based memory acquisition for incident
    response scenarios: Cold boot using Coreboot and the Intel memory
    scrambler"
    
    Contents of the patch:
    * Config files for Coreboot and SeaBIOS
    * Increase of the CAR size
    * Two way serial communication
    * Disabling stolen memory regions: graphics, SMRAM and Intel ME
    * Selecting different scrambling seeds or disabling
    scrambling all together (on every reset)
    * Disable MRC cache and fast boot (to initialize
    the DIMM completely)
    * SATA PIO driver (to write memory images to hard disk from CAR)
    * Enabling paging (to access all memory from CAR)
    * Writing reproducible pseudo-random data to RAM (to verify the
    access to all memory)
    * Detect the insertion of a DIMM
    
    Each "#if false [...] #endif" block in raminit.c can be enabled
    separately to add some functionality. I chose to have the code
    like this as otherwise Coreboot wouldn't build due to unused
    initialized functions
    
    Some functionality required patching the ME descriptor and firmware.
    Not handing ME any RAM or stalling the boot for a significant amount
    of time before ME is initialized results unpredictable behavior.
    Patching the ME binaries resulted in a bootable system but is left
    as an exercise for the reader. Enabling soft straps in the
    descriptor.bin and increasing the UMA size in me.bin did the trick
    for us. Probably crashing the ME enough to allow us to continue boot.
    
    A similar/related efforts can be found here:
    https://www.coreboot.org/pipermail/coreboot/2015-January/079135.html
    https://review.coreboot.org/#/c/6158/8/SerialICE/serialice.c
    https://github.com/NicoHeijningen/IntelMemoryScrambler
    
    Change-Id: Ia6a75a7fad34e28e43277850698ae822f4efb396
    Signed-off-by: Nico van Heijningen <nico.heijningen at gmail.com>
---
 .config                                         |  634 ++++++
 seabiosconfig.txt                               |   96 +
 src/lib/romstage_stack.c                        |    2 +-
 src/mainboard/gigabyte/ga-b75m-d3v/cmos.default |    3 +-
 src/northbridge/intel/sandybridge/Kconfig       |    4 +-
 src/northbridge/intel/sandybridge/early_init.c  |   67 +-
 src/northbridge/intel/sandybridge/raminit.c     | 2368 +++++++++++++++++++++--
 7 files changed, 3006 insertions(+), 168 deletions(-)

diff --git a/.config b/.config
new file mode 100644
index 0000000..1a7656c
--- /dev/null
+++ b/.config
@@ -0,0 +1,634 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# coreboot configuration
+#
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_CBFS_PREFIX="fallback"
+CONFIG_COMPILER_GCC=y
+# CONFIG_COMPILER_LLVM_CLANG is not set
+# CONFIG_ANY_TOOLCHAIN is not set
+# CONFIG_CCACHE is not set
+# CONFIG_FMD_GENPARSER is not set
+# CONFIG_SCONFIG_GENPARSER is not set
+# CONFIG_USE_OPTION_TABLE is not set
+# CONFIG_UNCOMPRESSED_RAMSTAGE is not set
+CONFIG_COMPRESS_RAMSTAGE=y
+CONFIG_INCLUDE_CONFIG_FILE=y
+# CONFIG_NO_XIP_EARLY_STAGES is not set
+CONFIG_EARLY_CBMEM_INIT=y
+# CONFIG_EARLY_CBMEM_LIST is not set
+# CONFIG_COLLECT_TIMESTAMPS is not set
+# CONFIG_USE_BLOBS is not set
+# CONFIG_COVERAGE is not set
+CONFIG_RELOCATABLE_MODULES=y
+# CONFIG_RELOCATABLE_RAMSTAGE is not set
+# CONFIG_NO_STAGE_CACHE is not set
+CONFIG_BOOTBLOCK_SIMPLE=y
+# CONFIG_BOOTBLOCK_NORMAL is not set
+CONFIG_BOOTBLOCK_CUSTOM=y
+CONFIG_BOOTBLOCK_SOURCE="bootblock_simple.c"
+# CONFIG_C_ENVIRONMENT_BOOTBLOCK is not set
+# CONFIG_UPDATE_IMAGE is not set
+# CONFIG_GENERIC_GPIO_LIB is not set
+# CONFIG_BOARD_ID_AUTO is not set
+# CONFIG_BOARD_ID_MANUAL is not set
+# CONFIG_RAM_CODE_SUPPORT is not set
+# CONFIG_BOOTSPLASH_IMAGE is not set
+
+#
+# Mainboard
+#
+# CONFIG_VENDOR_A_TREND is not set
+# CONFIG_VENDOR_AAEON is not set
+# CONFIG_VENDOR_ABIT is not set
+# CONFIG_VENDOR_ADI is not set
+# CONFIG_VENDOR_ADLINK is not set
+# CONFIG_VENDOR_ADVANSUS is not set
+# CONFIG_VENDOR_AMD is not set
+# CONFIG_VENDOR_AOPEN is not set
+# CONFIG_VENDOR_APPLE is not set
+# CONFIG_VENDOR_ARTECGROUP is not set
+# CONFIG_VENDOR_ASROCK is not set
+# CONFIG_VENDOR_ASUS is not set
+# CONFIG_VENDOR_AVALUE is not set
+# CONFIG_VENDOR_AZZA is not set
+# CONFIG_VENDOR_BACHMANN is not set
+# CONFIG_VENDOR_BAP is not set
+# CONFIG_VENDOR_BCOM is not set
+# CONFIG_VENDOR_BIFFEROS is not set
+# CONFIG_VENDOR_BIOSTAR is not set
+# CONFIG_VENDOR_BROADCOM is not set
+# CONFIG_VENDOR_COMPAQ is not set
+# CONFIG_VENDOR_CUBIETECH is not set
+# CONFIG_VENDOR_DIGITALLOGIC is not set
+# CONFIG_VENDOR_DMP is not set
+# CONFIG_VENDOR_ECS is not set
+# CONFIG_VENDOR_ELMEX is not set
+# CONFIG_VENDOR_EMULATION is not set
+# CONFIG_VENDOR_ESD is not set
+# CONFIG_VENDOR_GETAC is not set
+CONFIG_VENDOR_GIGABYTE=y
+# CONFIG_VENDOR_GIZMOSPHERE is not set
+# CONFIG_VENDOR_GOOGLE is not set
+# CONFIG_VENDOR_HP is not set
+# CONFIG_VENDOR_IBASE is not set
+# CONFIG_VENDOR_IEI is not set
+# CONFIG_VENDOR_INTEL is not set
+# CONFIG_VENDOR_IWAVE is not set
+# CONFIG_VENDOR_IWILL is not set
+# CONFIG_VENDOR_JETWAY is not set
+# CONFIG_VENDOR_KONTRON is not set
+# CONFIG_VENDOR_LANNER is not set
+# CONFIG_VENDOR_LENOVO is not set
+# CONFIG_VENDOR_LINUTOP is not set
+# CONFIG_VENDOR_LIPPERT is not set
+# CONFIG_VENDOR_MITAC is not set
+# CONFIG_VENDOR_MSI is not set
+# CONFIG_VENDOR_NEC is not set
+# CONFIG_VENDOR_NOKIA is not set
+# CONFIG_VENDOR_NVIDIA is not set
+# CONFIG_VENDOR_PACKARDBELL is not set
+# CONFIG_VENDOR_PCENGINES is not set
+# CONFIG_VENDOR_PURISM is not set
+# CONFIG_VENDOR_RCA is not set
+# CONFIG_VENDOR_RODA is not set
+# CONFIG_VENDOR_SAMSUNG is not set
+# CONFIG_VENDOR_SIEMENS is not set
+# CONFIG_VENDOR_SOYO is not set
+# CONFIG_VENDOR_SUNW is not set
+# CONFIG_VENDOR_SUPERMICRO is not set
+# CONFIG_VENDOR_TECHNEXION is not set
+# CONFIG_VENDOR_THOMSON is not set
+# CONFIG_VENDOR_TI is not set
+# CONFIG_VENDOR_TRAVERSE is not set
+# CONFIG_VENDOR_TYAN is not set
+# CONFIG_VENDOR_VIA is not set
+# CONFIG_VENDOR_WINENT is not set
+# CONFIG_VENDOR_WYSE is not set
+CONFIG_BOARD_SPECIFIC_OPTIONS=y
+CONFIG_MAINBOARD_DIR="gigabyte/ga-b75m-d3v"
+CONFIG_MAINBOARD_PART_NUMBER="GA-B75M-D3V"
+CONFIG_MAINBOARD_VENDOR="GIGABYTE"
+CONFIG_MAX_CPUS=8
+CONFIG_CACHE_ROM_SIZE_OVERRIDE=0x0
+CONFIG_CBFS_SIZE=0x100000
+CONFIG_UART_FOR_CONSOLE=0
+CONFIG_PAYLOAD_CONFIGFILE="$(PWD)/seabiosconfig.txt"
+CONFIG_VGA_BIOS_ID="8086,0152"
+CONFIG_ONBOARD_VGA_IS_PRIMARY=y
+CONFIG_VGA_BIOS=y
+CONFIG_MAINBOARD_SERIAL_NUMBER="123456789"
+CONFIG_DCACHE_RAM_BASE=0xFF000000
+CONFIG_DCACHE_RAM_SIZE=0x40000
+CONFIG_VGA_BIOS_FILE="bins/vgabios.bin"
+CONFIG_MMCONF_BASE_ADDRESS=0xf8000000
+CONFIG_MAINBOARD_SMBIOS_MANUFACTURER="GIGABYTE"
+CONFIG_HAVE_IFD_BIN=y
+CONFIG_HAVE_ME_BIN=y
+CONFIG_DRAM_RESET_GATE_GPIO=25
+CONFIG_POST_IO=y
+CONFIG_MAX_REBOOT_CNT=3
+CONFIG_ID_SECTION_OFFSET=0x80
+CONFIG_POST_DEVICE=y
+# CONFIG_BOARD_GIGABYTE_GA_6BXC is not set
+# CONFIG_BOARD_GIGABYTE_GA_6BXE is not set
+# CONFIG_BOARD_GIGABYTE_GA_B75M_D3H is not set
+CONFIG_BOARD_GIGABYTE_GA_B75M_D3V=y
+# CONFIG_BOARD_GIGABYTE_GA_G41M_ES2L is not set
+# CONFIG_BOARD_GIGABYTE_GA_2761GXDK is not set
+# CONFIG_BOARD_GIGABYTE_M57SLI is not set
+# CONFIG_BOARD_GIGABYTE_MA785GM is not set
+# CONFIG_BOARD_GIGABYTE_MA785GMT is not set
+# CONFIG_BOARD_GIGABYTE_MA78GM is not set
+CONFIG_USBDEBUG_HCD_INDEX=2
+CONFIG_IFD_BIOS_SECTION="0x00600000:0x007fffff"
+CONFIG_IFD_ME_SECTION="0x00001000:0x004fffff"
+CONFIG_BOOT_DEVICE_SPI_FLASH_BUS=0
+CONFIG_DRIVERS_PS2_KEYBOARD=y
+CONFIG_DEVICETREE="devicetree.cb"
+CONFIG_TTYS0_LCS=3
+# CONFIG_CONSOLE_POST is not set
+CONFIG_DRIVERS_UART_8250IO=y
+# CONFIG_HAVE_GBE_BIN is not set
+CONFIG_SEABIOS_PS2_TIMEOUT=0
+CONFIG_CPU_ADDR_BITS=36
+CONFIG_DEFAULT_CONSOLE_LOGLEVEL=7
+# CONFIG_USBDEBUG is not set
+CONFIG_MAINBOARD_VERSION="1.0"
+# CONFIG_NO_POST is not set
+CONFIG_BOARD_ROMSIZE_KB_8192=y
+# CONFIG_COREBOOT_ROMSIZE_KB_64 is not set
+# CONFIG_COREBOOT_ROMSIZE_KB_128 is not set
+# CONFIG_COREBOOT_ROMSIZE_KB_256 is not set
+# CONFIG_COREBOOT_ROMSIZE_KB_512 is not set
+# CONFIG_COREBOOT_ROMSIZE_KB_1024 is not set
+# CONFIG_COREBOOT_ROMSIZE_KB_2048 is not set
+# CONFIG_COREBOOT_ROMSIZE_KB_4096 is not set
+CONFIG_COREBOOT_ROMSIZE_KB_8192=y
+# CONFIG_COREBOOT_ROMSIZE_KB_12288 is not set
+# CONFIG_COREBOOT_ROMSIZE_KB_16384 is not set
+# CONFIG_COREBOOT_ROMSIZE_KB_32768 is not set
+# CONFIG_COREBOOT_ROMSIZE_KB_65536 is not set
+CONFIG_COREBOOT_ROMSIZE_KB=8192
+CONFIG_ROM_SIZE=0x800000
+CONFIG_FMDFILE=""
+# CONFIG_MAINBOARD_HAS_TPM2 is not set
+# CONFIG_SYSTEM_TYPE_LAPTOP is not set
+# CONFIG_CBFS_AUTOGEN_ATTRIBUTES is not set
+
+#
+# Chipset
+#
+
+#
+# SoC
+#
+# CONFIG_SOC_BROADCOM_CYGNUS is not set
+CONFIG_BOOTBLOCK_CPU_INIT="cpu/intel/model_206ax/bootblock.c"
+CONFIG_CPU_SPECIFIC_OPTIONS=y
+CONFIG_C_ENV_BOOTBLOCK_SIZE=0x10000
+CONFIG_X86_TOP4G_BOOTMEDIA_MAP=y
+CONFIG_ROMSTAGE_ADDR=0x2000000
+CONFIG_VERSTAGE_ADDR=0x2000000
+CONFIG_SPI_FLASH_INCLUDE_ALL_DRIVERS=y
+CONFIG_SMM_TSEG_SIZE=0x800000
+CONFIG_DCACHE_RAM_MRC_VAR_SIZE=0x0
+# CONFIG_BUILD_WITH_FAKE_IFD is not set
+CONFIG_BOOTBLOCK_NORTHBRIDGE_INIT="northbridge/intel/sandybridge/bootblock.c"
+CONFIG_BOOTBLOCK_SOUTHBRIDGE_INIT="southbridge/intel/bd82x6x/bootblock.c"
+CONFIG_CACHE_MRC_SIZE_KB=512
+CONFIG_TTYS0_BASE=0x3f8
+CONFIG_EHCI_BAR=0xfef00000
+CONFIG_SERIRQ_CONTINUOUS_MODE=y
+CONFIG_RAMTOP=0x200000
+CONFIG_HEAP_SIZE=0x4000
+CONFIG_CONSOLE_CBMEM=y
+CONFIG_UART_PCI_ADDR=0
+CONFIG_HPET_MIN_TICKS=0x80
+# CONFIG_SOC_MARVELL_ARMADA38X is not set
+# CONFIG_SOC_MARVELL_BG4CD is not set
+# CONFIG_SOC_MARVELL_MVMAP2315 is not set
+CONFIG_TTYS0_BAUD=115200
+# CONFIG_SOC_MEDIATEK_MT8173 is not set
+# CONFIG_SOC_NVIDIA_TEGRA124 is not set
+# CONFIG_SOC_NVIDIA_TEGRA210 is not set
+# CONFIG_SOC_QC_IPQ40XX is not set
+# CONFIG_SOC_QC_IPQ806X is not set
+# CONFIG_SOC_ROCKCHIP_RK3288 is not set
+# CONFIG_SOC_ROCKCHIP_RK3399 is not set
+# CONFIG_CPU_SAMSUNG_EXYNOS5250 is not set
+# CONFIG_CPU_SAMSUNG_EXYNOS5420 is not set
+# CONFIG_SOC_UCB_RISCV is not set
+
+#
+# CPU
+#
+# CONFIG_CPU_ALLWINNER_A10 is not set
+CONFIG_SOCKET_SPECIFIC_OPTIONS=y
+CONFIG_XIP_ROM_SIZE=0x10000
+CONFIG_NUM_IPI_STARTS=2
+# CONFIG_CPU_AMD_AGESA is not set
+# CONFIG_CPU_AMD_PI is not set
+# CONFIG_CPU_ARMLTD_CORTEX_A9 is not set
+CONFIG_CPU_INTEL_MODEL_206AX=y
+# CONFIG_ENABLE_VMX is not set
+CONFIG_SSE2=y
+CONFIG_CPU_INTEL_SOCKET_LGA1155=y
+# CONFIG_CPU_INTEL_FIRMWARE_INTERFACE_TABLE is not set
+# CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED is not set
+# CONFIG_CPU_TI_AM335X is not set
+# CONFIG_PARALLEL_CPU_INIT is not set
+# CONFIG_PARALLEL_MP is not set
+# CONFIG_UDELAY_IO is not set
+CONFIG_UDELAY_LAPIC=y
+CONFIG_LAPIC_MONOTONIC_TIMER=y
+CONFIG_UDELAY_TSC=y
+# CONFIG_TSC_CONSTANT_RATE is not set
+# CONFIG_TSC_MONOTONIC_TIMER is not set
+# CONFIG_UDELAY_TIMER2 is not set
+# CONFIG_TSC_SYNC_LFENCE is not set
+CONFIG_TSC_SYNC_MFENCE=y
+# CONFIG_NO_FIXED_XIP_ROM_SIZE is not set
+CONFIG_LOGICAL_CPUS=y
+CONFIG_SMM_TSEG=y
+CONFIG_SMM_MODULE_HEAP_SIZE=0x4000
+# CONFIG_SMM_LAPIC_REMAP_MITIGATION is not set
+# CONFIG_SERIALIZED_SMM_INITIALIZATION is not set
+# CONFIG_X86_AMD_FIXED_MTRRS is not set
+# CONFIG_PLATFORM_USES_FSP1_0 is not set
+# CONFIG_MIRROR_PAYLOAD_TO_RAM_BEFORE_LOADING is not set
+# CONFIG_SOC_SETS_MSRS is not set
+CONFIG_CACHE_AS_RAM=y
+CONFIG_SMP=y
+CONFIG_AP_SIPI_VECTOR=0xfffff000
+CONFIG_MMX=y
+CONFIG_SSE=y
+CONFIG_SUPPORT_CPU_UCODE_IN_CBFS=y
+# CONFIG_USES_MICROCODE_HEADER_FILES is not set
+# CONFIG_CPU_MICROCODE_CBFS_GENERATE is not set
+# CONFIG_CPU_MICROCODE_CBFS_EXTERNAL_HEADER is not set
+CONFIG_CPU_MICROCODE_CBFS_NONE=y
+
+#
+# Northbridge
+#
+# CONFIG_NORTHBRIDGE_AMD_AGESA is not set
+# CONFIG_AMD_NB_CIMX is not set
+# CONFIG_NORTHBRIDGE_AMD_CIMX_RD890 is not set
+CONFIG_VIDEO_MB=0
+# CONFIG_NORTHBRIDGE_AMD_PI is not set
+CONFIG_RAMBASE=0x100000
+CONFIG_NORTHBRIDGE_INTEL_COMMON_MRC_CACHE=y
+CONFIG_MRC_CACHE_SIZE=0x10000
+CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE=y
+CONFIG_USE_NATIVE_RAMINIT=y
+# CONFIG_SANDYBRIDGE_IVYBRIDGE_LVDS is not set
+CONFIG_HPET_ADDRESS=0xfed00000
+CONFIG_MAX_PIRQ_LINKS=4
+
+#
+# Southbridge
+#
+# CONFIG_AMD_SB_CIMX is not set
+# CONFIG_SOUTHBRIDGE_AMD_CIMX_SB800 is not set
+# CONFIG_SOUTHBRIDGE_AMD_CIMX_SB900 is not set
+CONFIG_SOUTHBRIDGE_INTEL_C216=y
+CONFIG_SOUTH_BRIDGE_OPTIONS=y
+CONFIG_LOCK_SPI_ON_RESUME_NONE=y
+# CONFIG_LOCK_SPI_ON_RESUME_RO is not set
+# CONFIG_LOCK_SPI_ON_RESUME_NO_ACCESS is not set
+CONFIG_SOUTHBRIDGE_INTEL_COMMON=y
+CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO=y
+CONFIG_IFD_BIN_PATH="bins/descriptor.bin"
+CONFIG_ME_BIN_PATH="bins/me.bin"
+# CONFIG_LOCK_MANAGEMENT_ENGINE is not set
+
+#
+# Super I/O
+#
+CONFIG_SUPERIO_ITE_COMMON_ROMSTAGE=y
+CONFIG_SUPERIO_ITE_IT8728F=y
+# CONFIG_SUPERIO_NUVOTON_NCT6776_COM_A is not set
+
+#
+# Embedded Controllers
+#
+CONFIG_HAVE_INTEL_FIRMWARE=y
+
+#
+# Intel Firmware
+#
+# CONFIG_EM100 is not set
+CONFIG_VBOOT_VBNV_OFFSET=0x26
+# CONFIG_VBOOT_VBNV_CMOS is not set
+# CONFIG_VBOOT_VBNV_EC is not set
+# CONFIG_VBOOT is not set
+# CONFIG_MAINBOARD_HAS_CHROMEOS is not set
+# CONFIG_UEFI_2_4_BINDING is not set
+# CONFIG_UDK_2015_BINDING is not set
+# CONFIG_USE_SIEMENS_HWILIB is not set
+# CONFIG_ARCH_ARM is not set
+# CONFIG_ARCH_BOOTBLOCK_ARM is not set
+# CONFIG_ARCH_VERSTAGE_ARM is not set
+# CONFIG_ARCH_ROMSTAGE_ARM is not set
+# CONFIG_ARCH_RAMSTAGE_ARM is not set
+# CONFIG_ARCH_BOOTBLOCK_ARMV4 is not set
+# CONFIG_ARCH_VERSTAGE_ARMV4 is not set
+# CONFIG_ARCH_ROMSTAGE_ARMV4 is not set
+# CONFIG_ARCH_RAMSTAGE_ARMV4 is not set
+# CONFIG_ARCH_BOOTBLOCK_ARMV7 is not set
+# CONFIG_ARCH_VERSTAGE_ARMV7 is not set
+# CONFIG_ARCH_ROMSTAGE_ARMV7 is not set
+# CONFIG_ARCH_RAMSTAGE_ARMV7 is not set
+# CONFIG_ARCH_BOOTBLOCK_ARMV7_M is not set
+# CONFIG_ARCH_VERSTAGE_ARMV7_M is not set
+# CONFIG_ARCH_BOOTBLOCK_ARMV7_R is not set
+# CONFIG_ARCH_VERSTAGE_ARMV7_R is not set
+# CONFIG_ARCH_ROMSTAGE_ARMV7_R is not set
+# CONFIG_ARCH_RAMSTAGE_ARMV7_R is not set
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_ARM64 is not set
+# CONFIG_ARCH_BOOTBLOCK_ARM64 is not set
+# CONFIG_ARCH_VERSTAGE_ARM64 is not set
+# CONFIG_ARCH_ROMSTAGE_ARM64 is not set
+# CONFIG_ARCH_RAMSTAGE_ARM64 is not set
+# CONFIG_ARCH_BOOTBLOCK_ARMV8_64 is not set
+# CONFIG_ARCH_VERSTAGE_ARMV8_64 is not set
+# CONFIG_ARCH_ROMSTAGE_ARMV8_64 is not set
+# CONFIG_ARCH_RAMSTAGE_ARMV8_64 is not set
+# CONFIG_ARM64_A53_ERRATUM_843419 is not set
+# CONFIG_ARCH_MIPS is not set
+# CONFIG_ARCH_BOOTBLOCK_MIPS is not set
+# CONFIG_ARCH_VERSTAGE_MIPS is not set
+# CONFIG_ARCH_ROMSTAGE_MIPS is not set
+# CONFIG_ARCH_RAMSTAGE_MIPS is not set
+# CONFIG_ARCH_POWER8 is not set
+# CONFIG_ARCH_BOOTBLOCK_POWER8 is not set
+# CONFIG_ARCH_VERSTAGE_POWER8 is not set
+# CONFIG_ARCH_ROMSTAGE_POWER8 is not set
+# CONFIG_ARCH_RAMSTAGE_POWER8 is not set
+# CONFIG_ARCH_RISCV is not set
+# CONFIG_ARCH_BOOTBLOCK_RISCV is not set
+# CONFIG_ARCH_VERSTAGE_RISCV is not set
+# CONFIG_ARCH_ROMSTAGE_RISCV is not set
+# CONFIG_ARCH_RAMSTAGE_RISCV is not set
+CONFIG_ARCH_X86=y
+CONFIG_ARCH_BOOTBLOCK_X86_32=y
+CONFIG_ARCH_VERSTAGE_X86_32=y
+CONFIG_ARCH_ROMSTAGE_X86_32=y
+CONFIG_ARCH_RAMSTAGE_X86_32=y
+# CONFIG_ARCH_BOOTBLOCK_X86_64 is not set
+# CONFIG_ARCH_VERSTAGE_X86_64 is not set
+# CONFIG_ARCH_ROMSTAGE_X86_64 is not set
+# CONFIG_ARCH_RAMSTAGE_X86_64 is not set
+# CONFIG_USE_MARCH_586 is not set
+# CONFIG_AP_IN_SIPI_WAIT is not set
+# CONFIG_SIPI_VECTOR_IN_ROM is not set
+# CONFIG_ROMCC is not set
+# CONFIG_LATE_CBMEM_INIT is not set
+CONFIG_PC80_SYSTEM=y
+# CONFIG_BOOTBLOCK_DEBUG_SPINLOOP is not set
+# CONFIG_BOOTBLOCK_SAVE_BIST_AND_TIMESTAMP is not set
+CONFIG_HAVE_CMOS_DEFAULT=y
+CONFIG_CMOS_DEFAULT_FILE="src/mainboard/$(MAINBOARDDIR)/cmos.default"
+CONFIG_IOAPIC_INTERRUPTS_ON_FSB=y
+# CONFIG_IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS is not set
+# CONFIG_POSTCAR_STAGE is not set
+# CONFIG_VERSTAGE_DEBUG_SPINLOOP is not set
+# CONFIG_ROMSTAGE_DEBUG_SPINLOOP is not set
+
+#
+# Devices
+#
+# CONFIG_MAINBOARD_HAS_NATIVE_VGA_INIT is not set
+CONFIG_NATIVE_VGA_INIT_USE_EDID=y
+# CONFIG_MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG is not set
+# CONFIG_VGA_ROM_RUN is not set
+# CONFIG_ON_DEVICE_ROM_LOAD is not set
+# CONFIG_MULTIPLE_VGA_ADAPTERS is not set
+# CONFIG_SMBUS_HAS_AUX_CHANNELS is not set
+# CONFIG_SPD_CACHE is not set
+CONFIG_PCI=y
+# CONFIG_HYPERTRANSPORT_PLUGIN_SUPPORT is not set
+CONFIG_PCIX_PLUGIN_SUPPORT=y
+CONFIG_PCIEXP_PLUGIN_SUPPORT=y
+CONFIG_CARDBUS_PLUGIN_SUPPORT=y
+# CONFIG_AZALIA_PLUGIN_SUPPORT is not set
+CONFIG_PCIEXP_COMMON_CLOCK=y
+CONFIG_PCIEXP_ASPM=y
+# CONFIG_PCIEXP_CLK_PM is not set
+# CONFIG_EARLY_PCI_BRIDGE is not set
+# CONFIG_PCIEXP_L1_SUB_STATE is not set
+CONFIG_SUBSYSTEM_VENDOR_ID=0x1458
+CONFIG_SUBSYSTEM_DEVICE_ID=0x5006
+# CONFIG_SOFTWARE_I2C is not set
+
+#
+# Generic Drivers
+#
+# CONFIG_DRIVERS_AS3722_RTC is not set
+# CONFIG_GIC is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_DRIVERS_LENOVO_WACOM is not set
+# CONFIG_DRIVERS_LENOVO_HYBRID_GRAPHICS is not set
+# CONFIG_REALTEK_8168_RESET is not set
+CONFIG_SPI_FLASH=y
+CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP=y
+# CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY is not set
+CONFIG_SPI_ATOMIC_SEQUENCING=y
+# CONFIG_SPI_FLASH_SMM is not set
+# CONFIG_SPI_FLASH_NO_FAST_READ is not set
+CONFIG_SPI_FLASH_ADESTO=y
+CONFIG_SPI_FLASH_AMIC=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+# CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B is not set
+# CONFIG_HAVE_SPI_CONSOLE_SUPPORT is not set
+CONFIG_DRIVERS_UART=y
+# CONFIG_DRIVERS_UART_8250IO_SKIP_INIT is not set
+# CONFIG_NO_UART_ON_SUPERIO is not set
+# CONFIG_UART_OVERRIDE_INPUT_CLOCK_DIVIDER is not set
+# CONFIG_UART_OVERRIDE_REFCLK is not set
+# CONFIG_DRIVERS_UART_8250MEM is not set
+# CONFIG_DRIVERS_UART_8250MEM_32 is not set
+# CONFIG_HAVE_UART_SPECIAL is not set
+# CONFIG_DRIVERS_UART_OXPCIE is not set
+# CONFIG_DRIVERS_UART_PL011 is not set
+# CONFIG_UART_USE_REFCLK_AS_INPUT_CLOCK is not set
+CONFIG_HAVE_USBDEBUG=y
+CONFIG_HAVE_USBDEBUG_OPTIONS=y
+# CONFIG_SMBIOS_PROVIDED_BY_MOBO is not set
+# CONFIG_DRIVERS_I2C_PCF8523 is not set
+# CONFIG_DRIVERS_I2C_RTD2132 is not set
+# CONFIG_MAINBOARD_HAS_I2C_TPM_CR50 is not set
+# CONFIG_DRIVER_I2C_TPM_ACPI is not set
+# CONFIG_INTEL_DP is not set
+# CONFIG_INTEL_DDI is not set
+# CONFIG_INTEL_EDID is not set
+CONFIG_INTEL_INT15=y
+CONFIG_INTEL_GMA_ACPI=y
+# CONFIG_DRIVER_INTEL_I210 is not set
+CONFIG_DRIVERS_INTEL_WIFI=y
+# CONFIG_DRIVER_MAXIM_MAX77686 is not set
+# CONFIG_DRIVER_PARADE_PS8625 is not set
+# CONFIG_DRIVER_PARADE_PS8640 is not set
+CONFIG_DRIVERS_MC146818=y
+# CONFIG_MAINBOARD_HAS_LPC_TPM is not set
+# CONFIG_DRIVERS_RICOH_RCE822 is not set
+# CONFIG_DRIVER_SIEMENS_NC_FPGA is not set
+# CONFIG_DRIVERS_SIL_3114 is not set
+# CONFIG_DRIVER_TI_TPS65090 is not set
+# CONFIG_DRIVERS_TI_TPS65913 is not set
+# CONFIG_DRIVERS_TI_TPS65913_RTC is not set
+# CONFIG_DRIVER_XPOWERS_AXP209 is not set
+CONFIG_ACPI_SATA_GENERATOR=y
+CONFIG_ACPI_INTEL_HARDWARE_SLEEP_VALUES=y
+# CONFIG_BOOT_DEVICE_NOT_SPI_FLASH is not set
+CONFIG_BOOT_DEVICE_SPI_FLASH=y
+CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y
+# CONFIG_BOOT_DEVICE_SUPPORTS_WRITES is not set
+CONFIG_RTC=y
+# CONFIG_TPM is not set
+CONFIG_STACK_SIZE=0x1000
+CONFIG_MMCONF_SUPPORT_DEFAULT=y
+CONFIG_MMCONF_SUPPORT=y
+
+#
+# Console
+#
+CONFIG_SQUELCH_EARLY_SMP=y
+CONFIG_CONSOLE_SERIAL=y
+
+#
+# I/O mapped, 8250-compatible
+#
+
+#
+# Serial port base address = 0x3f8
+#
+# CONFIG_CONSOLE_SERIAL_921600 is not set
+# CONFIG_CONSOLE_SERIAL_460800 is not set
+# CONFIG_CONSOLE_SERIAL_230400 is not set
+CONFIG_CONSOLE_SERIAL_115200=y
+# CONFIG_CONSOLE_SERIAL_57600 is not set
+# CONFIG_CONSOLE_SERIAL_38400 is not set
+# CONFIG_CONSOLE_SERIAL_19200 is not set
+# CONFIG_CONSOLE_SERIAL_9600 is not set
+# CONFIG_SPKMODEM is not set
+# CONFIG_CONSOLE_NE2K is not set
+CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x20000
+# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_8 is not set
+CONFIG_DEFAULT_CONSOLE_LOGLEVEL_7=y
+# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_6 is not set
+# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_5 is not set
+# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_4 is not set
+# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_3 is not set
+# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_2 is not set
+# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1 is not set
+# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_0 is not set
+# CONFIG_CMOS_POST is not set
+# CONFIG_POST_DEVICE_NONE is not set
+# CONFIG_POST_DEVICE_LPC is not set
+CONFIG_POST_DEVICE_PCI_PCIE=y
+CONFIG_POST_IO_PORT=0x680
+# CONFIG_NO_EARLY_BOOTBLOCK_POSTCODES is not set
+CONFIG_HAVE_ACPI_RESUME=y
+CONFIG_RESUME_PATH_SAME_AS_BOOT=y
+CONFIG_HAVE_HARD_RESET=y
+# CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK is not set
+# CONFIG_HAVE_ROMSTAGE_NVRAM_CBFS_SPINLOCK is not set
+# CONFIG_HAVE_ROMSTAGE_MICROCODE_CBFS_SPINLOCK is not set
+CONFIG_HAVE_MONOTONIC_TIMER=y
+# CONFIG_GENERIC_UDELAY is not set
+# CONFIG_TIMER_QUEUE is not set
+CONFIG_HAVE_OPTION_TABLE=y
+# CONFIG_PIRQ_ROUTE is not set
+CONFIG_HAVE_SMI_HANDLER=y
+# CONFIG_PCI_IO_CFG_EXT is not set
+CONFIG_IOAPIC=y
+CONFIG_USE_WATCHDOG_ON_BOOT=y
+# CONFIG_VGA is not set
+# CONFIG_GFXUMA is not set
+CONFIG_HAVE_ACPI_TABLES=y
+CONFIG_COMMON_FADT=y
+# CONFIG_ACPI_NHLT is not set
+
+#
+# System tables
+#
+# CONFIG_GENERATE_MP_TABLE is not set
+# CONFIG_GENERATE_PIRQ_TABLE is not set
+CONFIG_GENERATE_SMBIOS_TABLES=y
+CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME="GA-B75M-D3V"
+
+#
+# Payload
+#
+# CONFIG_PAYLOAD_NONE is not set
+# CONFIG_PAYLOAD_ELF is not set
+# CONFIG_PAYLOAD_BAYOU is not set
+# CONFIG_PAYLOAD_FILO is not set
+# CONFIG_PAYLOAD_GRUB2 is not set
+CONFIG_PAYLOAD_SEABIOS=y
+# CONFIG_PAYLOAD_UBOOT is not set
+# CONFIG_PAYLOAD_LINUX is not set
+# CONFIG_PAYLOAD_TIANOCORE is not set
+CONFIG_PAYLOAD_FILE="payloads/external/SeaBIOS/seabios/out/bios.bin.elf"
+# CONFIG_SEABIOS_STABLE is not set
+# CONFIG_SEABIOS_MASTER is not set
+CONFIG_SEABIOS_REVISION=y
+CONFIG_SEABIOS_REVISION_ID="remotes/origin/1.9-stable"
+# CONFIG_SEABIOS_THREAD_OPTIONROMS is not set
+CONFIG_SEABIOS_BOOTORDER_FILE=""
+CONFIG_PAYLOAD_OPTIONS=""
+# CONFIG_PXE is not set
+CONFIG_COMPRESSED_PAYLOAD_LZMA=y
+# CONFIG_PAYLOAD_IS_FLAT_BINARY is not set
+
+#
+# Secondary Payloads
+#
+CONFIG_COREINFO_SECONDARY_PAYLOAD=y
+CONFIG_MEMTEST_SECONDARY_PAYLOAD=y
+CONFIG_MEMTEST_STABLE=y
+# CONFIG_MEMTEST_MASTER is not set
+# CONFIG_NVRAMCUI_SECONDARY_PAYLOAD is not set
+# CONFIG_TINT_SECONDARY_PAYLOAD is not set
+
+#
+# Debugging
+#
+# CONFIG_GDB_STUB is not set
+# CONFIG_FATAL_ASSERTS is not set
+# CONFIG_DEBUG_CBFS is not set
+CONFIG_HAVE_DEBUG_RAM_SETUP=y
+# CONFIG_DEBUG_RAM_SETUP is not set
+# CONFIG_HAVE_DEBUG_CAR is not set
+# CONFIG_HAVE_DEBUG_SMBUS is not set
+# CONFIG_DEBUG_SMI is not set
+# CONFIG_DEBUG_SMM_RELOCATION is not set
+# CONFIG_DEBUG_MALLOC is not set
+# CONFIG_DEBUG_ACPI is not set
+# CONFIG_DEBUG_SPI_FLASH is not set
+# CONFIG_TRACE is not set
+# CONFIG_DEBUG_BOOT_STATE is not set
+# CONFIG_ENABLE_APIC_EXT_ID is not set
+CONFIG_WARNINGS_ARE_ERRORS=y
+# CONFIG_POWER_BUTTON_DEFAULT_ENABLE is not set
+# CONFIG_POWER_BUTTON_DEFAULT_DISABLE is not set
+# CONFIG_POWER_BUTTON_FORCE_ENABLE is not set
+# CONFIG_POWER_BUTTON_FORCE_DISABLE is not set
+# CONFIG_POWER_BUTTON_IS_OPTIONAL is not set
+# CONFIG_REG_SCRIPT is not set
+# CONFIG_CREATE_BOARD_CHECKLIST is not set
+# CONFIG_MAKE_CHECKLIST_PUBLIC is not set
diff --git a/seabiosconfig.txt b/seabiosconfig.txt
new file mode 100644
index 0000000..d514fb0
--- /dev/null
+++ b/seabiosconfig.txt
@@ -0,0 +1,96 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# SeaBIOS Configuration
+#
+
+#
+# General Features
+#
+CONFIG_COREBOOT=y
+# CONFIG_QEMU is not set
+# CONFIG_CSM is not set
+# CONFIG_QEMU_HARDWARE is not set
+CONFIG_THREADS=y
+CONFIG_RELOCATE_INIT=y
+CONFIG_BOOTMENU=y
+CONFIG_BOOTSPLASH=y
+CONFIG_BOOTORDER=y
+CONFIG_COREBOOT_FLASH=y
+CONFIG_LZMA=y
+CONFIG_CBFS_LOCATION=0
+CONFIG_MULTIBOOT=y
+CONFIG_ENTRY_EXTRASTACK=y
+CONFIG_MALLOC_UPPERMEMORY=y
+CONFIG_ROM_SIZE=0
+
+#
+# Hardware support
+#
+CONFIG_ATA=y
+CONFIG_ATA_DMA=y
+# CONFIG_ATA_PIO32 is not set
+CONFIG_AHCI=y
+# CONFIG_SDCARD is not set
+# CONFIG_MEGASAS is not set
+# CONFIG_FLOPPY is not set
+# CONFIG_FLASH_FLOPPY is not set
+CONFIG_PS2PORT=y
+CONFIG_USB=y
+CONFIG_USB_UHCI=y
+CONFIG_USB_OHCI=y
+CONFIG_USB_EHCI=y
+CONFIG_USB_XHCI=y
+CONFIG_USB_MSC=y
+CONFIG_USB_UAS=y
+CONFIG_USB_HUB=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_USB_MOUSE=y
+CONFIG_SERIAL=y
+# CONFIG_LPT is not set
+CONFIG_RTC_TIMER=y
+CONFIG_HARDWARE_IRQ=y
+CONFIG_PMTIMER=y
+CONFIG_TSC_TIMER=y
+
+#
+# BIOS interfaces
+#
+CONFIG_DRIVES=y
+CONFIG_CDROM_BOOT=y
+CONFIG_CDROM_EMU=y
+CONFIG_PCIBIOS=y
+CONFIG_APMBIOS=y
+CONFIG_PNPBIOS=y
+CONFIG_OPTIONROMS=y
+CONFIG_PMM=y
+CONFIG_BOOT=y
+CONFIG_KEYBOARD=y
+CONFIG_KBD_CALL_INT15_4F=y
+CONFIG_MOUSE=y
+CONFIG_S3_RESUME=y
+CONFIG_VGAHOOKS=y
+# CONFIG_DISABLE_A20 is not set
+CONFIG_TCGBIOS=y
+
+#
+# VGA ROM
+#
+# CONFIG_NO_VGABIOS=y
+# CONFIG_VGA_GEODEGX2 is not set
+# CONFIG_VGA_GEODELX is not set
+CONFIG_VGA_COREBOOT=y
+CONFIG_BUILD_VGABIOS=y
+CONFIG_VGA_EMULATE_TEXT=y
+CONFIG_VGA_FIXUP_ASM=y
+CONFIG_VGA_ALLOCATE_EXTRA_STACK=y
+CONFIG_VGA_EXTRA_STACK_SIZE=512
+CONFIG_VGA_VBE=y
+
+
+#
+# Debugging
+#
+CONFIG_DEBUG_LEVEL=3
+CONFIG_DEBUG_SERIAL=y
+CONFIG_DEBUG_SERIAL_PORT=0x3f8
+CONFIG_DEBUG_COREBOOT=y
diff --git a/src/lib/romstage_stack.c b/src/lib/romstage_stack.c
index fde9d1b..26ad6d1 100644
--- a/src/lib/romstage_stack.c
+++ b/src/lib/romstage_stack.c
@@ -21,7 +21,7 @@
  * Romstage needs quite a bit of stack for decompressing images since the lzma
  * lib keeps its state on the stack during romstage.
  */
-#define ROMSTAGE_RAM_STACK_SIZE 0x5000
+#define ROMSTAGE_RAM_STACK_SIZE 0xA000 // was 0x5000; 0xA000=2*0x5000 so we have place to save the paging tables
 
 uintptr_t romstage_ram_stack_base(size_t size, int src)
 {
diff --git a/src/mainboard/gigabyte/ga-b75m-d3v/cmos.default b/src/mainboard/gigabyte/ga-b75m-d3v/cmos.default
index 767372c..62c0409 100644
--- a/src/mainboard/gigabyte/ga-b75m-d3v/cmos.default
+++ b/src/mainboard/gigabyte/ga-b75m-d3v/cmos.default
@@ -4,5 +4,4 @@ debug_level=Spew
 power_on_after_fail=Enable
 nmi=Enable
 volume=0x3
-sata_mode=AHCI
-hyper_threading=Enable
+hyper_threading=Enable
\ No newline at end of file
diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig
index 2fb4551..e3449ca 100644
--- a/src/northbridge/intel/sandybridge/Kconfig
+++ b/src/northbridge/intel/sandybridge/Kconfig
@@ -77,11 +77,11 @@ if USE_NATIVE_RAMINIT
 
 config DCACHE_RAM_BASE
 	hex
-	default 0xfefe0000
+	default 0xFF000000 #used in MTRR so should be a multiple of its size; was 0xfefe0000
 
 config DCACHE_RAM_SIZE
 	hex
-	default 0x20000
+	default 0x40000 #used in MTRR so should be a power of 2; was 0x20000
 
 config DCACHE_RAM_MRC_VAR_SIZE
 	hex
diff --git a/src/northbridge/intel/sandybridge/early_init.c b/src/northbridge/intel/sandybridge/early_init.c
index 779f29b..924a04b 100644
--- a/src/northbridge/intel/sandybridge/early_init.c
+++ b/src/northbridge/intel/sandybridge/early_init.c
@@ -77,6 +77,20 @@ static void sandybridge_setup_bars(void)
 #endif
 }
 
+
+// We want to do serial uart comm
+#define UART_LSR 0x05
+#define UART_RBR 0x00
+#define SIO_PORT 0x3f8
+
+static u8 get_serial_input_once(void)
+{
+	u8 val;
+	val = inb(SIO_PORT + UART_RBR);
+	return val;
+}
+
+
 static void sandybridge_setup_graphics(void)
 {
 	u32 reg32;
@@ -184,10 +198,12 @@ static void start_peg_link_training(void)
 	}
 }
 
+
 void sandybridge_early_initialization(int chipset_type)
 {
 	u32 capid0_a;
 	u32 deven;
+	u16 reg16;
 	u8 reg8;
 
 	/* Device ID Override Enable should be done very early */
@@ -208,20 +224,47 @@ void sandybridge_early_initialization(int chipset_type)
 	/* Setup IOMMU BARs */
 	sandybridge_init_iommu();
 
-	/* Device Enable, don't touch PEG bits */
-	deven = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN) | DEVEN_IGD;
-	pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, deven);
 
-	sandybridge_setup_graphics();
+	printk(BIOS_DEBUG, "Press ' ' if you want to start OS, anything else defaults to acquisition (disabling graphics)\n");
+
+	if(!(get_serial_input_once() == ' '))  // default to disabling internal graphics. Only skip when there is some input
+	{
+		// Disable the IGD and PEG (PCIe Graphics Attach)
+		printk(BIOS_DEBUG, "Disabling internal graphics\n");
+
 
-	/* Write magic value to start PEG link training.
-	 * This should be done in PCI device enumeration, but
-	 * the PCIe specification requires to wait at least 100msec
-	 * after reset for devices to come up.
-	 * As we don't want to increase boot time, enable it early and
-	 * assume the PEG is up as soon as PCI enumeration starts.
-	 * TODO: use time stamps to ensure the timings are met */
-	start_peg_link_training();
+		/* Disable IGD Device (enabled on reset) */
+		deven = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN);
+		deven &= ~DEVEN_IGD; // disable IGD
+		pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, deven);
+
+		reg16 = pci_read_config16(PCI_DEV(0,0,0), GGC);
+		reg16 &= ~0x00f8; // Set amount of graphics memory to acquire to zero
+		reg16 |= 0x0002; // Disable IGD
+		pci_write_config16(PCI_DEV(0,0,0), GGC, reg16);
+
+	}
+	else
+	{
+		printk(BIOS_DEBUG, "Skipping disabling internal graphics, so we enable as normal\n");
+
+
+		/* Device Enable IGD, don't touch PEG bits */
+		deven = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN) | DEVEN_IGD;
+		pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, deven);
+
+		sandybridge_setup_graphics(); // initialize graphics
+
+
+		/* Write magic value to start PEG link training.
+		 * This should be done in PCI device enumeration, but
+		 * the PCIe specification requires to wait at least 100msec
+		 * after reset for devices to come up.
+		 * As we don't want to increase boot time, enable it early and
+		 * assume the PEG is up as soon as PCI enumeration starts.
+		 * TODO: use time stamps to ensure the timings are met */
+		start_peg_link_training();
+	}
 }
 
 void northbridge_romstage_finalize(int s3resume)
diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c
index 45bf476..65c5895 100644
--- a/src/northbridge/intel/sandybridge/raminit.c
+++ b/src/northbridge/intel/sandybridge/raminit.c
@@ -213,6 +213,76 @@ static const char *ecc_decoder[] = {
 	"active"
 };
 
+
+
+
+
+
+
+// We want to do serial uart comm
+#define UART_LSR 0x05
+#define UART_RBR 0x00
+#define SIO_PORT 0x3f8
+
+
+static u8 get_serial_input_once(void)
+{
+	u8 val;
+	val = inb(SIO_PORT + UART_RBR);
+	return val;
+}
+
+
+static u8 get_serial_input_blocking(void)
+{
+	while (!(inb(SIO_PORT + UART_LSR) & 0x01)) ;
+	u8 val;
+	val = inb(SIO_PORT + UART_RBR);
+
+	if(val == '!')
+	{
+		printk(BIOS_DEBUG, "Received reset signal, are you sure you want to reset the machine? Press 'y'\n");
+
+		if(get_serial_input_blocking() == 'y')
+		{
+			// Reset
+			outb(0x6, 0xcf9);
+			halt();
+		}
+
+	}
+
+
+	return val;
+}
+
+#if false
+static bool check_serial_input_once(void)
+{
+	u8 val = (inb(SIO_PORT + UART_LSR) & 0x01);
+
+	return (val & 0b1);
+}
+#endif
+
+static uint32_t get_serial_input_blocking32(void)
+{
+	uint32_t val=0;
+	for(int i=0;i<4;i++)
+	{
+		while (!(inb(SIO_PORT + UART_LSR) & 0x01)) ;
+		val |= (inb(SIO_PORT + UART_RBR) << (24-(8*i))); // fills val from msb to lsb
+	}
+	return val;
+}
+
+
+
+
+
+
+
+
 static void wait_txt_clear(void)
 {
 	struct cpuid_result cp;
@@ -342,6 +412,7 @@ static void report_memory_config(void)
 /*
  * Return CRC16 match for all SPDs.
  */
+#if false //Not needed only used with MRC cache which we dont use
 static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
 {
 	int channel, slot, spd_slot;
@@ -356,6 +427,7 @@ static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
 	}
 	return match;
 }
+#endif
 
 void read_spd(spd_raw_data * spd, u8 addr)
 {
@@ -449,8 +521,11 @@ static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
 			ctrl->ref_card_offset[channel] = 0;
 	}
 
-	if (!dimms)
-		die("No DIMMs were found");
+	if (!dimms) { // We dont want to die when no DIMMs are found, we want to loop!
+		printk(BIOS_DEBUG, "No DIMMs were found, sleep and recurse\n");
+		delay(1); // sleep a second
+		dram_find_spds_ddr3(spd, ctrl); // Recurse for now, we should however count how much we tried..
+	}
 }
 
 static void dram_find_common_params(ramctr_timing *ctrl)
@@ -828,8 +903,9 @@ static void dram_freq(ramctr_timing * ctrl)
 		reg1 = FRQ;
 		reg1 |= 0x80000000;	// set running bit
 		MCHBAR32(0x5e00) = reg1;
-		while (reg1 & 0x80000000) {
-			printk(BIOS_DEBUG, " PLL busy...");
+		while (reg1 & 0x80000000) { // TODO this code could do infinite loop, make sure this doesnt happen
+
+			printk(BIOS_DEBUG, " PLL busy..."); 
 			reg1 = MCHBAR32(0x5e00);
 		}
 		printk(BIOS_DEBUG, "done\n");
@@ -1090,32 +1166,85 @@ static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
 	uint16_t ggc;
 
 	mmiosize = get_mmio_size();
+	printk(BIOS_DEBUG, "mmiosize %d, mmiosize bytes 0x%016llx\n", (int) mmiosize, ((uint64_t)((uint64_t)get_mmio_size())*1024*1024));
+
 
 	ggc = pci_read_config16(NORTHBRIDGE, GGC);
+
 	if (!(ggc & 2)) {
 		gfxstolen = ((ggc >> 3) & 0x1f) * 32;
 		gttsize = ((ggc >> 8) & 0x3);
 	} else {
+
 		gfxstolen = 0;
 		gttsize = 0;
 	}
 
-	tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
+	printk(BIOS_DEBUG, "Press ' ' if you want to start OS, anything else defaults to acquisition (disabling TSEG)\n");
+
+
+
+	if(!(get_serial_input_once() == ' ')) // default to disabling TSEG. Only skip when there is some input
+	{
+		tsegsize = 0;
+
+		printk(BIOS_DEBUG, "Reading SMRAMC - SMM RAM control register\n");
+		uint32_t SMRAMC = pcie_read_config32(NORTHBRIDGE, SMRAM);
+		printk(BIOS_DEBUG, "SMRAMC=0x%08x\n", SMRAMC);
+		SMRAMC |= (1 << 6); // enable D_OPEN
+		SMRAMC |= (1 << 3); // enable G_SMRAM
+		SMRAMC &= ~(1 << 4); // disable D_LOCK
+
+		printk(BIOS_DEBUG, "Trying to make SMRAM area readable\n");
+		printk(BIOS_DEBUG, "setting SMRAMC=0x%08x\n", SMRAMC);
+		pcie_write_config32(NORTHBRIDGE, SMRAM, SMRAMC);
+
+		printk(BIOS_DEBUG, "Reading SMRAMC back again\n");
+		SMRAMC = pcie_read_config32(NORTHBRIDGE, SMRAM);
+		printk(BIOS_DEBUG, "SMRAMC=0x%08x\n", SMRAMC);
+
+		printk(BIOS_DEBUG, "Mmiosize=%d, gfxstolen=%d, gttsize=%d, me_uma_size=%d, CONFIG_SMM_TSEG_SIZE=%d, tsegsize=%d \n", (int) mmiosize, (int) gfxstolen, (int) gttsize, (int) me_uma_size, (int) CONFIG_SMM_TSEG_SIZE, (int) tsegsize); // able to check whether gfx steals mem..
+
+		tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
+
+		mestolenbase = tom - me_uma_size;
+
+		toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
+				tom - me_uma_size);
+		gfxstolenbase = toludbase - gfxstolen;
+		gttbase = gfxstolenbase - gttsize;
+
+		tsegbase = gttbase - tsegsize;
+
+
+
+		// Disable tseg, base delta equal to base
+		tsegbasedelta = 0;
+		tsegbase = tsegbase;
+	}
+	else
+	{
+		tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
+
+		printk(BIOS_DEBUG, "mmiosize=%d, gfxstolen=%d, gttsize=%d, me_uma_size=%d, CONFIG_SMM_TSEG_SIZE=%d, tsegsize=%d \n", (int) mmiosize, (int) gfxstolen, (int) gttsize, (int) me_uma_size, (int) CONFIG_SMM_TSEG_SIZE, (int) tsegsize); // able to check whether gfx steals mem..
+
+		tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
 
-	tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
+		mestolenbase = tom - me_uma_size;
 
-	mestolenbase = tom - me_uma_size;
+		toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
+				tom - me_uma_size);
+		gfxstolenbase = toludbase - gfxstolen;
+		gttbase = gfxstolenbase - gttsize;
 
-	toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
-			tom - me_uma_size);
-	gfxstolenbase = toludbase - gfxstolen;
-	gttbase = gfxstolenbase - gttsize;
+		tsegbase = gttbase - tsegsize;
 
-	tsegbase = gttbase - tsegsize;
+		// Round tsegbase down to nearest address aligned to tsegsize
+		tsegbasedelta = tsegbase & (tsegsize - 1);
+		tsegbase &= ~(tsegsize - 1);
+	}
 
-	// Round tsegbase down to nearest address aligned to tsegsize
-	tsegbasedelta = tsegbase & (tsegsize - 1);
-	tsegbase &= ~(tsegsize - 1);
+	printk(BIOS_DEBUG, "tsegbasedelta=0x%zx, tsegbase=0x%zx\n",tsegbasedelta,tsegbase);
 
 	gttbase -= tsegbasedelta;
 	gfxstolenbase -= tsegbasedelta;
@@ -1135,6 +1264,8 @@ static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
 		touudbase = tom - me_uma_size;
 	}
 
+	printk(BIOS_DEBUG, "tom %d, toludbase 0x%zx, touudbase 0x%zx, tsegbase 0x%zx \n", tom, toludbase, touudbase, tsegbase);
+
 	// Update memory map in pci-e configuration space
 	printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
 
@@ -1181,6 +1312,8 @@ static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
 		pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
 		pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
 	}
+
+
 	// TSEG
 	reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
 	val = tsegbase & 0xfff;
@@ -1203,6 +1336,7 @@ static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
 	pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
 
 	if (me_uma_size) {
+		printk(BIOS_DEBUG, "ME stole some memory\n");
 		reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
 		val = (0x80000 - me_uma_size) & 0xfffff000;
 		reg = (reg & ~0x000fffff) | (val >> 12);
@@ -1234,6 +1368,7 @@ static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
 	}
 }
 
+
 static void dram_ioregs(ramctr_timing * ctrl)
 {
 	u32 reg, comp2;
@@ -1286,9 +1421,17 @@ static void dram_ioregs(ramctr_timing * ctrl)
 
 static void wait_428c(int channel)
 {
+	uint64_t counter = 0;  // TODO this code could do infinite loop, make sure this doesnt happen
 	while (1) {
 		if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
 			return;
+
+		if(counter == 5000)
+		{
+			printk(BIOS_DEBUG, "Stuck in wait_428c() printing every 5000 iterations\n");
+			counter = 0;
+		}
+		counter++;
 	}
 }
 
@@ -2926,6 +3069,7 @@ static void reprogram_320c(ramctr_timing * ctrl)
 
 	/* refresh disable */
 	write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
+
 	FOR_ALL_POPULATED_CHANNELS {
 		wait_428c(channel);
 
@@ -3759,19 +3903,89 @@ static int channel_test(ramctr_timing *ctrl)
 static void set_scrambling_seed(ramctr_timing * ctrl)
 {
 	int channel;
+	uint8_t serialInput;
 
 	/* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
 	   I don't think so.  */
-	static u32 seeds[NUM_CHANNELS][3] = {
-		{0x00009a36, 0xbafcfdcf, 0x46d1ab68},
+	u32 seeds[NUM_CHANNELS][3] = {
+		// scramblingseed1, scramblingseed2HIGH, scramblingseed2LOW
+		{0x00009a36, 0xbafcfdcf, 0x46d1ab68}, // two channels, three seeds for every channel
 		{0x00028bfa, 0x53fe4b49, 0x19ed5483}
 	};
+
+
+
+	//#if false //disable scrambling seed selection
+	printk(BIOS_DEBUG, "Select whether you want to change the scrambling seeds by entering 'y' or 'd' loads default NULL seeds, anything else skips this\n");
+	serialInput = get_serial_input_blocking();
+	if(serialInput == 'y')
+	{
+		printk(BIOS_DEBUG, "Enter a 32 bits you want to change the seeds into (ASCII representation)\n");
+
+		printk(BIOS_DEBUG, "seed1\n");
+		uint32_t seed1Input = get_serial_input_blocking32();
+		printk(BIOS_DEBUG, "Received seed1: 0x%08x \n", (uint32_t) seed1Input);
+
+		printk(BIOS_DEBUG, "seed2high\n");
+		uint32_t seed2HighInput = get_serial_input_blocking32();
+		printk(BIOS_DEBUG, "Received seed2high: 0x%08x \n", (uint32_t) seed2HighInput);
+
+		printk(BIOS_DEBUG, "seed2low\n");
+		uint32_t seed2LowInput = get_serial_input_blocking32();
+		printk(BIOS_DEBUG, "Received seed2low: 0x%08x \n", (uint32_t) seed2LowInput);
+
+		FOR_ALL_CHANNELS {
+				seeds[channel][0] = (uint32_t) seed1Input; 
+				seeds[channel][1] = (uint32_t) seed2HighInput; 
+				seeds[channel][2] = (uint32_t) seed2LowInput; 
+		}
+	} else if(serialInput == 'd') {
+		FOR_ALL_CHANNELS {
+			seeds[channel][0] = (uint32_t) 0x0;
+			seeds[channel][1] = (uint32_t) 0x0;
+			seeds[channel][2] = (uint32_t) 0x0;
+			printk(BIOS_DEBUG, "seed1=seed2high=seed2low=0x0\n");
+		}
+
+	} else {
+			printk(BIOS_DEBUG, "Skipping seed changing\n");
+	}
+
+
+	printk(BIOS_DEBUG, "Select whether you want to disable scrambling by entering 'y', anything else skips this\n");
+	serialInput = get_serial_input_blocking();
+	if(serialInput == 'y')
+	{
+		printk(BIOS_DEBUG, "Scrambling was not enabled (disabled) \n");
+		FOR_ALL_POPULATED_CHANNELS {
+			MCHBAR32(0x4020 + 0x400 * channel) |= 0x10000000; // enable scrambling
+			write32(DEFAULT_MCHBAR + 0x4034, 0x0); // scramblingseed1
+			write32(DEFAULT_MCHBAR + 0x403c, 0x0); // scramblingseed2HIGH
+			write32(DEFAULT_MCHBAR + 0x4038, 0x0); // scramblingseed2LOW
+		}
+	}
+	else
+	{
+		printk(BIOS_DEBUG, "Enabling scrambling as normal\n");
+		FOR_ALL_POPULATED_CHANNELS {
+			MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000; // enable scrambling
+			write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]); // scramblingseed1
+			write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]); // scramblingseed2HIGH
+			write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]); // scramblingseed2LOW
+		}
+	}
+	//#endif //disable scrambling seed selection
+
+
+	#if false // disable setting scrambling seeds automatically 
+	printk(BIOS_DEBUG, "Enabling scrambling as normal\n");
 	FOR_ALL_POPULATED_CHANNELS {
-		MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
-		write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
-		write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
-		write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
+		MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000; // enable scrambling
+		write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]); // scramblingseed1
+		write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]); // scramblingseed2HIGH
+		write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]); // scramblingseed2LOW
 	}
+	#endif
 }
 
 static void set_4f8c(void)
@@ -3941,11 +4155,14 @@ static void final_registers(ramctr_timing * ctrl)
 		 | 0xc);
 }
 
+// We don't want to store any timings
+#if false
 static void save_timings(ramctr_timing *ctrl)
 {
 	/* Save the MRC S3 restore data to cbmem */
 	store_current_mrc_cache(ctrl, sizeof(*ctrl));
 }
+#endif
 
 static void restore_timings(ramctr_timing * ctrl)
 {
@@ -4043,6 +4260,7 @@ static void restore_timings(ramctr_timing * ctrl)
 	write32(DEFAULT_MCHBAR + 0x4ea8, 0);
 }
 
+
 static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot,
 		int s3_resume, int me_uma_size)
 {
@@ -4117,11 +4335,12 @@ static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot,
 		/* Prepare for memory training */
 		prepare_training(ctrl);
 
+
 		err = read_training(ctrl);
 		if (err)
 			return err;
 
-		err = write_training(ctrl);
+		err = write_training(ctrl); // TODO write_training disables and enables refresh, check if this does harm to the data. It probably does!
 		if (err)
 			return err;
 
@@ -4163,170 +4382,2005 @@ static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot,
 	return 0;
 }
 
-void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck,
-	int s3resume)
-{
-	int me_uma_size;
-	int cbmem_was_inited;
-	ramctr_timing ctrl;
-	int fast_boot;
-	struct mrc_data_container *mrc_cache;
-	ramctr_timing *ctrl_cached;
-	int err;
-
-	MCHBAR32(0x5f00) |= 1;
 
-	report_platform_info();
 
-	/* Wait for ME to be ready */
-	intel_early_me_init();
-	me_uma_size = intel_early_me_uma_size();
+//#iffalse // Disable ATA PIO
+#include <delay.h>
+// Stolen from seabios/src/hw/ata.h
+
+// Global defines -- ATA register and register bits.
+// command block & control block regs
+#define ATA_CB_DATA  0   // data reg         in/out pio_base_addr1+0
+#define ATA_CB_ERR   1   // error            in     pio_base_addr1+1
+#define ATA_CB_FR    1   // feature reg         out pio_base_addr1+1
+#define ATA_CB_SC    2   // sector count     in/out pio_base_addr1+2
+#define ATA_CB_SN    3   // sector number    in/out pio_base_addr1+3
+#define ATA_CB_CL    4   // cylinder low     in/out pio_base_addr1+4
+#define ATA_CB_CH    5   // cylinder high    in/out pio_base_addr1+5
+#define ATA_CB_DH    6   // device head      in/out pio_base_addr1+6
+#define ATA_CB_STAT  7   // primary status   in     pio_base_addr1+7
+#define ATA_CB_CMD   7   // command             out pio_base_addr1+7
+
+
+#define ATA_CB_ASTAT 2   // alternate status in     pio_base_addr2+2
+#define ATA_CB_DC    2   // device control      out pio_base_addr2+2
+#define ATA_CB_DA    3   // device address   in     pio_base_addr2+3
+
+#define ATA_CB_ER_ICRC 0x80    // ATA Ultra DMA bad CRC
+#define ATA_CB_ER_BBK  0x80    // ATA bad block
+#define ATA_CB_ER_UNC  0x40    // ATA uncorrected error
+#define ATA_CB_ER_MC   0x20    // ATA media change
+#define ATA_CB_ER_IDNF 0x10    // ATA id not found
+#define ATA_CB_ER_MCR  0x08    // ATA media change request
+#define ATA_CB_ER_ABRT 0x04    // ATA command aborted
+#define ATA_CB_ER_NTK0 0x02    // ATA track 0 not found
+#define ATA_CB_ER_NDAM 0x01    // ATA address mark not found
+
+#define ATA_CB_ER_P_SNSKEY 0xf0   // ATAPI sense key (mask)
+#define ATA_CB_ER_P_MCR    0x08   // ATAPI Media Change Request
+#define ATA_CB_ER_P_ABRT   0x04   // ATAPI command abort
+#define ATA_CB_ER_P_EOM    0x02   // ATAPI End of Media
+#define ATA_CB_ER_P_ILI    0x01   // ATAPI Illegal Length Indication
+
+// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC)
+#define ATA_CB_SC_P_TAG    0xf8   // ATAPI tag (mask)
+#define ATA_CB_SC_P_REL    0x04   // ATAPI release
+#define ATA_CB_SC_P_IO     0x02   // ATAPI I/O
+#define ATA_CB_SC_P_CD     0x01   // ATAPI C/D
+
+// bits 7-4 of the device/head (CB_DH) reg
+#define ATA_CB_DH_DEV0 0xa0    // select device 0
+#define ATA_CB_DH_DEV1 0xb0    // select device 1
+#define ATA_CB_DH_LBA 0x40    // use LBA
+
+// status reg (CB_STAT and CB_ASTAT) bits
+#define ATA_CB_STAT_BSY  0x80  // busy
+#define ATA_CB_STAT_RDY  0x40  // ready
+#define ATA_CB_STAT_DF   0x20  // device fault
+#define ATA_CB_STAT_WFT  0x20  // write fault (old name)
+#define ATA_CB_STAT_SKC  0x10  // seek complete
+#define ATA_CB_STAT_SERV 0x10  // service
+#define ATA_CB_STAT_DRQ  0x08  // data request
+#define ATA_CB_STAT_CORR 0x04  // corrected
+#define ATA_CB_STAT_IDX  0x02  // index
+#define ATA_CB_STAT_ERR  0x01  // error (ATA)
+#define ATA_CB_STAT_CHK  0x01  // check (ATAPI)
+
+// device control reg (CB_DC) bits
+#define ATA_CB_DC_HD15   0x08  // bit should always be set to one
+#define ATA_CB_DC_SRST   0x04  // soft reset
+#define ATA_CB_DC_NIEN   0x02  // disable interrupts
+
+// Most mandtory and optional ATA commands (from ATA-3),
+#define ATA_CMD_NOP                          0x00
+#define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE     0x03
+#define ATA_CMD_DEVICE_RESET                 0x08
+#define ATA_CMD_RECALIBRATE                  0x10
+#define ATA_CMD_READ_SECTORS                 0x20
+#define ATA_CMD_READ_SECTORS_EXT             0x24
+#define ATA_CMD_READ_DMA_EXT                 0x25
+#define ATA_CMD_READ_DMA_QUEUED_EXT          0x26
+#define ATA_CMD_READ_NATIVE_MAX_ADDRESS_EXT  0x27
+#define ATA_CMD_READ_MULTIPLE_EXT            0x29
+#define ATA_CMD_READ_LOG_EXT                 0x2F
+#define ATA_CMD_WRITE_SECTORS                0x30
+#define ATA_CMD_WRITE_SECTORS_EXT            0x34
+#define ATA_CMD_WRITE_DMA_EXT                0x35
+#define ATA_CMD_WRITE_DMA_QUEUED_EXT         0x36
+#define ATA_CMD_SET_MAX_ADDRESS_EXT          0x37
+#define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE   0x38
+#define ATA_CMD_WRITE_MULTIPLE_EXT           0x39
+#define ATA_CMD_WRITE_VERIFY                 0x3C
+#define ATA_CMD_WRITE_LOG_EXT                0x3F
+#define ATA_CMD_READ_VERIFY_SECTORS          0x40
+#define ATA_CMD_READ_VERIFY_SECTORS_EXT      0x42
+#define ATA_CMD_FORMAT_TRACK                 0x50
+#define ATA_CMD_SEEK                         0x70
+#define ATA_CMD_CFA_TRANSLATE_SECTOR         0x87
+#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC    0x90
+#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
+#define ATA_CMD_STANDBY_IMMEDIATE2           0x94
+#define ATA_CMD_IDLE_IMMEDIATE2              0x95
+#define ATA_CMD_STANDBY2                     0x96
+#define ATA_CMD_IDLE2                        0x97
+#define ATA_CMD_CHECK_POWER_MODE2            0x98
+#define ATA_CMD_SLEEP2                       0x99
+#define ATA_CMD_PACKET                       0xA0
+#define ATA_CMD_IDENTIFY_PACKET_DEVICE       0xA1
+#define ATA_CMD_CFA_ERASE_SECTORS            0xC0
+#define ATA_CMD_READ_MULTIPLE                0xC4
+#define ATA_CMD_WRITE_MULTIPLE               0xC5
+#define ATA_CMD_SET_MULTIPLE_MODE            0xC6
+#define ATA_CMD_READ_DMA_QUEUED              0xC7
+#define ATA_CMD_READ_DMA                     0xC8
+#define ATA_CMD_WRITE_DMA                    0xCA
+#define ATA_CMD_WRITE_DMA_QUEUED             0xCC
+#define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE  0xCD
+#define ATA_CMD_STANDBY_IMMEDIATE            0xE0
+#define ATA_CMD_IDLE_IMMEDIATE               0xE1
+#define ATA_CMD_STANDBY                      0xE2
+#define ATA_CMD_IDLE                         0xE3
+#define ATA_CMD_READ_BUFFER                  0xE4
+#define ATA_CMD_CHECK_POWER_MODE             0xE5
+#define ATA_CMD_SLEEP                        0xE6
+#define ATA_CMD_FLUSH_CACHE                  0xE7
+#define ATA_CMD_WRITE_BUFFER                 0xE8
+#define ATA_CMD_IDENTIFY_DEVICE              0xEC
+#define ATA_CMD_SET_FEATURES                 0xEF
+#define ATA_CMD_READ_NATIVE_MAX_ADDRESS      0xF8
+#define ATA_CMD_SET_MAX                      0xF9
+
+#define DISK_SECTOR_SIZE  512 // Stolen from seabios/src/block.h
+
+
+#define IDE_TIMEOUT 32000 //32 seconds max for IDE ops
+
+
+
+
+//	u16 iobase1 = 0x2068; // works! finds sata2-1
+//	u16 iobase2 = 0x2074; // works! finds sata2-1
+#define IOBASE1 0x2068
+#define IOBASE2 0x2074
+#define RESERVED_SECTORS_IMAGE_TABLE 4
+
+// Stolen from coreboot/src/southbridge/intel/bd82x6x/sata.c
+static inline u32 sir_read(pci_devfn_t dev, int idx)
+{
+	pci_write_config32(dev, SATA_SIRI, idx);
+	return pci_read_config32(dev, SATA_SIRD);
+}
 
-	printk(BIOS_DEBUG, "Starting native Platform init\n");
+static inline void sir_write(pci_devfn_t dev, int idx, u32 value)
+{
+	pci_write_config32(dev, SATA_SIRI, idx);
+	pci_write_config32(dev, SATA_SIRD, value);
+}
 
-	u32 reg_5d10;
 
-	wait_txt_clear();
+// Stolen from coreboot/src/southbridge/intel/bd82x6x/pch.c
+static inline int pch_silicon_revision(void)
+{
+	int pch_revision_id = -1;
+
+#ifdef __SIMPLE_DEVICE__
+	pci_devfn_t dev;
+	dev = PCI_DEV(0, 0x1f, 0);
+#else
+	device_t dev;
+	dev = dev_find_slot(0, PCI_DEVFN(0x1f, 0));
+#endif
+
+	if (pch_revision_id < 0)
+		pch_revision_id = pci_read_config8(dev,	PCI_REVISION_ID);
+	return pch_revision_id;
+}
 
-	wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
+static inline int pch_silicon_type(void)
+{
+	int pch_type = -1;
+
+#ifdef __SIMPLE_DEVICE__
+	pci_devfn_t dev;
+	dev = PCI_DEV(0, 0x1f, 0);
+#else
+	device_t dev;
+	dev = dev_find_slot(0, PCI_DEVFN(0x1f, 0));
+#endif
+
+	if (pch_type < 0)
+		pch_type = pci_read_config8(dev, PCI_DEVICE_ID + 1);
+	return pch_type;
+}
 
-	reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10);	// !!! = 0x00000000
-	if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20	/* 0x0004 */
-	    && reg_5d10 && !s3resume) {
-		write32(DEFAULT_MCHBAR + 0x5d10, 0);
-		/* Need reset.  */
-		outb(0x6, 0xcf9);
+static inline int pch_silicon_supported(int type, int rev)
+{
+	int cur_type = pch_silicon_type();
+	int cur_rev = pch_silicon_revision();
+
+	switch (type) {
+	case PCH_TYPE_CPT:
+		/* CougarPoint minimum revision */
+		if (cur_type == PCH_TYPE_CPT && cur_rev >= rev)
+			return 1;
+		/* PantherPoint any revision */
+		if (cur_type == PCH_TYPE_PPT)
+			return 1;
+		break;
 
-		halt();
+	case PCH_TYPE_PPT:
+		/* PantherPoint minimum revision */
+		if (cur_type == PCH_TYPE_PPT && cur_rev >= rev)
+			return 1;
+		break;
 	}
 
-	memset(&ctrl, 0, sizeof (ctrl));
-
-	early_pch_init_native();
-	early_thermal_init();
+	return 0;
+}
 
-	/* try to find timings in MRC cache */
-	mrc_cache = find_current_mrc_cache();
-	if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(ctrl))) {
-		if (s3resume) {
-			/* Failed S3 resume, reset to come up cleanly */
-			outb(0x6, 0xcf9);
-			halt();
-		}
-		ctrl_cached = NULL;
-	} else {
-		ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data;
+#define IOBP_RETRY 1000
+static inline int iobp_poll(void)
+{
+	unsigned try = IOBP_RETRY;
+	u32 data;
+
+	while (try--) {
+		data = RCBA32(IOBPS);
+		if ((data & 1) == 0)
+			return 1;
+		udelay(10);
 	}
 
-	/* verify MRC cache for fast boot */
-	if (ctrl_cached) {
-		/* check SPD CRC16 to make sure the DIMMs haven't been replaced */
-		fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
-		if (!fast_boot)
-			printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
-		if (!fast_boot && s3resume) {
-			/* Failed S3 resume, reset to come up cleanly */
-			outb(0x6, 0xcf9);
-			halt();
-		}
-	} else
-		fast_boot = 0;
+	printk(BIOS_ERR, "IOBP timeout\n");
+	return 0;
+}
 
-	if (fast_boot) {
-		printk(BIOS_DEBUG, "Trying stored timings.\n");
-		memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
 
-		err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
-		if (err) {
-			if (s3resume) {
-				/* Failed S3 resume, reset to come up cleanly */
-				outb(0x6, 0xcf9);
-				halt();
-			}
-			/* no need to erase bad mrc cache here, it gets overwritten on
-			 * successful boot. */
-			printk(BIOS_ERR, "Stored timings are invalid !\n");
-			fast_boot = 0;
-		}
-	}
-	if (!fast_boot) {
-		ctrl.mobile = mobile;
-		ctrl.tCK = min_tck;
+static inline void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
+{
+	u32 data;
 
-		/* Get DDR3 SPD data */
-		dram_find_spds_ddr3(spds, &ctrl);
+	/* Set the address */
+	RCBA32(IOBPIRI) = address;
 
-		err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
-	}
+	/* READ OPCODE */
+	if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0))
+		RCBA32(IOBPS) = IOBPS_RW_BX;
+	else
+		RCBA32(IOBPS) = IOBPS_READ_AX;
+	if (!iobp_poll())
+		return;
 
-	if (err && (ctrl.tCK < TCK_400MHZ)) {
-		/* fallback: lower clock frequency */
-		printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
-		printram("Decreasing clock frequency.\n");
-		ctrl.tCK++;
-		err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
-	}
+	/* Read IOBP data */
+	data = RCBA32(IOBPD);
+	if (!iobp_poll())
+		return;
 
-	if (err && (ctrl.tCK < TCK_400MHZ)) {
-		/* fallback: lower clock frequency */
-		printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
-		printram("Decreasing clock frequency.\n");
-		ctrl.tCK++;
-		err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
+	/* Check for successful transaction */
+	if ((RCBA32(IOBPS) & 0x6) != 0) {
+		printk(BIOS_ERR, "IOBP read 0x%08x failed\n", address);
+		return;
 	}
 
-	if (err) {
-		/* fallback: disable failing channel */
-		printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
-		printram("Disable failing channel.\n");
+	/* Update the data */
+	data &= andvalue;
+	data |= orvalue;
 
-		/* Reset DDR3 frequency */
-		dram_find_spds_ddr3(spds, &ctrl);
+	/* WRITE OPCODE */
+	if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0))
+		RCBA32(IOBPS) = IOBPS_RW_BX;
+	else
+		RCBA32(IOBPS) = IOBPS_WRITE_AX;
+	if (!iobp_poll())
+		return;
 
-		/* disable failing channel */
-		disable_channel(&ctrl, GET_ERR_CHANNEL(err));
+	/* Write IOBP data */
+	RCBA32(IOBPD) = data;
+	if (!iobp_poll())
+		return;
+}
 
-		err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
-	}
 
-	if (err)
-		die("raminit failed");
+// Stolen from seabios/src/hw/ata.c
+struct ata_pio_command {
+    u8 feature;
+    u8 sector_count;
+    u8 lba_low;
+    u8 lba_mid;
+    u8 lba_high;
+    u8 device;
+    u8 command;
+
+    u8 feature2;
+    u8 sector_count2;
+    u8 lba_low2;
+    u8 lba_mid2;
+    u8 lba_high2;
+};
 
-	/* FIXME: should be hardware revision-dependent.  */
-	write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
 
-	set_scrambling_seed(&ctrl);
+// Wait for the specified ide state
+static inline int
+await_ide(u8 mask, u8 flags, u16 base, u16 timeout)
+{
+    for (;;) {
+		printk(BIOS_SPEW, "Better to have a timer but hey, this works.. \n"); // TODO use timer whilst waiting for ide..
+        u8 status = inb(base+ATA_CB_STAT);
+        if ((status & mask) == flags)
+            return status;
+    }
+}
 
-	set_42a0(&ctrl);
 
-	final_registers(&ctrl);
+// Wait for the device to be ready.
+static int await_rdy(u16 base)
+{
+    return await_ide(ATA_CB_STAT_RDY, ATA_CB_STAT_RDY, base, IDE_TIMEOUT);
+}
 
-	/* Zone config */
-	dram_zones(&ctrl, 0);
+// Wait for the device to be not-busy.
+static int
+await_not_bsy(u16 base)
+{
+    return await_ide(ATA_CB_STAT_BSY, 0, base, IDE_TIMEOUT);
+}
 
-	if (!fast_boot)
-		quick_ram_check();
 
-	intel_early_me_status();
-	intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
-	intel_early_me_status();
+// Wait for ide state - pause for 400ns first.
+static inline int
+ndelay_await_not_bsy(u16 iobase1)
+{
+    udelay(40);
+    return await_not_bsy(iobase1);
+}
 
-	report_memory_config();
 
-	cbmem_was_inited = !cbmem_recovery(s3resume);
-	if (!fast_boot)
-		save_timings(&ctrl);
-	if (s3resume && !cbmem_was_inited) {
-		/* Failed S3 resume, reset to come up cleanly */
-		outb(0x6, 0xcf9);
-		halt();
-	}
+// Wait for ide state - pauses for one ata cycle first.
+static inline int
+pause_await_not_bsy(u16 iobase1, u16 iobase2)
+{
+    // Wait one PIO transfer cycle.
+    inb(iobase2 + ATA_CB_ASTAT);
 
-	fill_smbios17(&ctrl);
+    return await_not_bsy(iobase1);
 }
 
-#define HOST_BRIDGE	PCI_DEVFN(0, 0)
-#define DEFAULT_TCK	TCK_800MHZ
+
+static void ata_reset(u32 iobase1, u32 iobase2, int slave)
+{
+	//Stolen from seabios ata.c ata_reset()
+
+    // Pulse SRST
+    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST, iobase2+ATA_CB_DC);
+    udelay(5);
+    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC);    // Disable interrupts
+    udelay(200);
+
+
+	int status = await_not_bsy(iobase1);
+
+	if(slave)
+	{
+        for (;;) 
+		{
+			printk(BIOS_DEBUG, "here2\n");
+            outb(ATA_CB_DH_DEV1 | ATA_CB_DH_LBA, iobase1 + ATA_CB_DH); // Also have drive in lba mode
+            status = ndelay_await_not_bsy(iobase1);
+            if (status < 0)
+			{
+                printk(BIOS_DEBUG, "ATA status error..");
+			}
+
+            if (inb(iobase1 + ATA_CB_DH) == ATA_CB_DH_DEV1)
+                break;
+		}
+	}
+	else
+	{
+		outb(ATA_CB_DH_DEV0 | ATA_CB_DH_LBA, iobase1 + ATA_CB_DH);	// also have drive in lba mode
+	}
+
+	status = await_rdy(iobase1);
+
+    printk(BIOS_DEBUG, "ata_reset exit status=%x\n", status);
+
+	// if(reset == 7f) then disk is not connected..
+	// if(reset == 50) then we've found a correct disk...
+}
+
+
+
+static void ata_readwrite(uint64_t lba, int count, int iswrite, u8 *buffer)
+{
+	int usepio = 1;
+	int status = 0; 
+	int iobase1 = IOBASE1; // TODO remove should only use define
+	int iobase2 = IOBASE2; // TODO remove should only use define
+
+	// Stolen from seabios ata.c ata_readwrite()
+    struct ata_pio_command cmd;
+    memset(&cmd, 0, sizeof(cmd));
+
+    if (count >= (1<<8) || lba + count >= (1<<28)) 
+	{
+		printk(BIOS_DEBUG, "use ata ext\n");
+        cmd.sector_count2 = count >> 8;
+        cmd.lba_low2 = lba >> 24;
+        cmd.lba_mid2 = lba >> 32;
+        cmd.lba_high2 = lba >> 40;
+        lba &= 0xffffff;
+
+        if (usepio)
+            cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS_EXT
+                           : ATA_CMD_READ_SECTORS_EXT);
+        else
+            cmd.command = (iswrite ? ATA_CMD_WRITE_DMA_EXT
+                           : ATA_CMD_READ_DMA_EXT);
+    } else {
+		printk(BIOS_SPEW, "use ata normal\n");
+        if (usepio)
+		{
+            cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS
+                           : ATA_CMD_READ_SECTORS); // read without retry
+			if(iswrite)
+			{
+				printk(BIOS_SPEW, "write cmd\n");
+			}
+			else
+			{
+				printk(BIOS_SPEW, "read cmd\n");
+			}
+		}
+        else
+		{
+			cmd.command = (iswrite ? ATA_CMD_WRITE_DMA
+                           : ATA_CMD_READ_DMA);
+		}
+    }
+
+    cmd.sector_count = count;
+    cmd.lba_low = lba;
+    cmd.lba_mid = lba >> 8;
+    cmd.lba_high = lba >> 16;
+    cmd.device = ((lba >> 24) & 0xf) | ATA_CB_DH_LBA;
+
+    if (usepio)
+	{
+		// Stolen from send_cmd()
+		// Check for ATA_CMD_(READ|WRITE)_(SECTORS|DMA)_EXT commands.
+		if ((cmd.command & ~0x11) == ATA_CMD_READ_SECTORS_EXT) {
+			printk(BIOS_DEBUG, "(cmd.command & ~0x11) == ATA_CMD_READ_SECTORS_EXT)\n");
+			outb(cmd.feature2, iobase1 + ATA_CB_FR);
+			outb(cmd.sector_count2, iobase1 + ATA_CB_SC);
+			outb(cmd.lba_low2, iobase1 + ATA_CB_SN);
+			outb(cmd.lba_mid2, iobase1 + ATA_CB_CL);
+			outb(cmd.lba_high2, iobase1 + ATA_CB_CH);
+		}
+
+		outb(cmd.sector_count, iobase1 + ATA_CB_SC);
+		outb(cmd.lba_low, iobase1 + ATA_CB_SN);
+		outb(cmd.lba_mid, iobase1 + ATA_CB_CL);
+		outb(cmd.lba_high, iobase1 + ATA_CB_CH);
+		outb(cmd.command, iobase1 + ATA_CB_CMD);
+
+		// Stolen from ata_wait_data()
+		status = ndelay_await_not_bsy(iobase1);
+    	printk(BIOS_SPEW, "ata_wait_data exit status=%x\n", status);
+
+
+		int sectors_left=count;
+		// Stolen from ata_pio_transfer()
+		// Transfer 'op->count' blocks (of 'blocksize' bytes) to/from drive 'op->drive_gf'.
+		for (;;) 
+		{
+			if(iswrite)
+			{
+				for(u16 k=0;k<(DISK_SECTOR_SIZE/2);k++) //Transfer 256 16-bit values, a uint16_t at a time, into your buffer or 
+				{
+					u16 twobytes = (buffer[k*2] << 8) |  buffer[(k*2)+1];
+					u16 swappedbytes = (twobytes << 8) | (twobytes >> 8); //BYTES HAVE TO BE SWAPPED....
+					outw(swappedbytes, iobase1+ATA_CB_DATA);
+				}
+			}
+			else
+			{
+				for(u16 k=0;k<(DISK_SECTOR_SIZE/2);k++) //Transfer 256 16-bit values, a uint16_t at a time, into your buffer or 
+				{
+					u16 twobytes = inw(iobase1+ATA_CB_DATA);
+
+					buffer[k*2] = twobytes & 0xff; // first byte
+					buffer[(k*2)+1] = (twobytes >> 8) & 0xff; // second byte
+				}
+			}
+
+			status = pause_await_not_bsy(iobase1, iobase2);
+
+			if( (status & ATA_CB_STAT_ERR) == ATA_CB_STAT_ERR)
+			{
+				// Error
+				printk(BIOS_DEBUG, "ATA error..\n");
+				printk(BIOS_DEBUG, "ata error information 0x%02x\n", inb(iobase1+ATA_CB_ERR));
+			}
+			else
+			{
+				printk(BIOS_SPEW, "ATA status during reading 0x%02x\n", status);
+			}
+
+
+
+			sectors_left=sectors_left-1; // reading a single byte per inb()...
+			if (!sectors_left)
+				break;
+			status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR);
+			if (status != ATA_CB_STAT_DRQ) {
+				printk(BIOS_SPEW, "ata_pio_transfer : more sectors left (status %02x)\n", status);
+			}
+		}
+
+		status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR);
+		if (!iswrite)
+			status &= ~ATA_CB_STAT_DF;
+		if (status != 0) {
+			printk(BIOS_DEBUG, "ata_pio_transfer : no sectors left (status %02x)\n", status);
+
+			if(status == 1) // check for errors..
+				printk(BIOS_DEBUG, "ata error information 0x%02x\n", inb(iobase1+ATA_CB_ERR));
+		}
+	}
+}
+
+
+
+static void read_sector(uint64_t lba, u8 *buffer)
+{
+	//ata_readwrite(uint64_t lba, int count, int iswrite, u8 *buffer)
+	ata_readwrite(lba, 1, 0, buffer);
+	return;
+}
+
+
+
+static void write_sector(uint64_t lba, u8 *buffer)
+{
+	//ata_readwrite(uint64_t lba, int count, int iswrite, u8 *buffer)
+	ata_readwrite(lba, 1, 1, buffer);
+	return;
+}
+
+// amount in bytes
+static void read_memory(uint64_t address, int amount, u8 *buffer)
+{
+	volatile uint8_t *ptr = (void *) (uint32_t) address;
+	for(int j=0;j<amount;j++) 
+	{
+		buffer[j]=*(ptr+j);
+//		buffer[j]=ptr[j];
+	}
+}
+
+
+
+struct RAMACQ_imagerecord {
+	uint64_t start_lba;
+	uint64_t end_lba;
+	uint64_t third;
+	uint64_t fourth;
+	uint64_t fifth;
+	uint64_t sixth;
+	uint64_t seventh;
+	uint64_t eighth;
+};
+
+
+
+struct RAMACQ_imagetable {
+	struct RAMACQ_imagerecord imagerecord[8]; // 8 image records per sector 512 bytes/64 bytes (8 entries of 8 bytes each) = 8 imagerecords
+};
+
+//#endif // Disable ATA PIO
+
+
+
+
+
+
+
+// -------------------------- begin paging
+
+#define NUMBEROFGBPAGED 4 // the number of gigabyte present in our pagingtables.. 
+//  should remain 4 as this is the space we reserved for our paging tables
+//  increasing this number will therefore not work, and should not be necessary anyhow
+
+
+typedef struct {
+	uint64_t pagedirptr[512]; //Actually 4, but must be page alligned. 512*8bytes=4096 (4mb pages)
+	uint64_t pagedir[512*4];
+} pagetbl;
+
+
+/*
+ * Intel CPU features in CR4
+ */
+#define X86_CR4_VME     0x00000001 /* enable vm86 extensions */
+#define X86_CR4_PVI     0x00000002 /* virtual interrupts flag enable */
+#define X86_CR4_TSD     0x00000004 /* disable time stamp at ipl 3 */
+#define X86_CR4_DE      0x00000008 /* enable debugging extensions */
+#define X86_CR4_PSE     0x00000010 /* enable page size extensions */
+#define X86_CR4_PAE     0x00000020 /* enable physical address extensions */
+#define X86_CR4_MCE     0x00000040 /* Machine check enable */
+#define X86_CR4_PGE     0x00000080 /* enable global pages */
+#define X86_CR4_PCE     0x00000100 /* enable performance counters at ipl 3 */
+#define X86_CR4_OSFXSR  0x00000200 /* enable fast FPU save and restore */
+#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
+#define X86_CR4_VMXE    0x00002000 /* enable VMX virtualization */
+#define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
+
+static void enablePaging(pagetbl *PTBL)
+{
+
+	printk(BIOS_DEBUG, "enablePaging(pagetbl *PTBL)\n");
+	printk(BIOS_DEBUG, "pagetable address: 0x%p\n", &(PTBL->pagedirptr[0]));
+	printk(BIOS_DEBUG, "pagetable_end address: 0x%p\n", &(PTBL->pagedir[(512*NUMBEROFGBPAGED)]));
+	printk(BIOS_DEBUG, "pagetable size is 0x%zx\n", sizeof(pagetbl));
+
+	//debugPagingTable(PTBL);
+
+	for(uint64_t pagenr=0;pagenr<NUMBEROFGBPAGED;pagenr++)
+		printk(BIOS_DEBUG,"PTBL->pagedirptr[%lld] 0x%016llx\n", pagenr, PTBL->pagedirptr[pagenr]);
+
+	do {
+		unsigned int mmu_cr4_features;
+		unsigned int mmu_cr0;
+
+		__asm__ __volatile__(
+				"movl %%cr4, %0;                     \n"
+				"movl %%cr0, %1;                     \n"
+				: "=&r" (mmu_cr4_features),
+				  "=&r" (mmu_cr0)
+				:
+				: "memory");
+
+		mmu_cr4_features = mmu_cr4_features | X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE;
+		mmu_cr0 = mmu_cr0 | 0x80000000; //Paging On
+
+
+
+
+		printk(BIOS_DEBUG, "enabling paging, registers will be\n");
+		printk(BIOS_DEBUG, "CR0: 0x%08x\n", mmu_cr0);
+		printk(BIOS_DEBUG, "CR3: 0x%08x\n", (uint32_t)&(PTBL->pagedirptr[0]));
+		printk(BIOS_DEBUG, "CR4: 0x%08x\n", mmu_cr4_features);
+
+		__asm__ __volatile__(
+				"movl %1, %%cr4;  # turn on extensions     \n"
+				"movl %0, %%cr3;  # Set Pagetable        \n"
+				"movl %2, %%cr0;  # Enable paging \n"
+				"ljmp $0x08,$1f\n"
+				"1:\n"
+				:
+				: "r" ((uint32_t)&(PTBL->pagedirptr[0])),
+				"r" (mmu_cr4_features),
+				"r" (mmu_cr0)
+				: "memory");
+	} while (0);
+	printk(BIOS_DEBUG, "paging enabled\n");
+}
+
+static void pagingWindowGigabyte(pagetbl *PTBL, uint8_t windowed_gig)
+{
+	printk(BIOS_DEBUG, "pagingWindowGigabyte(), windowed_gig=%d\n", windowed_gig);
+
+
+	printk(BIOS_DEBUG, "pagetable address: 0x%p\n", &(PTBL->pagedirptr[0]));
+	printk(BIOS_DEBUG, "pagetable_end address: 0x%p\n", &(PTBL->pagedir[(512*NUMBEROFGBPAGED)]));
+	printk(BIOS_DEBUG, "pagetable size is 0x%zx\n", sizeof(pagetbl));
+
+
+	uint64_t pagenr = 0;
+	// set whole PTBL to predefined initial value (all zeroes)
+	for(pagenr=0;pagenr<512;pagenr++)
+		PTBL->pagedirptr[pagenr]= 0;
+
+	for(pagenr=0;pagenr<512*4;pagenr++)
+		PTBL->pagedir[pagenr]= 0;
+
+
+	for(pagenr=0;pagenr<NUMBEROFGBPAGED;pagenr++)
+		PTBL->pagedirptr[pagenr]=0x1 | (uint64_t)(uintptr_t) &PTBL->pagedir[pagenr*512];  // set pagedirptrs to addresses of pagedirs
+
+	for (pagenr=0;pagenr<(NUMBEROFGBPAGED*512);pagenr++)
+		PTBL->pagedir[pagenr]=0xe3 | pagenr*(2*1024*1024);
+
+	// Window a gigabyte
+	uint64_t windowbase= ((uint64_t)windowed_gig)*0x40000000L; // Entering 04 will show the area between 4 and 5G at address 0x40000000
+
+	for (pagenr=512;pagenr<(2*512);pagenr++)
+		PTBL->pagedir[pagenr]=0xe3 | ((pagenr-512) *(2*1024*1024)) | windowbase ;
+
+
+	enablePaging(PTBL);
+}
+
+
+static void disablePaging(pagetbl *PTBL)
+{
+	pagingWindowGigabyte(PTBL, 1); // reset paging tables to map transparently i.e. window from 1gb logical addresses to 1gb physical addresses
+
+	unsigned int mmu_cr4_features;
+	unsigned int mmu_cr0;
+
+	do {
+		__asm__ __volatile__(
+				"movl %%cr4, %0;                     \n"
+				"movl %%cr0, %1;                     \n"
+				: "=&r" (mmu_cr4_features),
+				  "=&r" (mmu_cr0)
+				:
+				: "memory");
+
+	} while (0);
+
+
+	mmu_cr4_features = mmu_cr4_features & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE);
+	mmu_cr0 = mmu_cr0 & ~0x80000000; //Paging off
+
+
+	printk(BIOS_DEBUG, "disabling paging, registers will be\n");
+	printk(BIOS_DEBUG, "CR0: 0x%08x\n", mmu_cr0);
+	printk(BIOS_DEBUG, "CR3: 0x%08x\n", (uint32_t)0x0);
+	printk(BIOS_DEBUG, "CR4: 0x%08x\n", mmu_cr4_features);
+
+	do {
+		__asm__ __volatile__(
+				"movl %0, %%cr0;  # Disable paging \n"
+				"ljmp $0x08,$2f\n"
+				"2:\n"
+				:
+				: "r" (mmu_cr0)
+				: "memory");
+	} while (0);
+
+	printk(BIOS_DEBUG, "paging disabled");
+
+
+	do {
+		__asm__ __volatile__(
+			"movl %1, %%cr4;  # Disable extentions     \n"
+			"movl %0, %%cr3;  # Set Pagetable address       \n"
+			"ljmp $0x08,$2f\n"
+			"2:\n"
+			:
+			: "r" ((uint32_t)0x0),
+			"r" (mmu_cr4_features)
+			: "memory");
+	} while (0);
+
+
+	printk(BIOS_DEBUG, " - extentions and cr3 disabled\n");
+}
+// -------------------------- end paging
+
+
+
+#if false // -------------- begin RC4 code 
+// Stolen from http://bradconte.com/rc4_c
+static void write_memory(uint64_t address, int amount, u8 *buffer)
+{
+	volatile uint8_t *ptr = (void *) (uint32_t) address;
+	for(int j=0;j<amount;j++) 
+	{
+		*(ptr+j)=buffer[j];
+
+		do 
+		{
+			// make sure to flush the cache line
+			asm volatile("clflush (%0)" : : "r" (ptr+j) : "memory");
+		} while (0);
+	}
+}
+
+
+// Key Scheduling Algorithm 
+// Input: state - the state used to generate the keystream
+//        key - Key to use to initialize the state 
+//        len - length of key in bytes
+static void ksa(uint8_t *state, uint8_t *key, int len)
+{
+   int i,j=0,t; 
+
+   for (i=0; i < 256; ++i)
+	  state[i] = i; 
+   for (i=0; i < 256; ++i) {
+	  j = (j + state[i] + key[i % len]) % 256; 
+	  t = state[i]; 
+	  state[i] = state[j]; 
+	  state[j] = t; 
+   }
+}
+
+// Pseudo-Random Generator Algorithm 
+// Input: state - the state used to generate the keystream 
+//        out - Must be of at least "len" length
+//        len - number of bytes to generate 
+static void prga(uint8_t *state, uint8_t *out, int len)
+{
+   int i=0,j=0,x,t;
+
+   for (x=0; x < len; ++x)  {
+	  i = (i + 1) % 256; 
+	  j = (j + state[i]) % 256; 
+	  t = state[i]; 
+	  state[i] = state[j]; 
+	  state[j] = t; 
+	  out[x] = state[(state[i] + state[j]) % 256];
+   }
+}
+#endif // -------------- end RC4 code
+
+void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck,
+	int s3resume)
+{
+	int me_uma_size;
+	int cbmem_was_inited;
+	ramctr_timing ctrl;
+	int fast_boot;
+	//struct mrc_data_container *mrc_cache;
+	//ramctr_timing *ctrl_cached;
+	int err;
+
+
+
+	uint8_t serialInput;
+	volatile uint8_t *ptr;
+
+
+
+
+	MCHBAR32(0x5f00) |= 1; //Enable System Agent Clock Gating by setting
+
+	report_platform_info();
+
+	/* Wait for ME to be ready */
+	intel_early_me_init();
+	me_uma_size = 0; // disable me_uma
+
+	printk(BIOS_DEBUG, "Starting native Platform init\n");
+
+	wait_txt_clear();
+
+	wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
+
+	#if false //We don't want to reset for no clear reason
+	u32 reg_5d10;
+	reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10);
+	if (
+		// SOUTHBRIDGE HAS BEEN DEFINED AS PCI_DEV(0, 0x1f, 0)
+		(pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20
+	    && reg_5d10  // scratchpad register contains some value
+		&& !s3resume // not in s3 resume
+	) {
+		write32(DEFAULT_MCHBAR + 0x5d10, 0);
+		/* Need reset.  */
+		outb(0x6, 0xcf9);
+
+		halt();
+	}
+	#endif
+
+	memset(&ctrl, 0, sizeof (ctrl));
+
+	early_pch_init_native();
+	early_thermal_init();
+
+
+
+
+#if false // We dont want to do MRC cache
+	/* try to find timings in MRC cache */
+	mrc_cache = find_current_mrc_cache();
+	if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(ctrl))) {
+		if (s3resume) {
+			/* Failed S3 resume, reset to come up cleanly */
+			outb(0x6, 0xcf9);
+			halt();
+		}
+		ctrl_cached = NULL;
+	} else {
+		ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data;
+	}
+
+	/* verify MRC cache for fast boot */
+	if (ctrl_cached) {
+		/* check SPD CRC16 to make sure the DIMMs haven't been replaced */
+		fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
+		if (!fast_boot)
+			printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
+		if (!fast_boot && s3resume) {
+			/* Failed S3 resume, reset to come up cleanly */
+			outb(0x6, 0xcf9);
+			halt();
+		}
+	} else
+		fast_boot = 0;
+
+	if (fast_boot) {
+		printk(BIOS_DEBUG, "Trying stored timings.\n");
+		memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
+
+		err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
+		if (err) {
+			if (s3resume) {
+				/* Failed S3 resume, reset to come up cleanly */
+				outb(0x6, 0xcf9);
+				halt();
+			}
+			/* no need to erase bad mrc cache here, it gets overwritten on
+			 * successful boot. */
+			printk(BIOS_ERR, "Stored timings are invalid !\n");
+			fast_boot = 0;
+		}
+	}
+#endif // We dont want to do MRC cache
+
+
+fast_boot = 0; // no fast boot, we want to initialize memory without any caches as it will probably be a different DIMM
+
+	if (!fast_boot) {
+		ctrl.mobile = mobile;
+		ctrl.tCK = min_tck;
+
+		/* Get DDR3 SPD data */
+		dram_find_spds_ddr3(spds, &ctrl);
+		printk(BIOS_ERR, "dram found spds\n");
+		err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
+	}
+
+	if (err && (ctrl.tCK < TCK_400MHZ)) {
+		/* fallback: lower clock frequency */
+		printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
+		printram("Decreasing clock frequency.\n");
+		ctrl.tCK++;
+		err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
+	}
+
+	if (err && (ctrl.tCK < TCK_400MHZ)) {
+		/* fallback: lower clock frequency */
+		printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
+		printram("Decreasing clock frequency.\n");
+		ctrl.tCK++;
+		err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
+	}
+
+	if (err) {
+		/* fallback: disable failing channel */
+		printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
+		printram("Disable failing channel.\n");
+
+		/* Reset DDR3 frequency */
+		dram_find_spds_ddr3(spds, &ctrl);
+
+		/* disable failing channel */
+		disable_channel(&ctrl, GET_ERR_CHANNEL(err));
+
+		err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
+	}
+
+	if (err)
+		die("raminit failed"); // TODO remove this die() and fall back e.g. reset machine
+
+	/* FIXME: should be hardware revision-dependent.  */
+	write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce); // 0x5024 == CHANNEL_HASH defines the MC channel selection function.
+
+	set_scrambling_seed(&ctrl);
+
+	set_42a0(&ctrl);
+
+	final_registers(&ctrl);
+
+	/* Zone config */
+	dram_zones(&ctrl, 0);
+
+	if (!fast_boot)
+		quick_ram_check(); // TODO we probably want to disable these
+
+	intel_early_me_status();
+	intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
+	intel_early_me_status();
+
+	report_memory_config();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	uint64_t tom_mb = ctrl.channel_size_mb[0] + ctrl.channel_size_mb[1]; // Loop over installed amount of memory
+	printk(BIOS_DEBUG, "Top of memory %lld megabytes, %lld gb, hex (tom_mb*1024*1024)-1) 0x%016llx\n", tom_mb, tom_mb/1024, (tom_mb*1024*1024)-1);
+
+
+
+
+
+	//#if false // Disable PRBS profiling
+	uint32_t offset = 0x01000000;
+	uint32_t bytesToProcess = 128; // two keyblocks of 64 bytes
+	ptr = (void *) offset;
+
+
+
+	printk(BIOS_DEBUG, "Do you want to change bytesToProcess? Press 'y' to change all else skips? \n");
+	serialInput = get_serial_input_blocking();
+
+	if(serialInput == 'y')
+	{
+		printk(BIOS_DEBUG, "Enter how many bytes do you want to process (as a 32bit value) \n");
+		bytesToProcess = get_serial_input_blocking32();
+		printk(BIOS_DEBUG, "bytesToProcess=0x%08x=%d\n", bytesToProcess, bytesToProcess);
+	}
+	else
+	{
+		printk(BIOS_DEBUG, "Skipping default bytesToProcess = 128\n");
+	}
+
+
+	uint8_t groundstateDimm[bytesToProcess];
+	uint8_t keyInMemory[bytesToProcess];
+	uint8_t xoredKey[bytesToProcess];
+
+
+	printk(BIOS_DEBUG, "Do you want to write all 0xFF groundstate in DIMM? Press 'y' all else skips? \n");
+	printk(BIOS_DEBUG, "-- it only makes sense to do this when memory scrambling has been disabled!\n");
+	serialInput = get_serial_input_blocking();
+
+	if(serialInput == 'y')
+	{
+		for(int i=0; i<bytesToProcess; i++)
+		{
+			*(ptr+i) = 0xFF;
+
+			do 
+			{
+				// make sure to flush the cache line we just wrote 0xFF to. // TODO optimize flush memory range from cache.
+				asm volatile("clflush (%0)" : : "r" (ptr+i) : "memory");
+			} while (0);
+
+		}
+
+		printk(BIOS_DEBUG, "groundstate set\n");
+	}
+
+	// Always set groundstate of dimm to 0xFF, set other arrays to default value 0x0
+	for(int i=0; i<bytesToProcess; i++)
+	{
+		groundstateDimm[i] = 0xFF;
+		keyInMemory[i] = 0;
+		xoredKey[i] = 0;
+	}
+
+	for(int i=0; i<bytesToProcess; i++)
+	{
+		keyInMemory[i] = *(ptr+i);
+	}
+
+	for(int i=0; i<bytesToProcess; i++)
+	{
+		xoredKey[i] = keyInMemory[i] ^ groundstateDimm[i];
+	}
+
+	uint32_t seed1 = 0;
+	uint32_t seed2High = 0;
+	uint32_t seed2Low = 0; 
+
+
+	seed1 = read32(DEFAULT_MCHBAR + 0x4034); // scramblingseed1
+	seed2High = read32(DEFAULT_MCHBAR + 0x403c); // scramblingseed2HIGH
+	seed2Low = read32(DEFAULT_MCHBAR + 0x4038); // scramblingseed2LOW
+
+
+	printk(BIOS_DEBUG, "Seed1: 0x%08x \n", (uint32_t) seed1);
+	printk(BIOS_DEBUG, "Seed2high: 0x%08x \n", (uint32_t) seed2High);
+	printk(BIOS_DEBUG, "Seed2low: 0x%08x \n", (uint32_t) seed2Low);
+
+
+	printk(BIOS_DEBUG, "do you want to print debug groundstateDimm and keyInMemory, press 'y' anything else skips\n");
+	serialInput = get_serial_input_blocking();
+	if(serialInput == 'y')
+	{
+		printk(BIOS_DEBUG, "GroundstateDimm:\n");
+		for(int i=0; i<bytesToProcess; i++)
+		{
+			if ((i!=0) && (i%64==0)) {
+				printk(BIOS_DEBUG, "\n");
+				printk(BIOS_DEBUG, "\n");
+			}
+			else if(i%16==0)	{
+				printk(BIOS_DEBUG, "\n");
+			}
+			else if(i%8==0) {
+				printk(BIOS_DEBUG, " ");
+			}
+
+			printk(BIOS_DEBUG, "%02X ", groundstateDimm[i]);
+		}
+		printk(BIOS_DEBUG, "\n");
+		printk(BIOS_DEBUG, "\n");
+
+		printk(BIOS_DEBUG, "KeyInMemory (what's in memory):\n");
+		for(int i=0; i<bytesToProcess; i++)
+		{
+			if ((i!=0) && (i%64==0)) {
+				printk(BIOS_DEBUG, "\n");
+				printk(BIOS_DEBUG, "\n");
+			}
+			else if(i%16==0)	{
+				printk(BIOS_DEBUG, "\n");
+			}
+			else if(i%8==0) {
+				printk(BIOS_DEBUG, " ");
+			}
+
+			printk(BIOS_DEBUG, "%02X ", keyInMemory[i]);
+		}
+		printk(BIOS_DEBUG, "\n");
+		printk(BIOS_DEBUG, "\n");
+	}
+
+
+	// Print PRBS hexadecimal
+	printk(BIOS_DEBUG, "XoredKey (the PRBS, correct endianness):\n");
+	for(int i=0; i<bytesToProcess; i++)
+	{
+		// layout
+		if ((i!=0) && (i%64==0)) {
+			printk(BIOS_DEBUG, "\n");
+			printk(BIOS_DEBUG, "\n");
+		}
+		else if(i%16==0)	{
+			printk(BIOS_DEBUG, "\n");
+		}
+		else if(i%8==0) {
+			printk(BIOS_DEBUG, " ");
+		}
+
+		// correct endianness
+		if((i%2)==0)
+		{
+			printk(BIOS_DEBUG, "%02X ", xoredKey[i+1]);	// even so print next already
+		}
+		else
+		{
+			printk(BIOS_DEBUG, "%02X ", xoredKey[i-1]); // odd so print previous
+		}
+	}
+	printk(BIOS_DEBUG, "\n");
+	printk(BIOS_DEBUG, "\n");
+
+
+
+	// Print PRBS binary
+	printk(BIOS_DEBUG, "XoredKey (the PRBS, correct endianness):\n");
+	for(int i=0; i<bytesToProcess; i++)
+	{
+		// layout
+		if ((i!=0) && (i%64==0)) {
+			printk(BIOS_DEBUG, "\n");
+			printk(BIOS_DEBUG, "\n");
+		}
+		else if(i%16==0)	{
+			printk(BIOS_DEBUG, "\n");
+		}
+		else if(i%8==0) {
+			printk(BIOS_DEBUG, " ");
+		}
+
+		// correct endianness
+		if((i%2)==0)
+		{
+			for(int j=0;j<8;j++) 
+			{
+				// even so print next already
+				if((xoredKey[i+1] & 0x80) >> 7)
+				{
+					printk(BIOS_DEBUG, "1");
+				}
+				else
+				{
+					printk(BIOS_DEBUG, "0");
+				}
+				xoredKey[i+1] = (xoredKey[i+1] << 1);
+			}
+
+			printk(BIOS_DEBUG, " ");
+		}
+		else
+		{
+			// odd so print previous
+			for(int j=0;j<8;j++) 
+			{
+				// even so print next already
+				if((xoredKey[i-1] & 0x80) >> 7)
+				{
+					printk(BIOS_DEBUG, "1");
+				}
+				else
+				{
+					printk(BIOS_DEBUG, "0");
+				}
+				xoredKey[i-1] = (xoredKey[i-1] << 1);
+			}
+			printk(BIOS_DEBUG, " ");
+		}
+	}
+	printk(BIOS_DEBUG, "\n");
+	printk(BIOS_DEBUG, "\n");
+
+
+
+	printk(BIOS_DEBUG, "Halting for input\n");
+	serialInput = get_serial_input_blocking();
+	//#endif // Disable PRBS profiling
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	pagetbl PTBL __attribute__((aligned(4096))); // align the pagetables on page borders
+
+	printk(BIOS_DEBUG, "pagetable address: 0x%p\n", &(PTBL.pagedirptr[0]));
+	printk(BIOS_DEBUG, "pagetable_end address: 0x%p\n", &(PTBL.pagedir[(512*NUMBEROFGBPAGED)]));
+	printk(BIOS_DEBUG, "pagetable size is 0x%zx\n", sizeof(pagetbl));
+
+	// set whole PTBL to predefined initial value (all zeroes)
+	for(uint64_t pagenr=0;pagenr<512;pagenr++)
+		PTBL.pagedirptr[pagenr]= 0;
+
+	for(uint64_t pagenr=0;pagenr<512*4;pagenr++)
+		PTBL.pagedir[pagenr]= 0;
+
+
+
+
+
+
+	// declare variables that are both used for RC4 as ATA code-blocks
+	//  used in both blocks to determine what addresses to write/acquire
+	//  because we have ME and GFX, and TSEG disabled: area from 0 to tolud and 4gb to TOUUD is routed to DRAM, other is MMIO
+	uint64_t outputBlockLen=512; //  write 512 bytes at a time, more would hog memory, furthermore chosen as 512 as this is also the SECTOR_SIZE used in ata communication (buffer can be reused)
+	// code assumes that DISK_SECTOR_SIZE==outputBlockLen
+
+	uint8_t buffer[outputBlockLen]; 
+	uint64_t totalOutput = (tom_mb*1024*1024); // in bytes (the total number of bytes to write)
+	uint64_t remainingOutput = totalOutput;
+	u32 reg = 0;
+
+	// TOLUD (top of low used dram) 
+	reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
+	uint64_t tolud = (reg & 0xfff00000);
+	printk(BIOS_DEBUG, "TOLUD = 0x%016llx\n", tolud); // for 1gb dimms tolud should be 0x40000000, as MMIO is mapped above TOM
+
+	reg = 0;
+
+	// TOUUD MSB
+	reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
+	//of address A8-AFh bits 38:20 - total 18 bits
+	printk(BIOS_DEBUG, "0xac reg = 0x%08x\n", reg);
+	uint64_t touud = (reg & 0x7f); // only bottom 7 bits are of interest
+	touud = touud << 32; // shift these 7 bits to position 38-32
+
+	// TOUUD LSB (top of upper usable dram) 
+	reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
+	printk(BIOS_DEBUG, "0xa8 reg = 0x%08x\n", reg);
+	touud |= (reg & 0xfff00000);
+	//touud = (touud & 0xFFFFFF80000FFFFF);
+	printk(BIOS_DEBUG, "TOUUD = 0x%016llx\n", touud); // for 1gb dimms touud should be 0, there is no dram above 1gb
+
+
+
+
+
+
+	#if false // Disable write RC4
+
+	printk(BIOS_DEBUG, "EXPERIMENTAL VALIDATION FUNCTIONALITY, DO NOT USE ON ACQUISITION\n");
+	printk(BIOS_DEBUG, "Select to write random data to memory by entering 'w', anything else skips this\n");
+	uint8_t writeRandomData = get_serial_input_blocking();
+	if(writeRandomData == 'w')
+	{
+		printk(BIOS_DEBUG, "Writing random data to memory\n");
+		uint8_t state[256];
+		uint8_t key[]={"validationexperiment7"};
+		uint64_t keyLen = sizeof(key)-1;
+		uint64_t idx=0; 
+
+		for(idx=0;idx<256;idx++)
+		{
+			state[idx]=0;
+		}
+
+		for(idx=0;idx<outputBlockLen;idx++)
+		{
+			buffer[idx]=0x0;
+		}
+
+		ksa(state, key, keyLen); // key schedule
+
+		uint64_t address = (totalOutput-remainingOutput); // will be zero at first
+
+		while(remainingOutput != 0)
+		{
+			// do not write to memory for addresses between tolud and 4gb ; write until max(touud, tom)
+			if((address >= tolud) && (address < 4294967296)) // bigger than tolud, smaller than 4gb
+			{
+				// address in the MMIO range
+				if(((address % 52428800)==0) || (address == tolud) || (address == 4294967296)) // only print address on multiples of 50mb
+				{
+					printk(BIOS_DEBUG, "Address 0x%llx in MMIO range so skipping, remaining output 0x%llx\n", address, remainingOutput);
+				}
+			}
+			else
+			{
+				uint64_t pagedAddress = address;
+				if((address >= 4294967296)) // address bigger than 32 bit && address is a whole gigabyte border
+				{
+
+					if(((address % (1024*1024*1024))==0))
+					{ 
+						// enable paging for a 1gb window, only when we exhaust this window, enable paging for another window
+						pagingWindowGigabyte(&PTBL, address/(1024*1024*1024)); // window the fifth gigabyte and read from it..
+					}
+
+					// change the addresses to paged addresses for all addresses > 4gb
+					pagedAddress = ((uint64_t)address % 0x40000000) + 0x40000000;
+
+					if(((address % 52428800)==0) || (address == tolud) || (address == 4294967296) || (pagedAddress <= 512)) // only print address: on multiples of 50mb, when it is the same as tolud or when it is at 4gb border
+					{
+						// only print this for >4gb every 40 mb..
+						printk(BIOS_DEBUG, "Enabling paging for address: 0x%llx instead writing to pagedAddress: 0x%llx\n", address, pagedAddress);
+					}
+				}
+
+				if(((address % 52428800)==0) || (address == tolud) || (address == 4294967296) || (pagedAddress <= 512)) // only print address: on multiples of 50mb, when it is the same as tolud or when it is at 4gb border
+				{
+					printk(BIOS_DEBUG, "Writing to address 0x%llx, pagedAddress 0x%llx, remaining output 0x%llx\n", address, pagedAddress, remainingOutput);
+					printk(BIOS_DEBUG, "Reading from address 0x200\n");
+					ptr = (void *) (uint32_t) 0x200; // just read from start memory
+					for(int j=0;j<512;j++) 
+					{
+						printk(BIOS_DEBUG, "%02x", *(ptr+j));
+
+						if((j+1)%512 == 0)
+							printk(BIOS_DEBUG, "\n");
+					}
+					printk(BIOS_DEBUG, "\n");
+				}
+
+				prga(state, buffer, outputBlockLen); // produce new random block
+
+
+				if(((address % 52428800)==0) || (address == tolud) || (address == 4294967296) || (pagedAddress <= 512))
+				{
+					// print buffer
+					printk(BIOS_DEBUG, "The buffer that will be written to address 0x%llx, pagedAddress 0x%llx\n", address, pagedAddress);
+					for(idx=0;idx<outputBlockLen;idx++)
+					{
+						printk(BIOS_DEBUG, "%02x", buffer[idx]);
+					}
+					printk(BIOS_DEBUG, "\n");
+				}
+
+				write_memory(pagedAddress, outputBlockLen, buffer); // address, amount, buffer
+				remainingOutput = remainingOutput-outputBlockLen; // only decrement remaining output when data has been written
+
+				if(((address % 52428800)==0) || (address == tolud) || (address == 4294967296) || (pagedAddress <= 512))
+				{
+					// print memory after writing
+					printk(BIOS_DEBUG, "Reading from address 0x%llx, pagedAddress 0x%llx of memory\n", address, pagedAddress);
+					ptr = (void *) (uint32_t) pagedAddress; // just read from start memory
+					for(int j=0;j<512;j++) 
+					{
+						printk(BIOS_DEBUG, "%02x", *(ptr+j));
+
+						if((j+1)%512 == 0)
+							printk(BIOS_DEBUG, "\n\n");
+					}
+					printk(BIOS_DEBUG, "\n");
+				}
+
+			}
+
+			address = address+outputBlockLen; // always increment address
+		}
+		printk(BIOS_DEBUG, "Final address written to was 0x%llx\n", address);
+		printk(BIOS_DEBUG, "Done writing random data to memory, flushed cache lines\n");
+
+		disablePaging(&PTBL);
+	}
+	else
+	{
+		printk(BIOS_DEBUG, "Skipping writing random data to memory\n");
+	}
+
+	#endif // ------------ End write RC4
+
+
+
+
+
+
+
+
+
+
+
+
+
+	#if false // ------------ Begin window a gigabyte
+	printk(BIOS_DEBUG, "Select to window a gigabyte and read from it by pressing 'w', anything else skips this\n");
+	if(get_serial_input_blocking() == 'w')
+	{
+		while(true) 
+		{
+
+			printk(BIOS_DEBUG, "Reading from start of memory\n");
+			ptr = (void *) (uint32_t) 0x0; // just read from start memory
+			for(int j=0;j<1024;j++) 
+			{
+				printk(BIOS_DEBUG, "%02x", *(ptr+j));
+
+				if((j+1)%512 == 0)
+					printk(BIOS_DEBUG, "\n\n");
+			}
+			printk(BIOS_DEBUG, "\n");
+
+
+
+			printk(BIOS_DEBUG, "Reading from 0x20000000 (512mb)\n");
+			ptr = (void *) (uint32_t) 0x20000000; // just read from start memory
+			for(int j=0;j<1024;j++) 
+			{
+				printk(BIOS_DEBUG, "%02x", *(ptr+j));
+
+				if((j+1)%512 == 0)
+					printk(BIOS_DEBUG, "\n\n");
+			}
+			printk(BIOS_DEBUG, "\n");
+
+
+
+
+			printk(BIOS_DEBUG, "Reading from 0x20000000 (512mb)\n");
+			ptr = (void *) (uint32_t) 0x20000000; // just read from start memory
+			for(int j=0;j<1024;j++) 
+			{
+				printk(BIOS_DEBUG, "%02x", *(ptr+j));
+
+				if((j+1)%512 == 0)
+					printk(BIOS_DEBUG, "\n\n");
+			}
+			printk(BIOS_DEBUG, "\n");
+
+
+
+			pagingWindowGigabyte(&PTBL, 4); // window the fourth gigabyte and read from it
+
+			printk(BIOS_DEBUG, "Reading 0x13FFFF3F0\n");
+			ptr = (void *) (uint32_t) 0x7FFFF3F0; // we want to read from end fourth gb
+			for(int j=0;j<1024;j++) 
+			{
+				printk(BIOS_DEBUG, "%02x", *(ptr+j));
+
+				if((j+1)%512 == 0)
+					printk(BIOS_DEBUG, "\n\n");
+			}
+			printk(BIOS_DEBUG, "\n");
+
+
+
+			pagingWindowGigabyte(&PTBL, 5); // window the fifth gigabyte and read from it..
+
+
+
+			printk(BIOS_DEBUG, "Reading just after fifth gigabyte mark\n");
+			ptr = (void *) (uint32_t) 0x40000000; // the paged window starts at 1gb mark but because of paging now maps to 5 gb mark
+			for(int j=0;j<1024;j++) 
+			{
+				printk(BIOS_DEBUG, "%02x", *(ptr+j));
+
+				if((j+1)%512 == 0)
+					printk(BIOS_DEBUG, "\n\n");
+
+			}
+			printk(BIOS_DEBUG, "\n");
+
+			disablePaging(&PTBL);
+
+
+
+
+			printk(BIOS_DEBUG, "Do you want to try again press 'y', anything else skips\n");
+			serialInput = get_serial_input_blocking();
+			if(serialInput == 'y')
+			{
+				// doe niets, itereer
+			}
+			else
+			{
+				break;
+			}
+		}
+
+	}
+	else
+	{
+
+		printk(BIOS_DEBUG, "Skipping windowing a gigabyte\n");
+	}
+
+	#endif // ------------ End window a gigabyte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	// ----------- Begin ATA PIO based on http://wiki.osdev.org/ATA_PIO_Mode#28_bit_PIO
+
+
+	// Disable ATA PIO
+
+	// Initialize the sata controller using ATA PIO mode.. 
+		// stolen from src/southbridge/intel/bd82x6x/sata.c:sata_init()
+
+	printk(BIOS_DEBUG, "Select whether you want to read data from the hdd or write memory by entering 'r'/'w', anything else skips this\n");
+	uint8_t serialInputHardDisk = get_serial_input_blocking();
+	if((serialInputHardDisk == 'w') | (serialInputHardDisk == 'r'))
+	{
+		// Only initialize ata controller when we want to read/write something to the harddisk
+		pci_devfn_t dev;
+		dev = pci_locate_device_on_bus(PCI_ID(0x8086,0x1e00), 0); // use static PCI_ID for the sata controller of our motherboard
+
+		if(dev==PCI_DEV_INVALID)
+		{
+			printk(BIOS_DEBUG, "Cannot find sata controller\n");
+			die("Cannot find sata controller\n");
+		}
+		else
+		{
+			printk(BIOS_DEBUG, "Found the sata controller\n");
+		}
+
+		// Check IO Space Enable bit
+		uint16_t PCICMD = pci_io_read_config16(dev, 0x04); // PCICMD—PCI Command Register (SATA–D31:F2)
+		printk(BIOS_DEBUG, "PCICMD 1 is 0x%04x\n", PCICMD); // LSB should be 0 here, meaning that IO is disabled..
+
+
+		// check PCMD_BAR, default value should be 00000001h
+		uint32_t PCMD_BAR = pci_io_read_config32(dev, 0x10);
+		printk(BIOS_DEBUG, "PCMD_BAR 1 is 0x%08x\n", PCMD_BAR);
+
+		pci_io_write_config32(dev, 0x10, 0x00002061); // set the IO address..
+
+		PCMD_BAR = pci_io_read_config32(dev, 0x10);
+		printk(BIOS_DEBUG, "PCMD_BAR 2 is 0x%08x\n", PCMD_BAR);
+
+
+
+		// BEGIN PRINT SOME DEBUG BASE ADDRESS..
+		// check PCNL_BAR, default value should be 00000001h
+		uint32_t PCNL_BAR = pci_io_read_config32(dev, 0x14);
+		printk(BIOS_DEBUG, "PCNL_BAR 1 is 0x%08x\n", PCNL_BAR);
+
+		pci_io_write_config32(dev, 0x14, 0x00002071); // set the IO address..
+
+		PCNL_BAR = pci_io_read_config32(dev, 0x14);
+		printk(BIOS_DEBUG, "PCNL_BAR 2 is 0x%08x\n", PCNL_BAR);
+
+
+
+		// check SCMD_BAR, default value should be 00000001h
+		uint32_t SCMD_BAR = pci_io_read_config32(dev, 0x18);
+		printk(BIOS_DEBUG, "SCMD_BAR 1 is 0x%08x\n", SCMD_BAR);
+
+		pci_io_write_config32(dev, 0x18, 0x00002069); // set the IO address..
+
+		SCMD_BAR = pci_io_read_config32(dev, 0x18);
+		printk(BIOS_DEBUG, "SCMD_BAR 2 is 0x%08x\n", SCMD_BAR);
+
+
+
+		// check SCNL_BAR, default value should be 00000001h
+		uint32_t SCNL_BAR = pci_io_read_config32(dev, 0x1c);
+		printk(BIOS_DEBUG, "SCNL_BAR 1 is 0x%08x\n", SCNL_BAR);
+
+		pci_io_write_config32(dev, 0x1c, 0x00002075); // set the IO address..
+
+		SCNL_BAR = pci_io_read_config32(dev, 0x1c);
+		printk(BIOS_DEBUG, "SCNL_BAR 2 is 0x%08x\n", SCNL_BAR);
+
+		printk(BIOS_DEBUG, "IO Space Enable bit should still be enabled but read/writing works without enabling??\n");
+		// END PRINT SOME DEBUG BASE ADDRESS..
+
+
+
+
+		u16 reg16;
+		u32 reg32;
+
+		#define sata_port_map  0x3f // the port to communicate to the sata controller with
+		// Stolen from coreboot/src/mainboard/gigabyte/ga-b75m-d3v/devicetree.cb
+
+		/* Enable BARs */
+		pci_write_config16(dev, PCI_COMMAND, 0x0007);
+
+		printk(BIOS_DEBUG, "SATA: Controller in plain mode.\n");
+
+		/* No AHCI: clear AHCI base */
+		pci_write_config32(dev, 0x24, 0x00000000);
+
+		/* And without AHCI BAR no memory decoding */
+		reg16 = pci_read_config16(dev, PCI_COMMAND);
+		reg16 &= ~PCI_COMMAND_MEMORY;
+		pci_write_config16(dev, PCI_COMMAND, reg16);
+
+		/* Native mode capable on both primary and secondary (0xa)
+		 * or'ed with enabled (0x50) = 0xf
+		 */
+		pci_write_config8(dev, 0x09, 0x8f);
+
+		/* Set Interrupt Line */
+		/* Interrupt Pin is set by D31IP.PIP */
+		pci_write_config8(dev, INTR_LN, 0xff);
+
+		/* Set timings */
+		pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
+				IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
+				IDE_PPE0 | IDE_IE0 | IDE_TIME0);
+		pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
+				IDE_SITRE | IDE_ISP_3_CLOCKS |
+				IDE_RCT_1_CLOCKS | IDE_IE0 | IDE_TIME0);
+
+		/* Sync DMA */
+		pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0 | IDE_PSDE0);
+		pci_write_config16(dev, IDE_SDMA_TIM, 0x0201);
+
+		/* Set IDE I/O Configuration */
+		reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
+		pci_write_config32(dev, IDE_CONFIG, reg32);
+
+		/* Port enable */
+		reg16 = pci_read_config16(dev, 0x92);
+		reg16 &= ~0x3f;
+		reg16 |= sata_port_map;
+		pci_write_config16(dev, 0x92, reg16);
+
+		/* SATA Initialization register */
+		pci_write_config32(dev, 0x94,
+			   ((sata_port_map ^ 0x3f) << 24) | 0x183);
+
+
+		/* Additional Programming Requirements */
+		sir_write(dev, 0x04, 0x00001600);
+		sir_write(dev, 0x28, 0xa0000033);
+		reg32 = sir_read(dev, 0x54);
+		reg32 &= 0xff000000;
+		reg32 |= 0x5555aa;
+		sir_write(dev, 0x54, reg32);
+		sir_write(dev, 0x64, 0xcccc8484);
+		reg32 = sir_read(dev, 0x68);
+		reg32 &= 0xffff0000;
+		reg32 |= 0xcccc;
+		sir_write(dev, 0x68, reg32);
+		reg32 = sir_read(dev, 0x78);
+		reg32 &= 0x0000ffff;
+		reg32 |= 0x88880000;
+		sir_write(dev, 0x78, reg32);
+		sir_write(dev, 0x84, 0x001c7000);
+		sir_write(dev, 0x88, 0x88338822);
+		sir_write(dev, 0xa0, 0x001c7000);
+		// a4
+		sir_write(dev, 0xc4, 0x0c0c0c0c);
+		sir_write(dev, 0xc8, 0x0c0c0c0c);
+		sir_write(dev, 0xd4, 0x10000000);
+
+
+
+
+
+		// added pch_iobp_update() as static function, stolen from coreboot/src/southbridge/intel/bd82x6x/pch.h
+		pch_iobp_update(0xea004001, 0x3fffffff, 0xc0000000);
+		pch_iobp_update(0xea00408a, 0xfffffcff, 0x00000100);
+
+
+
+
+
+		// try to enable sata.. 
+			// stolen from coreboot/src/southbridge/intel/bd82x6x/sata.c:sata_enable()
+
+		u16 map = 0;
+		map |= (sata_port_map ^ 0x3f) << 8;
+		pci_write_config16(dev, 0x90, map);
+		u8 slave = 0x0;
+
+
+		ata_reset(IOBASE1, IOBASE2, slave); // obligitory reset of the sata device
+
+
+
+
+
+		// how many hdd sectors will be written?
+		uint64_t number_of_bytes_required = (uint64_t) (tom_mb * 1024 * 1024);
+		printk(BIOS_DEBUG, "The number of bytes in memory %lld\n", number_of_bytes_required);
+
+		if((number_of_bytes_required%DISK_SECTOR_SIZE)!=0) // round memory to be written to blocksize
+			number_of_bytes_required = number_of_bytes_required-(number_of_bytes_required%DISK_SECTOR_SIZE)+DISK_SECTOR_SIZE;
+
+		uint64_t number_of_sectors_required = (uint64_t) number_of_bytes_required/DISK_SECTOR_SIZE;
+
+		printk(BIOS_DEBUG, "The number of hdd sectors the memory will take up %lld\n", number_of_sectors_required);
+
+
+		// the buffer we will use to save memory and write to harddisk
+		//uint8_t buffer[DISK_SECTOR_SIZE]; // reuse buffer as declared above..
+		memset(buffer, 0, sizeof(buffer));
+
+
+		// Rudimentary filesystem or image table
+		// first RESERVED_SECTORS_IMAGE_TABLE sectors of disk are reserved for a table which holds metadata about the images saved
+
+		// A record holds metadata on a single image, a record consists of eight 64bit entries.
+		// first entry is used to save start LBA
+		// second entry is used to save end LBA
+		// third is reserved 
+		// fourth is reserved
+		// fifth is reserved
+		// sixth is reserved (start image timestamp?)
+		// seventh and eight entry are used to save md5 sum of the image (md5 digest is 128 bits or 2*64bits)
+
+		// Total number of records that can be saved per sector is
+		// Sector 512 bytes, record 8*64bit=64 bytes
+		// 512/64 = 8 records per sector
+
+		// With 4 reserved sectors * 8 records per sector is room for 32 images 
+		// Assuming 4gb DIMMs/images we require a 128gb harddisk.
+
+		uint64_t image_start_lba = RESERVED_SECTORS_IMAGE_TABLE+1; // start at the fifth lba for saving images
+
+
+		// WRITING OR READING ATA
+		if(serialInputHardDisk == 'w')
+		{
+			printk(BIOS_DEBUG, "Writing to harddisk\n");
+
+
+			printk(BIOS_DEBUG, "Adding record to imagetable\n");
+			// detect where we can put the memory image on the hdd
+			for(int l=0; l<RESERVED_SECTORS_IMAGE_TABLE; l++)
+			{
+				memset(buffer, 0, sizeof(buffer));
+				read_sector(l, buffer);
+				struct RAMACQ_imagetable *imagetable_ptr = (void *) buffer;
+				for(int k=0;k<8;k++) // loop through 8 imagerecords per sector
+				{
+					printk(BIOS_DEBUG, "l=%d, k=%d, start_lba=%lld\n", l, k, imagetable_ptr->imagerecord[k].start_lba);
+					if(imagetable_ptr->imagerecord[k].start_lba == (uint64_t) 0x0000000000000000)
+					{
+						// fill the empty record with data
+						imagetable_ptr->imagerecord[k].start_lba = (uint64_t) image_start_lba; // lba where the image starts
+						imagetable_ptr->imagerecord[k].end_lba = (uint64_t) (image_start_lba + number_of_sectors_required); // lba where the image ends
+
+						printk(BIOS_DEBUG, "Adding image record, %d starting at lba %lld, ending at lba %lld\n", (l+1)*k, imagetable_ptr->imagerecord[k].start_lba, imagetable_ptr->imagerecord[k].end_lba);
+						printk(BIOS_DEBUG, "Second 64 bit variable of sector %d, record %d (zero indexed) should be %016llx\n",l, k, (uint64_t) (image_start_lba + number_of_sectors_required));
+						write_sector((uint64_t) l, buffer); // write the sector we changed back to the hdd
+						l=RESERVED_SECTORS_IMAGE_TABLE+666; // break on its own doesnt break out of outer loop; TODO should be a function but hey this works..
+						break;
+					}
+					else
+					{
+						printk(BIOS_DEBUG, "Found imagerecord %d starting at lba %lld, ending at lba %lld\n", (l+1)*k, imagetable_ptr->imagerecord[k].start_lba, imagetable_ptr->imagerecord[k].end_lba);
+
+						image_start_lba = imagetable_ptr->imagerecord[k].end_lba + 1; // if this is the last record we can use the next lba 
+					}
+				}
+			}
+
+
+
+
+
+			printk(BIOS_DEBUG, "Write all memory to disk press 'q' to cancel (will print status every percent) \n");
+
+			remainingOutput = totalOutput; // reset remainingOutput to be the same as totalOutput TODO probably best to scope this var smaller..
+			uint64_t address = (totalOutput-remainingOutput); // will be zero at first
+			while(remainingOutput != 0)
+			{
+				memset(buffer, 0, sizeof(buffer)); // reset buffer to all zeroes
+
+				// do not write to memory for addresses between tolud and 4gb ; write until max(touud, tom)
+				if((address >= tolud) && (address < 4294967296)) // bigger than tolud, smaller than 4gb
+				{
+					// address in the MMIO range
+					if(((address % 52428800)==0) || (address == tolud) || (address == 4294967296)) // only print address: on multiples of 50mb, when it is the same as tolud or when it is at 4gb border
+					{
+						printk(BIOS_DEBUG, "Address 0x%llx in MMIO range so skipping, remaining output 0x%llx\n", (uint64_t) address, (uint64_t) remainingOutput);
+					}
+				}
+				else
+				{
+					uint64_t pagedAddress = address;
+
+					if((address >= 4294967296)) // address bigger than 32 bit && address is a whole gigabyte border
+					{
+
+						if(((address % (1024*1024*1024))==0))
+						{ 
+							// enable paging for a 1gb window, only when we exhaust this window, enable paging for another window
+							pagingWindowGigabyte(&PTBL, address/(1024*1024*1024)); // window the fifth gigabyte and read from it..
+						}
+
+						// change the addresses to paged addresses for all addresses > 4gb
+						pagedAddress = ((uint64_t)address % 0x40000000) + 0x40000000;
+
+						if(((address % 52428800)==0) || (address == tolud) || (address == 4294967296) || (pagedAddress <= 512)) // only print address: on multiples of 50mb, when it is the same as tolud or when it is at 4gb border
+						{
+							// only print this for >4gb every 50 mb..
+							printk(BIOS_DEBUG, "Enabling paging for address: 0x%llx instead reading from pagedAddress: 0x%llx\n", address, pagedAddress);
+						}
+					}
+
+					// read from the pagedAddress memory address
+					read_memory(pagedAddress, outputBlockLen, buffer); // read 512 bytes at a time
+
+
+					uint64_t addressToAtaWrite = address;
+					uint64_t numberOfMMIOBytes = ((uint64_t)((uint64_t)get_mmio_size())*1024*1024);
+					if(address >= tolud)
+					{
+						addressToAtaWrite = (addressToAtaWrite - numberOfMMIOBytes); // substract number of MMIO bytes from the address
+
+						if(((address % 52428800)==0) || (address == tolud) || (address == 4294967296)) // only print address: on multiples of 50mb, when it is the same as tolud or when it is at 4gb border
+						{
+							printk(BIOS_DEBUG, "Past tolud so skipping MMIO for ata writes; adress: 0x%llx instead writing to addressToAtaWrite: 0x%llx\n", (uint64_t) address, (uint64_t) addressToAtaWrite);
+						}
+					}
+
+
+					if(((address % 52428800)==0) || (address == tolud) || (address == 4294967296)) // only print address: on multiples of 50mb, when it is the same as tolud or when it is at 4gb border
+					{
+						printk(BIOS_DEBUG, "Writing address 0x%llx to hdd LBA 0x%llx remaining output 0x%llx\n", (uint64_t) address, (uint64_t) image_start_lba+(addressToAtaWrite/outputBlockLen), (uint64_t) remainingOutput);
+					}
+
+
+					write_sector((uint64_t) image_start_lba+(addressToAtaWrite/outputBlockLen), buffer); // as the loop iterates with address increasing with outputBlockLen=512 we can use this as the sector to be written i.e. to build the LBA
+
+					remainingOutput = remainingOutput-outputBlockLen; // only decrement remaining output when data has been written
+				}
+				address = address+outputBlockLen; // always increment address
+			}
+
+			disablePaging(&PTBL);
+			printk(BIOS_DEBUG, "Final address written to hdd was 0x%llx\n", (uint64_t) address);
+			printk(BIOS_DEBUG, "Done writing memory to hdd\n");
+
+
+
+			printk(BIOS_DEBUG, "Halting for input\n");
+			serialInput = get_serial_input_blocking();
+		}
+		else
+		{
+			if(serialInputHardDisk == 'r')
+			{
+				printk(BIOS_DEBUG, "Read from harddisk\n");
+
+
+				printk(BIOS_DEBUG, "Reading first %d sectors from harddisk\n", RESERVED_SECTORS_IMAGE_TABLE);
+
+
+				memset(buffer, 0, sizeof(buffer));
+				for(int k=0;k<RESERVED_SECTORS_IMAGE_TABLE;k++) 
+				{
+					read_sector(k,buffer);
+					printk(BIOS_DEBUG, "\nSector %d:", k);
+					for(int z=0;z<DISK_SECTOR_SIZE;z++)
+					{
+						printk(BIOS_DEBUG, "%02x", buffer[z]);
+					}
+				}
+				printk(BIOS_DEBUG, "\n");
+
+			}
+			else 
+			{
+				printk(BIOS_DEBUG, "Skipping writing/reading harddisk\n");
+			}
+		}
+	}
+
+	// Disable ATA PIO
+	// ----------- End ATA PIO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	cbmem_was_inited = !cbmem_recovery(s3resume);
+	if (!fast_boot)
+		//save_timings(&ctrl); // We don't want to save any timings..
+	if (s3resume && !cbmem_was_inited) {
+		/* Failed S3 resume, reset to come up cleanly */
+		outb(0x6, 0xcf9);
+		halt();
+	}
+
+	fill_smbios17(&ctrl);
+}
+
+#define HOST_BRIDGE	PCI_DEVFN(0, 0)
+#define DEFAULT_TCK	TCK_800MHZ
 
 static unsigned int get_mem_min_tck(void)
 {
@@ -4403,10 +6457,11 @@ static unsigned int get_mmio_size(void)
 		cfg = dev->chip_info;
 
 	/* If this is zero, it just means devicetree.cb didn't set it */
-	if (!cfg || cfg->pci_mmio_size == 0)
+	if (!cfg || cfg->pci_mmio_size == 0){
 		return DEFAULT_PCI_MMIO_SIZE;
-	else
+	} else {
 		return cfg->pci_mmio_size;
+	}
 }
 
 void perform_raminit(int s3resume)
@@ -4418,6 +6473,17 @@ void perform_raminit(int s3resume)
 	memset (spd, 0, sizeof (spd));
 	mainboard_get_spd(spd);
 
+
+	while((uint8_t) spd[0][0] == (uint8_t) 255) // If very first data of spd is incorrect rest probably is also. 
+		//TODO could also check multiple bytes or CRC of SPD but this seems to suffice..
+	{
+		printk(BIOS_DEBUG, "No correct SPD found, sleep and recurse\n");
+		// may be better to recurse even before doing anything with ME as DID is not received in time otherwise..
+		mainboard_get_spd(spd);
+		delay(1); // sleep one second anyway, to make sure DIMM is inserted all the way...
+	}
+
+
 	timestamp_add_now(TS_BEFORE_INITRAM);
 
 	init_dram_ddr3(spd, 1, get_mem_min_tck(), s3resume);



More information about the coreboot-gerrit mailing list