From 42ef7079224abc7c6073c0bab63f3aa6fffd5d00 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 25 Jun 2019 23:52:04 +0300 Subject: [PATCH 01/19] x86: edison: Enable SD slot Enable SD slot on Intel Edison platform. By default firmware doesn't put device on active state. Thus, we have to do this explicitly. Signed-off-by: Andy Shevchenko Reviewed-by: Bin Meng --- arch/x86/dts/edison.dts | 5 ----- board/intel/edison/edison.c | 10 ++++++++++ configs/edison_defconfig | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/x86/dts/edison.dts b/arch/x86/dts/edison.dts index c0487656d3..df24aa0d26 100644 --- a/arch/x86/dts/edison.dts +++ b/arch/x86/dts/edison.dts @@ -84,15 +84,10 @@ reg = <0xff3fc000 0x1000>; }; -/* - * FIXME: For now U-Boot DM model doesn't allow to power up this controller. - * Enabling it will make U-Boot hang. - * sdcard: mmc@ff3fa000 { compatible = "intel,sdhci-tangier"; reg = <0xff3fa000 0x1000>; }; - */ pmu: power@ff00b000 { compatible = "intel,pmu-mid"; diff --git a/board/intel/edison/edison.c b/board/intel/edison/edison.c index 5faf3c57f2..d80ee3aa8a 100644 --- a/board/intel/edison/edison.c +++ b/board/intel/edison/edison.c @@ -13,9 +13,19 @@ #include #include +#include #include #include +/* List of Intel Tangier LSSs */ +#define PMU_LSS_TANGIER_SDIO0_01 1 + +int board_early_init_r(void) +{ + pmu_turn_power(PMU_LSS_TANGIER_SDIO0_01, true); + return 0; +} + static struct dwc3_device dwc3_device_data = { .maximum_speed = USB_SPEED_HIGH, .base = CONFIG_SYS_USB_OTG_BASE, diff --git a/configs/edison_defconfig b/configs/edison_defconfig index 468754493e..cac6e4201f 100644 --- a/configs/edison_defconfig +++ b/configs/edison_defconfig @@ -4,6 +4,7 @@ CONFIG_NR_DRAM_BANKS=3 CONFIG_VENDOR_INTEL=y CONFIG_TARGET_EDISON=y CONFIG_SMP=y +CONFIG_BOARD_EARLY_INIT_R=y CONFIG_LAST_STAGE_INIT=y CONFIG_HUSH_PARSER=y # CONFIG_CMDLINE_EDITING is not set From 00f237e226bc8a6ecf168ca0d2e1853f203f17d1 Mon Sep 17 00:00:00 2001 From: Joshua Watt Date: Wed, 3 Jul 2019 12:45:32 -0500 Subject: [PATCH 02/19] qemu-x86: Use config_distro_bootcmd Converts qemu x86 machines to boot using distro_config. The intent is to allow u-boot in qemu to be maximally compatible with many boot methods without having to change the config. Previously, u-boot would only boot in a very limited set of circumstances where there was a /boot/vmlinuz on scsi 0:3 with no ramdisk. Signed-off-by: Joshua Watt Reviewed-by: Bin Meng [bmeng: convert doc updates to reST] Signed-off-by: Bin Meng --- configs/qemu-x86_64_defconfig | 1 + configs/qemu-x86_defconfig | 1 + doc/board/emulation/qemu-x86.rst | 17 +++++++++++++++++ include/configs/qemu-x86.h | 25 +++++++++++++++++++++++++ 4 files changed, 44 insertions(+) diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 532611f4a9..53d9c8cf82 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -12,6 +12,7 @@ CONFIG_SMP=y CONFIG_GENERATE_PIRQ_TABLE=y CONFIG_GENERATE_MP_TABLE=y CONFIG_GENERATE_ACPI_TABLE=y +CONFIG_DISTRO_DEFAULTS=y CONFIG_BUILD_ROM=y CONFIG_FIT=y CONFIG_SPL_LOAD_FIT=y diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index ef85c52592..ad56135401 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -6,6 +6,7 @@ CONFIG_SMP=y CONFIG_GENERATE_PIRQ_TABLE=y CONFIG_GENERATE_MP_TABLE=y CONFIG_GENERATE_ACPI_TABLE=y +CONFIG_DISTRO_DEFAULTS=y CONFIG_BUILD_ROM=y CONFIG_FIT=y CONFIG_BOOTSTAGE=y diff --git a/doc/board/emulation/qemu-x86.rst b/doc/board/emulation/qemu-x86.rst index c2e704afb2..db842f2ece 100644 --- a/doc/board/emulation/qemu-x86.rst +++ b/doc/board/emulation/qemu-x86.rst @@ -54,6 +54,23 @@ If you want to check both consoles, use '-serial stdio'. Multicore is also supported by QEMU via '-smp n' where n is the number of cores to instantiate. Note, the maximum supported CPU number in QEMU is 255. +U-Boot uses 'distro_bootcmd' by default when booting on x86 QEMU. This tries to +load a boot script, kernel, and ramdisk from several different interfaces. For +the default boot order, see 'qemu-x86.h'. For more information, see +'README.distro'. Most Linux distros can be booted by writing a uboot script. +For example, Debian (stretch) can be booted by creating a script file named +'boot.txt' with the contents:: + + setenv bootargs root=/dev/sda1 ro + load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} /vmlinuz + load ${devtype} ${devnum}:${distro_bootpart} ${ramdisk_addr_r} /initrd.img + zboot ${kernel_addr_r} - ${ramdisk_addr_r} ${filesize} + +Then compile and install it with:: + + $ apt install u-boot-tools && \ + mkimage -T script -C none -n "Boot script" -d boot.txt /boot/boot.scr + The fw_cfg interface in QEMU also provides information about kernel data, initrd, command-line arguments and more. U-Boot supports directly accessing these informtion from fw_cfg interface, which saves the time of loading them diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h index 64e7a60b8a..097ed414f8 100644 --- a/include/configs/qemu-x86.h +++ b/include/configs/qemu-x86.h @@ -10,8 +10,33 @@ #ifndef __CONFIG_H #define __CONFIG_H +#include + +#define BOOT_TARGET_DEVICES(func) \ + func(USB, usb, 0) \ + func(SCSI, scsi, 0) \ + func(VIRTIO, virtio, 0) \ + func(IDE, ide, 0) \ + func(DHCP, dhcp, na) + +#include #include +#undef CONFIG_ENV_SIZE +#define CONFIG_ENV_SIZE SZ_256K + +#define CONFIG_PREBOOT "pci enum" + +#undef CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS \ + CONFIG_STD_DEVICES_SETTINGS \ + "scriptaddr=0x7000000\0" \ + "kernel_addr_r=0x1000000\0" \ + "ramdisk_addr_r=0x4000000\0" \ + "consoledev=ttyS0\0" \ + CONFIG_OTHBOOTARGS \ + BOOTENV + #define CONFIG_SYS_MONITOR_LEN (1 << 20) #define CONFIG_STD_DEVICES_SETTINGS "stdin=serial,i8042-kbd\0" \ From 68d70a1cf6f0d4f7f013af1652b1525042f38daf Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 28 Jul 2019 08:13:58 -0700 Subject: [PATCH 03/19] x86: qemu: Fix non-working ramboot and nfsboot environment variables With qemu-x86 starting to use config_distro_bootcmd, the pre-defined ramboot and nfsboot commands do not work any more. This is caused by undefined environment variable 'ramdiskaddr' that was previously set in CONFIG_EXTRA_ENV_SETTINGS but later CONFIG_EXTRA_ENV_SETTINGS was redefined for distro boot. Update the x86 generic CONFIG_EXTRA_ENV_SETTINGS to consider distro boot, and remove the one in qemu-x86.h. Signed-off-by: Bin Meng --- include/configs/qemu-x86.h | 10 ---------- include/configs/x86-common.h | 21 ++++++++++++++------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h index 097ed414f8..c5574201dd 100644 --- a/include/configs/qemu-x86.h +++ b/include/configs/qemu-x86.h @@ -27,16 +27,6 @@ #define CONFIG_PREBOOT "pci enum" -#undef CONFIG_EXTRA_ENV_SETTINGS -#define CONFIG_EXTRA_ENV_SETTINGS \ - CONFIG_STD_DEVICES_SETTINGS \ - "scriptaddr=0x7000000\0" \ - "kernel_addr_r=0x1000000\0" \ - "ramdisk_addr_r=0x4000000\0" \ - "consoledev=ttyS0\0" \ - CONFIG_OTHBOOTARGS \ - BOOTENV - #define CONFIG_SYS_MONITOR_LEN (1 << 20) #define CONFIG_STD_DEVICES_SETTINGS "stdin=serial,i8042-kbd\0" \ diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h index c4deef80af..ca27a4f9e2 100644 --- a/include/configs/x86-common.h +++ b/include/configs/x86-common.h @@ -105,30 +105,37 @@ #define CONFIG_OTHBOOTARGS "othbootargs=acpi=off\0" #endif +#ifndef CONFIG_DISTRO_DEFAULTS +#define BOOTENV +#endif + #define CONFIG_EXTRA_ENV_SETTINGS \ CONFIG_STD_DEVICES_SETTINGS \ "pciconfighost=1\0" \ "netdev=eth0\0" \ "consoledev=ttyS0\0" \ CONFIG_OTHBOOTARGS \ - "ramdiskaddr=0x4000000\0" \ - "ramdiskfile=initramfs.gz\0" + "scriptaddr=0x7000000\0" \ + "kernel_addr_r=0x1000000\0" \ + "ramdisk_addr_r=0x4000000\0" \ + "ramdiskfile=initramfs.gz\0" \ + BOOTENV #define CONFIG_RAMBOOTCOMMAND \ "setenv bootargs root=/dev/ram rw " \ "ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off " \ "console=$consoledev,$baudrate $othbootargs;" \ - "tftpboot $loadaddr $bootfile;" \ - "tftpboot $ramdiskaddr $ramdiskfile;" \ - "zboot $loadaddr 0 $ramdiskaddr $filesize" + "tftpboot $kernel_addr_r $bootfile;" \ + "tftpboot $ramdisk_addr_r $ramdiskfile;" \ + "zboot $kernel_addr_r 0 $ramdisk_addr_r $filesize" #define CONFIG_NFSBOOTCOMMAND \ "setenv bootargs root=/dev/nfs rw " \ "nfsroot=$serverip:$rootpath " \ "ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off " \ "console=$consoledev,$baudrate $othbootargs;" \ - "tftpboot $loadaddr $bootfile;" \ - "zboot $loadaddr" + "tftpboot $kernel_addr_r $bootfile;" \ + "zboot $kernel_addr_r" #endif /* __CONFIG_H */ From eef30079454c744ad1c9d4202ac2e4066986ffec Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 14 Jul 2019 19:23:56 +0300 Subject: [PATCH 04/19] x86: acpi: Add CSRT description Add CSRT [1] description as it provided in Linux kernel. [1]: http://www.uefi.org/sites/default/files/resources/CSRT%20v2.pdf Signed-off-by: Andy Shevchenko Reviewed-by: Bin Meng --- arch/x86/include/asm/acpi_table.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index e3b65cff66..a70abd5d75 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -303,6 +303,37 @@ struct acpi_mcfg_mmconfig { /* ACPI global NVS structure */ struct acpi_global_nvs; +/* CSRT (Core System Resource Table) */ +struct acpi_csrt { + struct acpi_table_header header; +}; + +struct acpi_csrt_group { + u32 length; + u32 vendor_id; + u32 subvendor_id; + u16 device_id; + u16 subdevice_id; + u16 revision; + u16 reserved; + u32 shared_info_length; +}; + +struct acpi_csrt_shared_info { + u16 major_version; + u16 minor_version; + u32 mmio_base_low; + u32 mmio_base_high; + u32 gsi_interrupt; + u8 interrupt_polarity; + u8 interrupt_mode; + u8 num_channels; + u8 dma_address_width; + u16 base_request_line; + u16 num_handshake_signals; + u32 max_block_size; +}; + /* DBG2 definitions are partially used for SPCR interface_type */ /* Types for port_type field */ From ddd2a4244c26068ae1a4e3161b21b738a8bec46e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 14 Jul 2019 19:23:57 +0300 Subject: [PATCH 05/19] x86: acpi: Introduce a stub to generate CSRT Here is a stub function that generates an empty CSRT. If the target platform provides acpi_fill_csrt() function, it will be used to populate the table. Signed-off-by: Andy Shevchenko Reviewed-by: Bin Meng --- arch/x86/include/asm/acpi_table.h | 1 + arch/x86/lib/acpi_table.c | 32 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index a70abd5d75..02aea127c1 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -401,6 +401,7 @@ u32 acpi_fill_madt(u32 current); int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base, u16 seg_nr, u8 start, u8 end); u32 acpi_fill_mcfg(u32 current); +u32 acpi_fill_csrt(u32 current); void acpi_create_gnvs(struct acpi_global_nvs *gnvs); ulong write_acpi_tables(ulong start); diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 270274f6b3..0d69cf271f 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -337,6 +337,30 @@ static void acpi_create_mcfg(struct acpi_mcfg *mcfg) header->checksum = table_compute_checksum((void *)mcfg, header->length); } +__weak u32 acpi_fill_csrt(u32 current) +{ + return current; +} + +static void acpi_create_csrt(struct acpi_csrt *csrt) +{ + struct acpi_table_header *header = &(csrt->header); + u32 current = (u32)csrt + sizeof(struct acpi_csrt); + + memset((void *)csrt, 0, sizeof(struct acpi_csrt)); + + /* Fill out header fields */ + acpi_fill_header(header, "CSRT"); + header->length = sizeof(struct acpi_csrt); + header->revision = 0; + + current = acpi_fill_csrt(current); + + /* (Re)calculate length and checksum */ + header->length = current - (u32)csrt; + header->checksum = table_compute_checksum((void *)csrt, header->length); +} + static void acpi_create_spcr(struct acpi_spcr *spcr) { struct acpi_table_header *header = &(spcr->header); @@ -464,6 +488,7 @@ ulong write_acpi_tables(ulong start) struct acpi_fadt *fadt; struct acpi_mcfg *mcfg; struct acpi_madt *madt; + struct acpi_csrt *csrt; struct acpi_spcr *spcr; int i; @@ -553,6 +578,13 @@ ulong write_acpi_tables(ulong start) acpi_add_table(rsdp, mcfg); current = ALIGN(current, 16); + debug("ACPI: * CSRT\n"); + csrt = (struct acpi_csrt *)current; + acpi_create_csrt(csrt); + current += csrt->header.length; + acpi_add_table(rsdp, csrt); + current = ALIGN(current, 16); + debug("ACPI: * SPCR\n"); spcr = (struct acpi_spcr *)current; acpi_create_spcr(spcr); From e3be52ceac7fab098c47d1b7fd2f1456e8e43f7e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 14 Jul 2019 19:23:58 +0300 Subject: [PATCH 06/19] x86: acpi: Enable ACPI companion for Intel iDMA 32-bit ACPI has a capability to specify DMA parameters for DMA channel consumers. To enable this for Intel Edison, describe GP DMA device in ACPI table in order to get an ACPI handle to it in OS. This works in conjunction with CSRT, which must be in align with DSDT. Signed-off-by: Andy Shevchenko Reviewed-by: Bin Meng --- .../asm/arch-tangier/acpi/southcluster.asl | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl index 8b5b709045..b8b783b82e 100644 --- a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl +++ b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl @@ -421,6 +421,28 @@ Device (PCI0) } } } + + Device (GDMA) + { + Name (_ADR, 0x00150000) + Name (_HID, "808611A2") + Name (_UID, Zero) + + Method (_STA, 0, NotSerialized) + { + Return (STA_VISIBLE) + } + + Method (_CRS, 0, Serialized) + { + Name (RBUF, ResourceTemplate () + { + Memory32Fixed(ReadWrite, 0xFF192000, 0x00001000) + Interrupt(ResourceConsumer, Level, ActiveHigh, Shared, ,, ) { 32 } + }) + Return (RBUF) + } + } } Device (FLIS) From 5e99fde34a77b0a2e8e7b171225e638c4cbe6f1b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 14 Jul 2019 19:23:59 +0300 Subject: [PATCH 07/19] x86: tangier: Populate CSRT for shared DMA controller Intel Tangier has a shared DMA controller that, according to Microsoft spec, has to be presented in CSRT table. Signed-off-by: Andy Shevchenko Reviewed-by: Bin Meng --- arch/x86/cpu/tangier/acpi.c | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/arch/x86/cpu/tangier/acpi.c b/arch/x86/cpu/tangier/acpi.c index 0e4f961c53..61b2642aa9 100644 --- a/arch/x86/cpu/tangier/acpi.c +++ b/arch/x86/cpu/tangier/acpi.c @@ -68,6 +68,44 @@ u32 acpi_fill_mcfg(u32 current) return current; } +static u32 acpi_fill_csrt_dma(struct acpi_csrt_group *grp) +{ + struct acpi_csrt_shared_info *si = (struct acpi_csrt_shared_info *)&grp[1]; + + /* Fill the Resource Group with Shared Information attached */ + memset(grp, 0, sizeof(*grp)); + grp->shared_info_length = sizeof(struct acpi_csrt_shared_info); + grp->length = sizeof(struct acpi_csrt_group) + grp->shared_info_length; + /* TODO: All values below should come from U-Boot DT somehow */ + sprintf((char *)&grp->vendor_id, "%04X", 0x8086); + grp->device_id = 0x11a2; + + /* Fill the Resource Group Shared Information */ + memset(si, 0, sizeof(*si)); + si->major_version = 1; + si->minor_version = 0; + /* TODO: All values below should come from U-Boot DT somehow */ + si->mmio_base_low = 0xff192000; + si->mmio_base_high = 0; + si->gsi_interrupt = 32; + si->interrupt_polarity = 1; + si->interrupt_mode = 0; + si->num_channels = 8; + si->dma_address_width = 32; + si->base_request_line = 0; + si->num_handshake_signals = 16; + si->max_block_size = 0x20000; + + return grp->length; +} + +u32 acpi_fill_csrt(u32 current) +{ + current += acpi_fill_csrt_dma((struct acpi_csrt_group *)current); + + return current; +} + void acpi_create_gnvs(struct acpi_global_nvs *gnvs) { struct udevice *dev; From c1865bbd166eed8913afe3b66c8b28b7c83a46fc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 28 Jul 2019 14:16:28 -0600 Subject: [PATCH 08/19] x86: Avoid writing temporary asl files into the source tree At present the iasl tool (Intel ACPI (Advanced Configuration and Power Interface) Source Language Compiler) is called in such a way that it uses the source directory for its temporary files. This means we end up with these files when building x86 boards: board/dfi/dfi-bt700/dsdt.aml board/dfi/dfi-bt700/dsdt.asl.tmp Update the code to put temporary files in the target directory instead. The iasl tool is quite confusing since it generates files with different extensions and does not allow these to be individually specified. Add some documentation to help with this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng [bmeng: remove dsdt.hex from 'make clean' rules and correct U-Boot spelling] Signed-off-by: Bin Meng --- scripts/Makefile.lib | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 2f5e28cac3..ef116e0e0a 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -395,11 +395,22 @@ $(obj)/%_efi.so: $(obj)/%.o $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_free # ACPI # --------------------------------------------------------------------------- +# +# This first sends the file (typically dsdt.asl) through the preprocessor +# resolve includes and any CONFIG options used. This produces dsdt.asl.tmp +# which is pure ASL code. The Intel ASL (ACPI (Advanced Configuration and Power +# Interface) Source Language compiler (iasl) then converts this ASL code into a +# C file containing the hex data to build into U-Boot. This file is called +# dsdt.hex (despite us setting the prefix to .../dsdt.asl.tmp) so must be +# renamed to dsdt.c for consumption by the build system. +ASL_TMP = $(patsubst %.c,%.asl.tmp,$@) + quiet_cmd_acpi_c_asl= ASL $< cmd_acpi_c_asl= \ - $(CPP) -x assembler-with-cpp -D__ASSEMBLY__ -P $(UBOOTINCLUDE) -o $<.tmp $<; \ - iasl -p $< -tc $<.tmp $(if $(KBUILD_VERBOSE:1=), >/dev/null) && \ - mv $(patsubst %.asl,%.hex,$<) $@ + $(CPP) -x assembler-with-cpp -D__ASSEMBLY__ -P $(UBOOTINCLUDE) \ + -o $(ASL_TMP) $< && \ + iasl -p $@ -tc $(ASL_TMP) $(if $(KBUILD_VERBOSE:1=), >/dev/null) && \ + mv $(patsubst %.c,%.hex,$@) $@ $(obj)/dsdt.c: $(src)/dsdt.asl $(call cmd,acpi_c_asl) From fd95e1017897474b18ac1a4a7915bf8e59ec204f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 1 Aug 2019 19:37:08 +0200 Subject: [PATCH 09/19] bios_emulator: remove stray break Remove a stray break which suppresses some debug messages. Indicated by cppcheck. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Acked-by: Bin Meng --- drivers/bios_emulator/atibios.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c index 4f362d1453..fb806b53d4 100644 --- a/drivers/bios_emulator/atibios.c +++ b/drivers/bios_emulator/atibios.c @@ -136,7 +136,6 @@ static int atibios_debug_mode(BE_VGAInfo *vga_info, RMREGS *regs, bool linear_ok; int attr; - break; debug("Mode %x: ", mode); memset(buffer, '\0', sizeof(struct vbe_mode_info)); regs->e.eax = VESA_GET_MODE_INFO; From 0709ddb68fed4dbeae09d919fc54d7235918d47b Mon Sep 17 00:00:00 2001 From: Bernhard Messerklinger Date: Fri, 2 Aug 2019 08:38:34 +0200 Subject: [PATCH 10/19] x86: ich-spi: Convert driver to spi-mem ops With the introduction of the new spi-mem model operations changed slightly. The new spi-mem operations make things a bit easier to handle for ich-spi flash interface. This patch converts the ich-spi driver by using spi-mem operations. Signed-off-by: Bernhard Messerklinger Reviewed-by: Bin Meng Tested on Intel CrownBay and MinnowMax Tested-by: Bin Meng [bmeng: fix compiler warnings when building the driver for 64-bit] Signed-off-by: Bin Meng --- drivers/spi/ich.c | 274 +++++++++++++++++----------------------------- drivers/spi/ich.h | 9 +- 2 files changed, 103 insertions(+), 180 deletions(-) diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index 03531a8c0c..fbb58c783e 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "ich.h" @@ -171,18 +173,6 @@ static int ich_init_controller(struct udevice *dev, return 0; } -static inline void spi_use_out(struct spi_trans *trans, unsigned bytes) -{ - trans->out += bytes; - trans->bytesout -= bytes; -} - -static inline void spi_use_in(struct spi_trans *trans, unsigned bytes) -{ - trans->in += bytes; - trans->bytesin -= bytes; -} - static void spi_lock_down(struct ich_spi_platdata *plat, void *sbase) { if (plat->ich_version == ICHV_7) { @@ -213,47 +203,12 @@ static bool spi_lock_status(struct ich_spi_platdata *plat, void *sbase) return lock != 0; } -static void spi_setup_type(struct spi_trans *trans, int data_bytes) -{ - trans->type = 0xFF; - - /* Try to guess spi type from read/write sizes */ - if (trans->bytesin == 0) { - if (trans->bytesout + data_bytes > 4) - /* - * If bytesin = 0 and bytesout > 4, we presume this is - * a write data operation, which is accompanied by an - * address. - */ - trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS; - else - trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS; - return; - } - - if (trans->bytesout == 1) { /* and bytesin is > 0 */ - trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS; - return; - } - - if (trans->bytesout == 4) /* and bytesin is > 0 */ - trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; - - /* Fast read command is called with 5 bytes instead of 4 */ - if (trans->out[0] == SPI_OPCODE_FAST_READ && trans->bytesout == 5) { - trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; - --trans->bytesout; - } -} - static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans, bool lock) { uint16_t optypes; uint8_t opmenu[ctlr->menubytes]; - trans->opcode = trans->out[0]; - spi_use_out(trans, 1); if (!lock) { /* The lock is off, so just use index 0. */ ich_writeb(ctlr, trans->opcode, ctlr->opmenu); @@ -285,12 +240,7 @@ static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans, optypes = ich_readw(ctlr, ctlr->optype); optype = (optypes >> (opcode_index * 2)) & 0x3; - if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS && - optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS && - trans->bytesout >= 3) { - /* We guessed wrong earlier. Fix it up. */ - trans->type = optype; - } + if (optype != trans->type) { printf("ICH SPI: Transaction doesn't fit type %d\n", optype); @@ -300,26 +250,6 @@ static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans, } } -static int spi_setup_offset(struct spi_trans *trans) -{ - /* Separate the SPI address and data */ - switch (trans->type) { - case SPI_OPCODE_TYPE_READ_NO_ADDRESS: - case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS: - return 0; - case SPI_OPCODE_TYPE_READ_WITH_ADDRESS: - case SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS: - trans->offset = ((uint32_t)trans->out[0] << 16) | - ((uint32_t)trans->out[1] << 8) | - ((uint32_t)trans->out[2] << 0); - spi_use_out(trans, 3); - return 1; - default: - printf("Unrecognized SPI transaction type %#x\n", trans->type); - return -EPROTO; - } -} - /* * Wait for up to 6s til status register bit(s) turn 1 (in case wait_til_set * below is true) or 0. In case the wait was for the bit(s) to set - write @@ -350,7 +280,7 @@ static int ich_status_poll(struct ich_spi_priv *ctlr, u16 bitmask, return -ETIMEDOUT; } -void ich_spi_config_opcode(struct udevice *dev) +static void ich_spi_config_opcode(struct udevice *dev) { struct ich_spi_priv *ctlr = dev_get_priv(dev); @@ -365,90 +295,38 @@ void ich_spi_config_opcode(struct udevice *dev) ich_writel(ctlr, SPI_OPMENU_UPPER, ctlr->opmenu + sizeof(u32)); } -static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) +static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) { - struct udevice *bus = dev_get_parent(dev); + struct udevice *bus = dev_get_parent(slave->dev); struct ich_spi_platdata *plat = dev_get_platdata(bus); struct ich_spi_priv *ctlr = dev_get_priv(bus); uint16_t control; int16_t opcode_index; int with_address; int status; - int bytes = bitlen / 8; struct spi_trans *trans = &ctlr->trans; - unsigned type = flags & (SPI_XFER_BEGIN | SPI_XFER_END); - int using_cmd = 0; bool lock = spi_lock_status(plat, ctlr->base); - int ret; + int ret = 0; - /* We don't support writing partial bytes */ - if (bitlen % 8) { - debug("ICH SPI: Accessing partial bytes not supported\n"); - return -EPROTONOSUPPORT; - } + trans->in = NULL; + trans->out = NULL; + trans->type = 0xFF; - /* An empty end transaction can be ignored */ - if (type == SPI_XFER_END && !dout && !din) - return 0; - - if (type & SPI_XFER_BEGIN) - memset(trans, '\0', sizeof(*trans)); - - /* Dp we need to come back later to finish it? */ - if (dout && type == SPI_XFER_BEGIN) { - if (bytes > ICH_MAX_CMD_LEN) { - debug("ICH SPI: Command length limit exceeded\n"); - return -ENOSPC; + if (op->data.nbytes) { + if (op->data.dir == SPI_MEM_DATA_IN) { + trans->in = op->data.buf.in; + trans->bytesin = op->data.nbytes; + } else { + trans->out = op->data.buf.out; + trans->bytesout = op->data.nbytes; } - memcpy(trans->cmd, dout, bytes); - trans->cmd_len = bytes; - debug_trace("ICH SPI: Saved %d bytes\n", bytes); + } + + if (trans->opcode != op->cmd.opcode) + trans->opcode = op->cmd.opcode; + + if (lock && trans->opcode == SPI_OPCODE_WRDIS) return 0; - } - - /* - * We process a 'middle' spi_xfer() call, which has no - * SPI_XFER_BEGIN/END, as an independent transaction as if it had - * an end. We therefore repeat the command. This is because ICH - * seems to have no support for this, or because interest (in digging - * out the details and creating a special case in the code) is low. - */ - if (trans->cmd_len) { - trans->out = trans->cmd; - trans->bytesout = trans->cmd_len; - using_cmd = 1; - debug_trace("ICH SPI: Using %d bytes\n", trans->cmd_len); - } else { - trans->out = dout; - trans->bytesout = dout ? bytes : 0; - } - - trans->in = din; - trans->bytesin = din ? bytes : 0; - - /* There has to always at least be an opcode */ - if (!trans->bytesout) { - debug("ICH SPI: No opcode for transfer\n"); - return -EPROTO; - } - - ret = ich_status_poll(ctlr, SPIS_SCIP, 0); - if (ret < 0) - return ret; - - if (plat->ich_version == ICHV_7) - ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status); - else - ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status); - - spi_setup_type(trans, using_cmd ? bytes : 0); - opcode_index = spi_setup_opcode(ctlr, trans, lock); - if (opcode_index < 0) - return -EINVAL; - with_address = spi_setup_offset(trans); - if (with_address < 0) - return -EINVAL; if (trans->opcode == SPI_OPCODE_WREN) { /* @@ -461,6 +339,40 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, return 0; } + ret = ich_status_poll(ctlr, SPIS_SCIP, 0); + if (ret < 0) + return ret; + + if (plat->ich_version == ICHV_7) + ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status); + else + ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status); + + /* Try to guess spi transaction type */ + if (op->data.dir == SPI_MEM_DATA_OUT) { + if (op->addr.nbytes) + trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS; + else + trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS; + } else { + if (op->addr.nbytes) + trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; + else + trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS; + } + /* Special erase case handling */ + if (op->addr.nbytes && !op->data.buswidth) + trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS; + + opcode_index = spi_setup_opcode(ctlr, trans, lock); + if (opcode_index < 0) + return -EINVAL; + + if (op->addr.nbytes) { + trans->offset = op->addr.val; + with_address = 1; + } + if (ctlr->speed && ctlr->max_speed >= 33000000) { int byte; @@ -472,13 +384,6 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, ich_writeb(ctlr, byte, ctlr->speed); } - /* See if we have used up the command data */ - if (using_cmd && dout && bytes) { - trans->out = dout; - trans->bytesout = bytes; - debug_trace("ICH SPI: Moving to data, %d bytes\n", bytes); - } - /* Preset control fields */ control = SPIC_SCGO | ((opcode_index & 0x07) << 4); @@ -513,22 +418,6 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, return 0; } - /* - * Check if this is a write command atempting to transfer more bytes - * than the controller can handle. Iterations for writes are not - * supported here because each SPI write command needs to be preceded - * and followed by other SPI commands, and this sequence is controlled - * by the SPI chip driver. - */ - if (trans->bytesout > ctlr->databytes) { - debug("ICH SPI: Too much to write. This should be prevented by the driver's max_write_size?\n"); - return -EPROTO; - } - - /* - * Read or write up to databytes bytes at a time until everything has - * been sent. - */ while (trans->bytesout || trans->bytesin) { uint32_t data_length; @@ -543,9 +432,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, /* Program data into FDATA0 to N */ if (trans->bytesout) { write_reg(ctlr, trans->out, ctlr->data, data_length); - spi_use_out(trans, data_length); - if (with_address) - trans->offset += data_length; + trans->bytesout -= data_length; } /* Add proper control fields' values */ @@ -568,9 +455,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, if (trans->bytesin) { read_reg(ctlr, ctlr->data, trans->in, data_length); - spi_use_in(trans, data_length); - if (with_address) - trans->offset += data_length; + trans->bytesin -= data_length; } } @@ -581,6 +466,40 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, return 0; } +static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op) +{ + unsigned int page_offset; + int addr = op->addr.val; + unsigned int byte_count = op->data.nbytes; + + if (hweight32(ICH_BOUNDARY) == 1) { + page_offset = addr & (ICH_BOUNDARY - 1); + } else { + u64 aux = addr; + + page_offset = do_div(aux, ICH_BOUNDARY); + } + + if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) { + op->data.nbytes = min(ICH_BOUNDARY - page_offset, + slave->max_read_size); + } else if (slave->max_write_size) { + op->data.nbytes = min(ICH_BOUNDARY - page_offset, + slave->max_write_size); + } + + op->data.nbytes = min(op->data.nbytes, byte_count); + + return 0; +} + +static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + printf("ICH SPI: Only supports memory operations\n"); + return -1; +} + static int ich_spi_probe(struct udevice *dev) { struct ich_spi_platdata *plat = dev_get_platdata(dev); @@ -686,10 +605,17 @@ static int ich_spi_ofdata_to_platdata(struct udevice *dev) return ret; } +static const struct spi_controller_mem_ops ich_controller_mem_ops = { + .adjust_op_size = ich_spi_adjust_size, + .supports_op = NULL, + .exec_op = ich_spi_exec_op, +}; + static const struct dm_spi_ops ich_spi_ops = { .xfer = ich_spi_xfer, .set_speed = ich_spi_set_speed, .set_mode = ich_spi_set_mode, + .mem_ops = &ich_controller_mem_ops, /* * cs_info is not needed, since we require all chip selects to be * in the device tree explicitly diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h index a974241f98..3dfb2aaff1 100644 --- a/drivers/spi/ich.h +++ b/drivers/spi/ich.h @@ -100,13 +100,8 @@ enum { HSFC_FSMIE = 0x8000 }; -enum { - ICH_MAX_CMD_LEN = 5, -}; - struct spi_trans { - uint8_t cmd[ICH_MAX_CMD_LEN]; - int cmd_len; + uint8_t cmd; const uint8_t *out; uint32_t bytesout; uint8_t *in; @@ -166,6 +161,8 @@ struct spi_trans { #define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \ (SPI_OPMENU_1 << 8) | (SPI_OPMENU_0 << 0)) +#define ICH_BOUNDARY 0x1000 + enum ich_version { ICHV_7, ICHV_9, From 544293f87850b415721690533dae2d27f77f44f3 Mon Sep 17 00:00:00 2001 From: "Park, Aiden" Date: Sat, 3 Aug 2019 08:30:12 +0000 Subject: [PATCH 11/19] x86: Add new slimbootloader CPU type This slimbootloader CPU type is to enable U-Boot as a payload which runs on top of Slim Bootloader (https://github.com/slimbootloader). The Slim Bootloader is designed with multi-stage architecture for the execution from reset vector to OS booting, and supports QEMU, Apollolake, Whiskeylake and Coffeelake platforms consuming Intel FSP (https://github.com/IntelFsp) for silicon initialization including CAR and memory initialization. The Slim Bootloader generates new HOB (Hand Off Block) which are serial port info, memory map info, performance data info and so on, and passes it to a Payload. U-Boot as a payload will use these HOB information for basic initialization such as serial console. As an initial commit, - Add CONFIG_SYS_SLIMBOOTLOADER to enable slimbootloader CPU type - Add new arch/x86/cpu/slimbootloader directory with minimum codes - Get hob_list pointer from Slim Bootloader Signed-off-by: Aiden Park Reviewed-by: Bin Meng Reviewed-by: Andy Shevchenko Tested-by: Bin Meng --- arch/x86/Kconfig | 9 +++++++++ arch/x86/cpu/Makefile | 1 + arch/x86/cpu/slimbootloader/Kconfig | 19 ++++++++++++++++++ arch/x86/cpu/slimbootloader/Makefile | 5 +++++ arch/x86/cpu/slimbootloader/car.S | 14 +++++++++++++ arch/x86/cpu/slimbootloader/slimbootloader.c | 21 ++++++++++++++++++++ arch/x86/cpu/start.S | 6 ++++-- arch/x86/include/asm/global_data.h | 2 +- arch/x86/lib/asm-offsets.c | 2 +- 9 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 arch/x86/cpu/slimbootloader/Kconfig create mode 100644 arch/x86/cpu/slimbootloader/Makefile create mode 100644 arch/x86/cpu/slimbootloader/car.S create mode 100644 arch/x86/cpu/slimbootloader/slimbootloader.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 70f939869a..218e817cf3 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -115,6 +115,7 @@ source "arch/x86/cpu/efi/Kconfig" source "arch/x86/cpu/qemu/Kconfig" source "arch/x86/cpu/quark/Kconfig" source "arch/x86/cpu/queensbay/Kconfig" +source "arch/x86/cpu/slimbootloader/Kconfig" source "arch/x86/cpu/tangier/Kconfig" # architecture-specific options below @@ -344,9 +345,17 @@ config INTEL_ME_FILE The filename of the file to use as Intel Management Engine in the board directory. +config USE_HOB + bool "Use HOB (Hand-Off Block)" + help + Select this option to access HOB (Hand-Off Block) data structures + and parse HOBs. This HOB infra structure can be reused with + different solutions across different platforms. + config HAVE_FSP bool "Add an Firmware Support Package binary" depends on !EFI + select USE_HOB help Select this option to add an Firmware Support Package binary to the resulting U-Boot image. It is a binary blob which U-Boot uses diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 85fd5e616e..3f1f62da2b 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/ obj-$(CONFIG_INTEL_BRASWELL) += braswell/ obj-$(CONFIG_INTEL_BROADWELL) += broadwell/ obj-$(CONFIG_SYS_COREBOOT) += coreboot/ +obj-$(CONFIG_SYS_SLIMBOOTLOADER) += slimbootloader/ obj-$(CONFIG_EFI) += efi/ obj-$(CONFIG_QEMU) += qemu/ obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/ diff --git a/arch/x86/cpu/slimbootloader/Kconfig b/arch/x86/cpu/slimbootloader/Kconfig new file mode 100644 index 0000000000..3ea4c9958c --- /dev/null +++ b/arch/x86/cpu/slimbootloader/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2019 Intel Corporation + +config SYS_SLIMBOOTLOADER + bool + select USE_HOB + imply SYS_NS16550 + imply AHCI_PCI + imply SCSI + imply SCSI_AHCI + imply MMC + imply MMC_PCI + imply MMC_SDHCI + imply MMC_SDHCI_SDMA + imply USB + imply USB_EHCI_HCD + imply USB_XHCI_HCD + imply E1000 diff --git a/arch/x86/cpu/slimbootloader/Makefile b/arch/x86/cpu/slimbootloader/Makefile new file mode 100644 index 0000000000..627a721e8c --- /dev/null +++ b/arch/x86/cpu/slimbootloader/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2019 Intel Corporation + +obj-y += car.o slimbootloader.o diff --git a/arch/x86/cpu/slimbootloader/car.S b/arch/x86/cpu/slimbootloader/car.S new file mode 100644 index 0000000000..6e0304333c --- /dev/null +++ b/arch/x86/cpu/slimbootloader/car.S @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019 Intel Corporation + */ + +#include + +.section .text + +.globl car_init +car_init: + /* Get hob pointer parameter from previous stage's stack */ + mov 0x4(%esp), %esi + jmp car_init_ret diff --git a/arch/x86/cpu/slimbootloader/slimbootloader.c b/arch/x86/cpu/slimbootloader/slimbootloader.c new file mode 100644 index 0000000000..9f3a61ec61 --- /dev/null +++ b/arch/x86/cpu/slimbootloader/slimbootloader.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Intel Corporation + */ + +#include + +int arch_cpu_init(void) +{ + return x86_cpu_init_f(); +} + +int checkcpu(void) +{ + return 0; +} + +int print_cpuinfo(void) +{ + return default_print_cpuinfo(); +} diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 4a82add76b..71cd70f9cd 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -97,7 +97,7 @@ early_board_init_ret: jmp car_init .globl car_init_ret car_init_ret: -#ifndef CONFIG_HAVE_FSP +#ifndef CONFIG_USE_HOB /* * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, * or fully initialised SDRAM - we really don't care which) @@ -137,12 +137,13 @@ car_init_ret: /* Get address of global_data */ mov %fs:0, %edx -#ifdef CONFIG_HAVE_FSP +#ifdef CONFIG_USE_HOB /* Store the HOB list if we have one */ test %esi, %esi jz skip_hob movl %esi, GD_HOB_LIST(%edx) +#ifdef CONFIG_HAVE_FSP /* * After fsp_init() returns, the stack has already been switched to a * place within system memory as defined by CONFIG_FSP_TEMP_RAM_ADDR. @@ -151,6 +152,7 @@ car_init_ret: */ subl $CONFIG_FSP_SYS_MALLOC_F_LEN, %esp movl %esp, GD_MALLOC_BASE(%edx) +#endif skip_hob: #else /* Store table pointer */ diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 9398ec33b2..797397e697 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -83,7 +83,7 @@ struct arch_global_data { const struct pch_gpio_map *gpio_map; /* board GPIO map */ struct memory_info meminfo; /* Memory information */ struct pei_memory_info pei_meminfo; /* PEI memory information */ -#ifdef CONFIG_HAVE_FSP +#ifdef CONFIG_USE_HOB void *hob_list; /* FSP HOB list */ #endif struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS]; diff --git a/arch/x86/lib/asm-offsets.c b/arch/x86/lib/asm-offsets.c index 90dce22b25..47b38cd9e7 100644 --- a/arch/x86/lib/asm-offsets.c +++ b/arch/x86/lib/asm-offsets.c @@ -17,7 +17,7 @@ int main(void) { DEFINE(GD_BIST, offsetof(gd_t, arch.bist)); -#ifdef CONFIG_HAVE_FSP +#ifdef CONFIG_USE_HOB DEFINE(GD_HOB_LIST, offsetof(gd_t, arch.hob_list)); #endif DEFINE(GD_TABLE, offsetof(gd_t, arch.table)); From 5b931a508053b63b8596f6f65f211017b8a82394 Mon Sep 17 00:00:00 2001 From: "Park, Aiden" Date: Sat, 3 Aug 2019 08:30:20 +0000 Subject: [PATCH 12/19] x86: lib: fsp: Use EFI_GUID and efi_guid_t Use existing EFI_GUID and efi_guid_t instead of struct efi_guid. This is pre-work before making a common HOB library. - Change 'struct efi_guid' to efi_guit_t - Remove 'struct efi_guid' - Define GUIDs with EFI_GUID() macro - Use guidcmp() instead of compare_guid() - Remove compare_guid() Signed-off-by: Aiden Park Reviewed-by: Andy Shevchenko Reviewed-by: Bin Meng Tested on MinnowMax Tested-by: Bin Meng --- arch/x86/include/asm/fsp/fsp_ffs.h | 4 +- arch/x86/include/asm/fsp/fsp_fv.h | 4 +- arch/x86/include/asm/fsp/fsp_hob.h | 76 +++++++++++++------------ arch/x86/include/asm/fsp/fsp_support.h | 6 +- arch/x86/include/asm/fsp/fsp_types.h | 8 --- arch/x86/lib/fsp/fsp_support.c | 78 ++++++++++---------------- cmd/x86/fsp.c | 10 ++-- 7 files changed, 81 insertions(+), 105 deletions(-) diff --git a/arch/x86/include/asm/fsp/fsp_ffs.h b/arch/x86/include/asm/fsp/fsp_ffs.h index 61ce63c08e..b7558e5a17 100644 --- a/arch/x86/include/asm/fsp/fsp_ffs.h +++ b/arch/x86/include/asm/fsp/fsp_ffs.h @@ -45,7 +45,7 @@ struct __packed ffs_file_header { * This GUID is the file name. * It is used to uniquely identify the file. */ - struct efi_guid name; + efi_guid_t name; /* Used to verify the integrity of the file */ union ffs_integrity integrity; /* Identifies the type of file */ @@ -68,7 +68,7 @@ struct __packed ffs_file_header2 { * Name in any given firmware volume, except if the file type is * EFI_FV_FILE_TYPE_FFS_PAD. */ - struct efi_guid name; + efi_guid_t name; /* Used to verify the integrity of the file */ union ffs_integrity integrity; /* Identifies the type of file */ diff --git a/arch/x86/include/asm/fsp/fsp_fv.h b/arch/x86/include/asm/fsp/fsp_fv.h index 190aedcf44..511dfb78b8 100644 --- a/arch/x86/include/asm/fsp/fsp_fv.h +++ b/arch/x86/include/asm/fsp/fsp_fv.h @@ -80,7 +80,7 @@ struct fv_header { * Declares the file system with which the firmware volume * is formatted. */ - struct efi_guid fs_guid; + efi_guid_t fs_guid; /* * Length in bytes of the complete firmware volume, including * the header. @@ -128,7 +128,7 @@ struct fv_header { /* Extension header pointed by ExtHeaderOffset of volume header */ struct fv_ext_header { /* firmware volume name */ - struct efi_guid fv_name; + efi_guid_t fv_name; /* Size of the rest of the extension header including this structure */ u32 ext_hdr_size; }; diff --git a/arch/x86/include/asm/fsp/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h index 00657b62c7..843d7b513b 100644 --- a/arch/x86/include/asm/fsp/fsp_hob.h +++ b/arch/x86/include/asm/fsp/fsp_hob.h @@ -8,6 +8,7 @@ #define __FSP_HOB_H__ #include +#include /* Type of HOB Header */ #define HOB_TYPE_MEM_ALLOC 0x0002 @@ -40,7 +41,7 @@ struct hob_mem_alloc { * present for the memory allocation HOB. Type efi_guid is defined in * InstallProtocolInterface() in the UEFI 2.0 specification. */ - struct efi_guid name; + efi_guid_t name; /* * The base address of memory allocated by this HOB. * Type phys_addr_t is defined in AllocatePages() in the UEFI 2.0 @@ -106,7 +107,7 @@ struct hob_res_desc { * used by HOB consumer phase components to correlate device * ownership of a resource. */ - struct efi_guid owner; + efi_guid_t owner; u32 type; u32 attr; /* The physical start address of the resource region */ @@ -122,7 +123,7 @@ struct hob_res_desc { struct hob_guid { struct hob_header hdr; /* A GUID that defines the contents of this HOB */ - struct efi_guid name; + efi_guid_t name; /* GUID specific data goes here */ }; @@ -223,56 +224,57 @@ static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) #define FSP_GUID_DATA4_6 0x3f #define FSP_GUID_DATA4_7 0x0c +#define FSP_GUID_BYTE0 0xbe +#define FSP_GUID_BYTE1 0x40 +#define FSP_GUID_BYTE2 0x27 +#define FSP_GUID_BYTE3 0x91 +#define FSP_GUID_BYTE4 0x84 +#define FSP_GUID_BYTE5 0x22 +#define FSP_GUID_BYTE6 0x34 +#define FSP_GUID_BYTE7 0x47 +#define FSP_GUID_BYTE8 FSP_GUID_DATA4_0 +#define FSP_GUID_BYTE9 FSP_GUID_DATA4_1 +#define FSP_GUID_BYTE10 FSP_GUID_DATA4_2 +#define FSP_GUID_BYTE11 FSP_GUID_DATA4_3 +#define FSP_GUID_BYTE12 FSP_GUID_DATA4_4 +#define FSP_GUID_BYTE13 FSP_GUID_DATA4_5 +#define FSP_GUID_BYTE14 FSP_GUID_DATA4_6 +#define FSP_GUID_BYTE15 FSP_GUID_DATA4_7 + #define FSP_HEADER_GUID \ - { \ - FSP_GUID_DATA1, FSP_GUID_DATA2, FSP_GUID_DATA3, \ - { FSP_GUID_DATA4_0, FSP_GUID_DATA4_1, FSP_GUID_DATA4_2, \ - FSP_GUID_DATA4_3, FSP_GUID_DATA4_4, FSP_GUID_DATA4_5, \ - FSP_GUID_DATA4_6, FSP_GUID_DATA4_7 } \ - } + EFI_GUID(FSP_GUID_DATA1, FSP_GUID_DATA2, FSP_GUID_DATA3, \ + FSP_GUID_DATA4_0, FSP_GUID_DATA4_1, FSP_GUID_DATA4_2, \ + FSP_GUID_DATA4_3, FSP_GUID_DATA4_4, FSP_GUID_DATA4_5, \ + FSP_GUID_DATA4_6, FSP_GUID_DATA4_7) #define FSP_NON_VOLATILE_STORAGE_HOB_GUID \ - { \ - 0x721acf02, 0x4d77, 0x4c2a, \ - { 0xb3, 0xdc, 0x27, 0xb, 0x7b, 0xa9, 0xe4, 0xb0 } \ - } + EFI_GUID(0x721acf02, 0x4d77, 0x4c2a, \ + 0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0) #define FSP_BOOTLOADER_TEMP_MEM_HOB_GUID \ - { \ - 0xbbcff46c, 0xc8d3, 0x4113, \ - { 0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e } \ - } + EFI_GUID(0xbbcff46c, 0xc8d3, 0x4113, \ + 0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e) #define FSP_HOB_RESOURCE_OWNER_FSP_GUID \ - { \ - 0x69a79759, 0x1373, 0x4367, \ - { 0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e } \ - } + EFI_GUID(0x69a79759, 0x1373, 0x4367, \ + 0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e) #define FSP_HOB_RESOURCE_OWNER_TSEG_GUID \ - { \ - 0xd038747c, 0xd00c, 0x4980, \ - { 0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55 } \ - } + EFI_GUID(0xd038747c, 0xd00c, 0x4980, \ + 0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55) #define FSP_HOB_RESOURCE_OWNER_GRAPHICS_GUID \ - { \ - 0x9c7c3aa7, 0x5332, 0x4917, \ - { 0x82, 0xb9, 0x56, 0xa5, 0xf3, 0xe6, 0x2a, 0x07 } \ - } + EFI_GUID(0x9c7c3aa7, 0x5332, 0x4917, \ + 0x82, 0xb9, 0x56, 0xa5, 0xf3, 0xe6, 0x2a, 0x07) /* The following GUIDs are newly introduced in FSP spec 1.1 */ #define FSP_HOB_RESOURCE_OWNER_BOOTLOADER_TOLUM_GUID \ - { \ - 0x73ff4f56, 0xaa8e, 0x4451, \ - { 0xb3, 0x16, 0x36, 0x35, 0x36, 0x67, 0xad, 0x44 } \ - } + EFI_GUID(0x73ff4f56, 0xaa8e, 0x4451, \ + 0xb3, 0x16, 0x36, 0x35, 0x36, 0x67, 0xad, 0x44) #define FSP_GRAPHICS_INFO_HOB_GUID \ - { \ - 0x39f62cce, 0x6825, 0x4669, \ - { 0xbb, 0x56, 0x54, 0x1a, 0xba, 0x75, 0x3a, 0x07 } \ - } + EFI_GUID(0x39f62cce, 0x6825, 0x4669, \ + 0xbb, 0x56, 0x54, 0x1a, 0xba, 0x75, 0x3a, 0x07) #endif diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index 7e51f24b12..0cca948184 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -106,7 +106,7 @@ u64 fsp_get_usable_highmem_top(const void *hob_list); * 0 if this region does not exist. */ u64 fsp_get_reserved_mem_from_guid(const void *hob_list, - u64 *len, struct efi_guid *guid); + u64 *len, const efi_guid_t *guid); /** * This function retrieves the FSP reserved normal memory. @@ -149,7 +149,7 @@ const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list); * * @retval: A HOB object with matching GUID; Otherwise NULL. */ -const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid, +const struct hob_header *fsp_get_next_guid_hob(const efi_guid_t *guid, const void *hob_list); /** @@ -164,7 +164,7 @@ const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid, * @retval others: GUID HOB data buffer pointer. */ void *fsp_get_guid_hob_data(const void *hob_list, u32 *len, - struct efi_guid *guid); + const efi_guid_t *guid); /** * This function retrieves FSP Non-volatile Storage HOB buffer and size. diff --git a/arch/x86/include/asm/fsp/fsp_types.h b/arch/x86/include/asm/fsp/fsp_types.h index 5247102f75..3d5b17ecf1 100644 --- a/arch/x86/include/asm/fsp/fsp_types.h +++ b/arch/x86/include/asm/fsp/fsp_types.h @@ -7,14 +7,6 @@ #ifndef __FSP_TYPES_H__ #define __FSP_TYPES_H__ -/* 128 bit buffer containing a unique identifier value */ -struct efi_guid { - u32 data1; - u16 data2; - u16 data3; - u8 data4[8]; -}; - /** * Returns a 16-bit signature built from 2 ASCII characters. * diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c index 90e4e7db26..353fa82de5 100644 --- a/arch/x86/lib/fsp/fsp_support.c +++ b/arch/x86/lib/fsp/fsp_support.c @@ -8,27 +8,6 @@ #include #include -/** - * Compares two GUIDs - * - * If the GUIDs are identical then true is returned. - * If there are any bit differences in the two GUIDs, then false is returned. - * - * @guid1: A pointer to a 128 bit GUID. - * @guid2: A pointer to a 128 bit GUID. - * - * @retval true: guid1 and guid2 are identical. - * @retval false: guid1 and guid2 are not identical. - */ -static bool compare_guid(const struct efi_guid *guid1, - const struct efi_guid *guid2) -{ - if (memcmp(guid1, guid2, sizeof(struct efi_guid)) == 0) - return true; - else - return false; -} - struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void) { /* @@ -58,17 +37,22 @@ struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void) /* Check the FFS GUID */ if (fsp && - ((struct ffs_file_header *)fsp)->name.data1 == FSP_GUID_DATA1 && - ((struct ffs_file_header *)fsp)->name.data2 == FSP_GUID_DATA2 && - ((struct ffs_file_header *)fsp)->name.data3 == FSP_GUID_DATA3 && - ((struct ffs_file_header *)fsp)->name.data4[0] == FSP_GUID_DATA4_0 && - ((struct ffs_file_header *)fsp)->name.data4[1] == FSP_GUID_DATA4_1 && - ((struct ffs_file_header *)fsp)->name.data4[2] == FSP_GUID_DATA4_2 && - ((struct ffs_file_header *)fsp)->name.data4[3] == FSP_GUID_DATA4_3 && - ((struct ffs_file_header *)fsp)->name.data4[4] == FSP_GUID_DATA4_4 && - ((struct ffs_file_header *)fsp)->name.data4[5] == FSP_GUID_DATA4_5 && - ((struct ffs_file_header *)fsp)->name.data4[6] == FSP_GUID_DATA4_6 && - ((struct ffs_file_header *)fsp)->name.data4[7] == FSP_GUID_DATA4_7) { + ((struct ffs_file_header *)fsp)->name.b[0] == FSP_GUID_BYTE0 && + ((struct ffs_file_header *)fsp)->name.b[1] == FSP_GUID_BYTE1 && + ((struct ffs_file_header *)fsp)->name.b[2] == FSP_GUID_BYTE2 && + ((struct ffs_file_header *)fsp)->name.b[3] == FSP_GUID_BYTE3 && + ((struct ffs_file_header *)fsp)->name.b[4] == FSP_GUID_BYTE4 && + ((struct ffs_file_header *)fsp)->name.b[5] == FSP_GUID_BYTE5 && + ((struct ffs_file_header *)fsp)->name.b[6] == FSP_GUID_BYTE6 && + ((struct ffs_file_header *)fsp)->name.b[7] == FSP_GUID_BYTE7 && + ((struct ffs_file_header *)fsp)->name.b[8] == FSP_GUID_BYTE8 && + ((struct ffs_file_header *)fsp)->name.b[9] == FSP_GUID_BYTE9 && + ((struct ffs_file_header *)fsp)->name.b[10] == FSP_GUID_BYTE10 && + ((struct ffs_file_header *)fsp)->name.b[11] == FSP_GUID_BYTE11 && + ((struct ffs_file_header *)fsp)->name.b[12] == FSP_GUID_BYTE12 && + ((struct ffs_file_header *)fsp)->name.b[13] == FSP_GUID_BYTE13 && + ((struct ffs_file_header *)fsp)->name.b[14] == FSP_GUID_BYTE14 && + ((struct ffs_file_header *)fsp)->name.b[15] == FSP_GUID_BYTE15) { /* Add the FFS header size to find the raw section header */ fsp += sizeof(struct ffs_file_header); } else { @@ -305,7 +289,7 @@ u64 fsp_get_usable_highmem_top(const void *hob_list) } u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, - struct efi_guid *guid) + const efi_guid_t *guid) { const struct hob_header *hdr; struct hob_res_desc *res_desc; @@ -318,7 +302,7 @@ u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, if (hdr->type == HOB_TYPE_RES_DESC) { res_desc = (struct hob_res_desc *)hdr; if (res_desc->type == RES_MEM_RESERVED) { - if (compare_guid(&res_desc->owner, guid)) { + if (!guidcmp(&res_desc->owner, guid)) { if (len) *len = (u32)(res_desc->len); @@ -334,12 +318,12 @@ u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len) { - const struct efi_guid guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID; + const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID; u64 length; u32 base; base = (u32)fsp_get_reserved_mem_from_guid(hob_list, - &length, (struct efi_guid *)&guid); + &length, &guid); if ((len != 0) && (base != 0)) *len = (u32)length; @@ -348,12 +332,12 @@ u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len) u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len) { - const struct efi_guid guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID; + const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID; u64 length; u32 base; base = (u32)fsp_get_reserved_mem_from_guid(hob_list, - &length, (struct efi_guid *)&guid); + &length, &guid); if ((len != 0) && (base != 0)) *len = (u32)length; @@ -377,7 +361,7 @@ const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list) return NULL; } -const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid, +const struct hob_header *fsp_get_next_guid_hob(const efi_guid_t *guid, const void *hob_list) { const struct hob_header *hdr; @@ -387,7 +371,7 @@ const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid, while ((hdr = fsp_get_next_hob(HOB_TYPE_GUID_EXT, hdr)) != NULL) { guid_hob = (struct hob_guid *)hdr; - if (compare_guid(guid, &(guid_hob->name))) + if (!guidcmp(guid, &guid_hob->name)) break; hdr = get_next_hob(hdr); } @@ -396,7 +380,7 @@ const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid, } void *fsp_get_guid_hob_data(const void *hob_list, u32 *len, - struct efi_guid *guid) + const efi_guid_t *guid) { const struct hob_header *guid_hob; @@ -413,21 +397,21 @@ void *fsp_get_guid_hob_data(const void *hob_list, u32 *len, void *fsp_get_nvs_data(const void *hob_list, u32 *len) { - const struct efi_guid guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; + const efi_guid_t guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; - return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid); + return fsp_get_guid_hob_data(hob_list, len, &guid); } void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len) { - const struct efi_guid guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; + const efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; - return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid); + return fsp_get_guid_hob_data(hob_list, len, &guid); } void *fsp_get_graphics_info(const void *hob_list, u32 *len) { - const struct efi_guid guid = FSP_GRAPHICS_INFO_HOB_GUID; + const efi_guid_t guid = FSP_GRAPHICS_INFO_HOB_GUID; - return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid); + return fsp_get_guid_hob_data(hob_list, len, &guid); } diff --git a/cmd/x86/fsp.c b/cmd/x86/fsp.c index 9f94ca9876..1b4c0207ce 100644 --- a/cmd/x86/fsp.c +++ b/cmd/x86/fsp.c @@ -78,6 +78,7 @@ static int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) uint type; char *desc; int i = 0; + char uuid[UUID_STR_LEN + 1]; hdr = gd->arch.hob_list; @@ -102,13 +103,10 @@ static int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (type == HOB_TYPE_MEM_ALLOC || type == HOB_TYPE_RES_DESC || type == HOB_TYPE_GUID_EXT) { - struct efi_guid *guid = (struct efi_guid *)(hdr + 1); - int j; + efi_guid_t *guid = (efi_guid_t *)(hdr + 1); - printf("%08x-%04x-%04x", guid->data1, - guid->data2, guid->data3); - for (j = 0; j < ARRAY_SIZE(guid->data4); j++) - printf("-%02x", guid->data4[j]); + uuid_bin_to_str(guid->b, uuid, UUID_STR_FORMAT_GUID); + printf("%s", uuid); } else { printf("%42s", "Not Available"); } From 7165fd584fe7644113ebac98e4c5290685d2549c Mon Sep 17 00:00:00 2001 From: "Park, Aiden" Date: Sat, 3 Aug 2019 08:30:31 +0000 Subject: [PATCH 13/19] x86: Add a common HOB library FSP (CONFIG_HAVE_FSP) and Slim Bootloader (CONFIG_SYS_SLIMBOOTLOADER) consume HOB (CONFIG_USE_HOB) data from the each HOB list pointer. Add a common HOB library in lib/hob.c and include/asm/hob.h. Signed-off-by: Aiden Park Reviewed-by: Andy Shevchenko Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/include/asm/fsp/fsp_hob.h | 184 +------------------- arch/x86/include/asm/fsp/fsp_support.h | 37 +--- arch/x86/include/asm/hob.h | 230 +++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/fsp/fsp_support.c | 57 +----- arch/x86/lib/hob.c | 84 +++++++++ cmd/x86/Makefile | 1 + cmd/x86/fsp.c | 65 +------ cmd/x86/hob.c | 77 +++++++++ 9 files changed, 399 insertions(+), 337 deletions(-) create mode 100644 arch/x86/include/asm/hob.h create mode 100644 arch/x86/lib/hob.c create mode 100644 cmd/x86/hob.c diff --git a/arch/x86/include/asm/fsp/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h index 843d7b513b..3bb79c4b67 100644 --- a/arch/x86/include/asm/fsp/fsp_hob.h +++ b/arch/x86/include/asm/fsp/fsp_hob.h @@ -7,125 +7,7 @@ #ifndef __FSP_HOB_H__ #define __FSP_HOB_H__ -#include -#include - -/* Type of HOB Header */ -#define HOB_TYPE_MEM_ALLOC 0x0002 -#define HOB_TYPE_RES_DESC 0x0003 -#define HOB_TYPE_GUID_EXT 0x0004 -#define HOB_TYPE_UNUSED 0xFFFE -#define HOB_TYPE_EOH 0xFFFF - -/* - * Describes the format and size of the data inside the HOB. - * All HOBs must contain this generic HOB header. - */ -struct hob_header { - u16 type; /* HOB type */ - u16 len; /* HOB length */ - u32 reserved; /* always zero */ -}; - -/* - * Describes all memory ranges used during the HOB producer phase that - * exist outside the HOB list. This HOB type describes how memory is used, - * not the physical attributes of memory. - */ -struct hob_mem_alloc { - struct hob_header hdr; - /* - * A GUID that defines the memory allocation region's type and purpose, - * as well as other fields within the memory allocation HOB. This GUID - * is used to define the additional data within the HOB that may be - * present for the memory allocation HOB. Type efi_guid is defined in - * InstallProtocolInterface() in the UEFI 2.0 specification. - */ - efi_guid_t name; - /* - * The base address of memory allocated by this HOB. - * Type phys_addr_t is defined in AllocatePages() in the UEFI 2.0 - * specification. - */ - phys_addr_t mem_base; - /* The length in bytes of memory allocated by this HOB */ - phys_size_t mem_len; - /* - * Defines the type of memory allocated by this HOB. - * The memory type definition follows the EFI_MEMORY_TYPE definition. - * Type EFI_MEMORY_TYPE is defined in AllocatePages() in the UEFI 2.0 - * specification. - */ - enum efi_mem_type mem_type; - /* padding */ - u8 reserved[4]; -}; - -/* Value of ResourceType in HOB_RES_DESC */ -#define RES_SYS_MEM 0x00000000 -#define RES_MMAP_IO 0x00000001 -#define RES_IO 0x00000002 -#define RES_FW_DEVICE 0x00000003 -#define RES_MMAP_IO_PORT 0x00000004 -#define RES_MEM_RESERVED 0x00000005 -#define RES_IO_RESERVED 0x00000006 -#define RES_MAX_MEM_TYPE 0x00000007 - -/* - * These types can be ORed together as needed. - * - * The first three enumerations describe settings - * The rest of the settings describe capabilities - */ -#define RES_ATTR_PRESENT 0x00000001 -#define RES_ATTR_INITIALIZED 0x00000002 -#define RES_ATTR_TESTED 0x00000004 -#define RES_ATTR_SINGLE_BIT_ECC 0x00000008 -#define RES_ATTR_MULTIPLE_BIT_ECC 0x00000010 -#define RES_ATTR_ECC_RESERVED_1 0x00000020 -#define RES_ATTR_ECC_RESERVED_2 0x00000040 -#define RES_ATTR_READ_PROTECTED 0x00000080 -#define RES_ATTR_WRITE_PROTECTED 0x00000100 -#define RES_ATTR_EXECUTION_PROTECTED 0x00000200 -#define RES_ATTR_UNCACHEABLE 0x00000400 -#define RES_ATTR_WRITE_COMBINEABLE 0x00000800 -#define RES_ATTR_WRITE_THROUGH_CACHEABLE 0x00001000 -#define RES_ATTR_WRITE_BACK_CACHEABLE 0x00002000 -#define RES_ATTR_16_BIT_IO 0x00004000 -#define RES_ATTR_32_BIT_IO 0x00008000 -#define RES_ATTR_64_BIT_IO 0x00010000 -#define RES_ATTR_UNCACHED_EXPORTED 0x00020000 - -/* - * Describes the resource properties of all fixed, nonrelocatable resource - * ranges found on the processor host bus during the HOB producer phase. - */ -struct hob_res_desc { - struct hob_header hdr; - /* - * A GUID representing the owner of the resource. This GUID is - * used by HOB consumer phase components to correlate device - * ownership of a resource. - */ - efi_guid_t owner; - u32 type; - u32 attr; - /* The physical start address of the resource region */ - phys_addr_t phys_start; - /* The number of bytes of the resource region */ - phys_size_t len; -}; - -/* - * Allows writers of executable content in the HOB producer phase to - * maintain and manage HOBs with specific GUID. - */ -struct hob_guid { - struct hob_header hdr; - /* A GUID that defines the contents of this HOB */ - efi_guid_t name; - /* GUID specific data goes here */ -}; +#include enum pixel_format { pixel_rgbx_8bpc, /* RGB 8 bit per color */ @@ -147,70 +29,6 @@ struct __packed hob_graphics_info { u32 pixels_per_scanline; }; -/** - * get_next_hob() - return a pointer to the next HOB in the HOB list - * - * This macro returns a pointer to HOB that follows the HOB specified by hob - * in the HOB List. - * - * @hdr: A pointer to a HOB. - * - * @return: A pointer to the next HOB in the HOB list. - */ -static inline const struct hob_header *get_next_hob(const struct hob_header *hdr) -{ - return (const struct hob_header *)((uintptr_t)hdr + hdr->len); -} - -/** - * end_of_hob() - determine if a HOB is the last HOB in the HOB list - * - * This macro determine if the HOB specified by hob is the last HOB in the - * HOB list. If hob is last HOB in the HOB list, then true is returned. - * Otherwise, false is returned. - * - * @hdr: A pointer to a HOB. - * - * @retval true: The HOB specified by hdr is the last HOB in the HOB list. - * @retval false: The HOB specified by hdr is not the last HOB in the HOB list. - */ -static inline bool end_of_hob(const struct hob_header *hdr) -{ - return hdr->type == HOB_TYPE_EOH; -} - -/** - * get_guid_hob_data() - return a pointer to data buffer from a HOB of - * type HOB_TYPE_GUID_EXT - * - * This macro returns a pointer to the data buffer in a HOB specified by hob. - * hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT. - * - * @hdr: A pointer to a HOB. - * - * @return: A pointer to the data buffer in a HOB. - */ -static inline void *get_guid_hob_data(const struct hob_header *hdr) -{ - return (void *)((uintptr_t)hdr + sizeof(struct hob_guid)); -} - -/** - * get_guid_hob_data_size() - return the size of the data buffer from a HOB - * of type HOB_TYPE_GUID_EXT - * - * This macro returns the size, in bytes, of the data buffer in a HOB - * specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT. - * - * @hdr: A pointer to a HOB. - * - * @return: The size of the data buffer. - */ -static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) -{ - return hdr->len - sizeof(struct hob_guid); -} - /* FSP specific GUID HOB definitions */ #define FSP_GUID_DATA1 0x912740be #define FSP_GUID_DATA2 0x2284 diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index 0cca948184..7b92392a27 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -8,10 +8,10 @@ #define __FSP_SUPPORT_H__ #include "fsp_types.h" +#include "fsp_hob.h" #include "fsp_fv.h" #include "fsp_ffs.h" #include "fsp_api.h" -#include "fsp_hob.h" #include "fsp_infoheader.h" #include "fsp_bootmode.h" #include "fsp_azalia.h" @@ -131,41 +131,6 @@ u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len); */ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len); -/** - * Returns the next instance of a HOB type from the starting HOB. - * - * @type: HOB type to search - * @hob_list: A pointer to the HOB list - * - * @retval: A HOB object with matching type; Otherwise NULL. - */ -const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list); - -/** - * Returns the next instance of the matched GUID HOB from the starting HOB. - * - * @guid: GUID to search - * @hob_list: A pointer to the HOB list - * - * @retval: A HOB object with matching GUID; Otherwise NULL. - */ -const struct hob_header *fsp_get_next_guid_hob(const efi_guid_t *guid, - const void *hob_list); - -/** - * This function retrieves a GUID HOB data buffer and size. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the GUID HOB data buffer length. - * If the GUID HOB is located, the length will be updated. - * @guid A pointer to HOB GUID. - * - * @retval NULL: Failed to find the GUID HOB. - * @retval others: GUID HOB data buffer pointer. - */ -void *fsp_get_guid_hob_data(const void *hob_list, u32 *len, - const efi_guid_t *guid); - /** * This function retrieves FSP Non-volatile Storage HOB buffer and size. * diff --git a/arch/x86/include/asm/hob.h b/arch/x86/include/asm/hob.h new file mode 100644 index 0000000000..b4239821aa --- /dev/null +++ b/arch/x86/include/asm/hob.h @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: Intel */ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + */ + +#ifndef __HOB_H__ +#define __HOB_H__ + +#include +#include + +/* Type of HOB Header */ +#define HOB_TYPE_MEM_ALLOC 0x0002 +#define HOB_TYPE_RES_DESC 0x0003 +#define HOB_TYPE_GUID_EXT 0x0004 +#define HOB_TYPE_UNUSED 0xFFFE +#define HOB_TYPE_EOH 0xFFFF + +/* Value of ResourceType in HOB_RES_DESC */ +#define RES_SYS_MEM 0x00000000 +#define RES_MMAP_IO 0x00000001 +#define RES_IO 0x00000002 +#define RES_FW_DEVICE 0x00000003 +#define RES_MMAP_IO_PORT 0x00000004 +#define RES_MEM_RESERVED 0x00000005 +#define RES_IO_RESERVED 0x00000006 +#define RES_MAX_MEM_TYPE 0x00000007 + +/* + * These types can be ORed together as needed. + * + * The first three enumerations describe settings + * The rest of the settings describe capabilities + */ +#define RES_ATTR_PRESENT 0x00000001 +#define RES_ATTR_INITIALIZED 0x00000002 +#define RES_ATTR_TESTED 0x00000004 +#define RES_ATTR_SINGLE_BIT_ECC 0x00000008 +#define RES_ATTR_MULTIPLE_BIT_ECC 0x00000010 +#define RES_ATTR_ECC_RESERVED_1 0x00000020 +#define RES_ATTR_ECC_RESERVED_2 0x00000040 +#define RES_ATTR_READ_PROTECTED 0x00000080 +#define RES_ATTR_WRITE_PROTECTED 0x00000100 +#define RES_ATTR_EXECUTION_PROTECTED 0x00000200 +#define RES_ATTR_UNCACHEABLE 0x00000400 +#define RES_ATTR_WRITE_COMBINEABLE 0x00000800 +#define RES_ATTR_WRITE_THROUGH_CACHEABLE 0x00001000 +#define RES_ATTR_WRITE_BACK_CACHEABLE 0x00002000 +#define RES_ATTR_16_BIT_IO 0x00004000 +#define RES_ATTR_32_BIT_IO 0x00008000 +#define RES_ATTR_64_BIT_IO 0x00010000 +#define RES_ATTR_UNCACHED_EXPORTED 0x00020000 + +/* + * Describes the format and size of the data inside the HOB. + * All HOBs must contain this generic HOB header. + */ +struct hob_header { + u16 type; /* HOB type */ + u16 len; /* HOB length */ + u32 reserved; /* always zero */ +}; + +/* + * Describes all memory ranges used during the HOB producer phase that + * exist outside the HOB list. This HOB type describes how memory is used, + * not the physical attributes of memory. + */ +struct hob_mem_alloc { + struct hob_header hdr; + /* + * A GUID that defines the memory allocation region's type and purpose, + * as well as other fields within the memory allocation HOB. This GUID + * is used to define the additional data within the HOB that may be + * present for the memory allocation HOB. Type efi_guid_t is defined in + * InstallProtocolInterface() in the UEFI 2.0 specification. + */ + efi_guid_t name; + /* + * The base address of memory allocated by this HOB. + * Type phys_addr_t is defined in AllocatePages() in the UEFI 2.0 + * specification. + */ + phys_addr_t mem_base; + /* The length in bytes of memory allocated by this HOB */ + phys_size_t mem_len; + /* + * Defines the type of memory allocated by this HOB. + * The memory type definition follows the EFI_MEMORY_TYPE definition. + * Type EFI_MEMORY_TYPE is defined in AllocatePages() in the UEFI 2.0 + * specification. + */ + enum efi_mem_type mem_type; + /* padding */ + u8 reserved[4]; +}; + +/* + * Describes the resource properties of all fixed, nonrelocatable resource + * ranges found on the processor host bus during the HOB producer phase. + */ +struct hob_res_desc { + struct hob_header hdr; + /* + * A GUID representing the owner of the resource. This GUID is + * used by HOB consumer phase components to correlate device + * ownership of a resource. + */ + efi_guid_t owner; + u32 type; + u32 attr; + /* The physical start address of the resource region */ + phys_addr_t phys_start; + /* The number of bytes of the resource region */ + phys_size_t len; +}; + +/* + * Allows writers of executable content in the HOB producer phase to + * maintain and manage HOBs with specific GUID. + */ +struct hob_guid { + struct hob_header hdr; + /* A GUID that defines the contents of this HOB */ + efi_guid_t name; + /* GUID specific data goes here */ +}; + +/** + * get_next_hob() - return a pointer to the next HOB in the HOB list + * + * This macro returns a pointer to HOB that follows the HOB specified by hob + * in the HOB List. + * + * @hdr: A pointer to a HOB. + * + * @return: A pointer to the next HOB in the HOB list. + */ +static inline const struct hob_header *get_next_hob(const struct hob_header + *hdr) +{ + return (const struct hob_header *)((uintptr_t)hdr + hdr->len); +} + +/** + * end_of_hob() - determine if a HOB is the last HOB in the HOB list + * + * This macro determine if the HOB specified by hob is the last HOB in the + * HOB list. If hob is last HOB in the HOB list, then true is returned. + * Otherwise, false is returned. + * + * @hdr: A pointer to a HOB. + * + * @retval true: The HOB specified by hdr is the last HOB in the HOB list. + * @retval false: The HOB specified by hdr is not the last HOB in the HOB list. + */ +static inline bool end_of_hob(const struct hob_header *hdr) +{ + return hdr->type == HOB_TYPE_EOH; +} + +/** + * get_guid_hob_data() - return a pointer to data buffer from a HOB of + * type HOB_TYPE_GUID_EXT + * + * This macro returns a pointer to the data buffer in a HOB specified by hob. + * hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT. + * + * @hdr: A pointer to a HOB. + * + * @return: A pointer to the data buffer in a HOB. + */ +static inline void *get_guid_hob_data(const struct hob_header *hdr) +{ + return (void *)((uintptr_t)hdr + sizeof(struct hob_guid)); +} + +/** + * get_guid_hob_data_size() - return the size of the data buffer from a HOB + * of type HOB_TYPE_GUID_EXT + * + * This macro returns the size, in bytes, of the data buffer in a HOB + * specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT. + * + * @hdr: A pointer to a HOB. + * + * @return: The size of the data buffer. + */ +static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) +{ + return hdr->len - sizeof(struct hob_guid); +} + +/** + * Returns the next instance of a HOB type from the starting HOB. + * + * @type: HOB type to search + * @hob_list: A pointer to the HOB list + * + * @retval: A HOB object with matching type; Otherwise NULL. + */ +const struct hob_header *hob_get_next_hob(uint type, const void *hob_list); + +/** + * Returns the next instance of the matched GUID HOB from the starting HOB. + * + * @guid: GUID to search + * @hob_list: A pointer to the HOB list + * + * @retval: A HOB object with matching GUID; Otherwise NULL. + */ +const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, + const void *hob_list); + +/** + * This function retrieves a GUID HOB data buffer and size. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the GUID HOB data buffer length. + * If the GUID HOB is located, the length will be updated. + * @guid A pointer to HOB GUID. + * + * @retval NULL: Failed to find the GUID HOB. + * @retval others: GUID HOB data buffer pointer. + */ +void *hob_get_guid_hob_data(const void *hob_list, u32 *len, + const efi_guid_t *guid); + +#endif /* __HOB_H__ */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 436252dd83..906be5eab9 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -42,6 +42,7 @@ obj-y += tables.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_ZBOOT) += zimage.o endif +obj-$(CONFIG_USE_HOB) += hob.o obj-$(CONFIG_HAVE_FSP) += fsp/ ifdef CONFIG_SPL_BUILD diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c index 353fa82de5..0eaa9b232b 100644 --- a/arch/x86/lib/fsp/fsp_support.c +++ b/arch/x86/lib/fsp/fsp_support.c @@ -344,74 +344,23 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len) return base; } -const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list) -{ - const struct hob_header *hdr; - - hdr = hob_list; - - /* Parse the HOB list until end of list or matching type is found */ - while (!end_of_hob(hdr)) { - if (hdr->type == type) - return hdr; - - hdr = get_next_hob(hdr); - } - - return NULL; -} - -const struct hob_header *fsp_get_next_guid_hob(const efi_guid_t *guid, - const void *hob_list) -{ - const struct hob_header *hdr; - struct hob_guid *guid_hob; - - hdr = hob_list; - while ((hdr = fsp_get_next_hob(HOB_TYPE_GUID_EXT, - hdr)) != NULL) { - guid_hob = (struct hob_guid *)hdr; - if (!guidcmp(guid, &guid_hob->name)) - break; - hdr = get_next_hob(hdr); - } - - return hdr; -} - -void *fsp_get_guid_hob_data(const void *hob_list, u32 *len, - const efi_guid_t *guid) -{ - const struct hob_header *guid_hob; - - guid_hob = fsp_get_next_guid_hob(guid, hob_list); - if (guid_hob == NULL) { - return NULL; - } else { - if (len) - *len = get_guid_hob_data_size(guid_hob); - - return get_guid_hob_data(guid_hob); - } -} - void *fsp_get_nvs_data(const void *hob_list, u32 *len) { const efi_guid_t guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; - return fsp_get_guid_hob_data(hob_list, len, &guid); + return hob_get_guid_hob_data(hob_list, len, &guid); } void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len) { const efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; - return fsp_get_guid_hob_data(hob_list, len, &guid); + return hob_get_guid_hob_data(hob_list, len, &guid); } void *fsp_get_graphics_info(const void *hob_list, u32 *len) { const efi_guid_t guid = FSP_GRAPHICS_INFO_HOB_GUID; - return fsp_get_guid_hob_data(hob_list, len, &guid); + return hob_get_guid_hob_data(hob_list, len, &guid); } diff --git a/arch/x86/lib/hob.c b/arch/x86/lib/hob.c new file mode 100644 index 0000000000..dcee29b04c --- /dev/null +++ b/arch/x86/lib/hob.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: Intel +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + */ + +#include +#include + +/** + * Returns the next instance of a HOB type from the starting HOB. + * + * @type: HOB type to search + * @hob_list: A pointer to the HOB list + * + * @retval: A HOB object with matching type; Otherwise NULL. + */ +const struct hob_header *hob_get_next_hob(uint type, const void *hob_list) +{ + const struct hob_header *hdr; + + hdr = hob_list; + + /* Parse the HOB list until end of list or matching type is found */ + while (!end_of_hob(hdr)) { + if (hdr->type == type) + return hdr; + + hdr = get_next_hob(hdr); + } + + return NULL; +} + +/** + * Returns the next instance of the matched GUID HOB from the starting HOB. + * + * @guid: GUID to search + * @hob_list: A pointer to the HOB list + * + * @retval: A HOB object with matching GUID; Otherwise NULL. + */ +const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, + const void *hob_list) +{ + const struct hob_header *hdr; + struct hob_guid *guid_hob; + + hdr = hob_list; + while ((hdr = hob_get_next_hob(HOB_TYPE_GUID_EXT, hdr))) { + guid_hob = (struct hob_guid *)hdr; + if (!guidcmp(guid, &guid_hob->name)) + break; + hdr = get_next_hob(hdr); + } + + return hdr; +} + +/** + * This function retrieves a GUID HOB data buffer and size. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the GUID HOB data buffer length. + * If the GUID HOB is located, the length will be updated. + * @guid A pointer to HOB GUID. + * + * @retval NULL: Failed to find the GUID HOB. + * @retval others: GUID HOB data buffer pointer. + */ +void *hob_get_guid_hob_data(const void *hob_list, u32 *len, + const efi_guid_t *guid) +{ + const struct hob_header *guid_hob; + + guid_hob = hob_get_next_guid_hob(guid, hob_list); + if (!guid_hob) + return NULL; + + if (len) + *len = get_guid_hob_data_size(guid_hob); + + return get_guid_hob_data(guid_hob); +} diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile index 707161440d..144b1cf5ab 100644 --- a/cmd/x86/Makefile +++ b/cmd/x86/Makefile @@ -2,4 +2,5 @@ obj-y += mtrr.o obj-$(CONFIG_CMD_EXCEPTION) += exception.o +obj-$(CONFIG_USE_HOB) += hob.o obj-$(CONFIG_HAVE_FSP) += fsp.o diff --git a/cmd/x86/fsp.c b/cmd/x86/fsp.c index 1b4c0207ce..efa183854b 100644 --- a/cmd/x86/fsp.c +++ b/cmd/x86/fsp.c @@ -9,21 +9,6 @@ DECLARE_GLOBAL_DATA_PTR; -static char *hob_type[] = { - "reserved", - "Hand-off", - "Mem Alloc", - "Res Desc", - "GUID Ext", - "FV", - "CPU", - "Mem Pool", - "reserved", - "FV2", - "Load PEIM", - "Capsule", -}; - static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct fsp_header *hdr = find_fsp_header(); @@ -72,55 +57,8 @@ static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } -static int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - const struct hob_header *hdr; - uint type; - char *desc; - int i = 0; - char uuid[UUID_STR_LEN + 1]; - - hdr = gd->arch.hob_list; - - printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr); - - printf("# | Address | Type | Len | "); - printf("%42s\n", "GUID"); - printf("---|----------|-----------|------|-"); - printf("------------------------------------------\n"); - while (!end_of_hob(hdr)) { - printf("%02x | %08x | ", i, (unsigned int)hdr); - type = hdr->type; - if (type == HOB_TYPE_UNUSED) - desc = "*Unused*"; - else if (type == HOB_TYPE_EOH) - desc = "*EOH*"; - else if (type >= 0 && type <= ARRAY_SIZE(hob_type)) - desc = hob_type[type]; - else - desc = "*Invalid*"; - printf("%-9s | %04x | ", desc, hdr->len); - - if (type == HOB_TYPE_MEM_ALLOC || type == HOB_TYPE_RES_DESC || - type == HOB_TYPE_GUID_EXT) { - efi_guid_t *guid = (efi_guid_t *)(hdr + 1); - - uuid_bin_to_str(guid->b, uuid, UUID_STR_FORMAT_GUID); - printf("%s", uuid); - } else { - printf("%42s", "Not Available"); - } - printf("\n"); - hdr = get_next_hob(hdr); - i++; - } - - return 0; -} - static cmd_tbl_t fsp_commands[] = { U_BOOT_CMD_MKENT(hdr, 0, 1, do_hdr, "", ""), - U_BOOT_CMD_MKENT(hob, 0, 1, do_hob, "", ""), }; static int do_fsp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) @@ -144,6 +82,5 @@ static int do_fsp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( fsp, 2, 1, do_fsp, "Show Intel Firmware Support Package (FSP) related information", - "hdr - Print FSP header information\n" - "fsp hob - Print FSP Hand-Off Block (HOB) information" + "hdr - Print FSP header information" ); diff --git a/cmd/x86/hob.c b/cmd/x86/hob.c new file mode 100644 index 0000000000..3967a7ca5a --- /dev/null +++ b/cmd/x86/hob.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014-2015, Bin Meng + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static char *hob_type[] = { + "reserved", + "Hand-off", + "Mem Alloc", + "Res Desc", + "GUID Ext", + "FV", + "CPU", + "Mem Pool", + "reserved", + "FV2", + "Load PEIM", + "Capsule", +}; + +static int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const struct hob_header *hdr; + uint type; + char *desc; + int i = 0; + efi_guid_t *guid; + char uuid[UUID_STR_LEN + 1]; + + hdr = gd->arch.hob_list; + + printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr); + + printf("# | Address | Type | Len | "); + printf("%36s\n", "GUID"); + printf("---|----------|-----------|------|-"); + printf("------------------------------------\n"); + while (!end_of_hob(hdr)) { + printf("%02x | %08x | ", i, (unsigned int)hdr); + type = hdr->type; + if (type == HOB_TYPE_UNUSED) + desc = "*Unused*"; + else if (type == HOB_TYPE_EOH) + desc = "*EOH*"; + else if (type >= 0 && type <= ARRAY_SIZE(hob_type)) + desc = hob_type[type]; + else + desc = "*Invalid*"; + printf("%-9s | %04x | ", desc, hdr->len); + + if (type == HOB_TYPE_MEM_ALLOC || type == HOB_TYPE_RES_DESC || + type == HOB_TYPE_GUID_EXT) { + guid = (efi_guid_t *)(hdr + 1); + uuid_bin_to_str(guid->b, uuid, UUID_STR_FORMAT_GUID); + printf("%s", uuid); + } else { + printf("%36s", "Not Available"); + } + printf("\n"); + hdr = get_next_hob(hdr); + i++; + } + + return 0; +} + +U_BOOT_CMD(hob, 1, 1, do_hob, + "Print Hand-Off Block (HOB) information", + "" +); From 1fb17ea548b0f6902e1a45accb0c5d55415938ae Mon Sep 17 00:00:00 2001 From: "Park, Aiden" Date: Sat, 3 Aug 2019 08:30:36 +0000 Subject: [PATCH 14/19] x86: slimbootloader: Add memory configuration Slim Bootloader provides memory map info thru its HOB list pointer. Configure memory size and relocation memory from the HOB data, and provide e820 entries as well. - Get memory size from the memory map info HOB - Set available top memory lower than 4GB for U-Boot relocation - Provide e820 entries from the memory map info HOB Signed-off-by: Aiden Park Reviewed-by: Bin Meng Reviewed-by: Andy Shevchenko Tested-by: Bin Meng --- arch/x86/cpu/slimbootloader/Makefile | 2 +- arch/x86/cpu/slimbootloader/sdram.c | 151 ++++++++++++++++++ .../asm/arch-slimbootloader/slimbootloader.h | 53 ++++++ 3 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 arch/x86/cpu/slimbootloader/sdram.c create mode 100644 arch/x86/include/asm/arch-slimbootloader/slimbootloader.h diff --git a/arch/x86/cpu/slimbootloader/Makefile b/arch/x86/cpu/slimbootloader/Makefile index 627a721e8c..9e6822a6ec 100644 --- a/arch/x86/cpu/slimbootloader/Makefile +++ b/arch/x86/cpu/slimbootloader/Makefile @@ -2,4 +2,4 @@ # # Copyright (C) 2019 Intel Corporation -obj-y += car.o slimbootloader.o +obj-y += car.o slimbootloader.o sdram.o diff --git a/arch/x86/cpu/slimbootloader/sdram.c b/arch/x86/cpu/slimbootloader/sdram.c new file mode 100644 index 0000000000..05d40d196c --- /dev/null +++ b/arch/x86/cpu/slimbootloader/sdram.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Intel Corporation + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/** + * This returns a data pointer of memory map info from the guid hob. + * + * @return: A data pointer of memory map info hob + */ +static struct sbl_memory_map_info *get_memory_map_info(void) +{ + struct sbl_memory_map_info *data; + const efi_guid_t guid = SBL_MEMORY_MAP_INFO_GUID; + + if (!gd->arch.hob_list) + return NULL; + + data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid); + if (!data) + panic("memory map info hob not found\n"); + if (!data->count) + panic("invalid number of memory map entries\n"); + + return data; +} + +#define for_each_if(condition) if (!(condition)) {} else + +#define for_each_memory_map_entry_reversed(iter, entries) \ + for (iter = entries->count - 1; iter >= 0; iter--) \ + for_each_if(entries->entry[iter].type == E820_RAM) + +/** + * This is to give usable memory region information for u-boot relocation. + * so search usable memory region lower than 4GB. + * The memory map entries from Slim Bootloader hob are already sorted. + * + * @total_size: The memory size that u-boot occupies + * @return : The top available memory address lower than 4GB + */ +ulong board_get_usable_ram_top(ulong total_size) +{ + struct sbl_memory_map_info *data; + int i; + u64 addr_start; + u64 addr_end; + ulong ram_top; + + data = get_memory_map_info(); + + /** + * sorted memory map entries from Slim Bootloader based on physical + * start memory address, from low to high. So do reversed search to + * get highest usable, suitable size, 4KB aligned available memory + * under 4GB. + */ + ram_top = 0; + for_each_memory_map_entry_reversed(i, data) { + addr_start = data->entry[i].addr; + addr_end = addr_start + data->entry[i].size; + + if (addr_start > SZ_4G) + continue; + + if (addr_end > SZ_4G) + addr_end = SZ_4G; + + if (addr_end < total_size) + continue; + + /* to relocate u-boot at 4K aligned memory */ + addr_end = rounddown(addr_end - total_size, SZ_4K); + if (addr_end >= addr_start) { + ram_top = (ulong)addr_end + total_size; + break; + } + } + + if (!ram_top) + panic("failed to find available memory for relocation!"); + + return ram_top; +} + +/** + * The memory initialization has already been done in previous Slim Bootloader + * stage thru FSP-M. Instead, this sets the ram_size from the memory map info + * hob. + */ +int dram_init(void) +{ + struct sbl_memory_map_info *data; + int i; + u64 ram_size; + + data = get_memory_map_info(); + + /** + * sorted memory map entries from Slim Bootloader based on physical + * start memory address, from low to high. So do reversed search to + * simply get highest usable memory address as RAM size + */ + ram_size = 0; + for_each_memory_map_entry_reversed(i, data) { + /* simply use the highest usable memory address as RAM size */ + ram_size = data->entry[i].addr + data->entry[i].size; + break; + } + + if (!ram_size) + panic("failed to detect memory size"); + + gd->ram_size = ram_size; + return 0; +} + +int dram_init_banksize(void) +{ + if (!CONFIG_NR_DRAM_BANKS) + return 0; + + /* simply use a single bank to have whole size for now */ + gd->bd->bi_dram[0].start = 0; + gd->bd->bi_dram[0].size = gd->ram_size; + return 0; +} + +unsigned int install_e820_map(unsigned int max_entries, + struct e820_entry *entries) +{ + struct sbl_memory_map_info *data; + unsigned int i; + + data = get_memory_map_info(); + + for (i = 0; i < data->count; i++) { + entries[i].addr = data->entry[i].addr; + entries[i].size = data->entry[i].size; + entries[i].type = data->entry[i].type; + } + + return i; +} diff --git a/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h b/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h new file mode 100644 index 0000000000..4ee8a0627e --- /dev/null +++ b/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019 Intel Corporation + */ + +#ifndef __SLIMBOOTLOADER_ARCH_H__ +#define __SLIMBOOTLOADER_ARCH_H__ + +#include +#include + +/** + * A GUID to get MemoryMap info hob which is provided by Slim Bootloader + */ +#define SBL_MEMORY_MAP_INFO_GUID \ + EFI_GUID(0xa1ff7424, 0x7a1a, 0x478e, \ + 0xa9, 0xe4, 0x92, 0xf3, 0x57, 0xd1, 0x28, 0x32) + +/** + * A single entry of memory map information + * + * @addr: start address of a memory map entry + * @size: size of a memory map entry + * @type: usable:1, reserved:2, acpi:3, nvs:4, unusable:5 + * @flag: only used in Slim Bootloader + * @rsvd: padding for alignment + */ +struct sbl_memory_map_entry { + u64 addr; + u64 size; + u8 type; + u8 flag; + u8 rsvd[6]; +}; + +/** + * This includes all memory map entries which is sorted based on physical start + * address, from low to high, and carved out reserved, acpi nvs, acpi reclaim + * and usable memory. + * + * @rev : revision of memory_map_info structure. currently 1. + * @rsvd : padding for alignment + * @count: the number of memory map entries + * @entry: array of all memory map entries + */ +struct sbl_memory_map_info { + u8 rev; + u8 rsvd[3]; + u32 count; + struct sbl_memory_map_entry entry[0]; +}; + +#endif /* __SLIMBOOTLOADER_ARCH_H__ */ From 2869c3b3de390ed7dba3d854160d9b19dd4660a3 Mon Sep 17 00:00:00 2001 From: "Park, Aiden" Date: Sat, 3 Aug 2019 08:30:44 +0000 Subject: [PATCH 15/19] x86: slimbootloader: Add serial driver Slim Bootloader provides serial port info thru its HOB list pointer. All these HOBs are eligible for Slim Bootloader based board only. - Get serial port information from the serial port info HOB - Leverage ns16550 driver with slimbootloader specific platform data Signed-off-by: Aiden Park Reviewed-by: Bin Meng Reviewed-by: Andy Shevchenko Tested-by: Bin Meng --- arch/x86/cpu/slimbootloader/Makefile | 2 +- arch/x86/cpu/slimbootloader/serial.c | 67 +++++++++++++++++++ .../asm/arch-slimbootloader/slimbootloader.h | 34 ++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 arch/x86/cpu/slimbootloader/serial.c diff --git a/arch/x86/cpu/slimbootloader/Makefile b/arch/x86/cpu/slimbootloader/Makefile index 9e6822a6ec..aac9fa3db8 100644 --- a/arch/x86/cpu/slimbootloader/Makefile +++ b/arch/x86/cpu/slimbootloader/Makefile @@ -2,4 +2,4 @@ # # Copyright (C) 2019 Intel Corporation -obj-y += car.o slimbootloader.o sdram.o +obj-y += car.o slimbootloader.o sdram.o serial.o diff --git a/arch/x86/cpu/slimbootloader/serial.c b/arch/x86/cpu/slimbootloader/serial.c new file mode 100644 index 0000000000..7b44a59bff --- /dev/null +++ b/arch/x86/cpu/slimbootloader/serial.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Intel Corporation + */ + +#include +#include +#include +#include +#include + +/** + * The serial port info hob is generated by Slim Bootloader, so eligible for + * Slim Bootloader based boards only. + */ +static int slimbootloader_serial_ofdata_to_platdata(struct udevice *dev) +{ + const efi_guid_t guid = SBL_SERIAL_PORT_INFO_GUID; + struct sbl_serial_port_info *data; + struct ns16550_platdata *plat = dev->platdata; + + if (!gd->arch.hob_list) + panic("hob list not found!"); + + data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid); + if (!data) { + debug("failed to get serial port information\n"); + return -ENOENT; + } + debug("type:%d base=0x%08x baudrate=%d stride=%d clk=%d\n", + data->type, + data->base, + data->baud, + data->stride, + data->clk); + + /* + * The data->type provides port io or mmio access type info, + * but the access type will be controlled by + * CONFIG_SYS_NS16550_PORT_MAPPED or CONFIG_SYS_NS16550_MEM32. + * + * TBD: ns16550 access type configuration in runtime. + * ex) plat->access_type = data->type + */ + plat->base = data->base; + /* ns16550 uses reg_shift, then covert stride to shift */ + plat->reg_shift = data->stride >> 1; + plat->clock = data->clk; + + return 0; +} + +static const struct udevice_id slimbootloader_serial_ids[] = { + { .compatible = "intel,slimbootloader-uart" }, + {} +}; + +U_BOOT_DRIVER(serial_slimbootloader) = { + .name = "serial_slimbootloader", + .id = UCLASS_SERIAL, + .of_match = slimbootloader_serial_ids, + .ofdata_to_platdata = slimbootloader_serial_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct ns16550_platdata), + .priv_auto_alloc_size = sizeof(struct NS16550), + .probe = ns16550_serial_probe, + .ops = &ns16550_serial_ops, +}; diff --git a/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h b/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h index 4ee8a0627e..174a341d32 100644 --- a/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h +++ b/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h @@ -16,6 +16,13 @@ EFI_GUID(0xa1ff7424, 0x7a1a, 0x478e, \ 0xa9, 0xe4, 0x92, 0xf3, 0x57, 0xd1, 0x28, 0x32) +/** + * A GUID to get SerialPort info hob which is provided by Slim Bootloader + */ +#define SBL_SERIAL_PORT_INFO_GUID \ + EFI_GUID(0x6c6872fe, 0x56a9, 0x4403, \ + 0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1) + /** * A single entry of memory map information * @@ -50,4 +57,31 @@ struct sbl_memory_map_info { struct sbl_memory_map_entry entry[0]; }; +/** + * This includes serial port info which has already been initialized in previous + * Slim Bootloader stage. + * The Slim Bootloader initializes serial port regardless of debug/release build + * modes, and it passes the information to a payload thru hob. So, a payload can + * re-use the serial information without re-initializing serial port. + * + * @rev : revision of serial_port_info structure. currently 1. + * @rsvd : padding for alignment + * @type : port io: 1, mmio: 2 + * @base : io base address. ex) 0x3f8, 0x80001000 + * @baud : uart baud rate + * @stride: register stride in Bytes + * @clk : uart frequency in Hz + * @rsvd1 : reserved + */ +struct sbl_serial_port_info { + u8 rev; + u8 rsvd[3]; + u32 type; + u32 base; + u32 baud; + u32 stride; + u32 clk; + u32 rsvd1; +}; + #endif /* __SLIMBOOTLOADER_ARCH_H__ */ From 14360bf0591c88c0af7c1792a331579443089f20 Mon Sep 17 00:00:00 2001 From: "Park, Aiden" Date: Sat, 3 Aug 2019 08:30:52 +0000 Subject: [PATCH 16/19] x86: slimbootloader: Set TSC information for tsc_timer Slim Bootloader already calibrated TSC and provides it to U-Boot. Therefore, U-Boot does not have to re-calibrate TSC. Configuring tsc_base and clock_rate makes x86 tsc_timer driver bypass TSC calibration and use the provided TSC frequency. - Get TSC frequency from performance info hob - Set tsc_base and clock_rate for tsc_timer driver Signed-off-by: Aiden Park Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/x86/cpu/slimbootloader/slimbootloader.c | 37 +++++++++++++++++++ .../asm/arch-slimbootloader/slimbootloader.h | 28 ++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/arch/x86/cpu/slimbootloader/slimbootloader.c b/arch/x86/cpu/slimbootloader/slimbootloader.c index 9f3a61ec61..e6b174ca88 100644 --- a/arch/x86/cpu/slimbootloader/slimbootloader.c +++ b/arch/x86/cpu/slimbootloader/slimbootloader.c @@ -4,9 +4,46 @@ */ #include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/** + * This sets tsc_base and clock_rate for early_timer and tsc_timer. + * The performance info guid hob has all performance timestamp data, but + * the only tsc frequency info is used for the timer driver for now. + * + * Slim Bootloader already calibrated TSC and provides it to U-Boot. + * Therefore, U-Boot does not have to re-calibrate TSC. + * Configuring tsc_base and clock_rate here makes x86 tsc_timer driver + * bypass TSC calibration and use the provided TSC frequency. + */ +static void tsc_init(void) +{ + struct sbl_performance_info *data; + const efi_guid_t guid = SBL_PERFORMANCE_INFO_GUID; + + if (!gd->arch.hob_list) + panic("hob list not found!"); + + gd->arch.tsc_base = rdtsc(); + debug("tsc_base=0x%llx\n", gd->arch.tsc_base); + + data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid); + if (!data) { + debug("performance info hob not found\n"); + return; + } + + /* frequency is in KHz, so to Hz */ + gd->arch.clock_rate = data->frequency * 1000; + debug("freq=0x%lx\n", gd->arch.clock_rate); +} int arch_cpu_init(void) { + tsc_init(); + return x86_cpu_init_f(); } diff --git a/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h b/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h index 174a341d32..05dd1b2b44 100644 --- a/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h +++ b/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h @@ -23,6 +23,13 @@ EFI_GUID(0x6c6872fe, 0x56a9, 0x4403, \ 0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1) +/** + * A GUID to get boot performance info hob which is provided by Slim Bootloader + */ +#define SBL_PERFORMANCE_INFO_GUID \ + EFI_GUID(0x868204be, 0x23d0, 0x4ff9, \ + 0xac, 0x34, 0xb9, 0x95, 0xac, 0x04, 0xb1, 0xb9) + /** * A single entry of memory map information * @@ -84,4 +91,25 @@ struct sbl_serial_port_info { u32 rsvd1; }; +/** + * This includes timestamp data which has been collected in Slim Bootloader + * stages from the reset vector. In addition, this has TSC frequency in KHz to + * calculate each timestamp. + * + * @rev : revision of performance_info structure. currently 1. + * @rsvd : padding for alignment + * @count : the number of collected timestamp data + * @flags : only used in Slim Bootloader + * @frequency: tsc frequency in KHz + * @timestamp: the array of timestamp data which has 64-bit tsc value + */ +struct sbl_performance_info { + u8 rev; + u8 rsvd[3]; + u16 count; + u16 flags; + u32 frequency; + u64 timestamp[0]; +}; + #endif /* __SLIMBOOTLOADER_ARCH_H__ */ From 19cad267d92880dac3317ec43609910083152f5d Mon Sep 17 00:00:00 2001 From: "Park, Aiden" Date: Sat, 3 Aug 2019 08:31:00 +0000 Subject: [PATCH 17/19] x86: slimbootloader: Add a slimbootloader device tree Add a new device tree which has very minimum nodes - x86 reset - x86 tsc_timer - x86 pci - Slim Bootloader serial Signed-off-by: Aiden Park Reviewed-by: Bin Meng Reviewed-by: Andy Shevchenko Tested-by: Bin Meng --- arch/x86/dts/Makefile | 1 + arch/x86/dts/slimbootloader.dts | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 arch/x86/dts/slimbootloader.dts diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile index fa717bc096..d4bdf62be6 100644 --- a/arch/x86/dts/Makefile +++ b/arch/x86/dts/Makefile @@ -18,6 +18,7 @@ dtb-y += bayleybay.dtb \ qemu-x86_i440fx.dtb \ qemu-x86_q35.dtb \ theadorable-x86-dfi-bt700.dtb \ + slimbootloader.dtb \ baytrail_som-db5800-som-6867.dtb targets += $(dtb-y) diff --git a/arch/x86/dts/slimbootloader.dts b/arch/x86/dts/slimbootloader.dts new file mode 100644 index 0000000000..d04095c4f8 --- /dev/null +++ b/arch/x86/dts/slimbootloader.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Intel Corporation + */ + +/dts-v1/; + +/include/ "skeleton.dtsi" +/include/ "reset.dtsi" +/include/ "tsc_timer.dtsi" + +/ { + model = "slimbootloader x86 payload"; + compatible = "slimbootloader,x86-payload"; + + chosen { + stdout-path = &serial; + }; + + serial: serial { + compatible = "intel,slimbootloader-uart"; + }; + + pci { + compatible = "pci-x86"; + }; +}; From d8f6db4768bc8516cf346546435588427a06e46b Mon Sep 17 00:00:00 2001 From: "Park, Aiden" Date: Sat, 3 Aug 2019 08:31:11 +0000 Subject: [PATCH 18/19] board: intel: Add new slimbootloader board Add slimbootloader board to run U-boot as a Slim Bootloader payload - Add new board/intel/slimbootloader directory with minimum codes - Add slimbootloader configuration files - Add doc/board/intel/slimbootloader.rst Signed-off-by: Aiden Park Reviewed-by: Bin Meng Reviewed-by: Andy Shevchenko Tested-by: Bin Meng [bmeng: add slimbootloader board MAINTAINERS file] Signed-off-by: Bin Meng --- board/intel/Kconfig | 14 ++ board/intel/slimbootloader/Kconfig | 28 ++++ board/intel/slimbootloader/MAINTAINERS | 6 + board/intel/slimbootloader/Makefile | 5 + board/intel/slimbootloader/slimbootloader.c | 21 +++ board/intel/slimbootloader/start.S | 9 + configs/slimbootloader_defconfig | 22 +++ doc/board/intel/index.rst | 1 + doc/board/intel/slimbootloader.rst | 174 ++++++++++++++++++++ include/configs/slimbootloader.h | 62 +++++++ 10 files changed, 342 insertions(+) create mode 100644 board/intel/slimbootloader/Kconfig create mode 100644 board/intel/slimbootloader/MAINTAINERS create mode 100644 board/intel/slimbootloader/Makefile create mode 100644 board/intel/slimbootloader/slimbootloader.c create mode 100644 board/intel/slimbootloader/start.S create mode 100644 configs/slimbootloader_defconfig create mode 100644 doc/board/intel/slimbootloader.rst create mode 100644 include/configs/slimbootloader.h diff --git a/board/intel/Kconfig b/board/intel/Kconfig index 5131836cb0..7b16ec4dc1 100644 --- a/board/intel/Kconfig +++ b/board/intel/Kconfig @@ -73,6 +73,19 @@ config TARGET_MINNOWMAX Note that PCIE_ECAM_BASE is set up by the FSP so the value used by U-Boot matches that value. +config TARGET_SLIMBOOTLOADER + bool "slimbootloader" + help + This target is used for running U-Boot on top of Slim Bootloader + boot firmware as a payload. Slim Bootloader does memory initialization + and silicon initialization, and it passes necessary information in + HOB (Hand Off Block) to a payload. The payload consumes HOB data + which is generated by Slim Bootloader for its driver initialization. + Slim Bootloader consumes FSP and its HOB, but FSP HOB is cleared + Before launching a payload. Instead, Slim Bootloader generates its + HOB data such as memory info, serial port info and so on. + Refer to doc/board/intel/slimbootloader.rst for the details. + endchoice source "board/intel/bayleybay/Kconfig" @@ -82,5 +95,6 @@ source "board/intel/crownbay/Kconfig" source "board/intel/edison/Kconfig" source "board/intel/galileo/Kconfig" source "board/intel/minnowmax/Kconfig" +source "board/intel/slimbootloader/Kconfig" endif diff --git a/board/intel/slimbootloader/Kconfig b/board/intel/slimbootloader/Kconfig new file mode 100644 index 0000000000..8c7e22cc33 --- /dev/null +++ b/board/intel/slimbootloader/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2019 Intel Corporation + +if TARGET_SLIMBOOTLOADER + +config SYS_BOARD + default "slimbootloader" + +config SYS_VENDOR + default "intel" + +config SYS_SOC + default "slimbootloader" + +config SYS_CONFIG_NAME + default "slimbootloader" + +config SYS_TEXT_BASE + default 0x00100000 + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select SYS_SLIMBOOTLOADER + select USB_STORAGE + select USB_KEYBOARD + +endif diff --git a/board/intel/slimbootloader/MAINTAINERS b/board/intel/slimbootloader/MAINTAINERS new file mode 100644 index 0000000000..e6935517e0 --- /dev/null +++ b/board/intel/slimbootloader/MAINTAINERS @@ -0,0 +1,6 @@ +Intel Slim Bootloader Payload +M: Aiden Park +S: Maintained +F: board/intel/slimbootloader +F: include/configs/slimbootloader.h +F: configs/slimbootloader_defconfig diff --git a/board/intel/slimbootloader/Makefile b/board/intel/slimbootloader/Makefile new file mode 100644 index 0000000000..fd8fa98a8d --- /dev/null +++ b/board/intel/slimbootloader/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2019 Intel Corporation + +obj-y += start.o slimbootloader.o diff --git a/board/intel/slimbootloader/slimbootloader.c b/board/intel/slimbootloader/slimbootloader.c new file mode 100644 index 0000000000..f50eeb823f --- /dev/null +++ b/board/intel/slimbootloader/slimbootloader.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Intel Corporation + */ + +#include + +int board_early_init_r(void) +{ + /* + * Make sure PCI bus is enumerated so that peripherals on the PCI bus + * can be discovered by their drivers. + * + * Slim Bootloader has already done PCI bus enumeration before loading + * U-Boot, so U-Boot needs to preserve PCI configuration. + * Therefore, '# CONFIG_PCI_PNP is not set' is included in defconfig. + */ + pci_init(); + + return 0; +} diff --git a/board/intel/slimbootloader/start.S b/board/intel/slimbootloader/start.S new file mode 100644 index 0000000000..5c3f3df09e --- /dev/null +++ b/board/intel/slimbootloader/start.S @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019 Intel Corporation + */ + +/* board early initialization */ +.globl early_board_init +early_board_init: + jmp early_board_init_ret diff --git a/configs/slimbootloader_defconfig b/configs/slimbootloader_defconfig new file mode 100644 index 0000000000..b16ed71469 --- /dev/null +++ b/configs/slimbootloader_defconfig @@ -0,0 +1,22 @@ +CONFIG_X86=y +CONFIG_VENDOR_INTEL=y +CONFIG_TARGET_SLIMBOOTLOADER=y +CONFIG_DEFAULT_DEVICE_TREE="slimbootloader" +CONFIG_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_BOARD_EARLY_INIT_R=y +CONFIG_LAST_STAGE_INIT=y +CONFIG_HUSH_PARSER=y +CONFIG_CMD_MMC=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_FAT=y +CONFIG_CMD_USB=y +CONFIG_DOS_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_OF_CONTROL=y +CONFIG_BOOTSTAGE=y +CONFIG_BOOTSTAGE_REPORT=y +CONFIG_BOOTDELAY=10 +CONFIG_CONSOLE_SCROLL_LINES=5 +# CONFIG_PCI_PNP is not set diff --git a/doc/board/intel/index.rst b/doc/board/intel/index.rst index f416801910..f545dee87a 100644 --- a/doc/board/intel/index.rst +++ b/doc/board/intel/index.rst @@ -13,3 +13,4 @@ Intel edison galileo minnowmax + slimbootloader diff --git a/doc/board/intel/slimbootloader.rst b/doc/board/intel/slimbootloader.rst new file mode 100644 index 0000000000..4a46fed069 --- /dev/null +++ b/doc/board/intel/slimbootloader.rst @@ -0,0 +1,174 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. sectionauthor:: Aiden Park + +Slim Bootloader +=============== + +Introduction +------------ + +This target is to enable U-Boot_ as a payload of `Slim Bootloader`_ (a.k.a SBL) +boot firmware which currently supports QEMU, Apollolake, Whiskeylake, +Coffeelake-R platforms. + +The `Slim Bootloader`_ is designed with multi-stages (Stage1A/B, Stage2, Payload) +architecture to cover from reset vector to OS booting and it consumes +`Intel FSP`_ for silicon initialization. + +* Stage1A: Reset vector, CAR init with FSP-T +* Stage1B: Memory init with FSP-M, CAR teardown, Continue execution in memory +* Stage2 : Rest of Silicon init with FSP-S, Create HOB, Hand-off to Payload +* Payload: Payload init with HOB, Load OS from media, Booting OS + +The Slim Bootloader stages (Stage1A/B, Stage2) focus on chipset, hardware and +platform specific initialization, and it provides useful information to a +payload in a HOB (Hand-Off Block) which has serial port, memory map, performance +data info and so on. This is Slim Bootloader architectural design to make a +payload light-weight, platform independent and more generic across different +boot solutions or payloads, and to minimize hardware re-initialization in a +payload. + +Build Instruction for U-Boot as a Slim Bootloader payload +--------------------------------------------------------- + +Build U-Boot and obtain u-boot-dtb.bin:: + + $ make distclean + $ make slimbootloader_defconfig + $ make all + +Prepare Slim Bootloader +----------------------- + +1. Setup Build Environment for Slim Bootloader. + + Refer to `Getting Started`_ page in `Slim Bootloader`_ document site. + +2. Get source code. Let's simply clone the repo:: + + $ git clone https://github.com/slimbootloader/slimbootloader.git + +3. Copy u-boot-dtb.bin to Slim Bootloader. + Slim Bootloader looks for a payload from the specific location. + Copy the build u-boot-dtb.bin to the expected location:: + + $ mkdir -p /PayloadPkg/PayloadBins/ + $ cp /u-boot-dtb.bin /PayloadPkg/PayloadBins/u-boot-dtb.bin + +Build Instruction for Slim Bootloader for QEMU target +----------------------------------------------------- + +Slim Bootloader supports multiple payloads, and a board of Slim Bootloader +detects its target payload by PayloadId in board configuration. +The PayloadId can be any 4 Bytes value. + +1. Update PayloadId. Let's use 'U-BT' as an example:: + + $ vi Platform/QemuBoardPkg/CfgData/CfgDataExt_Brd1.dlt + -GEN_CFG_DATA.PayloadId | 'AUTO' + +GEN_CFG_DATA.PayloadId | 'U-BT' + +2. Update payload text base. PAYLOAD_EXE_BASE must be the same as U-Boot + CONFIG_SYS_TEXT_BASE in board/intel/slimbootloader/Kconfig. + PAYLOAD_LOAD_HIGH must be 0:: + + $ vi Platform/QemuBoardPkg/BoardConfig.py + + self.PAYLOAD_LOAD_HIGH = 0 + + self.PAYLOAD_EXE_BASE = 0x00100000 + +3. Build QEMU target. Make sure u-boot-dtb.bin and U-BT PayloadId + in build command. The output is Outputs/qemu/SlimBootloader.bin:: + + $ python BuildLoader.py build qemu -p "OsLoader.efi:LLDR:Lz4;u-boot-dtb.bin:U-BT:Lzma" + +4. Launch Slim Bootloader on QEMU. + You should reach at U-Boot serial console:: + + $ qemu-system-x86_64 -machine q35 -nographic -serial mon:stdio -pflash Outputs/qemu/SlimBootloader.bin + +Build Instruction for Slim Bootloader for LeafHill (APL) target +-------------------------------------------------------------- + +LeafHill is using PCI UART2 device as a serial port. +For MEM32 serial port, CONFIG_SYS_NS16550_MEM32 needs to be enabled in U-Boot. + +1. Enable CONFIG_SYS_NS16550_MEM32 in U-Boot:: + + $ vi include/configs/slimbootloader.h + +#define CONFIG_SYS_NS16550_MEM32 + #ifdef CONFIG_SYS_NS16550_MEM3 + +2. Build U-Boot:: + + $ make disclean + $ make slimbootloader_defconfig + $ make all + +3. Copy u-boot-dtb.bin to Slim Bootloader. + Slim Bootloader looks for a payload from the specific location. + Copy the build u-boot-dtb.bin to the expected location:: + + $ mkdir -p /PayloadPkg/PayloadBins/ + $ cp /u-boot-dtb.bin /PayloadPkg/PayloadBins/u-boot-dtb.bin + +4. Update PayloadId. Let's use 'U-BT' as an example:: + + $ vi Platform/ApollolakeBoardPkg/CfgData/CfgData_Int_LeafHill.dlt + -GEN_CFG_DATA.PayloadId | 'AUTO + +GEN_CFG_DATA.PayloadId | 'U-BT' + +5. Update payload text base. + +* PAYLOAD_EXE_BASE must be the same as U-Boot CONFIG_SYS_TEXT_BASE + in board/intel/slimbootloader/Kconfig. +* PAYLOAD_LOAD_HIGH must be 0:: + + $ vi Platform/ApollolakeBoardPkg/BoardConfig.py + + self.PAYLOAD_LOAD_HIGH = 0 + + self.PAYLOAD_EXE_BASE = 0x00100000 + +6. Build APL target. Make sure u-boot-dtb.bin and U-BT PayloadId + in build command. The output is Outputs/apl/Stitch_Components.zip:: + + $ python BuildLoader.py build apl -p "OsLoader.efi:LLDR:Lz4;u-boot-dtb.bin:U-BT:Lzma" + +7. Stitch IFWI. + + Refer to Apollolake_ page in Slim Bootloader document site:: + + $ python Platform/ApollolakeBoardPkg/Script/StitchLoader.py -i -s Outputs/apl/Stitch_Components.zip -o + +8. Flash IFWI. + + Use DediProg to flash IFWI. You should reach at U-Boot serial console. + + +Build Instruction to use ELF U-Boot +----------------------------------- + +1. Enable CONFIG_OF_EMBED:: + + $ vi configs/slimbootloader_defconfig + +CONFIG_OF_EMBED=y + +2. Build U-Boot:: + + $ make disclean + $ make slimbootloader_defconfig + $ make all + $ strip u-boot (removing symbol for reduced size) + +3. Do same steps as above + +* Copy u-boot (ELF) to PayloadBins directory +* Update PayloadId 'U-BT' as above. +* No need to set PAYLOAD_LOAD_HIGH and PAYLOAD_EXE_BASE. +* Build Slim Bootloader. Use u-boot instead of u-boot-dtb.bin:: + + $ python BuildLoader.py build -p "OsLoader.efi:LLDR:Lz4;u-boot:U-BT:Lzma" + +.. _U-Boot: https://gitlab.denx.de/ +.. _`Slim Bootloader`: https://github.com/slimbootloader/ +.. _`Intel FSP`: https://github.com/IntelFsp/ +.. _`Getting Started`: https://slimbootloader.github.io/getting-started/ +.. _Apollolake: https://slimbootloader.github.io/supported-hardware/apollo-lake-crb.html#stitching diff --git a/include/configs/slimbootloader.h b/include/configs/slimbootloader.h new file mode 100644 index 0000000000..e0011ed446 --- /dev/null +++ b/include/configs/slimbootloader.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019 Intel Corporation + */ + +#ifndef __SLIMBOOTLOADER_CONFIG_H__ +#define __SLIMBOOTLOADER_CONFIG_H__ + +#include + +/* + * By default, CONFIG_SYS_NS16550_PORT_MAPPED is enabled for port io serial. + * To use mmio base serial, enable CONFIG_SYS_NS16550_MEM32 and disable + * CONFIG_SYS_NS16550_PORT_MAPPED until ns16550 driver supports serial port + * configuration in run-time. + * + * #define CONFIG_SYS_NS16550_MEM32 + * #undef CONFIG_SYS_NS16550_PORT_MAPPED + */ +#ifdef CONFIG_SYS_NS16550_MEM32 +#undef CONFIG_SYS_NS16550_PORT_MAPPED +#endif + +#define CONFIG_STD_DEVICES_SETTINGS \ + "stdin=serial,i8042-kbd,usbkbd\0" \ + "stdout=serial\0" \ + "stderr=serial\0" + +/* + * Override CONFIG_EXTRA_ENV_SETTINGS in x86-common.h + */ +#undef CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS \ + CONFIG_STD_DEVICES_SETTINGS \ + "netdev=eth0\0" \ + "consoledev=ttyS0\0" \ + "ramdiskaddr=0x4000000\0" \ + "ramdiskfile=initrd\0" \ + "bootdev=usb\0" \ + "bootdevnum=0\0" \ + "bootdevpart=0\0" \ + "bootfsload=fatload\0" \ + "bootusb=setenv bootdev usb; boot\0" \ + "bootscsi=setenv bootdev scsi; boot\0" \ + "bootmmc=setenv bootdev mmc; boot\0" \ + "bootargs=console=ttyS0,115200 console=tty0\0" + +/* + * Override CONFIG_BOOTCOMMAND in x86-common.h + */ +#undef CONFIG_BOOTCOMMAND +#define CONFIG_BOOTCOMMAND \ + "if test ${bootdev} = \"usb\"; then ${bootdev} start; fi; " \ + "if test ${bootdev} = \"scsi\"; then ${bootdev} scan; fi; " \ + "${bootdev} info; " \ + "${bootfsload} ${bootdev} ${bootdevnum}:${bootdevpart} " \ + "${loadaddr} ${bootfile}; " \ + "${bootfsload} ${bootdev} ${bootdevnum}:${bootdevpart} " \ + "${ramdiskaddr} ${ramdiskfile}; " \ + "zboot ${loadaddr} 0 ${ramdiskaddr} ${filesize}" + +#endif /* __SLIMBOOTLOADER_CONFIG_H__ */ From dbaec467671fd5b56cf380121340844863f5472d Mon Sep 17 00:00:00 2001 From: "Park, Aiden" Date: Sat, 3 Aug 2019 08:31:20 +0000 Subject: [PATCH 19/19] x86: Skip setting up MTRRs in slimbootloader The setting up MTRRs have already been done in previous Slim Bootloader stages. Signed-off-by: Aiden Park Reviewed-by: Bin Meng Reviewed-by: Andy Shevchenko Tested-by: Bin Meng --- arch/x86/lib/init_helpers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 0481f453ca..5e19f13720 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -18,7 +18,8 @@ __weak ulong board_get_usable_ram_top(ulong total_size) int init_cache_f_r(void) { -#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP) +#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP) && \ + !defined(CONFIG_SYS_SLIMBOOTLOADER) int ret; ret = mtrr_commit(false);