diff options
-rw-r--r-- | arch/arm/dts/armada-3720-eDPU-u-boot.dtsi | 13 | ||||
-rw-r--r-- | arch/arm/dts/armada-3720-eDPU.dts | 47 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/alleycat5/cpu.c | 66 | ||||
-rw-r--r-- | board/Marvell/mvebu_armada-37xx/board.c | 159 | ||||
-rw-r--r-- | configs/eDPU_defconfig | 1 | ||||
-rw-r--r-- | configs/imx93_11x11_evk_defconfig | 2 | ||||
-rw-r--r-- | configs/imx93_11x11_evk_ld_defconfig | 2 | ||||
-rw-r--r-- | configs/imx93_var_som_defconfig | 46 | ||||
-rw-r--r-- | drivers/cpu/riscv_cpu.c | 4 | ||||
-rw-r--r-- | drivers/pinctrl/exynos/pinctrl-exynos.c | 125 | ||||
-rw-r--r-- | drivers/pinctrl/exynos/pinctrl-exynos.h | 36 | ||||
-rw-r--r-- | drivers/pinctrl/exynos/pinctrl-exynos7420.c | 2 | ||||
-rw-r--r-- | drivers/rng/arm_rndr.c | 6 | ||||
-rw-r--r-- | drivers/rng/riscv_zkr_rng.c | 34 | ||||
-rw-r--r-- | include/smbios.h | 6 | ||||
-rw-r--r-- | include/tables_csum.h | 2 | ||||
-rw-r--r-- | lib/efi_loader/Makefile | 7 | ||||
-rw-r--r-- | lib/efi_loader/efi_smbios.c | 3 | ||||
-rw-r--r-- | lib/efi_loader/smbiosdump.c | 622 | ||||
-rw-r--r-- | lib/smbios-parser.c | 21 | ||||
-rw-r--r-- | lib/smbios.c | 4 | ||||
-rw-r--r-- | lib/tables_csum.c | 4 |
22 files changed, 1055 insertions, 157 deletions
diff --git a/arch/arm/dts/armada-3720-eDPU-u-boot.dtsi b/arch/arm/dts/armada-3720-eDPU-u-boot.dtsi index cb02b70e54d..c3d450dd83b 100644 --- a/arch/arm/dts/armada-3720-eDPU-u-boot.dtsi +++ b/arch/arm/dts/armada-3720-eDPU-u-boot.dtsi @@ -32,14 +32,17 @@ bootph-all; }; -ð0 { - /* G.hn does not work without additional configuration */ - status = "disabled"; -}; - ð1 { fixed-link { speed = <1000>; full-duplex; }; }; + +/* + * eDPU v2 has a MV88E6361 switch on the MDIO bus and U-boot is used + * to patch the Linux DTS if its found so enable MDIO by default. + */ +&mdio { + status = "okay"; +}; diff --git a/arch/arm/dts/armada-3720-eDPU.dts b/arch/arm/dts/armada-3720-eDPU.dts index 57fc698e55d..d6d37a1f6f3 100644 --- a/arch/arm/dts/armada-3720-eDPU.dts +++ b/arch/arm/dts/armada-3720-eDPU.dts @@ -12,3 +12,50 @@ ð0 { phy-mode = "2500base-x"; }; + +/* + * External MV88E6361 switch is only available on v2 of the board. + * U-Boot will enable the MDIO bus and switch nodes. + */ +&mdio { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&smi_pins>; + + /* Actual device is MV88E6361 */ + switch: switch@0 { + compatible = "marvell,mv88e6190"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "cpu"; + phy-mode = "2500base-x"; + managed = "in-band-status"; + ethernet = <ð0>; + }; + + port@9 { + reg = <9>; + label = "downlink"; + phy-mode = "2500base-x"; + managed = "in-band-status"; + }; + + port@a { + reg = <10>; + label = "uplink"; + phy-mode = "2500base-x"; + managed = "in-band-status"; + sfp = <&sfp_eth1>; + }; + }; + }; +}; diff --git a/arch/arm/mach-mvebu/alleycat5/cpu.c b/arch/arm/mach-mvebu/alleycat5/cpu.c index 8204d962751..0f72ae1709b 100644 --- a/arch/arm/mach-mvebu/alleycat5/cpu.c +++ b/arch/arm/mach-mvebu/alleycat5/cpu.c @@ -16,7 +16,10 @@ DECLARE_GLOBAL_DATA_PTR; -#define RAM_SIZE SZ_1G +#define AC5_PTE_BLOCK_DEVICE \ + (PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | \ + PTE_BLOCK_NON_SHARE | \ + PTE_BLOCK_PXN | PTE_BLOCK_UXN) static struct mm_region ac5_mem_map[] = { { @@ -31,30 +34,63 @@ static struct mm_region ac5_mem_map[] = { .phys = 0x00000000, .virt = 0xa0000000, .size = 0x100000, - - .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | - PTE_BLOCK_NON_SHARE | - PTE_BLOCK_PXN | PTE_BLOCK_UXN + .attrs = AC5_PTE_BLOCK_DEVICE, }, { /* MMIO regions */ .phys = 0x100000, .virt = 0x100000, .size = 0x3ff00000, - - .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | - PTE_BLOCK_NON_SHARE | - PTE_BLOCK_PXN | PTE_BLOCK_UXN + .attrs = AC5_PTE_BLOCK_DEVICE, }, { - /* MMIO regions */ .phys = 0x7F000000, .virt = 0x7F000000, - .size = 0x21000000, - - .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | - PTE_BLOCK_NON_SHARE | - PTE_BLOCK_PXN | PTE_BLOCK_UXN + .size = SZ_8M, + .attrs = AC5_PTE_BLOCK_DEVICE, + }, + { + .phys = 0x7F800000, + .virt = 0x7F800000, + .size = SZ_4M, + .attrs = AC5_PTE_BLOCK_DEVICE, + }, + { + .phys = 0x7FC00000, + .virt = 0x7FC00000, + .size = SZ_512K, + .attrs = AC5_PTE_BLOCK_DEVICE, + }, + { + .phys = 0x7FC80000, + .virt = 0x7FC80000, + .size = SZ_512K, + .attrs = AC5_PTE_BLOCK_DEVICE, + }, + { + .phys = 0x7FD00000, + .virt = 0x7FD00000, + .size = SZ_512K, + .attrs = AC5_PTE_BLOCK_DEVICE, + }, + /* ATF region 0x7FE00000-0x7FE20000 not mapped */ + { + .phys = 0x7FE80000, + .virt = 0x7FE80000, + .size = SZ_512K, + .attrs = AC5_PTE_BLOCK_DEVICE, + }, + { + .phys = 0x7FFF0000, + .virt = 0x7FFF0000, + .size = SZ_1M, + .attrs = AC5_PTE_BLOCK_DEVICE, + }, + { + .phys = 0x80000000, + .virt = 0x80000000, + .size = SZ_2G, + .attrs = AC5_PTE_BLOCK_DEVICE, }, { 0, diff --git a/board/Marvell/mvebu_armada-37xx/board.c b/board/Marvell/mvebu_armada-37xx/board.c index 04124d8014d..1685b12b847 100644 --- a/board/Marvell/mvebu_armada-37xx/board.c +++ b/board/Marvell/mvebu_armada-37xx/board.c @@ -14,6 +14,7 @@ #include <mmc.h> #include <miiphy.h> #include <phy.h> +#include <fdt_support.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/arch/cpu.h> @@ -50,6 +51,7 @@ DECLARE_GLOBAL_DATA_PTR; /* Single-chip mode */ /* Switch Port Registers */ #define MVEBU_SW_LINK_CTRL_REG (1) +#define MVEBU_SW_PORT_SWITCH_ID (3) #define MVEBU_SW_PORT_CTRL_REG (4) #define MVEBU_SW_PORT_BASE_VLAN (6) @@ -57,6 +59,8 @@ DECLARE_GLOBAL_DATA_PTR; #define MVEBU_G2_SMI_PHY_CMD_REG (24) #define MVEBU_G2_SMI_PHY_DATA_REG (25) +#define SWITCH_88E6361_PRODUCT_NUMBER 0x2610 + /* * Memory Controller Registers * @@ -73,6 +77,30 @@ DECLARE_GLOBAL_DATA_PTR; #define A3700_MC_CTRL2_SDRAM_TYPE_DDR3 2 #define A3700_MC_CTRL2_SDRAM_TYPE_DDR4 3 +static bool is_edpu_plus(void) +{ + struct udevice *bus; + ofnode node; + int val; + + if (!CONFIG_IS_ENABLED(DM_MDIO)) + return false; + + node = ofnode_by_compatible(ofnode_null(), "marvell,orion-mdio"); + if (!ofnode_valid(node) || + uclass_get_device_by_ofnode(UCLASS_MDIO, node, &bus) || + device_probe(bus)) { + printf("Cannot find MDIO bus\n"); + return -ENODEV; + } + + val = dm_mdio_read(bus, 0x0, MDIO_DEVAD_NONE, MVEBU_SW_PORT_SWITCH_ID); + if (val == SWITCH_88E6361_PRODUCT_NUMBER) + return true; + else + return false; +} + int board_early_init_f(void) { return 0; @@ -301,14 +329,12 @@ static int mii_multi_chip_mode_write(struct udevice *bus, int dev_smi_addr, return 0; } -/* Bring-up board-specific network stuff */ -static int last_stage_init(void) +static int espressobin_last_stage_init(void) { struct udevice *bus; ofnode node; - if (!CONFIG_IS_ENABLED(DM_MDIO) || - !of_machine_is_compatible("globalscale,espressobin")) + if (!CONFIG_IS_ENABLED(DM_MDIO)) return 0; node = ofnode_by_compatible(ofnode_null(), "marvell,orion-mdio"); @@ -358,23 +384,66 @@ static int last_stage_init(void) return 0; } -EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init); +static int edpu_plus_last_stage_init(void) +{ + struct udevice *dev; + int ret; + + if (is_edpu_plus()) { + ret = uclass_get_device_by_name(UCLASS_ETH, + "ethernet@40000", + &dev); + if (!ret) { + device_remove(dev, DM_REMOVE_NORMAL); + device_unbind(dev); + } + + /* Currently no networking support on the eDPU+ board */ + ret = uclass_get_device_by_name(UCLASS_ETH, + "ethernet@30000", + &dev); + if (!ret) { + device_remove(dev, DM_REMOVE_NORMAL); + device_unbind(dev); + } + } else { + ret = uclass_get_device_by_name(UCLASS_ETH, + "ethernet@30000", + &dev); + if (!ret) { + device_remove(dev, DM_REMOVE_NORMAL); + device_unbind(dev); + } + } + + return 0; +} + +/* Bring-up board-specific network stuff */ +static int last_stage_init(void) +{ + + if (of_machine_is_compatible("globalscale,espressobin")) + return espressobin_last_stage_init(); + + if (of_machine_is_compatible("methode,edpu")) + return edpu_plus_last_stage_init(); + + return 0; +} +EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init); #endif #ifdef CONFIG_OF_BOARD_SETUP -int ft_board_setup(void *blob, struct bd_info *bd) +static int espressobin_fdt_setup(void *blob) { -#ifdef CONFIG_ENV_IS_IN_SPI_FLASH int ret; int spi_off; int parts_off; int part_off; /* Fill SPI MTD partitions for Linux kernel on Espressobin */ - if (!of_machine_is_compatible("globalscale,espressobin")) - return 0; - spi_off = fdt_node_offset_by_compatible(blob, -1, "jedec,spi-nor"); if (spi_off < 0) return 0; @@ -459,7 +528,77 @@ int ft_board_setup(void *blob, struct bd_info *bd) return 0; } + return 0; +} + +static int edpu_plus_fdt_setup(void *blob) +{ + const char *ports[] = { "downlink", "uplink" }; + uint8_t mac[ETH_ALEN]; + const char *path; + int i, ret; + + if (is_edpu_plus()) { + ret = fdt_set_status_by_compatible(blob, + "marvell,orion-mdio", + FDT_STATUS_OKAY); + if (ret) + printf("Failed to enable MDIO!\n"); + + ret = fdt_set_status_by_alias(blob, + "ethernet1", + FDT_STATUS_DISABLED); + if (ret) + printf("Failed to disable ethernet1!\n"); + + path = fdt_get_alias(blob, "ethernet0"); + if (path) + do_fixup_by_path_string(blob, path, "phy-mode", "2500base-x"); + else + printf("Failed to update ethernet0 phy-mode to 2500base-x!\n"); + + ret = fdt_set_status_by_compatible(blob, + "marvell,mv88e6190", + FDT_STATUS_OKAY); + if (ret) + printf("Failed to enable MV88E6361!\n"); + + /* + * MAC-s for Uplink and Downlink ports are stored under + * non standard variable names, so lets manually fixup the + * switch port nodes to have the desired MAC-s. + */ + for (i = 0; i < 2; i++) { + if (eth_env_get_enetaddr(ports[i], mac)) { + do_fixup_by_prop(blob, + "label", + ports[i], + strlen(ports[i]) + 1, + "mac-address", + mac, ARP_HLEN, 1); + + do_fixup_by_prop(blob, + "label", + ports[i], + strlen(ports[i]) + 1, + "local-mac-address", + mac, ARP_HLEN, 1); + } + } + } + + return 0; +} + +int ft_board_setup(void *blob, struct bd_info *bd) +{ +#ifdef CONFIG_ENV_IS_IN_SPI_FLASH + if (of_machine_is_compatible("globalscale,espressobin")) + return espressobin_fdt_setup(blob); #endif + if (of_machine_is_compatible("methode,edpu")) + return edpu_plus_fdt_setup(blob); + return 0; } #endif diff --git a/configs/eDPU_defconfig b/configs/eDPU_defconfig index 0b33ff297af..545fd4356a7 100644 --- a/configs/eDPU_defconfig +++ b/configs/eDPU_defconfig @@ -17,6 +17,7 @@ CONFIG_DEBUG_UART=y CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_DISTRO_DEFAULTS=y +CONFIG_OF_BOARD_SETUP=y CONFIG_USE_PREBOOT=y CONFIG_SYS_PBSIZE=1048 # CONFIG_DISPLAY_CPUINFO is not set diff --git a/configs/imx93_11x11_evk_defconfig b/configs/imx93_11x11_evk_defconfig index e53eea120d7..7f6cf78f705 100644 --- a/configs/imx93_11x11_evk_defconfig +++ b/configs/imx93_11x11_evk_defconfig @@ -9,7 +9,6 @@ CONFIG_NR_DRAM_BANKS=2 CONFIG_ENV_SIZE=0x4000 CONFIG_ENV_OFFSET=0x700000 CONFIG_IMX_CONFIG="arch/arm/mach-imx/imx9/imximage.cfg" -CONFIG_IMX_CONTAINER_CFG="arch/arm/mach-imx/imx9/container.cfg" CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="imx93-11x11-evk" CONFIG_SPL_TEXT_BASE=0x2049A000 @@ -37,6 +36,7 @@ CONFIG_SPL_BSS_MAX_SIZE=0x2000 CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_BOOTROM_SUPPORT=y CONFIG_SPL_LOAD_IMX_CONTAINER=y +CONFIG_IMX_CONTAINER_CFG="arch/arm/mach-imx/imx9/container.cfg" # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y diff --git a/configs/imx93_11x11_evk_ld_defconfig b/configs/imx93_11x11_evk_ld_defconfig index c24b722600c..958f825c6a1 100644 --- a/configs/imx93_11x11_evk_ld_defconfig +++ b/configs/imx93_11x11_evk_ld_defconfig @@ -9,7 +9,6 @@ CONFIG_NR_DRAM_BANKS=2 CONFIG_ENV_SIZE=0x4000 CONFIG_ENV_OFFSET=0x400000 CONFIG_IMX_CONFIG="arch/arm/mach-imx/imx9/imximage.cfg" -CONFIG_IMX_CONTAINER_CFG="arch/arm/mach-imx/imx9/container.cfg" CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="imx93-11x11-evk" CONFIG_SPL_TEXT_BASE=0x2049A000 @@ -38,6 +37,7 @@ CONFIG_SPL_BSS_MAX_SIZE=0x2000 CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_BOOTROM_SUPPORT=y CONFIG_SPL_LOAD_IMX_CONTAINER=y +CONFIG_IMX_CONTAINER_CFG="arch/arm/mach-imx/imx9/container.cfg" # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y diff --git a/configs/imx93_var_som_defconfig b/configs/imx93_var_som_defconfig index 17c94ed9367..cc0c5a79bc1 100644 --- a/configs/imx93_var_som_defconfig +++ b/configs/imx93_var_som_defconfig @@ -6,32 +6,33 @@ CONFIG_SYS_MALLOC_F_LEN=0x18000 CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_NR_DRAM_BANKS=2 -CONFIG_SYS_MEMTEST_START=0x80000000 -CONFIG_SYS_MEMTEST_END=0x90000000 CONFIG_ENV_SIZE=0x4000 CONFIG_ENV_OFFSET=0x700000 CONFIG_IMX_CONFIG="arch/arm/mach-imx/imx9/imximage.cfg" -CONFIG_IMX_CONTAINER_CFG="arch/arm/mach-imx/imx9/container.cfg" CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="imx93-var-som-symphony" CONFIG_SPL_TEXT_BASE=0x2049A000 CONFIG_TARGET_IMX93_VAR_SOM=y +CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_STACK=0x20519dd0 CONFIG_SPL=y CONFIG_CMD_DEKBLOB=y CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x88000000 -CONFIG_SPL_LOAD_IMX_CONTAINER=y -CONFIG_DISTRO_DEFAULTS=y -CONFIG_REMAKE_ELF=y CONFIG_SYS_LOAD_ADDR=0x80400000 +CONFIG_SYS_MEMTEST_START=0x80000000 +CONFIG_SYS_MEMTEST_END=0x90000000 +CONFIG_REMAKE_ELF=y CONFIG_FIT=y CONFIG_FIT_VERBOSE=y -CONFIG_OF_SYSTEM_SETUP=y +CONFIG_DISTRO_DEFAULTS=y CONFIG_BOOTDELAY=1 +CONFIG_OF_SYSTEM_SETUP=y CONFIG_BOOTCOMMAND="run bsp_bootcmd" CONFIG_DEFAULT_FDT_FILE="imx93-var-som-symphony.dtb" +CONFIG_SYS_CBSIZE=2048 +CONFIG_SYS_PBSIZE=2074 CONFIG_BOARD_EARLY_INIT_F=y CONFIG_BOARD_LATE_INIT=y CONFIG_SPL_MAX_SIZE=0x26000 @@ -40,11 +41,9 @@ CONFIG_SPL_BSS_START_ADDR=0x2051a000 CONFIG_SPL_BSS_MAX_SIZE=0x2000 CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_BOOTROM_SUPPORT=y +CONFIG_SPL_LOAD_IMX_CONTAINER=y +CONFIG_IMX_CONTAINER_CFG="arch/arm/mach-imx/imx9/container.cfg" # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set -CONFIG_SYS_SPL_MALLOC=y -CONFIG_HAS_CUSTOM_SPL_MALLOC_START=y -CONFIG_CUSTOM_SYS_SPL_MALLOC_ADDR=0x83200000 -CONFIG_SYS_SPL_MALLOC_SIZE=0x80000 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1040 CONFIG_SPL_I2C=y @@ -52,11 +51,8 @@ CONFIG_SPL_POWER=y CONFIG_SPL_WATCHDOG=y CONFIG_SYS_PROMPT="u-boot=> " CONFIG_SYS_MAXARGS=64 -CONFIG_SYS_CBSIZE=2048 -CONFIG_SYS_PBSIZE=2074 CONFIG_CMD_ERASEENV=y CONFIG_CMD_NVEDIT_EFI=y -CONFIG_CMD_NET=y CONFIG_CRC32_VERIFY=y CONFIG_CMD_EEPROM=y CONFIG_SYS_I2C_EEPROM_BUS=3 @@ -71,6 +67,8 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_POWEROFF=y +CONFIG_CMD_READ=y +CONFIG_CMD_WDT=y CONFIG_BOOTP_PREFER_SERVERIP=y CONFIG_CMD_SNTP=y CONFIG_CMD_CACHE=y @@ -92,16 +90,10 @@ CONFIG_SYS_MMC_ENV_DEV=1 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y -CONFIG_SYSCON=y CONFIG_SPL_CLK_IMX93=y CONFIG_CLK_IMX93=y CONFIG_DFU_MMC=y CONFIG_DFU_RAM=y -CONFIG_FASTBOOT_BUF_ADDR=0x82800000 -CONFIG_FASTBOOT_BUF_SIZE=0x20000000 -CONFIG_FASTBOOT_FLASH=y -CONFIG_FASTBOOT_UUU_SUPPORT=y -CONFIG_FASTBOOT_FLASH_MMC_DEV=1 CONFIG_GPIO_HOG=y CONFIG_IMX_RGPIO2P=y CONFIG_DM_PCA953X=y @@ -116,7 +108,6 @@ CONFIG_FSL_USDHC=y CONFIG_PHY_ADIN=y CONFIG_PHY_ATHEROS=y CONFIG_PHY_REALTEK=y -CONFIG_DM_ETH=y CONFIG_DM_ETH_PHY=y CONFIG_PHY_GIGE=y CONFIG_DWC_ETH_QOS=y @@ -124,12 +115,10 @@ CONFIG_DWC_ETH_QOS_IMX=y CONFIG_FEC_MXC=y CONFIG_MII=y CONFIG_MIPI_DPHY_HELPERS=y -CONFIG_PHY_IMX93_MIPI_DPHY=y CONFIG_PINCTRL=y CONFIG_SPL_PINCTRL=y CONFIG_PINCTRL_IMX93=y CONFIG_POWER_DOMAIN=y -CONFIG_IMX93_BLK_CTRL=y CONFIG_DM_PMIC=y CONFIG_SPL_DM_PMIC_PCA9450=y CONFIG_DM_REGULATOR=y @@ -141,16 +130,7 @@ CONFIG_DM_SERIAL=y CONFIG_FSL_LPUART=y CONFIG_DM_THERMAL=y CONFIG_IMX_TMU=y -CONFIG_CI_UDC=y CONFIG_ULP_WATCHDOG=y +CONFIG_WDT=y CONFIG_LZO=y CONFIG_BZIP2=y -CONFIG_OF_LIBFDT_OVERLAY=y -CONFIG_WATCHDOG=y -CONFIG_WDT=y -CONFIG_CMD_WDT=y -CONFIG_ETHPRIME="eth0" -CONFIG_SYS_I2C_SPEED=100000 -CONFIG_IMX_BOOTAUX=y -CONFIG_CMD_READ=y -CONFIG_SERIAL_TAG=y
\ No newline at end of file diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index d6484d7f4b4..034b9b49c05 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -98,6 +98,10 @@ static int riscv_cpu_bind(struct udevice *dev) /* save the hart id */ plat->cpu_id = dev_read_addr(dev); + if (IS_ENABLED(CONFIG_64BIT)) + plat->family = 0x201; + else + plat->family = 0x200; /* first examine the property in current cpu node */ ret = dev_read_u32(dev, "timebase-frequency", &plat->timebase_freq); /* if not found, then look at the parent /cpus node */ diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.c b/drivers/pinctrl/exynos/pinctrl-exynos.c index 898185479ba..8a045cdf7aa 100644 --- a/drivers/pinctrl/exynos/pinctrl-exynos.c +++ b/drivers/pinctrl/exynos/pinctrl-exynos.c @@ -9,11 +9,21 @@ #include <common.h> #include <dm.h> #include <errno.h> -#include <asm/global_data.h> #include <asm/io.h> #include "pinctrl-exynos.h" -DECLARE_GLOBAL_DATA_PTR; +/* CON, DAT, PUD, DRV */ +const struct samsung_pin_bank_type bank_type_alive = { + .fld_width = { 4, 1, 2, 2, }, + .reg_offset = { 0x00, 0x04, 0x08, 0x0c, }, +}; + +static const char * const exynos_pinctrl_props[PINCFG_TYPE_NUM] = { + [PINCFG_TYPE_FUNC] = "samsung,pin-function", + [PINCFG_TYPE_DAT] = "samsung,pin-val", + [PINCFG_TYPE_PUD] = "samsung,pin-pud", + [PINCFG_TYPE_DRV] = "samsung,pin-drv", +}; /** * exynos_pinctrl_setup_peri: setup pinctrl for a peripheral. @@ -34,30 +44,35 @@ void exynos_pinctrl_setup_peri(struct exynos_pinctrl_config_data *conf, } } -/* given a pin-name, return the address of pin config registers */ -static unsigned long pin_to_bank_base(struct udevice *dev, const char *pin_name, - u32 *pin) +static void parse_pin(const char *pin_name, u32 *pin, char *bank_name) { - struct exynos_pinctrl_priv *priv = dev_get_priv(dev); - const struct samsung_pin_ctrl *pin_ctrl_array = priv->pin_ctrl; - const struct samsung_pin_bank_data *bank_data; - u32 nr_banks, pin_ctrl_idx = 0, idx = 0, bank_base; - char bank[10]; + u32 idx = 0; /* - * The format of the pin name is <bank name>-<pin_number>. - * Example: gpa0-4 (gpa0 is the bank name and 4 is the pin number. + * The format of the pin name is <bank_name name>-<pin_number>. + * Example: gpa0-4 (gpa0 is the bank_name name and 4 is the pin number. */ while (pin_name[idx] != '-') { - bank[idx] = pin_name[idx]; + bank_name[idx] = pin_name[idx]; idx++; } - bank[idx] = '\0'; + bank_name[idx] = '\0'; *pin = pin_name[++idx] - '0'; +} + +/* given a bank name, find out the pin bank structure */ +static const struct samsung_pin_bank_data *get_bank(struct udevice *dev, + const char *bank_name) +{ + struct exynos_pinctrl_priv *priv = dev_get_priv(dev); + const struct samsung_pin_ctrl *pin_ctrl_array = priv->pin_ctrl; + const struct samsung_pin_bank_data *bank_data; + u32 nr_banks, pin_ctrl_idx = 0, idx = 0; /* lookup the pin bank data using the pin bank name */ while (true) { - const struct samsung_pin_ctrl *pin_ctrl = &pin_ctrl_array[pin_ctrl_idx]; + const struct samsung_pin_ctrl *pin_ctrl = + &pin_ctrl_array[pin_ctrl_idx]; nr_banks = pin_ctrl->nr_banks; if (!nr_banks) @@ -67,15 +82,29 @@ static unsigned long pin_to_bank_base(struct udevice *dev, const char *pin_name, for (idx = 0; idx < nr_banks; idx++) { debug("pinctrl[%d] bank_data[%d] name is: %s\n", pin_ctrl_idx, idx, bank_data[idx].name); - if (!strcmp(bank, bank_data[idx].name)) { - bank_base = priv->base + bank_data[idx].offset; - break; - } + if (!strcmp(bank_name, bank_data[idx].name)) + return &bank_data[idx]; } pin_ctrl_idx++; } - return bank_base; + return NULL; +} + +static void exynos_pinctrl_set_pincfg(unsigned long reg_base, u32 pin_num, + u32 val, enum pincfg_type pincfg, + const struct samsung_pin_bank_type *type) +{ + u32 width = type->fld_width[pincfg]; + u32 reg_offset = type->reg_offset[pincfg]; + u32 mask = (1 << width) - 1; + u32 shift = pin_num * width; + u32 data; + + data = readl(reg_base + reg_offset); + data &= ~(mask << shift); + data |= val << shift; + writel(data, reg_base + reg_offset); } /** @@ -85,50 +114,46 @@ static unsigned long pin_to_bank_base(struct udevice *dev, const char *pin_name, */ int exynos_pinctrl_set_state(struct udevice *dev, struct udevice *config) { - const void *fdt = gd->fdt_blob; - int node = dev_of_offset(config); - unsigned int count, idx, pin_num; - unsigned int pinfunc, pinpud, pindrv; - unsigned long reg, value; - const char *name; + struct exynos_pinctrl_priv *priv = dev_get_priv(dev); + unsigned int count, idx; + unsigned int pinvals[PINCFG_TYPE_NUM]; /* * refer to the following document for the pinctrl bindings * linux/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt */ - count = fdt_stringlist_count(fdt, node, "samsung,pins"); + count = dev_read_string_count(config, "samsung,pins"); if (count <= 0) return -EINVAL; - pinfunc = fdtdec_get_int(fdt, node, "samsung,pin-function", -1); - pinpud = fdtdec_get_int(fdt, node, "samsung,pin-pud", -1); - pindrv = fdtdec_get_int(fdt, node, "samsung,pin-drv", -1); + for (idx = 0; idx < PINCFG_TYPE_NUM; ++idx) { + pinvals[idx] = dev_read_u32_default(config, + exynos_pinctrl_props[idx], -1); + } + pinvals[PINCFG_TYPE_DAT] = -1; /* ignore GPIO data register */ for (idx = 0; idx < count; idx++) { - name = fdt_stringlist_get(fdt, node, "samsung,pins", idx, NULL); - if (!name) + const struct samsung_pin_bank_data *bank; + unsigned int pin_num; + char bank_name[10]; + unsigned long reg; + const char *name = NULL; + int pincfg, err; + + err = dev_read_string_index(config, "samsung,pins", idx, &name); + if (err || !name) continue; - reg = pin_to_bank_base(dev, name, &pin_num); - if (pinfunc != -1) { - value = readl(reg + PIN_CON); - value &= ~(0xf << (pin_num << 2)); - value |= (pinfunc << (pin_num << 2)); - writel(value, reg + PIN_CON); - } + parse_pin(name, &pin_num, bank_name); + bank = get_bank(dev, bank_name); + reg = priv->base + bank->offset; - if (pinpud != -1) { - value = readl(reg + PIN_PUD); - value &= ~(0x3 << (pin_num << 1)); - value |= (pinpud << (pin_num << 1)); - writel(value, reg + PIN_PUD); - } + for (pincfg = 0; pincfg < PINCFG_TYPE_NUM; ++pincfg) { + unsigned int val = pinvals[pincfg]; - if (pindrv != -1) { - value = readl(reg + PIN_DRV); - value &= ~(0x3 << (pin_num << 1)); - value |= (pindrv << (pin_num << 1)); - writel(value, reg + PIN_DRV); + if (val != -1) + exynos_pinctrl_set_pincfg(reg, pin_num, val, + pincfg, bank->type); } } diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.h b/drivers/pinctrl/exynos/pinctrl-exynos.h index cbc5174b48c..743bb557309 100644 --- a/drivers/pinctrl/exynos/pinctrl-exynos.h +++ b/drivers/pinctrl/exynos/pinctrl-exynos.h @@ -8,26 +8,52 @@ #ifndef __PINCTRL_EXYNOS_H_ #define __PINCTRL_EXYNOS_H_ -#define PIN_CON 0x00 /* Offset of pin function register */ -#define PIN_DAT 0x04 /* Offset of pin data register */ -#define PIN_PUD 0x08 /* Offset of pin pull up/down config register */ -#define PIN_DRV 0x0C /* Offset of pin drive strength register */ +/** + * enum pincfg_type - possible pin configuration types supported. + * @PINCFG_TYPE_FUNC: Function configuration. + * @PINCFG_TYPE_DAT: Pin value configuration. + * @PINCFG_TYPE_PUD: Pull up/down configuration. + * @PINCFG_TYPE_DRV: Drive strength configuration. + */ +enum pincfg_type { + PINCFG_TYPE_FUNC, + PINCFG_TYPE_DAT, + PINCFG_TYPE_PUD, + PINCFG_TYPE_DRV, + + PINCFG_TYPE_NUM +}; + +/** + * struct samsung_pin_bank_type: pin bank type description + * @fld_width: widths of configuration bitfields (0 if unavailable) + * @reg_offset: offsets of configuration registers (don't care of width is 0) + */ +struct samsung_pin_bank_type { + u8 fld_width[PINCFG_TYPE_NUM]; + u8 reg_offset[PINCFG_TYPE_NUM]; +}; /** * struct samsung_pin_bank_data: represent a controller pin-bank data. + * @type: type of the bank (register offsets and bitfield widths) * @offset: starting offset of the pin-bank registers. * @nr_pins: number of pins included in this bank. * @name: name to be prefixed for each pin in this pin bank. */ struct samsung_pin_bank_data { + const struct samsung_pin_bank_type *type; u32 offset; u8 nr_pins; const char *name; }; +extern const struct samsung_pin_bank_type bank_type_alive; + #define EXYNOS_PIN_BANK(pins, reg, id) \ { \ - .offset = reg, \ + .type = &bank_type_alive, \ + .offset = reg, \ .nr_pins = pins, \ .name = id \ } diff --git a/drivers/pinctrl/exynos/pinctrl-exynos7420.c b/drivers/pinctrl/exynos/pinctrl-exynos7420.c index 07870b7f51a..77d510d8f60 100644 --- a/drivers/pinctrl/exynos/pinctrl-exynos7420.c +++ b/drivers/pinctrl/exynos/pinctrl-exynos7420.c @@ -16,6 +16,8 @@ #include "pinctrl-exynos.h" #define GPD1_OFFSET 0xc0 +#define PIN_CON 0x00 /* Offset of pin function register */ +#define PIN_PUD 0x08 /* Offset of pin pull up/down config register */ static struct exynos_pinctrl_config_data serial2_conf[] = { { diff --git a/drivers/rng/arm_rndr.c b/drivers/rng/arm_rndr.c index 55989743eae..4512330e68d 100644 --- a/drivers/rng/arm_rndr.c +++ b/drivers/rng/arm_rndr.c @@ -62,10 +62,10 @@ static const struct dm_rng_ops arm_rndr_ops = { .read = arm_rndr_read, }; -static int arm_rndr_probe(struct udevice *dev) +static int arm_rndr_bind(struct udevice *dev) { if (!cpu_has_rndr()) - return -ENODEV; + return -ENOENT; return 0; } @@ -74,7 +74,7 @@ U_BOOT_DRIVER(arm_rndr) = { .name = DRIVER_NAME, .id = UCLASS_RNG, .ops = &arm_rndr_ops, - .probe = arm_rndr_probe, + .bind = arm_rndr_bind, }; U_BOOT_DRVINFO(cpu_arm_rndr) = { diff --git a/drivers/rng/riscv_zkr_rng.c b/drivers/rng/riscv_zkr_rng.c index 8c9e111e2e0..48a5251988f 100644 --- a/drivers/rng/riscv_zkr_rng.c +++ b/drivers/rng/riscv_zkr_rng.c @@ -55,7 +55,7 @@ static int riscv_zkr_read(struct udevice *dev, void *data, size_t len) } break; case DEAD: - return -ENODEV; + return -ENOENT; } } @@ -63,16 +63,16 @@ static int riscv_zkr_read(struct udevice *dev, void *data, size_t len) } /** - * riscv_zkr_probe() - check if the seed register is available + * riscv_zkr_bind() - check if the seed register is available * - * If the SBI software has not set mseccfg.sseed=1 or the Zkr - * extension is not available this probe function will result - * in an exception. Currently we cannot recover from this. + * If the SBI software has not set mseccfg.sseed=1 or the Zkr extension is not + * available, reading the seed register will result in an exception from which + * this function safely resumes. * * @dev: RNG device * Return: 0 if successfully probed */ -static int riscv_zkr_probe(struct udevice *dev) +static int riscv_zkr_bind(struct udevice *dev) { struct resume_data resume; int ret; @@ -87,7 +87,24 @@ static int riscv_zkr_probe(struct udevice *dev) val = read_seed(); set_resume(NULL); if (ret) - return -ENODEV; + return -ENOENT; + + return 0; +} + +/** + * riscv_zkr_probe() - check if entropy is available + * + * The bind method already checked that the seed register can be read without + * excpetiong. Here we wait for the self test to finish and entropy becoming + * available. + * + * @dev: RNG device + * Return: 0 if successfully probed + */ +static int riscv_zkr_probe(struct udevice *dev) +{ + u32 val; do { val = read_seed(); @@ -95,7 +112,7 @@ static int riscv_zkr_probe(struct udevice *dev) } while (val == BIST || val == WAIT); if (val == DEAD) - return -ENODEV; + return -ENOENT; return 0; } @@ -108,6 +125,7 @@ U_BOOT_DRIVER(riscv_zkr) = { .name = DRIVER_NAME, .id = UCLASS_RNG, .ops = &riscv_zkr_ops, + .bind = riscv_zkr_bind, .probe = riscv_zkr_probe, }; diff --git a/include/smbios.h b/include/smbios.h index 49de32fec2d..b507b9d9d72 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -8,7 +8,7 @@ #ifndef _SMBIOS_H_ #define _SMBIOS_H_ -#include <dm/ofnode.h> +#include <linux/types.h> /* SMBIOS spec version implemented */ #define SMBIOS_MAJOR_VER 3 @@ -80,10 +80,6 @@ struct __packed smbios3_entry { u64 struct_table_address; }; -/* These two structures should use the same amount of 16-byte-aligned space */ -static_assert(ALIGN(16, sizeof(struct smbios_entry)) == - ALIGN(16, sizeof(struct smbios3_entry))); - /* BIOS characteristics */ #define BIOS_CHARACTERISTICS_PCI_SUPPORTED (1 << 7) #define BIOS_CHARACTERISTICS_UPGRADEABLE (1 << 11) diff --git a/include/tables_csum.h b/include/tables_csum.h index 4812333093a..9207e85f91b 100644 --- a/include/tables_csum.h +++ b/include/tables_csum.h @@ -17,6 +17,6 @@ * @len: configuration table size * @return: the 8-bit checksum */ -u8 table_compute_checksum(void *v, int len); +u8 table_compute_checksum(const void *v, const int len); #endif diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 24d33d54099..25060bbd95a 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -16,6 +16,8 @@ CFLAGS_boothart.o := $(CFLAGS_EFI) -Os -ffreestanding CFLAGS_REMOVE_boothart.o := $(CFLAGS_NON_EFI) CFLAGS_helloworld.o := $(CFLAGS_EFI) -Os -ffreestanding CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI) +CFLAGS_smbiosdump.o := $(CFLAGS_EFI) -Os -ffreestanding +CFLAGS_REMOVE_smbiosdump.o := $(CFLAGS_NON_EFI) CFLAGS_dtbdump.o := $(CFLAGS_EFI) -Os -ffreestanding CFLAGS_REMOVE_dtbdump.o := $(CFLAGS_NON_EFI) CFLAGS_initrddump.o := $(CFLAGS_EFI) -Os -ffreestanding @@ -31,6 +33,11 @@ always += helloworld.efi targets += helloworld.o endif +ifneq ($(CONFIG_GENERATE_SMBIOS_TABLE),) +always += smbiosdump.efi +targets += smbiosdump.o +endif + ifeq ($(CONFIG_GENERATE_ACPI_TABLE),) always += dtbdump.efi targets += dtbdump.o diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index eb6d2ba43c9..b2ec1f79194 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -13,6 +13,9 @@ #include <mapmem.h> #include <smbios.h> #include <linux/sizes.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; const efi_guid_t smbios3_guid = SMBIOS3_TABLE_GUID; diff --git a/lib/efi_loader/smbiosdump.c b/lib/efi_loader/smbiosdump.c new file mode 100644 index 00000000000..f0b901897e9 --- /dev/null +++ b/lib/efi_loader/smbiosdump.c @@ -0,0 +1,622 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2023, Heinrich Schuchardt <heinrich.schuchardt@canonical.com> + * + * smbiosdump.efi saves the SMBIOS table as file. + * + * Specifying 'nocolor' as load option data suppresses colored output and + * clearing of the screen. + */ + +#include <efi_api.h> +#include <part.h> +#include <smbios.h> +#include <string.h> + +#define BUFFER_SIZE 64 + +static struct efi_simple_text_output_protocol *cerr; +static struct efi_simple_text_output_protocol *cout; +static struct efi_simple_text_input_protocol *cin; +static struct efi_boot_services *bs; +static efi_handle_t handle; +static struct efi_system_table *systable; +static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID; +static const efi_guid_t smbios3_guid = SMBIOS3_TABLE_GUID; +static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; +static const efi_guid_t guid_simple_file_system_protocol = + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; +static const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID; +static bool nocolor; + +/** + * color() - set foreground color + * + * @color: foreground color + */ +static void color(u8 color) +{ + if (!nocolor) + cout->set_attribute(cout, color | EFI_BACKGROUND_BLACK); +} + +/** + * print() - print string + * + * @string: text + */ +static void print(u16 *string) +{ + cout->output_string(cout, string); +} + +/** + * cls() - clear screen + */ +static void cls(void) +{ + if (nocolor) + print(u"\r\n"); + else + cout->clear_screen(cout); +} + +/** + * error() - print error string + * + * @string: error text + */ +static void error(u16 *string) +{ + color(EFI_LIGHTRED); + print(string); + color(EFI_LIGHTBLUE); +} + +/** + * efi_input_yn() - get answer to yes/no question + * + * Return: + * y or Y + * EFI_SUCCESS + * n or N + * EFI_ACCESS_DENIED + * ESC + * EFI_ABORTED + */ +static efi_status_t efi_input_yn(void) +{ + struct efi_input_key key = {0}; + efi_uintn_t index; + efi_status_t ret; + + /* Drain the console input */ + ret = cin->reset(cin, true); + for (;;) { + ret = bs->wait_for_event(1, &cin->wait_for_key, &index); + if (ret != EFI_SUCCESS) + continue; + ret = cin->read_key_stroke(cin, &key); + if (ret != EFI_SUCCESS) + continue; + switch (key.scan_code) { + case 0x17: /* Escape */ + return EFI_ABORTED; + default: + break; + } + /* Convert to lower case */ + switch (key.unicode_char | 0x20) { + case 'y': + return EFI_SUCCESS; + case 'n': + return EFI_ACCESS_DENIED; + default: + break; + } + } +} + +/** + * efi_input() - read string from console + * + * @buffer: input buffer + * @buffer_size: buffer size + * Return: status code + */ +static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size) +{ + struct efi_input_key key = {0}; + efi_uintn_t index; + efi_uintn_t pos = 0; + u16 outbuf[2] = u" "; + efi_status_t ret; + + /* Drain the console input */ + ret = cin->reset(cin, true); + *buffer = 0; + for (;;) { + ret = bs->wait_for_event(1, &cin->wait_for_key, &index); + if (ret != EFI_SUCCESS) + continue; + ret = cin->read_key_stroke(cin, &key); + if (ret != EFI_SUCCESS) + continue; + switch (key.scan_code) { + case 0x17: /* Escape */ + print(u"\r\nAborted\r\n"); + return EFI_ABORTED; + default: + break; + } + switch (key.unicode_char) { + case 0x08: /* Backspace */ + if (pos) { + buffer[pos--] = 0; + print(u"\b \b"); + } + break; + case 0x0a: /* Linefeed */ + case 0x0d: /* Carriage return */ + print(u"\r\n"); + return EFI_SUCCESS; + default: + break; + } + /* Ignore surrogate codes */ + if (key.unicode_char >= 0xD800 && key.unicode_char <= 0xDBFF) + continue; + if (key.unicode_char >= 0x20 && + pos < buffer_size - 1) { + *outbuf = key.unicode_char; + buffer[pos++] = key.unicode_char; + buffer[pos] = 0; + print(outbuf); + } + } +} + +/** + * skip_whitespace() - skip over leading whitespace + * + * @pos: UTF-16 string + * Return: pointer to first non-whitespace + */ +static u16 *skip_whitespace(u16 *pos) +{ + for (; *pos && *pos <= 0x20; ++pos) + ; + return pos; +} + +/** + * starts_with() - check if @string starts with @keyword + * + * @string: string to search for keyword + * @keyword: keyword to be searched + * Return: true fi @string starts with the keyword + */ +static bool starts_with(u16 *string, u16 *keyword) +{ + if (!string || !keyword) + return NULL; + + for (; *keyword; ++string, ++keyword) { + if (*string != *keyword) + return false; + } + return true; +} + +/** + * open_file_system() - open simple file system protocol + * + * file_system: interface of the simple file system protocol + * Return: status code + */ +static efi_status_t +open_file_system(struct efi_simple_file_system_protocol **file_system) +{ + struct efi_loaded_image *loaded_image; + efi_status_t ret; + efi_handle_t *handle_buffer = NULL; + efi_uintn_t count; + + ret = bs->open_protocol(handle, &loaded_image_guid, + (void **)&loaded_image, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) { + error(u"Loaded image protocol not found\r\n"); + return ret; + } + + /* Open the simple file system protocol on the same partition */ + ret = bs->open_protocol(loaded_image->device_handle, + &guid_simple_file_system_protocol, + (void **)file_system, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret == EFI_SUCCESS) + return ret; + + /* Open the simple file system protocol on the UEFI system partition */ + ret = bs->locate_handle_buffer(BY_PROTOCOL, &efi_system_partition_guid, + NULL, &count, &handle_buffer); + if (ret == EFI_SUCCESS && handle_buffer) + ret = bs->open_protocol(handle_buffer[0], + &guid_simple_file_system_protocol, + (void **)file_system, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + error(u"Failed to open simple file system protocol\r\n"); + if (handle) + bs->free_pool(handle_buffer); + + return ret; +} + +/** + * do_help() - print help + */ +static void do_help(void) +{ + error(u"check - check SMBIOS table\r\n"); + error(u"save <file> - save SMBIOS table to file\r\n"); + error(u"exit - exit the shell\r\n"); +} + +/** + * get_config_table() - get configuration table + * + * @guid: GUID of the configuration table + * Return: pointer to configuration table or NULL + */ +static void *get_config_table(const efi_guid_t *guid) +{ + size_t i; + + for (i = 0; i < systable->nr_tables; ++i) { + if (!memcmp(guid, &systable->tables[i].guid, 16)) + return systable->tables[i].table; + } + + return NULL; +} + +/** + * checksum() - calculate checksum + * + * @buf: buffer to checksum + * @len: length of buffer + * Return: checksum + */ +u8 checksum(void *buf, int len) +{ + u8 ret = 0; + + for (u8 *ptr = buf; len; --len, ++ptr) + ret -= *ptr; + + return ret; +} + +/** + * do_check() - check SMBIOS table + * + * Return: status code + */ +efi_status_t do_check(void) +{ + struct smbios3_entry *smbios3_anchor; + void *table, *table_end; + u32 len; + + smbios3_anchor = get_config_table(&smbios3_guid); + if (smbios3_anchor) { + int r; + + r = memcmp(smbios3_anchor->anchor, "_SM3_", 5); + if (r) { + error(u"Invalid anchor string\n"); + return EFI_LOAD_ERROR; + } + print(u"Found SMBIOS 3 entry point\n"); + if (smbios3_anchor->length != 0x18) { + error(u"Invalid anchor length\n"); + return EFI_LOAD_ERROR; + } + if (checksum(smbios3_anchor, smbios3_anchor->length)) { + error(u"Invalid anchor checksum\n"); + return EFI_LOAD_ERROR; + } + table = (void *)(uintptr_t)smbios3_anchor->struct_table_address; + len = smbios3_anchor->max_struct_size; + } else { + struct smbios_entry *smbios_anchor; + int r; + + smbios_anchor = get_config_table(&smbios_guid); + if (!smbios_anchor) { + error(u"No SMBIOS table\n"); + return EFI_NOT_FOUND; + } + r = memcmp(smbios_anchor->anchor, "_SM_", 4); + if (r) { + error(u"Invalid anchor string\n"); + return EFI_LOAD_ERROR; + } + print(u"Found SMBIOS 2.1 entry point\n"); + if (smbios_anchor->length != 0x1f) { + error(u"Invalid anchor length\n"); + return EFI_LOAD_ERROR; + } + if (checksum(smbios_anchor, smbios_anchor->length)) { + error(u"Invalid anchor checksum\n"); + return EFI_LOAD_ERROR; + } + r = memcmp(smbios_anchor->intermediate_anchor, "_DMI_", 5); + if (r) { + error(u"Invalid intermediate anchor string\n"); + return EFI_LOAD_ERROR; + } + if (checksum(&smbios_anchor->intermediate_anchor, 0xf)) { + error(u"Invalid intermediate anchor checksum\n"); + return EFI_LOAD_ERROR; + } + table = (void *)(uintptr_t)smbios_anchor->struct_table_address; + len = smbios_anchor->struct_table_length; + } + + table_end = (void *)((u8 *)table + len); + for (struct smbios_header *pos = table; ;) { + u8 *str = (u8 *)pos + pos->length; + + if (!*str) + ++str; + while (*str) { + for (; *str; ++str) { + if ((void *)str >= table_end) { + error(u"Structure table length exceeded\n"); + return EFI_LOAD_ERROR; + } + } + ++str; + } + ++str; + if ((void *)str > table_end) { + error(u"Structure table length exceeded\n"); + return EFI_LOAD_ERROR; + } + if (pos->type == 0x7f) /* End of table */ + break; + pos = (struct smbios_header *)str; + } + + return EFI_SUCCESS; +} + +/** + * save_file() - save file to EFI system partition + * + * @filename: file name + * @buf: buffer to write + * @size: size of the buffer + */ +efi_status_t save_file(u16 *filename, void *buf, efi_uintn_t size) +{ + efi_uintn_t ret; + struct efi_simple_file_system_protocol *file_system; + struct efi_file_handle *root, *file; + + ret = open_file_system(&file_system); + if (ret != EFI_SUCCESS) + return ret; + + /* Open volume */ + ret = file_system->open_volume(file_system, &root); + if (ret != EFI_SUCCESS) { + error(u"Failed to open volume\r\n"); + return ret; + } + /* Check if file already exists */ + ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0); + if (ret == EFI_SUCCESS) { + file->close(file); + print(u"Overwrite existing file (y/n)? "); + ret = efi_input_yn(); + print(u"\r\n"); + if (ret != EFI_SUCCESS) { + root->close(root); + error(u"Aborted by user\r\n"); + bs->free_pool(buf); + return ret; + } + } + + /* Create file */ + ret = root->open(root, &file, filename, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | + EFI_FILE_MODE_CREATE, EFI_FILE_ARCHIVE); + if (ret == EFI_SUCCESS) { + /* Write file */ + ret = file->write(file, &size, buf); + if (ret != EFI_SUCCESS) + error(u"Failed to write file\r\n"); + file->close(file); + } else { + error(u"Failed to open file\r\n"); + } + root->close(root); + + return ret; +} + +/** + * do_save() - save SMBIOS table + * + * @filename: file name + * Return: status code + */ +static efi_status_t do_save(u16 *filename) +{ + struct smbios3_entry *smbios3_anchor; + u8 *buf; + efi_uintn_t size; + efi_uintn_t ret; + + ret = do_check(); + if (ret != EFI_SUCCESS) + return ret; + + smbios3_anchor = get_config_table(&smbios3_guid); + if (smbios3_anchor) { + size = 0x20 + smbios3_anchor->max_struct_size; + ret = bs->allocate_pool(EFI_LOADER_DATA, size, (void **)&buf); + if (ret != EFI_SUCCESS) { + error(u"Out of memory\n"); + return ret; + } + + memset(buf, 0, size); + memcpy(buf, smbios3_anchor, smbios3_anchor->length); + memcpy(buf + 0x20, + (void *)(uintptr_t)smbios3_anchor->struct_table_address, + smbios3_anchor->max_struct_size); + + smbios3_anchor = (struct smbios3_entry *)buf; + smbios3_anchor->struct_table_address = 0x20; + smbios3_anchor->checksum += + checksum(smbios3_anchor, smbios3_anchor->length); + } else { + struct smbios_entry *smbios_anchor; + + smbios_anchor = get_config_table(&smbios_guid); + if (!smbios_anchor) { + /* Should not be reached after successful do_check() */ + error(u"No SMBIOS table\n"); + return EFI_NOT_FOUND; + } + + size = 0x20 + smbios_anchor->struct_table_length; + + ret = bs->allocate_pool(EFI_LOADER_DATA, size, (void **)&buf); + if (ret != EFI_SUCCESS) { + error(u"Out of memory\n"); + return ret; + } + + memset(buf, 0, size); + memcpy(buf, smbios_anchor, smbios_anchor->length); + memcpy(buf + 0x20, + (void *)(uintptr_t)smbios_anchor->struct_table_address, + smbios_anchor->struct_table_length); + + smbios_anchor = (struct smbios_entry *)buf; + smbios_anchor->struct_table_address = 0x20; + smbios_anchor->intermediate_checksum += + checksum(&smbios_anchor->intermediate_anchor, 0xf); + smbios_anchor->checksum += + checksum(smbios_anchor, smbios_anchor->length); + } + + filename = skip_whitespace(filename); + + ret = save_file(filename, buf, size); + + if (ret == EFI_SUCCESS) { + print(filename); + print(u" written\r\n"); + } + + bs->free_pool(buf); + + return ret; +} + +/** + * get_load_options() - get load options + * + * Return: load options or NULL + */ +static u16 *get_load_options(void) +{ + efi_status_t ret; + struct efi_loaded_image *loaded_image; + + ret = bs->open_protocol(handle, &loaded_image_guid, + (void **)&loaded_image, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) { + error(u"Loaded image protocol not found\r\n"); + return NULL; + } + + if (!loaded_image->load_options_size || !loaded_image->load_options) + return NULL; + + return loaded_image->load_options; +} + +/** + * command_loop - process user commands + */ +static void command_loop(void) +{ + for (;;) { + u16 command[BUFFER_SIZE]; + u16 *pos; + efi_uintn_t ret; + + print(u"=> "); + ret = efi_input(command, sizeof(command)); + if (ret == EFI_ABORTED) + break; + pos = skip_whitespace(command); + if (starts_with(pos, u"exit")) { + break; + } else if (starts_with(pos, u"check")) { + ret = do_check(); + if (ret == EFI_SUCCESS) + print(u"OK\n"); + } else if (starts_with(pos, u"save ")) { + do_save(pos + 5); + } else { + do_help(); + } + } +} + +/** + * efi_main() - entry point of the EFI application. + * + * @handle: handle of the loaded image + * @systab: system table + * Return: status code + */ +efi_status_t EFIAPI efi_main(efi_handle_t image_handle, + struct efi_system_table *systab) +{ + u16 *load_options; + + handle = image_handle; + systable = systab; + cerr = systable->std_err; + cout = systable->con_out; + cin = systable->con_in; + bs = systable->boottime; + load_options = get_load_options(); + + if (starts_with(load_options, u"nocolor")) + nocolor = true; + + color(EFI_WHITE); + cls(); + print(u"SMBIOS Dump\r\n===========\r\n\r\n"); + color(EFI_LIGHTBLUE); + + command_loop(); + + color(EFI_LIGHTGRAY); + cls(); + + return EFI_SUCCESS; +} diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c index b578c308408..e1180efae18 100644 --- a/lib/smbios-parser.c +++ b/lib/smbios-parser.c @@ -5,22 +5,11 @@ #define LOG_CATEGORY LOGC_BOOT +#include <errno.h> #include <smbios.h> - -static inline int verify_checksum(const struct smbios_entry *e) -{ - /* - * Checksums for SMBIOS tables are calculated to have a value, so that - * the sum over all bytes yields zero (using unsigned 8 bit arithmetic). - */ - u8 *byte = (u8 *)e; - u8 sum = 0; - - for (int i = 0; i < e->length; i++) - sum += byte[i]; - - return sum; -} +#include <string.h> +#include <tables_csum.h> +#include <linux/kernel.h> const struct smbios_entry *smbios_entry(u64 address, u32 size) { @@ -32,7 +21,7 @@ const struct smbios_entry *smbios_entry(u64 address, u32 size) if (memcmp(entry->anchor, "_SM_", 4)) return NULL; - if (verify_checksum(entry)) + if (table_compute_checksum(entry, entry->length)) return NULL; return entry; diff --git a/lib/smbios.c b/lib/smbios.c index d9d52bd58d7..41aa936c4c4 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -467,7 +467,8 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, } #endif - t->processor_family = processor_family; + t->processor_family = 0xfe; + t->processor_family2 = processor_family; t->processor_manufacturer = smbios_add_prop(ctx, NULL, vendor); t->processor_version = smbios_add_prop(ctx, NULL, name); } @@ -489,7 +490,6 @@ static int smbios_write_type4(ulong *current, int handle, t->l1_cache_handle = 0xffff; t->l2_cache_handle = 0xffff; t->l3_cache_handle = 0xffff; - t->processor_family2 = t->processor_family; len = t->length + smbios_string_table_len(ctx); *current += len; diff --git a/lib/tables_csum.c b/lib/tables_csum.c index 636aa596768..305b1ec31c5 100644 --- a/lib/tables_csum.c +++ b/lib/tables_csum.c @@ -5,9 +5,9 @@ #include <linux/types.h> -u8 table_compute_checksum(void *v, int len) +u8 table_compute_checksum(const void *v, const int len) { - u8 *bytes = v; + const u8 *bytes = v; u8 checksum = 0; int i; |