diff options
Diffstat (limited to 'arch')
102 files changed, 1770 insertions, 701 deletions
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 397a0ae..2d75f64 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -320,10 +320,10 @@ dtb-$(CONFIG_MX6) += imx6ull-14x14-evk.dtb \ dtb-$(CONFIG_MX7) += imx7-colibri.dtb -dtb-$(CONFIG_SOC_KEYSTONE) += k2hk-evm.dtb \ - k2l-evm.dtb \ - k2e-evm.dtb \ - k2g-evm.dtb +dtb-$(CONFIG_SOC_KEYSTONE) += keystone-k2hk-evm.dtb \ + keystone-k2l-evm.dtb \ + keystone-k2e-evm.dtb \ + keystone-k2g-evm.dtb dtb-$(CONFIG_TARGET_SAMA5D2_XPLAINED) += \ at91-sama5d2_xplained.dtb diff --git a/arch/arm/dts/exynos4210-trats.dts b/arch/arm/dts/exynos4210-trats.dts index 2ed38f3..69c0605 100644 --- a/arch/arm/dts/exynos4210-trats.dts +++ b/arch/arm/dts/exynos4210-trats.dts @@ -19,14 +19,6 @@ }; aliases { - i2c0 = "/i2c@13860000"; - i2c1 = "/i2c@13870000"; - i2c2 = "/i2c@13880000"; - i2c3 = "/i2c@13890000"; - i2c4 = "/i2c@138a0000"; - i2c5 = "/i2c@138b0000"; - i2c6 = "/i2c@138c0000"; - i2c7 = "/i2c@138d0000"; serial0 = "/serial@13800000"; console = "/serial@13820000"; mmc0 = "/sdhci@12510000"; @@ -122,3 +114,145 @@ status = "disabled"; }; }; + +&i2c_5 { + clock-frequency = <100000>; + status = "okay"; + + max8997-pmic@66 { + compatible = "maxim,max8997"; + reg = <0x66 0 0>; + voltage-regulators { + valive_reg: LDO2 { + regulator-name = "VALIVE_1.1V_C210"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + }; + + vusb_reg: LDO3 { + regulator-name = "VUSB_1.1V_C210"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + }; + + vmipi_reg: LDO4 { + regulator-name = "VMIPI_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vpda_reg: LDO6 { + regulator-name = "VCC_1.8V_PDA"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vcam_reg: LDO7 { + regulator-name = "CAM_ISP_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vusbdac_reg: LDO8 { + regulator-name = "VUSB+VDAC_3.3V_C210"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vccpda_reg: LDO9 { + regulator-name = "VCC_2.8V_PDA"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + vpll_reg: LDO10 { + regulator-name = "VPLL_1.1V_C210"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + }; + + vtcam_reg: LDO12 { + regulator-name = "VT_CAM_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vcclcd_reg: LDO13 { + regulator-name = "VCC_3.3V_LCD"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vlcd_reg: LDO15 { + regulator-name = "VLCD_2.2V"; + regulator-min-microvolt = <2200000>; + regulator-max-microvolt = <2200000>; + }; + + camsensor_reg: LDO16 { + regulator-name = "CAM_SENSOR_IO_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vddq_reg: LDO21 { + regulator-name = "VDDQ_M1M2_1.2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + varm_breg: BUCK1 { + /* + * HACK: The real name is VARM_1.2V_C210, + * but exynos-cpufreq does not support + * DT-based regulator lookup yet. + */ + regulator-name = "vdd_arm"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + }; + + vint_breg: BUCK2 { + regulator-name = "VINT_1.1V_C210"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + }; + + camisp_breg: BUCK4 { + regulator-name = "CAM_ISP_CORE_1.2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + vmem_breg: BUCK5 { + regulator-name = "VMEM_1.2V_C210"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + vccsub_breg: BUCK7 { + regulator-name = "VCC_SUB_2.0V"; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-always-on; + }; + + safe1_sreg: ESAFEOUT1 { + regulator-name = "SAFEOUT1"; + }; + + safe2_sreg: ESAFEOUT2 { + regulator-name = "SAFEOUT2"; + regulator-boot-on; + }; + }; + }; +}; diff --git a/arch/arm/dts/k2e-clocks.dtsi b/arch/arm/dts/keystone-k2e-clocks.dtsi index d56d68f..d56d68f 100644 --- a/arch/arm/dts/k2e-clocks.dtsi +++ b/arch/arm/dts/keystone-k2e-clocks.dtsi diff --git a/arch/arm/dts/k2e-evm.dts b/arch/arm/dts/keystone-k2e-evm.dts index e2c3fb4..3be8b53 100644 --- a/arch/arm/dts/k2e-evm.dts +++ b/arch/arm/dts/keystone-k2e-evm.dts @@ -10,7 +10,7 @@ /dts-v1/; #include "keystone.dtsi" -#include "k2e.dtsi" +#include "keystone-k2e.dtsi" / { compatible = "ti,k2e-evm","ti,keystone"; diff --git a/arch/arm/dts/k2e-netcp.dtsi b/arch/arm/dts/keystone-k2e-netcp.dtsi index b13b3c9..b13b3c9 100644 --- a/arch/arm/dts/k2e-netcp.dtsi +++ b/arch/arm/dts/keystone-k2e-netcp.dtsi diff --git a/arch/arm/dts/k2e.dtsi b/arch/arm/dts/keystone-k2e.dtsi index 675fb8e..b5d9061 100644 --- a/arch/arm/dts/k2e.dtsi +++ b/arch/arm/dts/keystone-k2e.dtsi @@ -41,7 +41,7 @@ }; soc { - /include/ "k2e-clocks.dtsi" + /include/ "keystone-k2e-clocks.dtsi" usb: usb@2680000 { interrupts = <GIC_SPI 152 IRQ_TYPE_EDGE_RISING>; @@ -142,6 +142,6 @@ clock-names = "fck"; bus_freq = <2500000>; }; - /include/ "k2e-netcp.dtsi" + /include/ "keystone-k2e-netcp.dtsi" }; }; diff --git a/arch/arm/dts/k2g-evm.dts b/arch/arm/dts/keystone-k2g-evm.dts index 61d0d55..696a0d7 100644 --- a/arch/arm/dts/k2g-evm.dts +++ b/arch/arm/dts/keystone-k2g-evm.dts @@ -1,7 +1,7 @@ /* * Copyright 2014 Texas Instruments, Inc. * - * Keystone 2 Galileo EVM device tree + * Device Tree Source for K2G EVM * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -9,11 +9,11 @@ */ /dts-v1/; -#include "k2g.dtsi" +#include "keystone-k2g.dtsi" / { compatible = "ti,k2g-evm","ti,keystone"; - model = "Texas Instruments Keystone 2 Galileo EVM"; + model = "Texas Instruments K2G General Purpose EVM"; chosen { stdout-path = &uart0; diff --git a/arch/arm/dts/k2g-netcp.dtsi b/arch/arm/dts/keystone-k2g-netcp.dtsi index 6f0ff86..a9b26c3 100644 --- a/arch/arm/dts/k2g-netcp.dtsi +++ b/arch/arm/dts/keystone-k2g-netcp.dtsi @@ -1,5 +1,5 @@ /* - * Device Tree Source for Keystone 2 Galileo Netcp driver + * Device Tree Source for K2G Netcp driver * * Copyright 2015 Texas Instruments, Inc. * diff --git a/arch/arm/dts/k2g.dtsi b/arch/arm/dts/keystone-k2g.dtsi index add03b7..2193f9f 100644 --- a/arch/arm/dts/k2g.dtsi +++ b/arch/arm/dts/keystone-k2g.dtsi @@ -1,7 +1,7 @@ /* * Copyright 2014 Texas Instruments, Inc. * - * Keystone 2 Galileo soc device tree + * Device Tree Source for K2G SOC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,7 +12,7 @@ #include "skeleton.dtsi" / { - model = "Texas Instruments Keystone 2 SoC"; + model = "Texas Instruments K2G SoC"; #address-cells = <1>; #size-cells = <1>; interrupt-parent = <&gic>; @@ -98,7 +98,7 @@ status = "disabled"; }; - #include "k2g-netcp.dtsi" + #include "keystone-k2g-netcp.dtsi" pmmc: pmmc@2900000 { compatible = "ti,power-processor"; diff --git a/arch/arm/dts/k2hk-clocks.dtsi b/arch/arm/dts/keystone-k2hk-clocks.dtsi index af9b719..af9b719 100644 --- a/arch/arm/dts/k2hk-clocks.dtsi +++ b/arch/arm/dts/keystone-k2hk-clocks.dtsi diff --git a/arch/arm/dts/k2hk-evm.dts b/arch/arm/dts/keystone-k2hk-evm.dts index c5cad2c..76a675f 100644 --- a/arch/arm/dts/k2hk-evm.dts +++ b/arch/arm/dts/keystone-k2hk-evm.dts @@ -10,7 +10,7 @@ /dts-v1/; #include "keystone.dtsi" -#include "k2hk.dtsi" +#include "keystone-k2hk.dtsi" / { compatible = "ti,k2hk-evm","ti,keystone"; diff --git a/arch/arm/dts/k2hk-netcp.dtsi b/arch/arm/dts/keystone-k2hk-netcp.dtsi index 77a32c3..77a32c3 100644 --- a/arch/arm/dts/k2hk-netcp.dtsi +++ b/arch/arm/dts/keystone-k2hk-netcp.dtsi diff --git a/arch/arm/dts/k2hk.dtsi b/arch/arm/dts/keystone-k2hk.dtsi index d0810a5..fc78696 100644 --- a/arch/arm/dts/k2hk.dtsi +++ b/arch/arm/dts/keystone-k2hk.dtsi @@ -41,7 +41,7 @@ }; soc { - /include/ "k2hk-clocks.dtsi" + /include/ "keystone-k2hk-clocks.dtsi" dspgpio0: keystone_dsp_gpio@02620240 { compatible = "ti,keystone-dsp-gpio"; @@ -109,6 +109,6 @@ clock-names = "fck"; bus_freq = <2500000>; }; - /include/ "k2hk-netcp.dtsi" + /include/ "keystone-k2hk-netcp.dtsi" }; }; diff --git a/arch/arm/dts/k2l-clocks.dtsi b/arch/arm/dts/keystone-k2l-clocks.dtsi index ef8464b..ef8464b 100644 --- a/arch/arm/dts/k2l-clocks.dtsi +++ b/arch/arm/dts/keystone-k2l-clocks.dtsi diff --git a/arch/arm/dts/k2l-evm.dts b/arch/arm/dts/keystone-k2l-evm.dts index da0661b..b5c5617 100644 --- a/arch/arm/dts/k2l-evm.dts +++ b/arch/arm/dts/keystone-k2l-evm.dts @@ -10,7 +10,7 @@ /dts-v1/; #include "keystone.dtsi" -#include "k2l.dtsi" +#include "keystone-k2l.dtsi" / { compatible = "ti,k2l-evm","ti,keystone"; diff --git a/arch/arm/dts/k2l-netcp.dtsi b/arch/arm/dts/keystone-k2l-netcp.dtsi index 6b95284..6b95284 100644 --- a/arch/arm/dts/k2l-netcp.dtsi +++ b/arch/arm/dts/keystone-k2l-netcp.dtsi diff --git a/arch/arm/dts/k2l.dtsi b/arch/arm/dts/keystone-k2l.dtsi index 49fd414..d681cab 100644 --- a/arch/arm/dts/k2l.dtsi +++ b/arch/arm/dts/keystone-k2l.dtsi @@ -29,7 +29,7 @@ }; soc { - /include/ "k2l-clocks.dtsi" + /include/ "keystone-k2l-clocks.dtsi" uart2: serial@02348400 { compatible = "ns16550a"; @@ -89,7 +89,7 @@ clock-names = "fck"; bus_freq = <2500000>; }; - /include/ "k2l-netcp.dtsi" + /include/ "keystone-k2l-netcp.dtsi" }; }; diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S index 91b19e0..19c6a98 100644 --- a/arch/arm/lib/crt0_64.S +++ b/arch/arm/lib/crt0_64.S @@ -117,10 +117,8 @@ relocation_return: */ ldr x0, =__bss_start /* this is auto-relocated! */ ldr x1, =__bss_end /* this is auto-relocated! */ - mov x2, #0 clear_loop: - str x2, [x0] - add x0, x0, #8 + str xzr, [x0], #8 cmp x0, x1 b.lo clear_loop diff --git a/arch/arm/lib/relocate_64.S b/arch/arm/lib/relocate_64.S index 242e56e..c760053 100644 --- a/arch/arm/lib/relocate_64.S +++ b/arch/arm/lib/relocate_64.S @@ -68,7 +68,7 @@ relocate_done: b 0f 1: mrs x0, sctlr_el1 0: tbz w0, #2, 5f /* skip flushing cache if disabled */ - tbz w0, #12, 4f /* invalide i-cache is enabled */ + tbz w0, #12, 4f /* skip invalidating i-cache if disabled */ ic iallu /* i-cache invalidate all */ isb sy 4: ldp x0, x1, [sp, #16] diff --git a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c index ace1028..cb6e03f 100644 --- a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c +++ b/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c @@ -392,7 +392,7 @@ static int ast2500_sdrammc_ofdata_to_platdata(struct udevice *dev) priv->regs = regmap_get_range(map, 0); priv->phy = regmap_get_range(map, 1); - priv->clock_rate = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + priv->clock_rate = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "clock-frequency", 0); if (!priv->clock_rate) { diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c index be3d713..89fd8e6 100644 --- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c +++ b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c @@ -1016,7 +1016,7 @@ static int rk3288_dmc_ofdata_to_platdata(struct udevice *dev) #if !CONFIG_IS_ENABLED(OF_PLATDATA) struct rk3288_sdram_params *params = dev_get_platdata(dev); const void *blob = gd->fdt_blob; - int node = dev->of_offset; + int node = dev_of_offset(dev); int ret; /* Rk3288 supports dual-channel, set default channel num to 2 */ diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c index aa71636..29e18f8 100644 --- a/arch/arm/mach-socfpga/clock_manager.c +++ b/arch/arm/mach-socfpga/clock_manager.c @@ -167,6 +167,9 @@ void cm_basic_init(const struct cm_config * const cfg) /* main mpu */ writel(cfg->mpuclk, &clock_manager_base->main_pll.mpuclk); + /* altera group mpuclk */ + writel(cfg->altera_grp_mpuclk, &clock_manager_base->altera.mpuclk); + /* main main clock */ writel(cfg->mainclk, &clock_manager_base->main_pll.mainclk); diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h index 2675951..803c926 100644 --- a/arch/arm/mach-socfpga/include/mach/clock_manager.h +++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h @@ -55,6 +55,9 @@ struct cm_config { uint32_t ddr2xdqsclk; uint32_t ddrdqclk; uint32_t s2fuser2clk; + + /* altera group */ + uint32_t altera_grp_mpuclk; }; void cm_basic_init(const struct cm_config * const cfg); diff --git a/arch/arm/mach-socfpga/wrap_pll_config.c b/arch/arm/mach-socfpga/wrap_pll_config.c index 8a0a0e6..72b5f92 100644 --- a/arch/arm/mach-socfpga/wrap_pll_config.c +++ b/arch/arm/mach-socfpga/wrap_pll_config.c @@ -116,6 +116,9 @@ static const struct cm_config cm_default_cfg = { CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_OFFSET) | (CONFIG_HPS_SDRPLLGRP_S2FUSER2CLK_CNT << CLKMGR_SDRPLLGRP_S2FUSER2CLK_CNT_OFFSET), + + /* altera group */ + CONFIG_HPS_ALTERAGRP_MPUCLK, }; const struct cm_config * const cm_get_default_config(void) diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig index cd9ba6b..5739325 100644 --- a/arch/arm/mach-uniphier/Kconfig +++ b/arch/arm/mach-uniphier/Kconfig @@ -13,6 +13,7 @@ config ARCH_UNIPHIER_32BIT config ARCH_UNIPHIER_64BIT bool select ARM64 + select CMD_UNZIP select SPL_SEPARATE_BSS if SPL select ARMV8_MULTIENTRY if SPL select ARMV8_SPIN_TABLE if SPL diff --git a/arch/nios2/cpu/cpu.c b/arch/nios2/cpu/cpu.c index 4f0f8fc..c1caa65 100644 --- a/arch/nios2/cpu/cpu.c +++ b/arch/nios2/cpu/cpu.c @@ -103,7 +103,7 @@ static int altera_nios2_get_count(struct udevice *dev) static int altera_nios2_probe(struct udevice *dev) { const void *blob = gd->fdt_blob; - int node = dev->of_offset; + int node = dev_of_offset(dev); gd->cpu_clk = fdtdec_get_int(blob, node, "clock-frequency", 0); diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts index e6d336f..2061464 100644 --- a/arch/sandbox/dts/sandbox.dts +++ b/arch/sandbox/dts/sandbox.dts @@ -203,6 +203,11 @@ stringarray = "one"; }; + spl-test4 { + u-boot,dm-pre-reloc; + compatible = "sandbox,spl-test.2"; + }; + square { compatible = "demo-shape"; colour = "blue"; diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0884af2..5f9597b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -5,6 +5,52 @@ config SYS_ARCH default "x86" choice + prompt "Run U-Boot in 32/64-bit mode" + default X86_RUN_32BIT + help + U-Boot can be built as a 32-bit binary which runs in 32-bit mode + even on 64-bit machines. In this case SPL is not used, and U-Boot + runs directly from the reset vector (via 16-bit start-up). + + Alternatively it can be run as a 64-bit binary, thus requiring a + 64-bit machine. In this case SPL runs in 32-bit mode (via 16-bit + start-up) then jumps to U-Boot in 64-bit mode. + + For now, 32-bit mode is recommended, as 64-bit is still + experimental and is missing a lot of features. + +config X86_RUN_32BIT + bool "32-bit" + help + Build U-Boot as a 32-bit binary with no SPL. This is the currently + supported normal setup. U-Boot will stay in 32-bit mode even on + 64-bit machines. When booting a 64-bit kernel, U-Boot will switch + to 64-bit just before starting the kernel. Only the bottom 4GB of + memory can be accessed through normal means, although + arch_phys_memset() can be used for basic access to other memory. + +config X86_RUN_64BIT + bool "64-bit" + select X86_64 + select SUPPORT_SPL + select SPL + select SPL_SEPARATE_BSS + help + Build U-Boot as a 64-bit binary with a 32-bit SPL. This is + experimental and many features are missing. U-Boot SPL starts up, + runs through the 16-bit and 32-bit init, then switches to 64-bit + mode and jumps to U-Boot proper. + +endchoice + +config X86_64 + bool + +config SPL_X86_64 + bool + depends on SPL + +choice prompt "Mainboard vendor" default VENDOR_EMULATION @@ -89,6 +135,46 @@ config X86_RESET_VECTOR bool default n +# The following options control where the 16-bit and 32-bit init lies +# If SPL is enabled then it normally holds this init code, and U-Boot proper +# is normally a 64-bit build. +# +# The 16-bit init refers to the reset vector and the small amount of code to +# get the processor into 32-bit mode. It may be in SPL or in U-Boot proper, +# or missing altogether if U-Boot is started from EFI or coreboot. +# +# The 32-bit init refers to processor init, running binary blobs including +# FSP, setting up interrupts and anything else that needs to be done in +# 32-bit code. It is normally in the same place as 16-bit init if that is +# enabled (i.e. they are both in SPL, or both in U-Boot proper). +config X86_16BIT_INIT + bool + depends on X86_RESET_VECTOR + default y if X86_RESET_VECTOR && !SPL + help + This is enabled when 16-bit init is in U-Boot proper + +config SPL_X86_16BIT_INIT + bool + depends on X86_RESET_VECTOR + default y if X86_RESET_VECTOR && SPL + help + This is enabled when 16-bit init is in SPL + +config X86_32BIT_INIT + bool + depends on X86_RESET_VECTOR + default y if X86_RESET_VECTOR && !SPL + help + This is enabled when 32-bit init is in U-Boot proper + +config SPL_X86_32BIT_INIT + bool + depends on X86_RESET_VECTOR + default y if X86_RESET_VECTOR && SPL + help + This is enabled when 32-bit init is in SPL + config RESET_SEG_START hex depends on X86_RESET_VECTOR @@ -109,6 +195,14 @@ config SYS_X86_START16 depends on X86_RESET_VECTOR default 0xfffff800 +config X86_LOAD_FROM_32_BIT + bool "Boot from a 32-bit program" + help + Define this to boot U-Boot from a 32-bit program which sets + the GDT differently. This can be used to boot directly from + any stage of coreboot, for example, bypassing the normal + payload-loading feature. + config BOARD_ROMSIZE_KB_512 bool config BOARD_ROMSIZE_KB_1024 diff --git a/arch/x86/Makefile b/arch/x86/Makefile index d104a49..4be1c35 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -3,12 +3,15 @@ # ifeq ($(CONFIG_EFI_APP),) +ifdef CONFIG_$(SPL_)X86_64 +head-y := arch/x86/cpu/start64.o +else head-y := arch/x86/cpu/start.o endif -ifeq ($(CONFIG_SPL_BUILD),y) -head-y += arch/x86/cpu/start16.o -head-y += arch/x86/cpu/resetvec.o endif +head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/start16.o +head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/resetvec.o + libs-y += arch/x86/cpu/ libs-y += arch/x86/lib/ diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 1697dca..74b87ce 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -15,11 +15,25 @@ PF_CPPFLAGS_X86 := $(call cc-option, -fno-toplevel-reorder, \ PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_X86) PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm + +ifdef CONFIG_SPL_BUILD +IS_32BIT := y +else +ifndef CONFIG_X86_64 +IS_32BIT := y +endif +endif + +ifeq ($(IS_32BIT),y) PLATFORM_CPPFLAGS += -march=i386 -m32 +else +PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common +endif PLATFORM_RELFLAGS += -ffunction-sections -fvisibility=hidden -PLATFORM_LDFLAGS += -Bsymbolic -Bsymbolic-functions -m elf_i386 +PLATFORM_LDFLAGS += -Bsymbolic -Bsymbolic-functions +PLATFORM_LDFLAGS += -m $(if $(IS_32BIT),elf_i386,elf_x86_64) LDFLAGS_FINAL += --wrap=__divdi3 --wrap=__udivdi3 LDFLAGS_FINAL += --wrap=__moddi3 --wrap=__umoddi3 @@ -31,7 +45,9 @@ LDFLAGS_EFI_PAYLOAD := -Bsymbolic -Bsymbolic-functions -shared --no-undefined OBJCOPYFLAGS_EFI := -j .text -j .sdata -j .data -j .dynamic -j .dynsym \ -j .rel -j .rela -j .reloc +ifeq ($(IS_32BIT),y) CFLAGS_NON_EFI := -mregparm=3 +endif CFLAGS_EFI := -fpic -fshort-wchar ifeq ($(CONFIG_EFI_STUB_64BIT),) @@ -62,8 +78,18 @@ else PLATFORM_CPPFLAGS += $(CFLAGS_NON_EFI) PLATFORM_LDFLAGS += --emit-relocs -LDFLAGS_FINAL += --gc-sections -pie +LDFLAGS_FINAL += --gc-sections $(if $(CONFIG_SPL_BUILD),,-pie) + +endif +ifdef CONFIG_X86_64 +ifndef CONFIG_SPL_BUILD +PLATFORM_CPPFLAGS += -D__x86_64__ +else +PLATFORM_CPPFLAGS += -D__I386__ +endif +else +PLATFORM_CPPFLAGS += -D__I386__ endif ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),) diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index f5b8c9e..92a9023 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -8,15 +8,22 @@ # SPDX-License-Identifier: GPL-2.0+ # +ifeq ($(CONFIG_$(SPL_)X86_64),y) +extra-y = start64.o +else extra-y = start.o -obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o -obj-y += interrupts.o cpu.o cpu_x86.o call64.o setjmp.o +endif +extra-$(CONFIG_$(SPL_)X86_16BIT_INIT) += resetvec.o start16.o +obj-y += cpu.o cpu_x86.o + +ifndef CONFIG_$(SPL_)X86_64 AFLAGS_REMOVE_call32.o := -mregparm=3 \ $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32) AFLAGS_call32.o := -fpic -fshort-wchar extra-y += call32.o +endif obj-y += intel_common/ obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/ @@ -27,9 +34,20 @@ obj-$(CONFIG_QEMU) += qemu/ obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/ obj-$(CONFIG_INTEL_QUARK) += quark/ obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/ -obj-y += irq.o lapic.o ioapic.o +obj-y += lapic.o ioapic.o +obj-y += irq.o +ifndef CONFIG_$(SPL_)X86_64 obj-$(CONFIG_SMP) += mp_init.o +endif obj-y += mtrr.o obj-$(CONFIG_PCI) += pci.o +ifndef CONFIG_$(SPL_)X86_64 obj-$(CONFIG_SMP) += sipi_vector.o +endif obj-y += turbo.o + +ifeq ($(CONFIG_$(SPL_)X86_64),y) +obj-y += x86_64/ +else +obj-y += i386/ +endif diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c index 6977e86..1b71d56 100644 --- a/arch/x86/cpu/broadwell/cpu.c +++ b/arch/x86/cpu/broadwell/cpu.c @@ -256,8 +256,8 @@ static void initialize_vr_config(struct udevice *dev) /* Set the slow ramp rate */ msr.hi &= ~(0x3 << (53 - 32)); /* Configure the C-state exit ramp rate */ - ramp = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "intel,slow-ramp", - -1); + ramp = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "intel,slow-ramp", -1); if (ramp != -1) { /* Configured slow ramp rate */ msr.hi |= ((ramp & 0x3) << (53 - 32)); @@ -271,8 +271,8 @@ static void initialize_vr_config(struct udevice *dev) } /* Set MIN_VID (31:24) to allow CPU to have full control */ msr.lo &= ~0xff000000; - min_vid = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "intel,min-vid", - 0); + min_vid = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "intel,min-vid", 0); msr.lo |= (min_vid & 0xff) << 24; msr_write(MSR_VR_MISC_CONFIG, msr); @@ -562,7 +562,7 @@ static void configure_thermal_target(struct udevice *dev) int tcc_offset; msr_t msr; - tcc_offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + tcc_offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "intel,tcc-offset", 0); /* Set TCC activaiton offset if supported */ diff --git a/arch/x86/cpu/broadwell/pch.c b/arch/x86/cpu/broadwell/pch.c index 317f57d..16eac3d 100644 --- a/arch/x86/cpu/broadwell/pch.c +++ b/arch/x86/cpu/broadwell/pch.c @@ -190,14 +190,14 @@ static int pch_power_options(struct udevice *dev) debug("Set power %s after power failure.\n", state); /* GPE setup based on device tree configuration */ - ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, + ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "intel,gpe0-en", enable, ARRAY_SIZE(enable)); if (ret) return -EINVAL; enable_all_gpe(enable[0], enable[1], enable[2], enable[3]); /* SMI setup based on device tree configuration */ - enable_alt_smi(dev, fdtdec_get_int(gd->fdt_blob, dev->of_offset, + enable_alt_smi(dev, fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "intel,alt-gp-smi-enable", 0)); return 0; diff --git a/arch/x86/cpu/broadwell/pinctrl_broadwell.c b/arch/x86/cpu/broadwell/pinctrl_broadwell.c index 2a3fced..881413f 100644 --- a/arch/x86/cpu/broadwell/pinctrl_broadwell.c +++ b/arch/x86/cpu/broadwell/pinctrl_broadwell.c @@ -51,7 +51,7 @@ static int broadwell_pinctrl_read_configs(struct udevice *dev, int node; debug("%s: starting\n", __func__); - for (node = fdt_first_subnode(blob, dev->of_offset); + for (node = fdt_first_subnode(blob, dev_of_offset(dev)); node > 0; node = fdt_next_subnode(blob, node)) { int phandle = fdt_get_phandle(blob, node); @@ -115,7 +115,7 @@ static int broadwell_pinctrl_read_pins(struct udevice *dev, int count = 0; int node; - for (node = fdt_first_subnode(blob, dev->of_offset); + for (node = fdt_first_subnode(blob, dev_of_offset(dev)); node > 0; node = fdt_next_subnode(blob, node)) { int len, i; diff --git a/arch/x86/cpu/broadwell/sata.c b/arch/x86/cpu/broadwell/sata.c index 2e47082..10461d9 100644 --- a/arch/x86/cpu/broadwell/sata.c +++ b/arch/x86/cpu/broadwell/sata.c @@ -235,7 +235,7 @@ static int broadwell_sata_ofdata_to_platdata(struct udevice *dev) { struct sata_platdata *plat = dev_get_platdata(dev); const void *blob = gd->fdt_blob; - int node = dev->of_offset; + int node = dev_of_offset(dev); plat->port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0); plat->port0_gen3_tx = fdtdec_get_int(blob, node, diff --git a/arch/x86/cpu/config.mk b/arch/x86/cpu/config.mk index 1263221..b519f43 100644 --- a/arch/x86/cpu/config.mk +++ b/arch/x86/cpu/config.mk @@ -7,11 +7,15 @@ CROSS_COMPILE ?= i386-linux- -PLATFORM_CPPFLAGS += -D__I386__ - # DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! LDPPFLAGS += -DRESET_SEG_START=$(CONFIG_RESET_SEG_START) LDPPFLAGS += -DRESET_SEG_SIZE=$(CONFIG_RESET_SEG_SIZE) LDPPFLAGS += -DRESET_VEC_LOC=$(CONFIG_RESET_VEC_LOC) LDPPFLAGS += -DSTART_16=$(CONFIG_SYS_X86_START16) LDPPFLAGS += -DRESET_BASE="CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE)" + +ifdef CONFIG_X86_64 +ifndef CONFIG_SPL_BUILD +LDSCRIPT = $(srctree)/arch/x86/cpu/u-boot-64.lds +endif +endif diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 7c1d6de..8fa6953 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -43,55 +43,6 @@ DECLARE_GLOBAL_DATA_PTR; -/* - * Constructor for a conventional segment GDT (or LDT) entry - * This is a macro so it can be used in initialisers - */ -#define GDT_ENTRY(flags, base, limit) \ - ((((base) & 0xff000000ULL) << (56-24)) | \ - (((flags) & 0x0000f0ffULL) << 40) | \ - (((limit) & 0x000f0000ULL) << (48-16)) | \ - (((base) & 0x00ffffffULL) << 16) | \ - (((limit) & 0x0000ffffULL))) - -struct gdt_ptr { - u16 len; - u32 ptr; -} __packed; - -struct cpu_device_id { - unsigned vendor; - unsigned device; -}; - -struct cpuinfo_x86 { - uint8_t x86; /* CPU family */ - uint8_t x86_vendor; /* CPU vendor */ - uint8_t x86_model; - uint8_t x86_mask; -}; - -/* - * List of cpu vendor strings along with their normalized - * id values. - */ -static const struct { - int vendor; - const char *name; -} x86_vendors[] = { - { X86_VENDOR_INTEL, "GenuineIntel", }, - { X86_VENDOR_CYRIX, "CyrixInstead", }, - { X86_VENDOR_AMD, "AuthenticAMD", }, - { X86_VENDOR_UMC, "UMC UMC UMC ", }, - { X86_VENDOR_NEXGEN, "NexGenDriven", }, - { X86_VENDOR_CENTAUR, "CentaurHauls", }, - { X86_VENDOR_RISE, "RiseRiseRise", }, - { X86_VENDOR_TRANSMETA, "GenuineTMx86", }, - { X86_VENDOR_TRANSMETA, "TransmetaCPU", }, - { X86_VENDOR_NSC, "Geode by NSC", }, - { X86_VENDOR_SIS, "SiS SiS SiS ", }, -}; - static const char *const x86_vendor_name[] = { [X86_VENDOR_INTEL] = "Intel", [X86_VENDOR_CYRIX] = "Cyrix", @@ -105,100 +56,6 @@ static const char *const x86_vendor_name[] = { [X86_VENDOR_SIS] = "SiS", }; -static void load_ds(u32 segment) -{ - asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE)); -} - -static void load_es(u32 segment) -{ - asm volatile("movl %0, %%es" : : "r" (segment * X86_GDT_ENTRY_SIZE)); -} - -static void load_fs(u32 segment) -{ - asm volatile("movl %0, %%fs" : : "r" (segment * X86_GDT_ENTRY_SIZE)); -} - -static void load_gs(u32 segment) -{ - asm volatile("movl %0, %%gs" : : "r" (segment * X86_GDT_ENTRY_SIZE)); -} - -static void load_ss(u32 segment) -{ - asm volatile("movl %0, %%ss" : : "r" (segment * X86_GDT_ENTRY_SIZE)); -} - -static void load_gdt(const u64 *boot_gdt, u16 num_entries) -{ - struct gdt_ptr gdt; - - gdt.len = (num_entries * X86_GDT_ENTRY_SIZE) - 1; - gdt.ptr = (ulong)boot_gdt; - - asm volatile("lgdtl %0\n" : : "m" (gdt)); -} - -void arch_setup_gd(gd_t *new_gd) -{ - u64 *gdt_addr; - - gdt_addr = new_gd->arch.gdt; - - /* - * CS: code, read/execute, 4 GB, base 0 - * - * Some OS (like VxWorks) requires GDT entry 1 to be the 32-bit CS - */ - gdt_addr[X86_GDT_ENTRY_UNUSED] = GDT_ENTRY(0xc09b, 0, 0xfffff); - gdt_addr[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff); - - /* DS: data, read/write, 4 GB, base 0 */ - gdt_addr[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff); - - /* FS: data, read/write, 4 GB, base (Global Data Pointer) */ - new_gd->arch.gd_addr = new_gd; - gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0xc093, - (ulong)&new_gd->arch.gd_addr, 0xfffff); - - /* 16-bit CS: code, read/execute, 64 kB, base 0 */ - gdt_addr[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x009b, 0, 0x0ffff); - - /* 16-bit DS: data, read/write, 64 kB, base 0 */ - gdt_addr[X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x0093, 0, 0x0ffff); - - gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_CS] = GDT_ENTRY(0x809b, 0, 0xfffff); - gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_DS] = GDT_ENTRY(0x8093, 0, 0xfffff); - - load_gdt(gdt_addr, X86_GDT_NUM_ENTRIES); - load_ds(X86_GDT_ENTRY_32BIT_DS); - load_es(X86_GDT_ENTRY_32BIT_DS); - load_gs(X86_GDT_ENTRY_32BIT_DS); - load_ss(X86_GDT_ENTRY_32BIT_DS); - load_fs(X86_GDT_ENTRY_32BIT_FS); -} - -#ifdef CONFIG_HAVE_FSP -/* - * Setup FSP execution environment GDT - * - * Per Intel FSP external architecture specification, before calling any FSP - * APIs, we need make sure the system is in flat 32-bit mode and both the code - * and data selectors should have full 4GB access range. Here we reuse the one - * we used in arch/x86/cpu/start16.S, and reload the segement registers. - */ -void setup_fsp_gdt(void) -{ - load_gdt((const u64 *)(gdt_rom + CONFIG_RESET_SEG_START), 4); - load_ds(X86_GDT_ENTRY_32BIT_DS); - load_ss(X86_GDT_ENTRY_32BIT_DS); - load_es(X86_GDT_ENTRY_32BIT_DS); - load_fs(X86_GDT_ENTRY_32BIT_DS); - load_gs(X86_GDT_ENTRY_32BIT_DS); -} -#endif - int __weak x86_cleanup_before_linux(void) { #ifdef CONFIG_BOOTSTAGE_STASH @@ -209,241 +66,6 @@ int __weak x86_cleanup_before_linux(void) return 0; } -/* - * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected - * by the fact that they preserve the flags across the division of 5/2. - * PII and PPro exhibit this behavior too, but they have cpuid available. - */ - -/* - * Perform the Cyrix 5/2 test. A Cyrix won't change - * the flags, while other 486 chips will. - */ -static inline int test_cyrix_52div(void) -{ - unsigned int test; - - __asm__ __volatile__( - "sahf\n\t" /* clear flags (%eax = 0x0005) */ - "div %b2\n\t" /* divide 5 by 2 */ - "lahf" /* store flags into %ah */ - : "=a" (test) - : "0" (5), "q" (2) - : "cc"); - - /* AH is 0x02 on Cyrix after the divide.. */ - return (unsigned char) (test >> 8) == 0x02; -} - -/* - * Detect a NexGen CPU running without BIOS hypercode new enough - * to have CPUID. (Thanks to Herbert Oppmann) - */ - -static int deep_magic_nexgen_probe(void) -{ - int ret; - - __asm__ __volatile__ ( - " movw $0x5555, %%ax\n" - " xorw %%dx,%%dx\n" - " movw $2, %%cx\n" - " divw %%cx\n" - " movl $0, %%eax\n" - " jnz 1f\n" - " movl $1, %%eax\n" - "1:\n" - : "=a" (ret) : : "cx", "dx"); - return ret; -} - -static bool has_cpuid(void) -{ - return flag_is_changeable_p(X86_EFLAGS_ID); -} - -static bool has_mtrr(void) -{ - return cpuid_edx(0x00000001) & (1 << 12) ? true : false; -} - -static int build_vendor_name(char *vendor_name) -{ - struct cpuid_result result; - result = cpuid(0x00000000); - unsigned int *name_as_ints = (unsigned int *)vendor_name; - - name_as_ints[0] = result.ebx; - name_as_ints[1] = result.edx; - name_as_ints[2] = result.ecx; - - return result.eax; -} - -static void identify_cpu(struct cpu_device_id *cpu) -{ - char vendor_name[16]; - int i; - - vendor_name[0] = '\0'; /* Unset */ - cpu->device = 0; /* fix gcc 4.4.4 warning */ - - /* Find the id and vendor_name */ - if (!has_cpuid()) { - /* Its a 486 if we can modify the AC flag */ - if (flag_is_changeable_p(X86_EFLAGS_AC)) - cpu->device = 0x00000400; /* 486 */ - else - cpu->device = 0x00000300; /* 386 */ - if ((cpu->device == 0x00000400) && test_cyrix_52div()) { - memcpy(vendor_name, "CyrixInstead", 13); - /* If we ever care we can enable cpuid here */ - } - /* Detect NexGen with old hypercode */ - else if (deep_magic_nexgen_probe()) - memcpy(vendor_name, "NexGenDriven", 13); - } - if (has_cpuid()) { - int cpuid_level; - - cpuid_level = build_vendor_name(vendor_name); - vendor_name[12] = '\0'; - - /* Intel-defined flags: level 0x00000001 */ - if (cpuid_level >= 0x00000001) { - cpu->device = cpuid_eax(0x00000001); - } else { - /* Have CPUID level 0 only unheard of */ - cpu->device = 0x00000400; - } - } - cpu->vendor = X86_VENDOR_UNKNOWN; - for (i = 0; i < ARRAY_SIZE(x86_vendors); i++) { - if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) { - cpu->vendor = x86_vendors[i].vendor; - break; - } - } -} - -static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms) -{ - c->x86 = (tfms >> 8) & 0xf; - c->x86_model = (tfms >> 4) & 0xf; - c->x86_mask = tfms & 0xf; - if (c->x86 == 0xf) - c->x86 += (tfms >> 20) & 0xff; - if (c->x86 >= 0x6) - c->x86_model += ((tfms >> 16) & 0xF) << 4; -} - -u32 cpu_get_family_model(void) -{ - return gd->arch.x86_device & 0x0fff0ff0; -} - -u32 cpu_get_stepping(void) -{ - return gd->arch.x86_mask; -} - -int x86_cpu_init_f(void) -{ - const u32 em_rst = ~X86_CR0_EM; - const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE; - - if (ll_boot_init()) { - /* initialize FPU, reset EM, set MP and NE */ - asm ("fninit\n" \ - "movl %%cr0, %%eax\n" \ - "andl %0, %%eax\n" \ - "orl %1, %%eax\n" \ - "movl %%eax, %%cr0\n" \ - : : "i" (em_rst), "i" (mp_ne_set) : "eax"); - } - - /* identify CPU via cpuid and store the decoded info into gd->arch */ - if (has_cpuid()) { - struct cpu_device_id cpu; - struct cpuinfo_x86 c; - - identify_cpu(&cpu); - get_fms(&c, cpu.device); - gd->arch.x86 = c.x86; - gd->arch.x86_vendor = cpu.vendor; - gd->arch.x86_model = c.x86_model; - gd->arch.x86_mask = c.x86_mask; - gd->arch.x86_device = cpu.device; - - gd->arch.has_mtrr = has_mtrr(); - } - /* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */ - gd->pci_ram_top = 0x80000000U; - - /* Configure fixed range MTRRs for some legacy regions */ - if (gd->arch.has_mtrr) { - u64 mtrr_cap; - - mtrr_cap = native_read_msr(MTRR_CAP_MSR); - if (mtrr_cap & MTRR_CAP_FIX) { - /* Mark the VGA RAM area as uncacheable */ - native_write_msr(MTRR_FIX_16K_A0000_MSR, - MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE), - MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE)); - - /* - * Mark the PCI ROM area as cacheable to improve ROM - * execution performance. - */ - native_write_msr(MTRR_FIX_4K_C0000_MSR, - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); - native_write_msr(MTRR_FIX_4K_C8000_MSR, - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); - native_write_msr(MTRR_FIX_4K_D0000_MSR, - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); - native_write_msr(MTRR_FIX_4K_D8000_MSR, - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); - - /* Enable the fixed range MTRRs */ - msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN); - } - } - -#ifdef CONFIG_I8254_TIMER - /* Set up the i8254 timer if required */ - i8254_init(); -#endif - - return 0; -} - -void x86_enable_caches(void) -{ - unsigned long cr0; - - cr0 = read_cr0(); - cr0 &= ~(X86_CR0_NW | X86_CR0_CD); - write_cr0(cr0); - wbinvd(); -} -void enable_caches(void) __attribute__((weak, alias("x86_enable_caches"))); - -void x86_disable_caches(void) -{ - unsigned long cr0; - - cr0 = read_cr0(); - cr0 |= X86_CR0_NW | X86_CR0_CD; - wbinvd(); - write_cr0(cr0); - wbinvd(); -} -void disable_caches(void) __attribute__((weak, alias("x86_disable_caches"))); - int x86_init_cache(void) { enable_caches(); @@ -483,11 +105,6 @@ void x86_full_reset(void) outb(FULL_RST | SYS_RST | RST_CPU, IO_PORT_RESET); } -int dcache_status(void) -{ - return !(read_cr0() & X86_CR0_CD); -} - /* Define these functions to allow ehch-hcd to function */ void flush_dcache_range(unsigned long start, unsigned long stop) { @@ -520,57 +137,6 @@ int icache_status(void) return 1; } -void cpu_enable_paging_pae(ulong cr3) -{ - __asm__ __volatile__( - /* Load the page table address */ - "movl %0, %%cr3\n" - /* Enable pae */ - "movl %%cr4, %%eax\n" - "orl $0x00000020, %%eax\n" - "movl %%eax, %%cr4\n" - /* Enable paging */ - "movl %%cr0, %%eax\n" - "orl $0x80000000, %%eax\n" - "movl %%eax, %%cr0\n" - : - : "r" (cr3) - : "eax"); -} - -void cpu_disable_paging_pae(void) -{ - /* Turn off paging */ - __asm__ __volatile__ ( - /* Disable paging */ - "movl %%cr0, %%eax\n" - "andl $0x7fffffff, %%eax\n" - "movl %%eax, %%cr0\n" - /* Disable pae */ - "movl %%cr4, %%eax\n" - "andl $0xffffffdf, %%eax\n" - "movl %%eax, %%cr4\n" - : - : - : "eax"); -} - -static bool can_detect_long_mode(void) -{ - return cpuid_eax(0x80000000) > 0x80000000UL; -} - -static bool has_long_mode(void) -{ - return cpuid_edx(0x80000001) & (1 << 29) ? true : false; -} - -int cpu_has_64bit(void) -{ - return has_cpuid() && can_detect_long_mode() && - has_long_mode(); -} - const char *cpu_vendor_name(int vendor) { const char *name; @@ -616,46 +182,6 @@ int default_print_cpuinfo(void) return 0; } -#define PAGETABLE_SIZE (6 * 4096) - -/** - * build_pagetable() - build a flat 4GiB page table structure for 64-bti mode - * - * @pgtable: Pointer to a 24iKB block of memory - */ -static void build_pagetable(uint32_t *pgtable) -{ - uint i; - - memset(pgtable, '\0', PAGETABLE_SIZE); - - /* Level 4 needs a single entry */ - pgtable[0] = (ulong)&pgtable[1024] + 7; - - /* Level 3 has one 64-bit entry for each GiB of memory */ - for (i = 0; i < 4; i++) - pgtable[1024 + i * 2] = (ulong)&pgtable[2048] + 0x1000 * i + 7; - - /* Level 2 has 2048 64-bit entries, each repesenting 2MiB */ - for (i = 0; i < 2048; i++) - pgtable[2048 + i * 2] = 0x183 + (i << 21UL); -} - -int cpu_jump_to_64bit(ulong setup_base, ulong target) -{ - uint32_t *pgtable; - - pgtable = memalign(4096, PAGETABLE_SIZE); - if (!pgtable) - return -ENOMEM; - - build_pagetable(pgtable); - cpu_call64((ulong)pgtable, setup_base, target); - free(pgtable); - - return -EFAULT; -} - void show_boot_progress(int val) { outb(val, POST_PORT); @@ -680,36 +206,6 @@ int last_stage_init(void) } #endif -#ifdef CONFIG_SMP -static int enable_smis(struct udevice *cpu, void *unused) -{ - return 0; -} - -static struct mp_flight_record mp_steps[] = { - MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL), - /* Wait for APs to finish initialization before proceeding */ - MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL), -}; - -static int x86_mp_init(void) -{ - struct mp_params mp_params; - - mp_params.parallel_microcode_load = 0, - mp_params.flight_plan = &mp_steps[0]; - mp_params.num_records = ARRAY_SIZE(mp_steps); - mp_params.microcode_pointer = 0; - - if (mp_init(&mp_params)) { - printf("Warning: MP init failure\n"); - return -EIO; - } - - return 0; -} -#endif - static int x86_init_cpus(void) { #ifdef CONFIG_SMP diff --git a/arch/x86/cpu/cpu_x86.c b/arch/x86/cpu/cpu_x86.c index 157f3de..8be14b5 100644 --- a/arch/x86/cpu/cpu_x86.c +++ b/arch/x86/cpu/cpu_x86.c @@ -17,7 +17,7 @@ int cpu_x86_bind(struct udevice *dev) struct cpu_platdata *plat = dev_get_parent_platdata(dev); struct cpuid_result res; - plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "intel,apic-id", -1); plat->family = gd->arch.x86; res = cpuid(1); diff --git a/arch/x86/cpu/i386/Makefile b/arch/x86/cpu/i386/Makefile new file mode 100644 index 0000000..0c47252 --- /dev/null +++ b/arch/x86/cpu/i386/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2016 Google, Inc +# Written by Simon Glass <sjg@chromium.org> +# + +obj-y += call64.o +obj-y += cpu.o +obj-y += interrupt.o +obj-y += setjmp.o diff --git a/arch/x86/cpu/call64.S b/arch/x86/cpu/i386/call64.S index 08dc473..970c461 100644 --- a/arch/x86/cpu/call64.S +++ b/arch/x86/cpu/i386/call64.S @@ -81,6 +81,9 @@ lret_target: jmp *%eax /* Jump to the 64-bit target */ .data + .align 16 + .globl gdt64 +gdt64: gdt: .word gdt_end - gdt - 1 .long gdt /* Fixed up by code above */ diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c new file mode 100644 index 0000000..aabdc94 --- /dev/null +++ b/arch/x86/cpu/i386/cpu.c @@ -0,0 +1,598 @@ +/* + * (C) Copyright 2008-2011 + * Graeme Russ, <graeme.russ@gmail.com> + * + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Part of this file is adapted from coreboot + * src/arch/x86/lib/cpu.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <malloc.h> +#include <asm/control_regs.h> +#include <asm/cpu.h> +#include <asm/mp.h> +#include <asm/msr.h> +#include <asm/mtrr.h> +#include <asm/processor-flags.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Constructor for a conventional segment GDT (or LDT) entry + * This is a macro so it can be used in initialisers + */ +#define GDT_ENTRY(flags, base, limit) \ + ((((base) & 0xff000000ULL) << (56-24)) | \ + (((flags) & 0x0000f0ffULL) << 40) | \ + (((limit) & 0x000f0000ULL) << (48-16)) | \ + (((base) & 0x00ffffffULL) << 16) | \ + (((limit) & 0x0000ffffULL))) + +struct gdt_ptr { + u16 len; + u32 ptr; +} __packed; + +struct cpu_device_id { + unsigned vendor; + unsigned device; +}; + +struct cpuinfo_x86 { + uint8_t x86; /* CPU family */ + uint8_t x86_vendor; /* CPU vendor */ + uint8_t x86_model; + uint8_t x86_mask; +}; + +/* + * List of cpu vendor strings along with their normalized + * id values. + */ +static const struct { + int vendor; + const char *name; +} x86_vendors[] = { + { X86_VENDOR_INTEL, "GenuineIntel", }, + { X86_VENDOR_CYRIX, "CyrixInstead", }, + { X86_VENDOR_AMD, "AuthenticAMD", }, + { X86_VENDOR_UMC, "UMC UMC UMC ", }, + { X86_VENDOR_NEXGEN, "NexGenDriven", }, + { X86_VENDOR_CENTAUR, "CentaurHauls", }, + { X86_VENDOR_RISE, "RiseRiseRise", }, + { X86_VENDOR_TRANSMETA, "GenuineTMx86", }, + { X86_VENDOR_TRANSMETA, "TransmetaCPU", }, + { X86_VENDOR_NSC, "Geode by NSC", }, + { X86_VENDOR_SIS, "SiS SiS SiS ", }, +}; + +static void load_ds(u32 segment) +{ + asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE)); +} + +static void load_es(u32 segment) +{ + asm volatile("movl %0, %%es" : : "r" (segment * X86_GDT_ENTRY_SIZE)); +} + +static void load_fs(u32 segment) +{ + asm volatile("movl %0, %%fs" : : "r" (segment * X86_GDT_ENTRY_SIZE)); +} + +static void load_gs(u32 segment) +{ + asm volatile("movl %0, %%gs" : : "r" (segment * X86_GDT_ENTRY_SIZE)); +} + +static void load_ss(u32 segment) +{ + asm volatile("movl %0, %%ss" : : "r" (segment * X86_GDT_ENTRY_SIZE)); +} + +static void load_gdt(const u64 *boot_gdt, u16 num_entries) +{ + struct gdt_ptr gdt; + + gdt.len = (num_entries * X86_GDT_ENTRY_SIZE) - 1; + gdt.ptr = (ulong)boot_gdt; + + asm volatile("lgdtl %0\n" : : "m" (gdt)); +} + +void arch_setup_gd(gd_t *new_gd) +{ + u64 *gdt_addr; + + gdt_addr = new_gd->arch.gdt; + + /* + * CS: code, read/execute, 4 GB, base 0 + * + * Some OS (like VxWorks) requires GDT entry 1 to be the 32-bit CS + */ + gdt_addr[X86_GDT_ENTRY_UNUSED] = GDT_ENTRY(0xc09b, 0, 0xfffff); + gdt_addr[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff); + + /* DS: data, read/write, 4 GB, base 0 */ + gdt_addr[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff); + + /* FS: data, read/write, 4 GB, base (Global Data Pointer) */ + new_gd->arch.gd_addr = new_gd; + gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0xc093, + (ulong)&new_gd->arch.gd_addr, 0xfffff); + + /* 16-bit CS: code, read/execute, 64 kB, base 0 */ + gdt_addr[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x009b, 0, 0x0ffff); + + /* 16-bit DS: data, read/write, 64 kB, base 0 */ + gdt_addr[X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x0093, 0, 0x0ffff); + + gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_CS] = GDT_ENTRY(0x809b, 0, 0xfffff); + gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_DS] = GDT_ENTRY(0x8093, 0, 0xfffff); + + load_gdt(gdt_addr, X86_GDT_NUM_ENTRIES); + load_ds(X86_GDT_ENTRY_32BIT_DS); + load_es(X86_GDT_ENTRY_32BIT_DS); + load_gs(X86_GDT_ENTRY_32BIT_DS); + load_ss(X86_GDT_ENTRY_32BIT_DS); + load_fs(X86_GDT_ENTRY_32BIT_FS); +} + +#ifdef CONFIG_HAVE_FSP +/* + * Setup FSP execution environment GDT + * + * Per Intel FSP external architecture specification, before calling any FSP + * APIs, we need make sure the system is in flat 32-bit mode and both the code + * and data selectors should have full 4GB access range. Here we reuse the one + * we used in arch/x86/cpu/start16.S, and reload the segement registers. + */ +void setup_fsp_gdt(void) +{ + load_gdt((const u64 *)(gdt_rom + CONFIG_RESET_SEG_START), 4); + load_ds(X86_GDT_ENTRY_32BIT_DS); + load_ss(X86_GDT_ENTRY_32BIT_DS); + load_es(X86_GDT_ENTRY_32BIT_DS); + load_fs(X86_GDT_ENTRY_32BIT_DS); + load_gs(X86_GDT_ENTRY_32BIT_DS); +} +#endif + +/* + * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected + * by the fact that they preserve the flags across the division of 5/2. + * PII and PPro exhibit this behavior too, but they have cpuid available. + */ + +/* + * Perform the Cyrix 5/2 test. A Cyrix won't change + * the flags, while other 486 chips will. + */ +static inline int test_cyrix_52div(void) +{ + unsigned int test; + + __asm__ __volatile__( + "sahf\n\t" /* clear flags (%eax = 0x0005) */ + "div %b2\n\t" /* divide 5 by 2 */ + "lahf" /* store flags into %ah */ + : "=a" (test) + : "0" (5), "q" (2) + : "cc"); + + /* AH is 0x02 on Cyrix after the divide.. */ + return (unsigned char) (test >> 8) == 0x02; +} + +/* + * Detect a NexGen CPU running without BIOS hypercode new enough + * to have CPUID. (Thanks to Herbert Oppmann) + */ +static int deep_magic_nexgen_probe(void) +{ + int ret; + + __asm__ __volatile__ ( + " movw $0x5555, %%ax\n" + " xorw %%dx,%%dx\n" + " movw $2, %%cx\n" + " divw %%cx\n" + " movl $0, %%eax\n" + " jnz 1f\n" + " movl $1, %%eax\n" + "1:\n" + : "=a" (ret) : : "cx", "dx"); + return ret; +} + +static bool has_cpuid(void) +{ + return flag_is_changeable_p(X86_EFLAGS_ID); +} + +static bool has_mtrr(void) +{ + return cpuid_edx(0x00000001) & (1 << 12) ? true : false; +} + +static int build_vendor_name(char *vendor_name) +{ + struct cpuid_result result; + result = cpuid(0x00000000); + unsigned int *name_as_ints = (unsigned int *)vendor_name; + + name_as_ints[0] = result.ebx; + name_as_ints[1] = result.edx; + name_as_ints[2] = result.ecx; + + return result.eax; +} + +static void identify_cpu(struct cpu_device_id *cpu) +{ + char vendor_name[16]; + int i; + + vendor_name[0] = '\0'; /* Unset */ + cpu->device = 0; /* fix gcc 4.4.4 warning */ + + /* Find the id and vendor_name */ + if (!has_cpuid()) { + /* Its a 486 if we can modify the AC flag */ + if (flag_is_changeable_p(X86_EFLAGS_AC)) + cpu->device = 0x00000400; /* 486 */ + else + cpu->device = 0x00000300; /* 386 */ + if ((cpu->device == 0x00000400) && test_cyrix_52div()) { + memcpy(vendor_name, "CyrixInstead", 13); + /* If we ever care we can enable cpuid here */ + } + /* Detect NexGen with old hypercode */ + else if (deep_magic_nexgen_probe()) + memcpy(vendor_name, "NexGenDriven", 13); + } + if (has_cpuid()) { + int cpuid_level; + + cpuid_level = build_vendor_name(vendor_name); + vendor_name[12] = '\0'; + + /* Intel-defined flags: level 0x00000001 */ + if (cpuid_level >= 0x00000001) { + cpu->device = cpuid_eax(0x00000001); + } else { + /* Have CPUID level 0 only unheard of */ + cpu->device = 0x00000400; + } + } + cpu->vendor = X86_VENDOR_UNKNOWN; + for (i = 0; i < ARRAY_SIZE(x86_vendors); i++) { + if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) { + cpu->vendor = x86_vendors[i].vendor; + break; + } + } +} + +static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms) +{ + c->x86 = (tfms >> 8) & 0xf; + c->x86_model = (tfms >> 4) & 0xf; + c->x86_mask = tfms & 0xf; + if (c->x86 == 0xf) + c->x86 += (tfms >> 20) & 0xff; + if (c->x86 >= 0x6) + c->x86_model += ((tfms >> 16) & 0xF) << 4; +} + +u32 cpu_get_family_model(void) +{ + return gd->arch.x86_device & 0x0fff0ff0; +} + +u32 cpu_get_stepping(void) +{ + return gd->arch.x86_mask; +} + +int x86_cpu_init_f(void) +{ + const u32 em_rst = ~X86_CR0_EM; + const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE; + + if (ll_boot_init()) { + /* initialize FPU, reset EM, set MP and NE */ + asm ("fninit\n" \ + "movl %%cr0, %%eax\n" \ + "andl %0, %%eax\n" \ + "orl %1, %%eax\n" \ + "movl %%eax, %%cr0\n" \ + : : "i" (em_rst), "i" (mp_ne_set) : "eax"); + } + + /* identify CPU via cpuid and store the decoded info into gd->arch */ + if (has_cpuid()) { + struct cpu_device_id cpu; + struct cpuinfo_x86 c; + + identify_cpu(&cpu); + get_fms(&c, cpu.device); + gd->arch.x86 = c.x86; + gd->arch.x86_vendor = cpu.vendor; + gd->arch.x86_model = c.x86_model; + gd->arch.x86_mask = c.x86_mask; + gd->arch.x86_device = cpu.device; + + gd->arch.has_mtrr = has_mtrr(); + } + /* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */ + gd->pci_ram_top = 0x80000000U; + + /* Configure fixed range MTRRs for some legacy regions */ + if (gd->arch.has_mtrr) { + u64 mtrr_cap; + + mtrr_cap = native_read_msr(MTRR_CAP_MSR); + if (mtrr_cap & MTRR_CAP_FIX) { + /* Mark the VGA RAM area as uncacheable */ + native_write_msr(MTRR_FIX_16K_A0000_MSR, + MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE), + MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE)); + + /* + * Mark the PCI ROM area as cacheable to improve ROM + * execution performance. + */ + native_write_msr(MTRR_FIX_4K_C0000_MSR, + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); + native_write_msr(MTRR_FIX_4K_C8000_MSR, + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); + native_write_msr(MTRR_FIX_4K_D0000_MSR, + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); + native_write_msr(MTRR_FIX_4K_D8000_MSR, + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); + + /* Enable the fixed range MTRRs */ + msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN); + } + } + +#ifdef CONFIG_I8254_TIMER + /* Set up the i8254 timer if required */ + i8254_init(); +#endif + + return 0; +} + +void x86_enable_caches(void) +{ + unsigned long cr0; + + cr0 = read_cr0(); + cr0 &= ~(X86_CR0_NW | X86_CR0_CD); + write_cr0(cr0); + wbinvd(); +} +void enable_caches(void) __attribute__((weak, alias("x86_enable_caches"))); + +void x86_disable_caches(void) +{ + unsigned long cr0; + + cr0 = read_cr0(); + cr0 |= X86_CR0_NW | X86_CR0_CD; + wbinvd(); + write_cr0(cr0); + wbinvd(); +} +void disable_caches(void) __attribute__((weak, alias("x86_disable_caches"))); + +int dcache_status(void) +{ + return !(read_cr0() & X86_CR0_CD); +} + +void cpu_enable_paging_pae(ulong cr3) +{ + __asm__ __volatile__( + /* Load the page table address */ + "movl %0, %%cr3\n" + /* Enable pae */ + "movl %%cr4, %%eax\n" + "orl $0x00000020, %%eax\n" + "movl %%eax, %%cr4\n" + /* Enable paging */ + "movl %%cr0, %%eax\n" + "orl $0x80000000, %%eax\n" + "movl %%eax, %%cr0\n" + : + : "r" (cr3) + : "eax"); +} + +void cpu_disable_paging_pae(void) +{ + /* Turn off paging */ + __asm__ __volatile__ ( + /* Disable paging */ + "movl %%cr0, %%eax\n" + "andl $0x7fffffff, %%eax\n" + "movl %%eax, %%cr0\n" + /* Disable pae */ + "movl %%cr4, %%eax\n" + "andl $0xffffffdf, %%eax\n" + "movl %%eax, %%cr4\n" + : + : + : "eax"); +} + +static bool can_detect_long_mode(void) +{ + return cpuid_eax(0x80000000) > 0x80000000UL; +} + +static bool has_long_mode(void) +{ + return cpuid_edx(0x80000001) & (1 << 29) ? true : false; +} + +int cpu_has_64bit(void) +{ + return has_cpuid() && can_detect_long_mode() && + has_long_mode(); +} + +#define PAGETABLE_SIZE (6 * 4096) + +/** + * build_pagetable() - build a flat 4GiB page table structure for 64-bti mode + * + * @pgtable: Pointer to a 24iKB block of memory + */ +static void build_pagetable(uint32_t *pgtable) +{ + uint i; + + memset(pgtable, '\0', PAGETABLE_SIZE); + + /* Level 4 needs a single entry */ + pgtable[0] = (ulong)&pgtable[1024] + 7; + + /* Level 3 has one 64-bit entry for each GiB of memory */ + for (i = 0; i < 4; i++) + pgtable[1024 + i * 2] = (ulong)&pgtable[2048] + 0x1000 * i + 7; + + /* Level 2 has 2048 64-bit entries, each repesenting 2MiB */ + for (i = 0; i < 2048; i++) + pgtable[2048 + i * 2] = 0x183 + (i << 21UL); +} + +int cpu_jump_to_64bit(ulong setup_base, ulong target) +{ + uint32_t *pgtable; + + pgtable = memalign(4096, PAGETABLE_SIZE); + if (!pgtable) + return -ENOMEM; + + build_pagetable(pgtable); + cpu_call64((ulong)pgtable, setup_base, target); + free(pgtable); + + return -EFAULT; +} + +/* + * Jump from SPL to U-Boot + * + * This function is work-in-progress with many issues to resolve. + * + * It works by setting up several regions: + * ptr - a place to put the code that jumps into 64-bit mode + * gdt - a place to put the global descriptor table + * pgtable - a place to put the page tables + * + * The cpu_call64() code is copied from ROM and then manually patched so that + * it has the correct GDT address in RAM. U-Boot is copied from ROM into + * its pre-relocation address. Then we jump to the cpu_call64() code in RAM, + * which changes to 64-bit mode and starts U-Boot. + */ +int cpu_jump_to_64bit_uboot(ulong target) +{ + typedef void (*func_t)(ulong pgtable, ulong setup_base, ulong target); + uint32_t *pgtable; + func_t func; + + /* TODO(sjg@chromium.org): Find a better place for this */ + pgtable = (uint32_t *)0x1000000; + if (!pgtable) + return -ENOMEM; + + build_pagetable(pgtable); + + /* TODO(sjg@chromium.org): Find a better place for this */ + char *ptr = (char *)0x3000000; + char *gdt = (char *)0x3100000; + + extern char gdt64[]; + + memcpy(ptr, cpu_call64, 0x1000); + memcpy(gdt, gdt64, 0x100); + + /* + * TODO(sjg@chromium.org): This manually inserts the pointers into + * the code. Tidy this up to avoid this. + */ + func = (func_t)ptr; + ulong ofs = (ulong)cpu_call64 - (ulong)ptr; + *(ulong *)(ptr + 7) = (ulong)gdt; + *(ulong *)(ptr + 0xc) = (ulong)gdt + 2; + *(ulong *)(ptr + 0x13) = (ulong)gdt; + *(ulong *)(ptr + 0x117 - 0xd4) -= ofs; + + /* + * Copy U-Boot from ROM + * TODO(sjg@chromium.org): Figure out a way to get the text base + * correctly here, and in the device-tree binman definition. + * + * Also consider using FIT so we get the correct image length and + * parameters. + */ + memcpy((char *)target, (char *)0xfff00000, 0x100000); + + /* Jump to U-Boot */ + func((ulong)pgtable, 0, (ulong)target); + + return -EFAULT; +} + +#ifdef CONFIG_SMP +static int enable_smis(struct udevice *cpu, void *unused) +{ + return 0; +} + +static struct mp_flight_record mp_steps[] = { + MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL), + /* Wait for APs to finish initialization before proceeding */ + MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL), +}; + +int x86_mp_init(void) +{ + struct mp_params mp_params; + + mp_params.parallel_microcode_load = 0, + mp_params.flight_plan = &mp_steps[0]; + mp_params.num_records = ARRAY_SIZE(mp_steps); + mp_params.microcode_pointer = 0; + + if (mp_init(&mp_params)) { + printf("Warning: MP init failure\n"); + return -EIO; + } + + return 0; +} +#endif diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/i386/interrupt.c index 5f6cdd3..a058303 100644 --- a/arch/x86/cpu/interrupts.c +++ b/arch/x86/cpu/i386/interrupt.c @@ -13,16 +13,12 @@ #include <common.h> #include <dm.h> -#include <asm/cache.h> #include <asm/control_regs.h> #include <asm/i8259.h> #include <asm/interrupt.h> #include <asm/io.h> #include <asm/lapic.h> -#include <asm/msr.h> #include <asm/processor-flags.h> -#include <asm/processor.h> -#include <asm/u-boot-x86.h> DECLARE_GLOBAL_DATA_PTR; @@ -238,7 +234,7 @@ int disable_interrupts(void) { long flags; -#ifdef CONFIG_X86_64 +#if CONFIG_IS_ENABLED(X86_64) asm volatile ("pushfq ; popq %0 ; cli\n" : "=g" (flags) : ); #else asm volatile ("pushfl ; popl %0 ; cli\n" : "=g" (flags) : ); diff --git a/arch/x86/cpu/setjmp.S b/arch/x86/cpu/i386/setjmp.S index 2ea1c6c..2ea1c6c 100644 --- a/arch/x86/cpu/setjmp.S +++ b/arch/x86/cpu/i386/setjmp.S diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile index 804c539..1145e78 100644 --- a/arch/x86/cpu/intel_common/Makefile +++ b/arch/x86/cpu/intel_common/Makefile @@ -4,13 +4,15 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-$(CONFIG_HAVE_MRC) += car.o +ifdef CONFIG_HAVE_MRC +obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += car.o +obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += me_status.o +obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += report_platform.o +obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += mrc.o +endif obj-y += cpu.o obj-y += lpc.o -obj-$(CONFIG_HAVE_MRC) += me_status.o ifndef CONFIG_TARGET_EFI obj-y += microcode.o endif obj-y += pch.o -obj-$(CONFIG_HAVE_MRC) += report_platform.o -obj-$(CONFIG_HAVE_MRC) += mrc.o diff --git a/arch/x86/cpu/intel_common/lpc.c b/arch/x86/cpu/intel_common/lpc.c index 03cb45b..696b630 100644 --- a/arch/x86/cpu/intel_common/lpc.c +++ b/arch/x86/cpu/intel_common/lpc.c @@ -50,7 +50,7 @@ int lpc_common_early_init(struct udevice *dev) int count; int i; - count = fdtdec_get_int_array_count(gd->fdt_blob, dev->of_offset, + count = fdtdec_get_int_array_count(gd->fdt_blob, dev_of_offset(dev), "intel,gen-dec", (u32 *)values, sizeof(values) / sizeof(u32)); if (count < 0) diff --git a/arch/x86/cpu/intel_common/mrc.c b/arch/x86/cpu/intel_common/mrc.c index 01b6e86..f1a249a 100644 --- a/arch/x86/cpu/intel_common/mrc.c +++ b/arch/x86/cpu/intel_common/mrc.c @@ -149,7 +149,7 @@ int mrc_locate_spd(struct udevice *dev, int size, const void **spd_datap) spd_index = dm_gpio_get_values_as_int(desc, ret); debug("spd index %d\n", spd_index); - node = fdt_first_subnode(blob, dev->of_offset); + node = fdt_first_subnode(blob, dev_of_offset(dev)); if (node < 0) return -EINVAL; for (spd_node = fdt_first_subnode(blob, node); diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index 9364410..f5654eb 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -17,8 +17,6 @@ DECLARE_GLOBAL_DATA_PTR; -static struct irq_routing_table *pirq_routing_table; - bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq) { struct irq_router *priv = dev_get_priv(dev); @@ -28,7 +26,7 @@ bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq) if (priv->config == PIRQ_VIA_PCI) dm_pci_read_config8(dev->parent, LINK_N2V(link, base), &pirq); else - pirq = readb(priv->ibase + LINK_N2V(link, base)); + pirq = readb((uintptr_t)priv->ibase + LINK_N2V(link, base)); pirq &= 0xf; @@ -58,7 +56,7 @@ void pirq_assign_irq(struct udevice *dev, int link, u8 irq) if (priv->config == PIRQ_VIA_PCI) dm_pci_write_config8(dev->parent, LINK_N2V(link, base), irq); else - writeb(irq, priv->ibase + LINK_N2V(link, base)); + writeb(irq, (uintptr_t)priv->ibase + LINK_N2V(link, base)); } static struct irq_info *check_dup_entry(struct irq_info *slot_base, @@ -98,7 +96,7 @@ static int create_pirq_routing_table(struct udevice *dev) int i; int ret; - node = dev->of_offset; + node = dev_of_offset(dev); /* extract the bdf from fdt_pci_addr */ priv->bdf = dm_pci_get_bdf(dev->parent); @@ -219,7 +217,7 @@ static int create_pirq_routing_table(struct udevice *dev) /* Fix up the table checksum */ rt->checksum = table_compute_checksum(rt, rt->size); - pirq_routing_table = rt; + gd->arch.pirq_routing_table = rt; return 0; } @@ -236,7 +234,7 @@ static void irq_enable_sci(struct udevice *dev) if (priv->config == PIRQ_VIA_PCI) dm_pci_write_config32(dev->parent, priv->actl_addr, 0); else - writel(0, priv->ibase + priv->actl_addr); + writel(0, (uintptr_t)priv->ibase + priv->actl_addr); } } @@ -250,8 +248,8 @@ int irq_router_common_init(struct udevice *dev) return ret; } /* Route PIRQ */ - pirq_route_irqs(dev, pirq_routing_table->slots, - get_irq_slot_count(pirq_routing_table)); + pirq_route_irqs(dev, gd->arch.pirq_routing_table->slots, + get_irq_slot_count(gd->arch.pirq_routing_table)); if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) irq_enable_sci(dev); @@ -264,12 +262,12 @@ int irq_router_probe(struct udevice *dev) return irq_router_common_init(dev); } -u32 write_pirq_routing_table(u32 addr) +ulong write_pirq_routing_table(ulong addr) { - if (!pirq_routing_table) + if (!gd->arch.pirq_routing_table) return addr; - return copy_pirq_routing_table(addr, pirq_routing_table); + return copy_pirq_routing_table(addr, gd->arch.pirq_routing_table); } static const struct udevice_id irq_router_ids[] = { diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 498e71a..25fbd59 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -7,12 +7,17 @@ ifdef CONFIG_HAVE_FSP obj-y += fsp_configs.o ivybridge.o else -obj-y += cpu.o +obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += cpu.o obj-y += early_me.o obj-y += lpc.o obj-y += model_206ax.o obj-y += northbridge.o +ifndef CONFIG_SPL_BUILD obj-y += sata.o -obj-y += sdram.o +endif +obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += sdram.o +ifndef CONFIG_$(SPL_)X86_32BIT_INIT +obj-y += sdram_nop.o +endif endif obj-y += bd82x6x.o diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index e63ea6b..e3eff69 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -19,6 +19,8 @@ #include <asm/arch/pch.h> #include <asm/arch/sandybridge.h> +DECLARE_GLOBAL_DATA_PTR; + #define GPIO_BASE 0x48 #define BIOS_CTRL 0xdc diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 85e361a..c4aca08 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -169,8 +169,10 @@ int print_cpuinfo(void) /* Enable SPD ROMs and DDR-III DRAM */ ret = uclass_first_device_err(UCLASS_I2C, &dev); - if (ret) + if (ret) { + debug("%s: Failed to get I2C (ret=%d)\n", __func__, ret); return ret; + } /* Prepare USB controller early in S3 resume */ if (boot_mode == PEI_BOOT_RESUME) { diff --git a/arch/x86/cpu/ivybridge/lpc.c b/arch/x86/cpu/ivybridge/lpc.c index 4af89b3..4e254b3 100644 --- a/arch/x86/cpu/ivybridge/lpc.c +++ b/arch/x86/cpu/ivybridge/lpc.c @@ -20,6 +20,8 @@ #include <asm/pci.h> #include <asm/arch/pch.h> +DECLARE_GLOBAL_DATA_PTR; + #define NMI_OFF 0 #define ENABLE_ACPI_MODE_IN_COREBOOT 0 @@ -84,7 +86,7 @@ static int pch_pirq_init(struct udevice *pch) { uint8_t route[8], *ptr; - if (fdtdec_get_byte_array(gd->fdt_blob, pch->of_offset, + if (fdtdec_get_byte_array(gd->fdt_blob, dev_of_offset(pch), "intel,pirq-routing", route, sizeof(route))) return -EINVAL; ptr = route; @@ -111,7 +113,7 @@ static int pch_gpi_routing(struct udevice *pch) u32 reg; int gpi; - if (fdtdec_get_byte_array(gd->fdt_blob, pch->of_offset, + if (fdtdec_get_byte_array(gd->fdt_blob, dev_of_offset(pch), "intel,gpi-routing", route, sizeof(route))) return -EINVAL; @@ -126,7 +128,7 @@ static int pch_gpi_routing(struct udevice *pch) static int pch_power_options(struct udevice *pch) { const void *blob = gd->fdt_blob; - int node = pch->of_offset; + int node = dev_of_offset(pch); u8 reg8; u16 reg16, pmbase; u32 reg32; diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c index 09b5342..81dedee 100644 --- a/arch/x86/cpu/ivybridge/model_206ax.c +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -22,6 +22,8 @@ #include <asm/turbo.h> #include <asm/arch/model_206ax.h> +DECLARE_GLOBAL_DATA_PTR; + static void enable_vmx(void) { struct cpuid_result regs; @@ -286,8 +288,8 @@ static int configure_thermal_target(struct udevice *dev) int tcc_offset; msr_t msr; - tcc_offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "tcc-offset", - 0); + tcc_offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "tcc-offset", 0); /* Set TCC activaiton offset if supported */ msr = msr_read(MSR_PLATFORM_INFO); diff --git a/arch/x86/cpu/ivybridge/northbridge.c b/arch/x86/cpu/ivybridge/northbridge.c index 491f289..94f31c4 100644 --- a/arch/x86/cpu/ivybridge/northbridge.c +++ b/arch/x86/cpu/ivybridge/northbridge.c @@ -19,6 +19,8 @@ #include <asm/arch/model_206ax.h> #include <asm/arch/sandybridge.h> +DECLARE_GLOBAL_DATA_PTR; + int bridge_silicon_revision(struct udevice *dev) { struct cpuid_result result; diff --git a/arch/x86/cpu/ivybridge/sata.c b/arch/x86/cpu/ivybridge/sata.c index 87ff872..0f5e190 100644 --- a/arch/x86/cpu/ivybridge/sata.c +++ b/arch/x86/cpu/ivybridge/sata.c @@ -39,7 +39,7 @@ static void bd82x6x_sata_init(struct udevice *dev, struct udevice *pch) { unsigned int port_map, speed_support, port_tx; const void *blob = gd->fdt_blob; - int node = dev->of_offset; + int node = dev_of_offset(dev); const char *mode; u32 reg32; u16 reg16; @@ -53,7 +53,7 @@ static void bd82x6x_sata_init(struct udevice *dev, struct udevice *pch) mode = fdt_getprop(blob, node, "intel,sata-mode", NULL); if (!mode || !strcmp(mode, "ahci")) { - u32 abar; + ulong abar; debug("SATA: Controller in AHCI mode\n"); @@ -72,7 +72,7 @@ static void bd82x6x_sata_init(struct udevice *dev, struct udevice *pch) /* Initialize AHCI memory-mapped space */ abar = dm_pci_read_bar32(dev, 5); - debug("ABAR: %08X\n", abar); + debug("ABAR: %08lx\n", abar); /* CAP (HBA Capabilities) : enable power management */ reg32 = readl(abar + 0x00); reg32 |= 0x0c006000; /* set PSC+SSC+SALP+SSS */ @@ -190,7 +190,7 @@ static void bd82x6x_sata_init(struct udevice *dev, struct udevice *pch) static void bd82x6x_sata_enable(struct udevice *dev) { const void *blob = gd->fdt_blob; - int node = dev->of_offset; + int node = dev_of_offset(dev); unsigned port_map; const char *mode; u16 map = 0; diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index e0b06b5..201368c 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -207,8 +207,10 @@ static int copy_spd(struct udevice *dev, struct pei_data *peid) int ret; ret = mrc_locate_spd(dev, sizeof(peid->spd_data[0]), &data); - if (ret) + if (ret) { + debug("%s: Could not locate SPD (ret=%d)\n", __func__, ret); return ret; + } memcpy(peid->spd_data[0], data, sizeof(peid->spd_data[0])); @@ -460,18 +462,27 @@ int dram_init(void) /* We need the pinctrl set up early */ ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &dev); - if (ret) + if (ret) { + debug("%s: Could not get pinconf (ret=%d)\n", __func__, ret); return ret; + } ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev); - if (ret) + if (ret) { + debug("%s: Could not get northbridge (ret=%d)\n", __func__, + ret); return ret; + } ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev); - if (ret) + if (ret) { + debug("%s: Could not get ME (ret=%d)\n", __func__, ret); return ret; + } ret = copy_spd(dev, pei_data); - if (ret) + if (ret) { + debug("%s: Could not get SPD (ret=%d)\n", __func__, ret); return ret; + } pei_data->boot_mode = gd->arch.pei_boot_mode; debug("Boot mode %d\n", gd->arch.pei_boot_mode); debug("mrc_input %p\n", pei_data->mrc_input); @@ -498,19 +509,27 @@ int dram_init(void) /* Wait for ME to be ready */ ret = intel_early_me_init(me_dev); - if (ret) + if (ret) { + debug("%s: Could not init ME (ret=%d)\n", __func__, ret); return ret; + } ret = intel_early_me_uma_size(me_dev); - if (ret < 0) + if (ret < 0) { + debug("%s: Could not get UMA size (ret=%d)\n", __func__, ret); return ret; + } ret = mrc_common_init(dev, pei_data, false); - if (ret) + if (ret) { + debug("%s: mrc_common_init() failed (ret=%d)\n", __func__, ret); return ret; + } ret = sdram_find(dev); - if (ret) + if (ret) { + debug("%s: sdram_find() failed (ret=%d)\n", __func__, ret); return ret; + } gd->ram_size = gd->arch.meminfo.total_32bit_memory; debug("MRC output data length %#x at %p\n", pei_data->mrc_output_len, diff --git a/arch/x86/cpu/ivybridge/sdram_nop.c b/arch/x86/cpu/ivybridge/sdram_nop.c new file mode 100644 index 0000000..bd1189e --- /dev/null +++ b/arch/x86/cpu/ivybridge/sdram_nop.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2016 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + gd->ram_size = 1ULL << 31; + gd->bd->bi_dram[0].start = 0; + gd->bd->bi_dram[0].size = gd->ram_size; + + return 0; +} diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index 2b6b3bd..988073c 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -568,7 +568,8 @@ int mp_init_cpu(struct udevice *cpu, void *unused) * seq num in the uclass_resolve_seq() during device_probe(). To avoid * this, set req_seq to the reg number in the device tree in advance. */ - cpu->req_seq = fdtdec_get_int(gd->fdt_blob, cpu->of_offset, "reg", -1); + cpu->req_seq = fdtdec_get_int(gd->fdt_blob, dev_of_offset(cpu), "reg", + -1); plat->ucode_version = microcode_read_rev(); plat->device_id = gd->arch.x86_device; diff --git a/arch/x86/cpu/qemu/e820.c b/arch/x86/cpu/qemu/e820.c index 63853e4..c1c9b89 100644 --- a/arch/x86/cpu/qemu/e820.c +++ b/arch/x86/cpu/qemu/e820.c @@ -7,6 +7,8 @@ #include <common.h> #include <asm/e820.h> +DECLARE_GLOBAL_DATA_PTR; + unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) { entries[0].addr = 0; diff --git a/arch/x86/cpu/qemu/qemu.c b/arch/x86/cpu/qemu/qemu.c index c3092f2..7153eb2 100644 --- a/arch/x86/cpu/qemu/qemu.c +++ b/arch/x86/cpu/qemu/qemu.c @@ -47,7 +47,7 @@ static void qemu_x86_fwcfg_read_entry_pio(uint16_t entry, static void qemu_x86_fwcfg_read_entry_dma(struct fw_cfg_dma_access *dma) { /* the DMA address register is big endian */ - outl(cpu_to_be32((uint32_t)dma), FW_DMA_PORT_HIGH); + outl(cpu_to_be32((uintptr_t)dma), FW_DMA_PORT_HIGH); while (be32_to_cpu(dma->control) & ~FW_CFG_DMA_ERROR) __asm__ __volatile__ ("pause"); @@ -137,14 +137,17 @@ static void qemu_chipset_init(void) #endif } +#if !CONFIG_IS_ENABLED(SPL_X86_32BIT_INIT) int arch_cpu_init(void) { post_code(POST_CPU_INIT); return x86_cpu_init_f(); } +#endif -#ifndef CONFIG_EFI_STUB +#if !CONFIG_IS_ENABLED(EFI_STUB) && \ + !CONFIG_IS_ENABLED(SPL_X86_32BIT_INIT) int print_cpuinfo(void) { post_code(POST_CPU_INFO); diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index a5cba1c..8de55a0 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -18,14 +18,6 @@ #include <generated/generic-asm-offsets.h> #include <generated/asm-offsets.h> -/* - * Define this to boot U-Boot from a 32-bit program which sets the GDT - * differently. This can be used to boot directly from any stage of coreboot, - * for example, bypassing the normal payload-loading feature. - * This is only useful for development. - */ -#undef LOAD_FROM_32_BIT - .section .text .code32 .globl _start @@ -76,7 +68,7 @@ _start: /* Save table pointer */ movl %ecx, %esi -#ifdef LOAD_FROM_32_BIT +#ifdef CONFIG_X86_LOAD_FROM_32_BIT lgdt gdt_ptr2 #endif @@ -233,7 +225,7 @@ multiboot_header: /* entry addr */ .long CONFIG_SYS_TEXT_BASE -#ifdef LOAD_FROM_32_BIT +#ifdef CONFIG_X86_LOAD_FROM_32_BIT /* * The following Global Descriptor Table is just enough to get us into * 'Flat Protected Mode' - It will be discarded as soon as the final diff --git a/arch/x86/cpu/start64.S b/arch/x86/cpu/start64.S new file mode 100644 index 0000000..651f16a --- /dev/null +++ b/arch/x86/cpu/start64.S @@ -0,0 +1,28 @@ +/* + * 64-bit x86 Startup Code + * + * (C) Copyright 216 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> + +.section .text +.code64 +.globl _start +.type _start, @function +_start: + /* Set up memory using the existing stack */ + mov %rsp, %rdi + call board_init_f_alloc_reserve + mov %rax, %rsp + + call board_init_f_init_reserve + + call board_init_f + call board_init_f_r + + /* Should not return here */ + jmp . diff --git a/arch/x86/cpu/turbo.c b/arch/x86/cpu/turbo.c index 254d0de..bbd255e 100644 --- a/arch/x86/cpu/turbo.c +++ b/arch/x86/cpu/turbo.c @@ -12,6 +12,8 @@ #include <asm/processor.h> #include <asm/turbo.h> +DECLARE_GLOBAL_DATA_PTR; + #if CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED static inline int get_global_turbo_state(void) { @@ -22,16 +24,14 @@ static inline void set_global_turbo_state(int state) { } #else -static int g_turbo_state = TURBO_UNKNOWN; - static inline int get_global_turbo_state(void) { - return g_turbo_state; + return gd->arch.turbo_state; } static inline void set_global_turbo_state(int state) { - g_turbo_state = state; + gd->arch.turbo_state = state; } #endif diff --git a/arch/x86/cpu/u-boot-64.lds b/arch/x86/cpu/u-boot-64.lds new file mode 100644 index 0000000..718790c --- /dev/null +++ b/arch/x86/cpu/u-boot-64.lds @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) + +SECTIONS +{ +#ifndef CONFIG_CMDLINE + /DISCARD/ : { *(.u_boot_list_2_cmd_*) } +#endif + + . = CONFIG_SYS_TEXT_BASE; /* Location of bootcode in flash */ + __text_start = .; + .text : { *(.text*); } + + . = ALIGN(4); + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { *(.data*) } + + . = ALIGN(4); + .hash : { *(.hash*) } + + . = ALIGN(4); + .got : { *(.got*) } + + . = ALIGN(4); + __data_end = .; + __init_end = .; + + . = ALIGN(4); + .dynsym : { *(.dynsym*) } + + . = ALIGN(4); + __rel_dyn_start = .; + .rela.dyn : { + *(.rela*) + } + __rel_dyn_end = .; + . = ALIGN(4); + + .dynamic : { *(.dynamic) } + + . = ALIGN(4); + _end = .; + + .bss __rel_dyn_start (OVERLAY) : { + __bss_start = .; + *(.bss) + *(COM*) + . = ALIGN(4); + __bss_end = .; + } + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} diff --git a/arch/x86/cpu/u-boot-spl.lds b/arch/x86/cpu/u-boot-spl.lds new file mode 100644 index 0000000..8a38d58 --- /dev/null +++ b/arch/x86/cpu/u-boot-spl.lds @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) + +SECTIONS +{ +#ifndef CONFIG_CMDLINE + /DISCARD/ : { *(.u_boot_list_2_cmd_*) } +#endif + + . = CONFIG_SPL_TEXT_BASE; /* Location of bootcode in flash */ + __text_start = .; + .text : { *(.text*); } + + . = ALIGN(4); + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { *(.data*) } + + . = ALIGN(4); + __data_end = .; + __init_end = .; + + _image_binary_end = .; + + . = 0x120000; + .bss (OVERLAY) : { + __bss_start = .; + *(.bss*) + *(COM*) + . = ALIGN(4); + __bss_end = .; + } + __bss_size = __bss_end - __bss_start; + + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } + +#ifdef CONFIG_SPL_X86_16BIT_INIT + /* + * The following expressions place the 16-bit Real-Mode code and + * Reset Vector at the end of the Flash ROM + */ + . = START_16 - RESET_SEG_START; + .start16 : AT (START_16) { + KEEP(*(.start16)); + } + + . = RESET_VEC_LOC - RESET_SEG_START; + .resetvec : AT (RESET_VEC_LOC) { + KEEP(*(.resetvec)); + } +#endif + +} diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index cca536b..186718d 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -103,7 +103,7 @@ SECTIONS /DISCARD/ : { *(.interp*) } /DISCARD/ : { *(.gnu*) } -#ifdef CONFIG_X86_RESET_VECTOR +#ifdef CONFIG_X86_16BIT_INIT /* * The following expressions place the 16-bit Real-Mode code and * Reset Vector at the end of the Flash ROM diff --git a/arch/x86/cpu/x86_64/Makefile b/arch/x86/cpu/x86_64/Makefile new file mode 100644 index 0000000..400f0ff --- /dev/null +++ b/arch/x86/cpu/x86_64/Makefile @@ -0,0 +1,6 @@ +# +# (C) Copyright 2016 Google, Inc +# Written by Simon Glass <sjg@chromium.org> +# + +obj-y += cpu.o interrupts.o setjmp.o diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c new file mode 100644 index 0000000..db171f7 --- /dev/null +++ b/arch/x86/cpu/x86_64/cpu.c @@ -0,0 +1,73 @@ +/* + * (C) Copyright 2016 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <debug_uart.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Global declaration of gd */ +struct global_data *global_data_ptr; + +void arch_setup_gd(gd_t *new_gd) +{ + global_data_ptr = new_gd; + + /* + * TODO(sjg@chromium.org): For some reason U-Boot does not boot + * without this line. It fails to start up U-Boot proper and instead + * restarts SPL. Need to figure out why: + * + * U-Boot SPL 2017.01 + * + * U-Boot SPL 2017.01 + * CPU: Intel(R) Core(TM) i5-3427U CPU @ 1.80GHz + * Trying to boot from SPIJumping to 64-bit U-Boot: Note many + * features are missing + * + * U-Boot SPL 2017.01 + */ +#ifdef CONFIG_DEBUG_UART + printch(' '); +#endif +} + +int cpu_has_64bit(void) +{ + return true; +} + +void enable_caches(void) +{ + /* Not implemented */ +} + +void disable_caches(void) +{ + /* Not implemented */ +} + +int dcache_status(void) +{ + return true; +} + +int x86_mp_init(void) +{ + /* Not implemented */ + return 0; +} + +int misc_init_r(void) +{ + return 0; +} + +int print_cpuinfo(void) +{ + return 0; +} diff --git a/arch/x86/cpu/x86_64/interrupts.c b/arch/x86/cpu/x86_64/interrupts.c new file mode 100644 index 0000000..3e06173 --- /dev/null +++ b/arch/x86/cpu/x86_64/interrupts.c @@ -0,0 +1,29 @@ +/* + * (C) Copyright 2016 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/processor-flags.h> + +void enable_interrupts(void) +{ + asm("sti\n"); +} + +int disable_interrupts(void) +{ + long flags; + + asm volatile ("pushfq ; popq %0 ; cli\n" : "=g" (flags) : ); + + return flags & X86_EFLAGS_IF; +} + +int interrupt_init(void) +{ + /* Nothing to do - this was already done in SPL */ + return 0; +} diff --git a/arch/x86/cpu/x86_64/setjmp.c b/arch/x86/cpu/x86_64/setjmp.c new file mode 100644 index 0000000..25f8d28 --- /dev/null +++ b/arch/x86/cpu/x86_64/setjmp.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/setjmp.h> + +int setjmp(struct jmp_buf_data *jmp_buf) +{ + printf("WARNING: setjmp() is not supported\n"); + + return 0; +} + +void longjmp(struct jmp_buf_data *jmp_buf, int val) +{ + printf("WARNING: longjmp() is not supported\n"); +} diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts index b932340..fab919a 100644 --- a/arch/x86/dts/chromebook_link.dts +++ b/arch/x86/dts/chromebook_link.dts @@ -26,12 +26,14 @@ cpus { #address-cells = <1>; #size-cells = <0>; + u-boot,dm-pre-reloc; cpu@0 { device_type = "cpu"; compatible = "intel,core-gen3"; reg = <0>; intel,apic-id = <0>; + u-boot,dm-pre-reloc; }; cpu@1 { @@ -39,6 +41,7 @@ compatible = "intel,core-gen3"; reg = <1>; intel,apic-id = <1>; + u-boot,dm-pre-reloc; }; cpu@2 { @@ -46,6 +49,7 @@ compatible = "intel,core-gen3"; reg = <2>; intel,apic-id = <2>; + u-boot,dm-pre-reloc; }; cpu@3 { @@ -53,6 +57,7 @@ compatible = "intel,core-gen3"; reg = <3>; intel,apic-id = <3>; + u-boot,dm-pre-reloc; }; }; @@ -229,14 +234,16 @@ northbridge@0,0 { reg = <0x00000000 0 0 0 0>; + u-boot,dm-pre-reloc; compatible = "intel,bd82x6x-northbridge"; board-id-gpios = <&gpio_b 9 0>, <&gpio_b 10 0>, <&gpio_b 11 0>, <&gpio_a 10 0>; - u-boot,dm-pre-reloc; spd { + u-boot,dm-pre-reloc; #address-cells = <1>; #size-cells = <0>; elpida_4Gb_1600_x16 { + u-boot,dm-pre-reloc; reg = <0>; data = [92 10 0b 03 04 19 02 02 03 52 01 08 0a 00 fe 00 @@ -272,6 +279,7 @@ 00 00 00 00 00 00 00 00]; }; samsung_4Gb_1600_1.35v_x16 { + u-boot,dm-pre-reloc; reg = <1>; data = [92 11 0b 03 04 19 02 02 03 11 01 08 0a 00 fe 00 @@ -391,9 +399,11 @@ #address-cells = <1>; #size-cells = <0>; compatible = "intel,ich9-spi"; + u-boot,dm-pre-reloc; spi-flash@0 { #size-cells = <1>; #address-cells = <1>; + u-boot,dm-pre-reloc; reg = <0>; compatible = "winbond,w25q64", "spi-flash"; @@ -401,6 +411,7 @@ rw-mrc-cache { label = "rw-mrc-cache"; reg = <0x003e0000 0x00010000>; + u-boot,dm-pre-reloc; }; }; }; @@ -478,7 +489,9 @@ }; microcode { + u-boot,dm-pre-reloc; update@0 { + u-boot,dm-pre-reloc; #include "microcode/m12306a9_0000001b.dtsi" }; }; diff --git a/arch/x86/dts/emulation-u-boot.dtsi b/arch/x86/dts/emulation-u-boot.dtsi index 56d34af..7714ed0 100644 --- a/arch/x86/dts/emulation-u-boot.dtsi +++ b/arch/x86/dts/emulation-u-boot.dtsi @@ -10,9 +10,15 @@ #ifdef CONFIG_ROM_SIZE / { binman { +#ifdef CONFIG_SPL + u-boot-spl-with-ucode-ptr { + optional-ucode; + }; +#else u-boot-with-ucode-ptr { optional-ucode; }; +#endif }; }; #endif diff --git a/arch/x86/dts/qemu-x86_i440fx.dts b/arch/x86/dts/qemu-x86_i440fx.dts index 9c3f2a0..afea14e 100644 --- a/arch/x86/dts/qemu-x86_i440fx.dts +++ b/arch/x86/dts/qemu-x86_i440fx.dts @@ -29,10 +29,12 @@ cpus { #address-cells = <1>; #size-cells = <0>; + u-boot,dm-pre-reloc; cpu@0 { device_type = "cpu"; compatible = "cpu-qemu"; + u-boot,dm-pre-reloc; reg = <0>; intel,apic-id = <0>; }; @@ -54,9 +56,11 @@ pch@1,0 { reg = <0x00000800 0 0 0 0>; compatible = "intel,pch7"; + u-boot,dm-pre-reloc; irq-router { compatible = "intel,irq-router"; + u-boot,dm-pre-reloc; intel,pirq-config = "pci"; intel,pirq-link = <0x60 4>; intel,pirq-mask = <0x0e40>; diff --git a/arch/x86/dts/qemu-x86_q35.dts b/arch/x86/dts/qemu-x86_q35.dts index 0d462a9..bc398dd 100644 --- a/arch/x86/dts/qemu-x86_q35.dts +++ b/arch/x86/dts/qemu-x86_q35.dts @@ -40,10 +40,12 @@ cpus { #address-cells = <1>; #size-cells = <0>; + u-boot,dm-pre-reloc; cpu@0 { device_type = "cpu"; compatible = "cpu-qemu"; + u-boot,dm-pre-reloc; reg = <0>; intel,apic-id = <0>; }; @@ -65,9 +67,11 @@ pch@1f,0 { reg = <0x0000f800 0 0 0 0>; compatible = "intel,pch9"; + u-boot,dm-pre-reloc; irq-router { compatible = "intel,irq-router"; + u-boot,dm-pre-reloc; intel,pirq-config = "pci"; intel,actl-8bit; intel,actl-addr = <0x44>; diff --git a/arch/x86/dts/serial.dtsi b/arch/x86/dts/serial.dtsi index 54c3faf..22f7b54 100644 --- a/arch/x86/dts/serial.dtsi +++ b/arch/x86/dts/serial.dtsi @@ -1,5 +1,6 @@ / { serial: serial { + u-boot,dm-pre-reloc; compatible = "ns16550"; reg = <0x3f8 8>; reg-shift = <0>; diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index 31f0b1a..69c1c1d 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -21,9 +21,22 @@ intel-me { }; #endif +#ifdef CONFIG_SPL + u-boot-spl-with-ucode-ptr { + pos = <CONFIG_SPL_TEXT_BASE>; + }; + + u-boot-dtb-with-ucode2 { + type = "u-boot-dtb-with-ucode"; + }; + u-boot { + pos = <0xfff00000>; + }; +#else u-boot-with-ucode-ptr { pos = <CONFIG_SYS_TEXT_BASE>; }; +#endif u-boot-dtb-with-ucode { }; u-boot-ucode { @@ -57,9 +70,15 @@ pos = <CONFIG_X86_REFCODE_ADDR>; }; #endif +#ifdef CONFIG_SPL + x86-start16-spl { + pos = <CONFIG_SYS_X86_START16>; + }; +#else x86-start16 { pos = <CONFIG_SYS_X86_START16>; }; +#endif }; }; #endif diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index caff4d8..bbd80a1 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -316,4 +316,4 @@ int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi, u8 cpu, u16 flags, u8 lint); u32 acpi_fill_madt(u32 current); void acpi_create_gnvs(struct acpi_global_nvs *gnvs); -u32 write_acpi_tables(u32 start); +ulong write_acpi_tables(ulong start); diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h index a373a79..48b138c 100644 --- a/arch/x86/include/asm/bootparam.h +++ b/arch/x86/include/asm/bootparam.h @@ -117,7 +117,8 @@ enum { X86_SUBARCH_PC = 0, X86_SUBARCH_LGUEST, X86_SUBARCH_XEN, - X86_SUBARCH_MRST, + X86_SUBARCH_INTEL_MID, + X86_SUBARCH_CE4100, X86_NR_SUBARCHS, }; #endif /* _ASM_X86_BOOTPARAM_H */ diff --git a/arch/x86/include/asm/byteorder.h b/arch/x86/include/asm/byteorder.h index 7dfeb8b..a2d1fd8 100644 --- a/arch/x86/include/asm/byteorder.h +++ b/arch/x86/include/asm/byteorder.h @@ -8,24 +8,25 @@ static __inline__ __u32 ___arch__swab32(__u32 x) { -#ifdef CONFIG_X86_BSWAP __asm__("bswap %0" : "=r" (x) : "0" (x)); -#else - __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ - "rorl $16,%0\n\t" /* swap words */ - "xchgb %b0,%h0" /* swap higher bytes */ - :"=q" (x) - : "0" (x)); -#endif + return x; } +#define _constant_swab16(x) ((__u16)( \ + (((__u16)(x) & (__u16)0x00ffU) << 8) | \ + (((__u16)(x) & (__u16)0xff00U) >> 8))) + static __inline__ __u16 ___arch__swab16(__u16 x) { +#if CONFIG_IS_ENABLED(X86_64) + return _constant_swab16(x); +#else __asm__("xchgb %b0,%h0" /* swap bytes */ \ : "=q" (x) \ : "0" (x)); \ return x; +#endif } #define __arch__swab32(x) ___arch__swab32(x) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 540024a..c651f2f 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -159,6 +159,8 @@ static inline unsigned int cpuid_edx(unsigned int op) return edx; } +#if !CONFIG_IS_ENABLED(X86_64) + /* Standard macro to see if a specific flag is changeable */ static inline int flag_is_changeable_p(uint32_t flag) { @@ -179,6 +181,7 @@ static inline int flag_is_changeable_p(uint32_t flag) : "ir" (flag)); return ((f1^f2) & flag) != 0; } +#endif static inline void mfence(void) { @@ -261,6 +264,15 @@ void cpu_call32(ulong code_seg32, ulong target, ulong table); int cpu_jump_to_64bit(ulong setup_base, ulong target); /** + * cpu_jump_to_64bit_uboot() - special function to jump from SPL to U-Boot + * + * This handles calling from 32-bit SPL to 64-bit U-Boot. + * + * @target: Address of U-Boot in RAM + */ +int cpu_jump_to_64bit_uboot(ulong target); + +/** * cpu_get_family_model() - Get the family and model for the CPU * * @return the CPU ID masked with 0x0fff0ff0 diff --git a/arch/x86/include/asm/fsp/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h index 3fb3546..7c22bcd 100644 --- a/arch/x86/include/asm/fsp/fsp_hob.h +++ b/arch/x86/include/asm/fsp/fsp_hob.h @@ -139,7 +139,7 @@ struct hob_guid { */ static inline const struct hob_header *get_next_hob(const struct hob_header *hdr) { - return (const struct hob_header *)((u32)hdr + hdr->len); + return (const struct hob_header *)((uintptr_t)hdr + hdr->len); } /** @@ -172,7 +172,7 @@ static inline bool end_of_hob(const struct hob_header *hdr) */ static inline void *get_guid_hob_data(const struct hob_header *hdr) { - return (void *)((u32)hdr + sizeof(struct hob_guid)); + return (void *)((uintptr_t)hdr + sizeof(struct hob_guid)); } /** diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 7434f77..4570bc7 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -93,6 +93,8 @@ struct arch_global_data { char *mrc_output; unsigned int mrc_output_len; ulong table; /* Table pointer from previous loader */ + int turbo_state; /* Current turbo state */ + struct irq_routing_table *pirq_routing_table; #ifdef CONFIG_SEABIOS u32 high_table_ptr; u32 high_table_limit; @@ -104,8 +106,9 @@ struct arch_global_data { #include <asm-generic/global_data.h> #ifndef __ASSEMBLY__ -# ifdef CONFIG_EFI_APP +# if defined(CONFIG_EFI_APP) || CONFIG_IS_ENABLED(X86_64) +/* TODO(sjg@chromium.org): Consider using a fixed register for gd on x86_64 */ #define gd global_data_ptr #define DECLARE_GLOBAL_DATA_PTR extern struct global_data *global_data_ptr @@ -114,7 +117,11 @@ static inline __attribute__((no_instrument_function)) gd_t *get_fs_gd_ptr(void) { gd_t *gd_ptr; +#if CONFIG_IS_ENABLED(X86_64) + asm volatile("fs mov 0, %0\n" : "=r" (gd_ptr)); +#else asm volatile("fs movl 0, %0\n" : "=r" (gd_ptr)); +#endif return gd_ptr; } diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h index 2e6c312..83b99dc 100644 --- a/arch/x86/include/asm/mp.h +++ b/arch/x86/include/asm/mp.h @@ -90,4 +90,7 @@ int mp_init(struct mp_params *params); /* Probes the CPU device */ int mp_init_cpu(struct udevice *cpu, void *unused); +/* Set up additional CPUs */ +int x86_mp_init(void); + #endif /* _X86_MP_H_ */ diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index ad8eba9..30dbdca 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -224,9 +224,9 @@ struct mp_ext_compat_address_space { * @mc: configuration table header address * @return: configuration table end address */ -static inline u32 mp_next_mpc_entry(struct mp_config_table *mc) +static inline ulong mp_next_mpc_entry(struct mp_config_table *mc) { - return (u32)mc + mc->mpc_length; + return (ulong)mc + mc->mpc_length; } /** @@ -254,9 +254,9 @@ static inline void mp_add_mpc_entry(struct mp_config_table *mc, uint length) * @mc: configuration table header address * @return: configuration table end address */ -static inline u32 mp_next_mpe_entry(struct mp_config_table *mc) +static inline ulong mp_next_mpe_entry(struct mp_config_table *mc) { - return (u32)mc + mc->mpc_length + mc->mpe_length; + return (ulong)mc + mc->mpc_length + mc->mpe_length; } /** @@ -456,6 +456,6 @@ int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq); * @addr: start address to write MP table * @return: end address of MP table */ -u32 write_mp_table(u32 addr); +ulong write_mp_table(ulong addr); #endif /* __ASM_MPSPEC_H */ diff --git a/arch/x86/include/asm/posix_types.h b/arch/x86/include/asm/posix_types.h index 5529f32..717f6cb 100644 --- a/arch/x86/include/asm/posix_types.h +++ b/arch/x86/include/asm/posix_types.h @@ -16,8 +16,13 @@ typedef int __kernel_pid_t; typedef unsigned short __kernel_ipc_pid_t; typedef unsigned short __kernel_uid_t; typedef unsigned short __kernel_gid_t; +#if CONFIG_IS_ENABLED(X86_64) +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +#else typedef unsigned int __kernel_size_t; typedef int __kernel_ssize_t; +#endif typedef int __kernel_ptrdiff_t; typedef long __kernel_time_t; typedef long __kernel_suseconds_t; diff --git a/arch/x86/include/asm/sfi.h b/arch/x86/include/asm/sfi.h index d1f0f0c..d6c44c9 100644 --- a/arch/x86/include/asm/sfi.h +++ b/arch/x86/include/asm/sfi.h @@ -132,6 +132,6 @@ typedef int (*sfi_table_handler) (struct sfi_table_header *table); * @base: Address to write table to * @return address to use for the next table */ -u32 write_sfi_table(u32 base); +ulong write_sfi_table(ulong base); #endif /*_LINUX_SFI_H */ diff --git a/arch/x86/include/asm/spl.h b/arch/x86/include/asm/spl.h new file mode 100644 index 0000000..d48a3fc --- /dev/null +++ b/arch/x86/include/asm/spl.h @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This file is required for SPL to build, but is empty. + */ diff --git a/arch/x86/include/asm/tables.h b/arch/x86/include/asm/tables.h index 81f98f2..d1b2388 100644 --- a/arch/x86/include/asm/tables.h +++ b/arch/x86/include/asm/tables.h @@ -65,6 +65,6 @@ void write_tables(void); * @start: start address to write PIRQ routing table * @return: end address of PIRQ routing table */ -u32 write_pirq_routing_table(u32 start); +ulong write_pirq_routing_table(ulong start); #endif /* _X86_TABLES_H_ */ diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h index 880dcb4..a47e581 100644 --- a/arch/x86/include/asm/types.h +++ b/arch/x86/include/asm/types.h @@ -44,7 +44,12 @@ typedef __INT64_TYPE__ s64; typedef __UINT64_TYPE__ u64; #endif +#if CONFIG_IS_ENABLED(X86_64) +#define BITS_PER_LONG 64 +#else #define BITS_PER_LONG 32 +#endif + /* Dma addresses are 32-bits wide. */ typedef u32 dma_addr_t; diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 723288f..1c2c085 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -5,10 +5,14 @@ # SPDX-License-Identifier: GPL-2.0+ # +ifndef CONFIG_X86_64 obj-y += bios.o obj-y += bios_asm.o obj-y += bios_interrupts.o +endif +ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_BOOTM) += bootm.o +endif obj-y += cmd_boot.o obj-$(CONFIG_SEABIOS) += coreboot_table.o obj-$(CONFIG_EFI) += efi/ @@ -35,8 +39,11 @@ ifndef CONFIG_QEMU obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o endif obj-y += tables.o +ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_ZBOOT) += zimage.o +endif obj-$(CONFIG_HAVE_FSP) += fsp/ +obj-$(CONFIG_SPL_BUILD) += spl.o extra-$(CONFIG_USE_PRIVATE_LIBGCC) += lib.a @@ -45,7 +52,9 @@ OBJCOPYFLAGS := --prefix-symbols=__normal_ $(obj)/lib.a: $(NORMAL_LIBGCC) FORCE $(call if_changed,objcopy) +ifeq ($(CONFIG_$(SPL_)X86_64),) obj-$(CONFIG_EFI_APP) += crt0_ia32_efi.o reloc_ia32_efi.o +endif ifneq ($(CONFIG_EFI_STUB),) @@ -65,5 +74,7 @@ extra-$(CONFIG_EFI_STUB_64BIT) += crt0_x86_64_efi.o reloc_x86_64_efi.o endif ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),) +ifeq ($(CONFIG_$(SPL_)X86_64),) extra-y += $(EFI_CRT0) $(EFI_RELOC) endif +endif diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 7001e8b..355456d 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -327,7 +327,7 @@ static void enter_acpi_mode(int pm1_cnt) * QEMU's version of write_acpi_tables is defined in * arch/x86/cpu/qemu/acpi_table.c */ -u32 write_acpi_tables(u32 start) +ulong write_acpi_tables(ulong start) { u32 current; struct acpi_rsdp *rsdp; @@ -345,7 +345,7 @@ u32 write_acpi_tables(u32 start) /* Align ACPI tables to 16 byte */ current = ALIGN(current, 16); - debug("ACPI: Writing ACPI tables at %x\n", start); + debug("ACPI: Writing ACPI tables at %lx\n", start); /* We need at least an RSDP and an RSDT Table */ rsdp = (struct acpi_rsdp *)current; diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index 9324bdb..66d7629 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -157,7 +157,7 @@ static void setup_realmode_idt(void) for (i = 0; i < 256; i++) { idts[i].cs = 0; idts[i].offset = 0x1000 + (i * __idt_handler_size); - write_idt_stub((void *)((u32)idts[i].offset), i); + write_idt_stub((void *)((ulong)idts[i].offset), i); } /* @@ -227,7 +227,7 @@ static void vbe_set_graphics(int vesa_mode, struct vbe_mode_info *mode_info) mode_info->video_mode = (1 << 14) | vesa_mode; vbe_get_mode_info(mode_info); - framebuffer = (unsigned char *)mode_info->vesa.phys_base_ptr; + framebuffer = (unsigned char *)(ulong)mode_info->vesa.phys_base_ptr; debug("VBE: resolution: %dx%d@%d\n", le16_to_cpu(mode_info->vesa.x_resolution), le16_to_cpu(mode_info->vesa.y_resolution), diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index e5e63f6..3c3d9e1 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -155,7 +155,14 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit) puts("Cannot boot 64-bit kernel on 32-bit machine\n"); return -EFAULT; } + /* At present 64-bit U-Boot does not support booting a + * kernel. + * TODO(sjg@chromium.org): Support booting both 32-bit and + * 64-bit kernels from 64-bit U-Boot. + */ +#if !CONFIG_IS_ENABLED(X86_64) return cpu_jump_to_64bit(setup_base, load_address); +#endif } else { /* * Set %ebx, %ebp, and %edi to 0, %esi to point to the diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 2a186fc..420393b 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -19,7 +19,7 @@ __weak ulong board_get_usable_ram_top(ulong total_size) int init_cache_f_r(void) { -#if defined(CONFIG_X86_RESET_VECTOR) & !defined(CONFIG_HAVE_FSP) +#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP) int ret; ret = mtrr_commit(false); diff --git a/arch/x86/lib/interrupts.c b/arch/x86/lib/interrupts.c index dd08402..d3ae6d9 100644 --- a/arch/x86/lib/interrupts.c +++ b/arch/x86/lib/interrupts.c @@ -33,6 +33,8 @@ #include <common.h> #include <asm/interrupt.h> +#if !CONFIG_IS_ENABLED(X86_64) + struct irq_action { interrupt_handler_t *handler; void *arg; @@ -118,10 +120,12 @@ void do_irq(int hw_irq) } } } +#endif #if defined(CONFIG_CMD_IRQ) int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { +#if !CONFIG_IS_ENABLED(X86_64) int irq; printf("Spurious IRQ: %u, last unknown IRQ: %d\n", @@ -139,6 +143,7 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) irq_handlers[irq].count); } } +#endif return 0; } diff --git a/arch/x86/lib/mpspec.c b/arch/x86/lib/mpspec.c index 6ab43f1..a6e493d 100644 --- a/arch/x86/lib/mpspec.c +++ b/arch/x86/lib/mpspec.c @@ -25,10 +25,10 @@ static bool isa_irq_occupied[16]; struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf) { - u32 mc; + ulong mc; memcpy(mf->mpf_signature, MPF_SIGNATURE, 4); - mf->mpf_physptr = (u32)mf + sizeof(struct mp_floating_table); + mf->mpf_physptr = (ulong)mf + sizeof(struct mp_floating_table); mf->mpf_length = 1; mf->mpf_spec = MPSPEC_V14; mf->mpf_checksum = 0; @@ -41,7 +41,7 @@ struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf) mf->mpf_feature5 = 0; mf->mpf_checksum = table_compute_checksum(mf, mf->mpf_length * 16); - mc = (u32)mf + sizeof(struct mp_floating_table); + mc = (ulong)mf + sizeof(struct mp_floating_table); return (struct mp_config_table *)mc; } @@ -219,14 +219,14 @@ void mp_write_compat_address_space(struct mp_config_table *mc, int busid, u32 mptable_finalize(struct mp_config_table *mc) { - u32 end; + ulong end; mc->mpe_checksum = table_compute_checksum((void *)mp_next_mpc_entry(mc), mc->mpe_length); mc->mpc_checksum = table_compute_checksum(mc, mc->mpc_length); end = mp_next_mpe_entry(mc); - debug("Write the MP table at: %x - %x\n", (u32)mc, end); + debug("Write the MP table at: %lx - %lx\n", (ulong)mc, end); return end; } @@ -304,7 +304,8 @@ static int mptable_add_intsrc(struct mp_config_table *mc, } /* Get I/O interrupt information from device tree */ - cell = fdt_getprop(blob, dev->of_offset, "intel,pirq-routing", &len); + cell = fdt_getprop(blob, dev_of_offset(dev), "intel,pirq-routing", + &len); if (!cell) return -ENOENT; @@ -365,13 +366,13 @@ static void mptable_add_lintsrc(struct mp_config_table *mc, int bus_isa) bus_isa, 0, MP_APIC_ALL, 1); } -u32 write_mp_table(u32 addr) +ulong write_mp_table(ulong addr) { struct mp_config_table *mc; int ioapic_id, ioapic_ver; int bus_isa = 0xff; int ret; - u32 end; + ulong end; /* 16 byte align the table address */ addr = ALIGN(addr, 16); diff --git a/arch/x86/lib/pinctrl_ich6.c b/arch/x86/lib/pinctrl_ich6.c index 3f94cdf..406852d 100644 --- a/arch/x86/lib/pinctrl_ich6.c +++ b/arch/x86/lib/pinctrl_ich6.c @@ -104,7 +104,7 @@ static int ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node) /* if iobase is present, let's configure the pad */ if (iobase != -1) { - int iobase_addr; + ulong iobase_addr; /* * The offset for the same pin for the IOBASE and GPIOBASE are @@ -187,7 +187,7 @@ static int ich6_pinctrl_probe(struct udevice *dev) return -EINVAL; } - for (pin_node = fdt_first_subnode(gd->fdt_blob, dev->of_offset); + for (pin_node = fdt_first_subnode(gd->fdt_blob, dev_of_offset(dev)); pin_node > 0; pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) { /* Configure the pin */ diff --git a/arch/x86/lib/pirq_routing.c b/arch/x86/lib/pirq_routing.c index a93d355..5df3cab 100644 --- a/arch/x86/lib/pirq_routing.c +++ b/arch/x86/lib/pirq_routing.c @@ -11,9 +11,8 @@ #include <asm/pci.h> #include <asm/pirq_routing.h> -static bool irq_already_routed[16]; - -static u8 pirq_get_next_free_irq(struct udevice *dev, u8 *pirq, u16 bitmap) +static u8 pirq_get_next_free_irq(struct udevice *dev, u8 *pirq, u16 bitmap, + bool irq_already_routed[]) { int i, link; u8 irq = 0; @@ -55,9 +54,11 @@ void pirq_route_irqs(struct udevice *dev, struct irq_info *irq, int num) { unsigned char irq_slot[MAX_INTX_ENTRIES]; unsigned char pirq[CONFIG_MAX_PIRQ_LINKS]; + bool irq_already_routed[16]; int i, intx; memset(pirq, 0, CONFIG_MAX_PIRQ_LINKS); + memset(irq_already_routed, '\0', sizeof(irq_already_routed)); /* Set PCI IRQs */ for (i = 0; i < num; i++) { @@ -83,7 +84,8 @@ void pirq_route_irqs(struct udevice *dev, struct irq_info *irq, int num) /* yet not routed */ if (!pirq[link]) { - irq = pirq_get_next_free_irq(dev, pirq, bitmap); + irq = pirq_get_next_free_irq(dev, pirq, bitmap, + irq_already_routed); pirq[link] = irq; } else { irq = pirq[link]; @@ -114,14 +116,14 @@ u32 copy_pirq_routing_table(u32 addr, struct irq_routing_table *rt) addr = ALIGN(addr, 16); debug("Copying Interrupt Routing Table to 0x%x\n", addr); - memcpy((void *)addr, rt, rt->size); + memcpy((void *)(uintptr_t)addr, rt, rt->size); /* * We do the sanity check here against the copied table after memcpy, * as something might go wrong after the memcpy, which is normally * due to the F segment decode is not turned on to systeam RAM. */ - rom_rt = (struct irq_routing_table *)addr; + rom_rt = (struct irq_routing_table *)(uintptr_t)addr; if (rom_rt->signature != PIRQ_SIGNATURE || rom_rt->version != PIRQ_VERSION || rom_rt->size % 16) { printf("Interrupt Routing Table not valid\n"); diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index 0d683bf..1da5210 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -26,7 +26,7 @@ DECLARE_GLOBAL_DATA_PTR; int copy_uboot_to_ram(void) { - size_t len = (size_t)&__data_end - (size_t)&__text_start; + size_t len = (uintptr_t)&__data_end - (uintptr_t)&__text_start; if (gd->flags & GD_FLG_SKIP_RELOC) return 0; @@ -38,7 +38,7 @@ int copy_uboot_to_ram(void) int clear_bss(void) { ulong dst_addr = (ulong)&__bss_start + gd->reloc_off; - size_t len = (size_t)&__bss_end - (size_t)&__bss_start; + size_t len = (uintptr_t)&__bss_end - (uintptr_t)&__bss_start; if (gd->flags & GD_FLG_SKIP_RELOC) return 0; @@ -47,38 +47,58 @@ int clear_bss(void) return 0; } -/* - * This function has more error checking than you might expect. Please see - * the commit message for more informaiton. - */ -int do_elf_reloc_fixups(void) +#if CONFIG_IS_ENABLED(X86_64) +static void do_elf_reloc_fixups64(unsigned int text_base, uintptr_t size, + Elf64_Rela *re_src, Elf64_Rela *re_end) { - Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); - Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end); + Elf64_Addr *offset_ptr_rom, *last_offset = NULL; + Elf64_Addr *offset_ptr_ram; - Elf32_Addr *offset_ptr_rom, *last_offset = NULL; - Elf32_Addr *offset_ptr_ram; - unsigned int text_base = 0; + do { + /* Get the location from the relocation entry */ + offset_ptr_rom = (Elf64_Addr *)(uintptr_t)re_src->r_offset; - /* The size of the region of u-boot that runs out of RAM. */ - uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start; + /* Check that the location of the relocation is in .text */ + if (offset_ptr_rom >= (Elf64_Addr *)(uintptr_t)text_base && + offset_ptr_rom > last_offset) { + /* Switch to the in-RAM version */ + offset_ptr_ram = (Elf64_Addr *)((ulong)offset_ptr_rom + + gd->reloc_off); - if (gd->flags & GD_FLG_SKIP_RELOC) - return 0; - if (re_src == re_end) - panic("No relocation data"); + /* Check that the target points into .text */ + if (*offset_ptr_ram >= text_base && + *offset_ptr_ram <= text_base + size) { + *offset_ptr_ram = gd->reloc_off + + re_src->r_addend; + } else { + debug(" %p: %lx: rom reloc %lx, ram %p, value %lx, limit %" + PRIXPTR "\n", + re_src, (ulong)re_src->r_info, + (ulong)re_src->r_offset, offset_ptr_ram, + (ulong)*offset_ptr_ram, text_base + size); + } + } else { + debug(" %p: %lx: rom reloc %lx, last %p\n", re_src, + (ulong)re_src->r_info, (ulong)re_src->r_offset, + last_offset); + } + last_offset = offset_ptr_rom; -#ifdef CONFIG_SYS_TEXT_BASE - text_base = CONFIG_SYS_TEXT_BASE; + } while (++re_src < re_end); +} #else - panic("No CONFIG_SYS_TEXT_BASE"); -#endif +static void do_elf_reloc_fixups32(unsigned int text_base, uintptr_t size, + Elf32_Rel *re_src, Elf32_Rel *re_end) +{ + Elf32_Addr *offset_ptr_rom, *last_offset = NULL; + Elf32_Addr *offset_ptr_ram; + do { /* Get the location from the relocation entry */ - offset_ptr_rom = (Elf32_Addr *)re_src->r_offset; + offset_ptr_rom = (Elf32_Addr *)(uintptr_t)re_src->r_offset; /* Check that the location of the relocation is in .text */ - if (offset_ptr_rom >= (Elf32_Addr *)text_base && + if (offset_ptr_rom >= (Elf32_Addr *)(uintptr_t)text_base && offset_ptr_rom > last_offset) { /* Switch to the in-RAM version */ @@ -103,6 +123,38 @@ int do_elf_reloc_fixups(void) last_offset = offset_ptr_rom; } while (++re_src < re_end); +} +#endif + +/* + * This function has more error checking than you might expect. Please see + * this commit message for more information: + * 62f7970a x86: Add error checking to x86 relocation code + */ +int do_elf_reloc_fixups(void) +{ + void *re_src = (void *)(&__rel_dyn_start); + void *re_end = (void *)(&__rel_dyn_end); + uint text_base; + + /* The size of the region of u-boot that runs out of RAM. */ + uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start; + + if (gd->flags & GD_FLG_SKIP_RELOC) + return 0; + if (re_src == re_end) + panic("No relocation data"); + +#ifdef CONFIG_SYS_TEXT_BASE + text_base = CONFIG_SYS_TEXT_BASE; +#else + panic("No CONFIG_SYS_TEXT_BASE"); +#endif +#if CONFIG_IS_ENABLED(X86_64) + do_elf_reloc_fixups64(text_base, size, re_src, re_end); +#else + do_elf_reloc_fixups32(text_base, size, re_src, re_end); +#endif return 0; } diff --git a/arch/x86/lib/sfi.c b/arch/x86/lib/sfi.c index 3d36580..507e037 100644 --- a/arch/x86/lib/sfi.c +++ b/arch/x86/lib/sfi.c @@ -38,14 +38,14 @@ static void *get_entry_start(struct table_info *tab) tab->table[tab->count] = tab->entry_start; tab->entry_start += sizeof(struct sfi_table_header); - return (void *)tab->entry_start; + return (void *)(uintptr_t)tab->entry_start; } static void finish_table(struct table_info *tab, const char *sig, void *entry) { struct sfi_table_header *hdr; - hdr = (struct sfi_table_header *)(tab->base + tab->ptr); + hdr = (struct sfi_table_header *)(uintptr_t)(tab->base + tab->ptr); strcpy(hdr->sig, sig); hdr->len = sizeof(*hdr) + ((ulong)entry - tab->entry_start); hdr->rev = 1; @@ -131,7 +131,7 @@ static int sfi_write_xsdt(struct table_info *tab) return 0; } -u32 write_sfi_table(u32 base) +ulong write_sfi_table(ulong base) { struct table_info table; diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c new file mode 100644 index 0000000..ed2d40b --- /dev/null +++ b/arch/x86/lib/spl.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2016 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <debug_uart.h> +#include <spl.h> +#include <asm/cpu.h> +#include <asm/init_helpers.h> +#include <asm/mtrr.h> +#include <asm/processor.h> +#include <asm-generic/sections.h> + +DECLARE_GLOBAL_DATA_PTR; + +__weak int arch_cpu_init_dm(void) +{ + return 0; +} + +static int x86_spl_init(void) +{ + /* + * TODO(sjg@chromium.org): We use this area of RAM for the stack + * and global_data in SPL. Once U-Boot starts up and releocates it + * is not needed. We could make this a CONFIG option or perhaps + * place it immediately below CONFIG_SYS_TEXT_BASE. + */ + char *ptr = (char *)0x110000; + int ret; + + debug("%s starting\n", __func__); + ret = spl_init(); + if (ret) { + debug("%s: spl_init() failed\n", __func__); + return ret; + } + preloader_console_init(); + + ret = arch_cpu_init(); + if (ret) { + debug("%s: arch_cpu_init() failed\n", __func__); + return ret; + } + ret = arch_cpu_init_dm(); + if (ret) { + debug("%s: arch_cpu_init_dm() failed\n", __func__); + return ret; + } + ret = print_cpuinfo(); + if (ret) { + debug("%s: print_cpuinfo() failed\n", __func__); + return ret; + } + ret = dram_init(); + if (ret) { + debug("%s: dram_init() failed\n", __func__); + return ret; + } + memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start); + + /* TODO(sjg@chromium.org): Consider calling cpu_init_r() here */ + ret = interrupt_init(); + if (ret) { + debug("%s: interrupt_init() failed\n", __func__); + return ret; + } + + /* + * The stack grows down from ptr. Put the global data at ptr. This + * will only be used for SPL. Once SPL loads U-Boot proper it will + * set up its own stack. + */ + gd->new_gd = (struct global_data *)ptr; + memcpy(gd->new_gd, gd, sizeof(*gd)); + arch_setup_gd(gd->new_gd); + gd->start_addr_sp = (ulong)ptr; + + /* Cache the SPI flash. Otherwise copying the code to RAM takes ages */ + ret = mtrr_add_request(MTRR_TYPE_WRBACK, + (1ULL << 32) - CONFIG_XIP_ROM_SIZE, + CONFIG_XIP_ROM_SIZE); + if (ret) { + debug("%s: SPI cache setup failed\n", __func__); + return ret; + } + + return 0; +} + +void board_init_f(ulong flags) +{ + int ret; + + ret = x86_spl_init(); + if (ret) { + debug("Error %d\n", ret); + hang(); + } + + /* Uninit CAR and jump to board_init_f_r() */ + board_init_f_r_trampoline(gd->start_addr_sp); +} + +void board_init_f_r(void) +{ + init_cache_f_r(); + gd->flags &= ~GD_FLG_SERIAL_READY; + debug("cache status %d\n", dcache_status()); + board_init_r(gd, 0); +} + +u32 spl_boot_device(void) +{ + return BOOT_DEVICE_BOARD; +} + +int spl_start_uboot(void) +{ + return 0; +} + +void spl_board_announce_boot_device(void) +{ + printf("SPI flash"); +} + +static int spl_board_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + spl_image->size = CONFIG_SYS_MONITOR_LEN; + spl_image->entry_point = CONFIG_SYS_TEXT_BASE; + spl_image->load_addr = CONFIG_SYS_TEXT_BASE; + spl_image->os = IH_OS_U_BOOT; + spl_image->name = "U-Boot"; + + debug("Loading to %lx\n", spl_image->load_addr); + + return 0; +} +SPL_LOAD_IMAGE_METHOD("SPI", 0, BOOT_DEVICE_BOARD, spl_board_load_image); + +int spl_spi_load_image(void) +{ + return -EPERM; +} + +void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) +{ + int ret; + + printf("Jumping to 64-bit U-Boot: Note many features are missing\n"); + ret = cpu_jump_to_64bit_uboot(spl_image->entry_point); + debug("ret=%d\n", ret); + while (1) + ; +} diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index 5966e58..4f5fe74 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -12,20 +12,13 @@ #include <asm/acpi_table.h> #include <asm/coreboot_tables.h> -#ifdef CONFIG_GENERATE_SMBIOS_TABLE -static u32 write_smbios_table_wrapper(u32 addr) -{ - return write_smbios_table(addr); -} -#endif - /** * Function prototype to write a specific configuration table * * @addr: start address to write the table * @return: end address of the table */ -typedef u32 (*table_write)(u32 addr); +typedef ulong (*table_write)(ulong addr); static table_write table_write_funcs[] = { #ifdef CONFIG_GENERATE_PIRQ_TABLE @@ -41,7 +34,7 @@ static table_write table_write_funcs[] = { write_acpi_tables, #endif #ifdef CONFIG_GENERATE_SMBIOS_TABLE - write_smbios_table_wrapper, + write_smbios_table, #endif }; diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 1b33c77..b6b0f2b 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -165,7 +165,7 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size, * A very old kernel MUST have its real-mode code * loaded at 0x90000 */ - if ((u32)setup_base != 0x90000) { + if ((ulong)setup_base != 0x90000) { /* Copy the real-mode kernel */ memmove((void *)0x90000, setup_base, setup_size); |