diff options
111 files changed, 5191 insertions, 2546 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index c024b41f13c..e1227f847cb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -310,6 +310,15 @@ S: Maintained T: git git://git.denx.de/u-boot-i2c.git F: drivers/i2c/ +LOGGING +M: Simon Glass <sjg@chromium.org> +S: Maintained +T: git git://git.denx.de/u-boot.git +F: common/log.c +F: cmd/log.c +F: test/log/log_test.c +F: test/py/tests/test_log.py + MICROBLAZE M: Michal Simek <monstr@monstr.eu> S: Maintained diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index 5daf79e9192..5a759204009 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -5,6 +5,10 @@ config ARCH_LS1012A select SYS_FSL_DDR_BE select SYS_FSL_MMDC select SYS_FSL_ERRATUM_A010315 + select SYS_FSL_ERRATUM_A009798 + select SYS_FSL_ERRATUM_A008997 + select SYS_FSL_ERRATUM_A009007 + select SYS_FSL_ERRATUM_A009008 select ARCH_EARLY_INIT_R select BOARD_EARLY_INIT_F @@ -244,6 +248,7 @@ config SYS_LS_PPA_ESBC_ADDR default 0x40680000 if SYS_LS_PPA_FW_IN_XIP && ARCH_LS1012A default 0x20680000 if SYS_LS_PPA_FW_IN_XIP && QSPI_BOOT && ARCH_LS2080A default 0x580680000 if SYS_LS_PPA_FW_IN_XIP && ARCH_LS2080A + default 0x20680000 if SYS_LS_PPA_FW_IN_XIP && ARCH_LS1088A default 0x680000 if SYS_LS_PPA_FW_IN_MMC default 0x680000 if SYS_LS_PPA_FW_IN_NAND help diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index ab5d76ea3b6..d08262971e7 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -29,6 +29,7 @@ #include <fsl_ddr.h> #endif #include <asm/arch/clock.h> +#include <hwconfig.h> DECLARE_GLOBAL_DATA_PTR; @@ -494,6 +495,41 @@ static inline int check_psci(void) return 0; } +static void config_core_prefetch(void) +{ + char *buf = NULL; + char buffer[HWCONFIG_BUFFER_SIZE]; + const char *prefetch_arg = NULL; + size_t arglen; + unsigned int mask; + struct pt_regs regs; + + if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0) + buf = buffer; + + prefetch_arg = hwconfig_subarg_f("core_prefetch", "disable", + &arglen, buf); + + if (prefetch_arg) { + mask = simple_strtoul(prefetch_arg, NULL, 0) & 0xff; + if (mask & 0x1) { + printf("Core0 prefetch can't be disabled\n"); + return; + } + +#define SIP_PREFETCH_DISABLE_64 0xC200FF13 + regs.regs[0] = SIP_PREFETCH_DISABLE_64; + regs.regs[1] = mask; + smc_call(®s); + + if (regs.regs[0]) + printf("Prefetch disable config failed for mask "); + else + printf("Prefetch disable config passed for mask "); + printf("0x%x\n", mask); + } +} + int arch_early_init_r(void) { #ifdef CONFIG_SYS_FSL_ERRATUM_A009635 @@ -521,6 +557,8 @@ int arch_early_init_r(void) fsl_rgmii_init(); #endif + config_core_prefetch(); + #ifdef CONFIG_SYS_HAS_SERDES fsl_serdes_init(); #endif diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.core_prefetch b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.core_prefetch new file mode 100644 index 00000000000..85cf6abd6da --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.core_prefetch @@ -0,0 +1,20 @@ +Core instruction prefetch disable +--------------------------------- +To disable instruction prefetch of core; hwconfig needs to be updated. +for e.g. +setenv hwconfig 'fsl_ddr:bank_intlv=auto;core_prefetch:disable=0x02' + +Here 0x02 can be replaced with any valid value except Mask[0] bit. It +represents 64 bit mask. The 64-bit Mask has one bit for each core. +Mask[0] = core0 +Mask[1] = core1 +Mask[2] = core2 +etc +If the bit is set ('b1) in the mask, then prefetch is disabled for +that core when it is released from reset. + +core0 prefetch should not be disabled i.e. Mask[0] should never be set. +Setting Mask[0] may lead to undefined behavior. + +Once disabled, prefetch remains disabled until the next reset. +There is no function to re-enable prefetch. diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c index 497a4b541df..ae57c0e31d7 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c @@ -66,10 +66,13 @@ static void erratum_a009008(void) #ifdef CONFIG_SYS_FSL_ERRATUM_A009008 u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; -#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) set_usb_txvreftune(scfg, SCFG_USB3PRM1CR_USB1); +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) set_usb_txvreftune(scfg, SCFG_USB3PRM1CR_USB2); set_usb_txvreftune(scfg, SCFG_USB3PRM1CR_USB3); +#endif #elif defined(CONFIG_ARCH_LS2080A) set_usb_txvreftune(scfg, SCFG_USB3PRM1CR); #endif @@ -87,17 +90,21 @@ static void erratum_a009798(void) #ifdef CONFIG_SYS_FSL_ERRATUM_A009798 u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; -#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB1); +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB2); set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB3); +#endif #elif defined(CONFIG_ARCH_LS2080A) set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR); #endif #endif /* CONFIG_SYS_FSL_ERRATUM_A009798 */ } -#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) static inline void set_usb_pcstxswingfull(u32 __iomem *scfg, u32 offset) { scfg_clrsetbits32(scfg + offset / 4, @@ -109,17 +116,21 @@ static inline void set_usb_pcstxswingfull(u32 __iomem *scfg, u32 offset) static void erratum_a008997(void) { #ifdef CONFIG_SYS_FSL_ERRATUM_A008997 -#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB1); +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB2); set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB3); #endif +#endif #endif /* CONFIG_SYS_FSL_ERRATUM_A008997 */ } -#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) #define PROGRAM_USB_PHY_RX_OVRD_IN_HI(phy) \ out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_1); \ @@ -139,16 +150,18 @@ static void erratum_a008997(void) static void erratum_a009007(void) { -#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) void __iomem *usb_phy = (void __iomem *)SCFG_USB_PHY1; PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy); - +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) usb_phy = (void __iomem *)SCFG_USB_PHY2; PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy); usb_phy = (void __iomem *)SCFG_USB_PHY3; PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy); +#endif #elif defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A) void __iomem *dcsr = (void __iomem *)DCSR_BASE; diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S index ccefce0b20a..9cb70552fed 100644 --- a/arch/arm/lib/crt0_64.S +++ b/arch/arm/lib/crt0_64.S @@ -120,8 +120,9 @@ relocation_return: #endif /* !CONFIG_SPL_BUILD */ #if defined(CONFIG_SPL_BUILD) bl spl_relocate_stack_gd /* may return NULL */ - /* set up gd here, outside any C code */ - mov x18, x0 + /* set up gd here, outside any C code, if new stack is returned */ + cmp x0, #0 + csel x18, x0, x18, ne /* * Perform 'sp = (x0 != NULL) ? x0 : sp' while working * around the constraint that conditional moves can not diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index c524957b6c5..9dd90a1b304 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -421,6 +421,17 @@ int os_get_filesize(const char *fname, loff_t *size) return 0; } +void os_putc(int ch) +{ + putchar(ch); +} + +void os_puts(const char *str) +{ + while (*str) + os_putc(*str++); +} + int os_write_ram_buf(const char *fname) { struct sandbox_state *state = state_get_current(); diff --git a/board/freescale/ls1088a/Kconfig b/board/freescale/ls1088a/Kconfig index 1ada661743e..4479dd07584 100644 --- a/board/freescale/ls1088a/Kconfig +++ b/board/freescale/ls1088a/Kconfig @@ -12,6 +12,7 @@ config SYS_SOC config SYS_CONFIG_NAME default "ls1088aqds" +source "board/freescale/common/Kconfig" endif if TARGET_LS1088ARDB @@ -28,4 +29,5 @@ config SYS_SOC config SYS_CONFIG_NAME default "ls1088ardb" +source "board/freescale/common/Kconfig" endif diff --git a/board/freescale/ls1088a/MAINTAINERS b/board/freescale/ls1088a/MAINTAINERS index b3d5c388ebe..de3961d510e 100644 --- a/board/freescale/ls1088a/MAINTAINERS +++ b/board/freescale/ls1088a/MAINTAINERS @@ -15,3 +15,15 @@ F: board/freescale/ls1088a/ F: include/configs/ls1088aqds.h F: configs/ls1088aqds_qspi_defconfig F: configs/ls1088aqds_sdcard_qspi_defconfig + +LS1088AQDS_QSPI_SECURE_BOOT BOARD +M: Udit Agarwal <udit.agarwal@nxp.com> +M: Vinitha Pillai-B57223 <vinitha.pillai@nxp.com> +S: Maintained +F: configs/ls1088aqds_qspi_SECURE_BOOT_defconfig + +LS1088ARDB_QSPI_SECURE_BOOT BOARD +M: Udit Agarwal <udit.agarwal@nxp.com> +M: Vinitha Pillai-B57223 <vinitha.pillai@nxp.com> +S: Maintained +F: configs/ls1088ardb_qspi_SECURE_BOOT_defconfig diff --git a/board/freescale/ls1088a/ls1088a.c b/board/freescale/ls1088a/ls1088a.c index 96d9ae7f1dc..9daa0075908 100644 --- a/board/freescale/ls1088a/ls1088a.c +++ b/board/freescale/ls1088a/ls1088a.c @@ -315,6 +315,9 @@ int board_init(void) out_le32(irq_ccsr + IRQCR_OFFSET / 4, AQR105_IRQ_MASK); #endif +#ifdef CONFIG_FSL_CAAM + sec_init(); +#endif #ifdef CONFIG_FSL_LS_PPA ppa_init(); #endif @@ -337,9 +340,6 @@ void detail_board_ddr_info(void) #if defined(CONFIG_ARCH_MISC_INIT) int arch_misc_init(void) { -#ifdef CONFIG_FSL_CAAM - sec_init(); -#endif return 0; } #endif @@ -368,6 +368,33 @@ void fdt_fixup_board_enet(void *fdt) #endif #ifdef CONFIG_OF_BOARD_SETUP +void fsl_fdt_fixup_flash(void *fdt) +{ + int offset; + +/* + * IFC-NOR and QSPI are muxed on SoC. + * So disable IFC node in dts if QSPI is enabled or + * disable QSPI node in dts in case QSPI is not enabled. + */ + +#ifdef CONFIG_FSL_QSPI + offset = fdt_path_offset(fdt, "/soc/ifc/nor"); + + if (offset < 0) + offset = fdt_path_offset(fdt, "/ifc/nor"); +#else + offset = fdt_path_offset(fdt, "/soc/quadspi"); + + if (offset < 0) + offset = fdt_path_offset(fdt, "/quadspi"); +#endif + if (offset < 0) + return; + + fdt_status_disabled(fdt, offset); +} + int ft_board_setup(void *blob, bd_t *bd) { int err, i; @@ -394,6 +421,8 @@ int ft_board_setup(void *blob, bd_t *bd) fdt_fixup_memory_banks(blob, base, size, CONFIG_NR_DRAM_BANKS); + fsl_fdt_fixup_flash(blob); + #ifdef CONFIG_FSL_MC_ENET fdt_fixup_board_enet(blob); err = fsl_mc_ldpaa_exit(bd); diff --git a/board/theobroma-systems/puma_rk3399/puma-rk3399.c b/board/theobroma-systems/puma_rk3399/puma-rk3399.c index 0ad267cdd07..27e3823d525 100644 --- a/board/theobroma-systems/puma_rk3399/puma-rk3399.c +++ b/board/theobroma-systems/puma_rk3399/puma-rk3399.c @@ -173,7 +173,7 @@ static void setup_serial(void) serialno = crc32_no_comp(0, low, 8); serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; - snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); + snprintf(serialno_str, sizeof(serialno_str), "%016llx", serialno); env_set("cpuid#", cpuid_str); env_set("serial#", serialno_str); diff --git a/cmd/Kconfig b/cmd/Kconfig index 5a6afab99b7..c0332235261 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1502,6 +1502,14 @@ config CMD_KGDB single-stepping, inspecting variables, etc. This is supported only on PowerPC at present. +config CMD_LOG + bool "log - Generation, control and access to logging" + help + This provides access to logging features. It allows the output of + log data to be controlled to a limited extent (setting up the default + maximum log level for emitting of records). It also provides access + to a command used for testing the log system. + config CMD_TRACE bool "trace - Support tracing of function calls and timing" help diff --git a/cmd/Makefile b/cmd/Makefile index 2b0444d5b77..00e38696daa 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -76,7 +76,7 @@ obj-$(CONFIG_LED_STATUS_CMD) += legacy_led.o obj-$(CONFIG_CMD_LED) += led.o obj-$(CONFIG_CMD_LICENSE) += license.o obj-y += load.o -obj-$(CONFIG_LOGBUFFER) += log.o +obj-$(CONFIG_CMD_LOG) += log.o obj-$(CONFIG_ID_EEPROM) += mac.o obj-$(CONFIG_CMD_MD5SUM) += md5sum.o obj-$(CONFIG_CMD_MEMORY) += mem.o diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 478bc116e24..78ff109835d 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -6,10 +6,12 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include <charset.h> #include <common.h> #include <command.h> #include <dm.h> #include <efi_loader.h> +#include <efi_selftest.h> #include <errno.h> #include <libfdt.h> #include <libfdt_env.h> @@ -43,12 +45,39 @@ static void efi_init_obj_list(void) #ifdef CONFIG_GENERATE_SMBIOS_TABLE efi_smbios_register(); #endif + efi_watchdog_register(); /* Initialize EFI runtime services */ efi_reset_system_init(); efi_get_time_init(); } +/* + * Set the load options of an image from an environment variable. + * + * @loaded_image_info: the image + * @env_var: name of the environment variable + */ +static void set_load_options(struct efi_loaded_image *loaded_image_info, + const char *env_var) +{ + size_t size; + const char *env = env_get(env_var); + + loaded_image_info->load_options = NULL; + loaded_image_info->load_options_size = 0; + if (!env) + return; + size = strlen(env) + 1; + loaded_image_info->load_options = calloc(size, sizeof(u16)); + if (!loaded_image_info->load_options) { + printf("ERROR: Out of memory\n"); + return; + } + utf8_to_utf16(loaded_image_info->load_options, (u8 *)env, size); + loaded_image_info->load_options_size = size * 2; +} + static void *copy_fdt(void *fdt) { u64 fdt_size = fdt_totalsize(fdt); @@ -92,10 +121,10 @@ static void *copy_fdt(void *fdt) return new_fdt; } -static ulong efi_do_enter(void *image_handle, - struct efi_system_table *st, - asmlinkage ulong (*entry)(void *image_handle, - struct efi_system_table *st)) +static efi_status_t efi_do_enter( + void *image_handle, struct efi_system_table *st, + asmlinkage ulong (*entry)(void *image_handle, + struct efi_system_table *st)) { efi_status_t ret = EFI_LOAD_ERROR; @@ -106,7 +135,7 @@ static ulong efi_do_enter(void *image_handle, } #ifdef CONFIG_ARM64 -static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)( +static efi_status_t efi_run_in_el2(asmlinkage ulong (*entry)( void *image_handle, struct efi_system_table *st), void *image_handle, struct efi_system_table *st) { @@ -121,9 +150,9 @@ static unsigned long efi_run_in_el2(asmlinkage ulong (*entry)( * Load an EFI payload into a newly allocated piece of memory, register all * EFI objects it would want to access and jump to it. */ -static unsigned long do_bootefi_exec(void *efi, void *fdt, - struct efi_device_path *device_path, - struct efi_device_path *image_path) +static efi_status_t do_bootefi_exec(void *efi, void *fdt, + struct efi_device_path *device_path, + struct efi_device_path *image_path) { struct efi_loaded_image loaded_image_info = {}; struct efi_object loaded_image_info_obj = {}; @@ -189,6 +218,8 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt, efi_install_configuration_table(&fdt_guid, NULL); } + /* Transfer environment variable bootargs as load options */ + set_load_options(&loaded_image_info, "bootargs"); /* Load the EFI payload */ entry = efi_load_pe(efi, &loaded_image_info); if (!entry) { @@ -223,7 +254,8 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt, dcache_disable(); /* flush cache before switch to EL2 */ /* Move into EL2 and keep running there */ - armv8_switch_to_el2((ulong)entry, (ulong)&loaded_image_info, + armv8_switch_to_el2((ulong)entry, + (ulong)&loaded_image_info_obj.handle, (ulong)&systab, 0, (ulong)efi_run_in_el2, ES_TO_AARCH64); @@ -232,7 +264,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt, } #endif - ret = efi_do_enter(&loaded_image_info, &systab, entry); + ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry); exit: /* image has returned, loaded-image obj goes *poof*: */ @@ -277,7 +309,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *saddr, *sfdt; unsigned long addr, fdt_addr = 0; - unsigned long r; + efi_status_t r; if (argc < 2) return CMD_RET_USAGE; @@ -298,6 +330,12 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) struct efi_loaded_image loaded_image_info = {}; struct efi_object loaded_image_info_obj = {}; + /* Construct a dummy device path. */ + bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, + (uintptr_t)&efi_selftest, + (uintptr_t)&efi_selftest); + bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest"); + efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj, bootefi_device_path, bootefi_image_path); @@ -310,7 +348,14 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* Initialize and populate EFI object list */ if (!efi_obj_list_initalized) efi_init_obj_list(); - return efi_selftest(&loaded_image_info, &systab); + /* Transfer environment variable efi_selftest as load options */ + set_load_options(&loaded_image_info, "efi_selftest"); + /* Execute the test */ + r = efi_selftest(loaded_image_info_obj.handle, &systab); + efi_restore_gd(); + free(loaded_image_info.load_options); + list_del(&loaded_image_info_obj.link); + return r != EFI_SUCCESS; } else #endif if (!strcmp(argv[1], "bootmgr")) { @@ -356,6 +401,8 @@ static char bootefi_help_text[] = #ifdef CONFIG_CMD_BOOTEFI_SELFTEST "bootefi selftest\n" " - boot an EFI selftest application stored within U-Boot\n" + " Use environment variable efi_selftest to select a single test.\n" + " Use 'setenv efi_selftest list' to enumerate all tests.\n" #endif "bootmgr [fdt addr]\n" " - load and boot EFI payload based on BootOrder/BootXXXX variables.\n" @@ -390,6 +437,8 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path) int part; desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10)); + if (!desc) + return; part = parse_partnum(devnr); bootefi_device_path = efi_dp_from_part(desc, part); diff --git a/cmd/i2c.c b/cmd/i2c.c index 3dd7c6ba4de..bfddf8be1b9 100644 --- a/cmd/i2c.c +++ b/cmd/i2c.c @@ -1156,7 +1156,10 @@ static int do_sdram (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) uint chip; u_char data[128]; u_char cksum; - int j; + int j, ret; +#ifdef CONFIG_DM_I2C + struct udevice *dev; +#endif static const char *decode_CAS_DDR2[] = { " TBD", " 6", " 5", " 4", " 3", " 2", " TBD", " TBD" @@ -1210,7 +1213,14 @@ static int do_sdram (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) */ chip = simple_strtoul (argv[1], NULL, 16); - if (i2c_read (chip, 0, 1, data, sizeof (data)) != 0) { +#ifdef CONFIG_DM_I2C + ret = i2c_get_cur_bus_chip(chip, &dev); + if (!ret) + ret = dm_i2c_read(dev, 0, data, sizeof(data)); +#else + ret = i2c_read(chip, 0, 1, data, sizeof(data)); +#endif + if (ret) { puts ("No SDRAM Serial Presence Detect found.\n"); return 1; } diff --git a/cmd/log.c b/cmd/log.c index 7a3bd5cd690..abc523b4971 100644 --- a/cmd/log.c +++ b/cmd/log.c @@ -1,313 +1,61 @@ /* - * (C) Copyright 2002-2007 - * Detlev Zundel, DENX Software Engineering, dzu@denx.de. + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> * - * Code used from linux/kernel/printk.c - * Copyright (C) 1991, 1992 Linus Torvalds - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Comments: - * - * After relocating the code, the environment variable "loglevel" is - * copied to console_loglevel. The functionality is similar to the - * handling in the Linux kernel, i.e. messages logged with a priority - * less than console_loglevel are also output to stdout. - * - * If you want messages with the default level (e.g. POST messages) to - * appear on stdout also, make sure the environment variable - * "loglevel" is set at boot time to a number higher than - * default_message_loglevel below. - */ - -/* - * Logbuffer handling routines + * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> #include <command.h> -#include <stdio_dev.h> -#include <post.h> -#include <logbuff.h> - -DECLARE_GLOBAL_DATA_PTR; - -/* Local prototypes */ -static void logbuff_putc(struct stdio_dev *dev, const char c); -static void logbuff_puts(struct stdio_dev *dev, const char *s); -static int logbuff_printk(const char *line); - -static char buf[1024]; - -/* This combination will not print messages with the default loglevel */ -static unsigned console_loglevel = 3; -static unsigned default_message_loglevel = 4; -static unsigned log_version = 1; -#ifdef CONFIG_ALT_LB_ADDR -static volatile logbuff_t *log; -#else -static logbuff_t *log; -#endif -static char *lbuf; - -unsigned long __logbuffer_base(void) -{ - return CONFIG_SYS_SDRAM_BASE + get_effective_memsize() - LOGBUFF_LEN; -} -unsigned long logbuffer_base(void) -__attribute__((weak, alias("__logbuffer_base"))); +#include <dm.h> +#include <log.h> -void logbuff_init_ptrs(void) +static int do_log_level(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - unsigned long tag, post_word; - char *s; - -#ifdef CONFIG_ALT_LB_ADDR - log = (logbuff_t *)CONFIG_ALT_LH_ADDR; - lbuf = (char *)CONFIG_ALT_LB_ADDR; -#else - log = (logbuff_t *)(logbuffer_base()) - 1; - lbuf = (char *)log->buf; -#endif - - /* Set up log version */ - s = env_get("logversion"); - if (s) - log_version = (int)simple_strtoul(s, NULL, 10); - - if (log_version == 2) - tag = log->v2.tag; + if (argc > 1) + gd->default_log_level = simple_strtol(argv[1], NULL, 10); else - tag = log->v1.tag; - post_word = post_word_load(); -#ifdef CONFIG_POST - /* The post routines have setup the word so we can simply test it */ - if (tag != LOGBUFF_MAGIC || (post_word & POST_COLDBOOT)) - logbuff_reset(); -#else - /* No post routines, so we do our own checking */ - if (tag != LOGBUFF_MAGIC || post_word != LOGBUFF_MAGIC) { - logbuff_reset (); - post_word_store (LOGBUFF_MAGIC); - } -#endif - if (log_version == 2 && (long)log->v2.start > (long)log->v2.con) - log->v2.start = log->v2.con; - - /* Initialize default loglevel if present */ - s = env_get("loglevel"); - if (s) - console_loglevel = (int)simple_strtoul(s, NULL, 10); + printf("Default log level: %d\n", gd->default_log_level); - gd->flags |= GD_FLG_LOGINIT; + return 0; } -void logbuff_reset(void) -{ -#ifndef CONFIG_ALT_LB_ADDR - memset(log, 0, sizeof(logbuff_t)); -#endif - if (log_version == 2) { - log->v2.tag = LOGBUFF_MAGIC; -#ifdef CONFIG_ALT_LB_ADDR - log->v2.start = 0; - log->v2.con = 0; - log->v2.end = 0; - log->v2.chars = 0; +static cmd_tbl_t log_sub[] = { + U_BOOT_CMD_MKENT(level, CONFIG_SYS_MAXARGS, 1, do_log_level, "", ""), +#ifdef CONFIG_LOG_TEST + U_BOOT_CMD_MKENT(test, 2, 1, do_log_test, "", ""), #endif - } else { - log->v1.tag = LOGBUFF_MAGIC; -#ifdef CONFIG_ALT_LB_ADDR - log->v1.dummy = 0; - log->v1.start = 0; - log->v1.size = 0; - log->v1.chars = 0; -#endif - } -} +}; -int drv_logbuff_init(void) +static int do_log(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - struct stdio_dev logdev; - int rc; - - /* Device initialization */ - memset (&logdev, 0, sizeof (logdev)); - - strcpy (logdev.name, "logbuff"); - logdev.ext = 0; /* No extensions */ - logdev.flags = DEV_FLAGS_OUTPUT; /* Output only */ - logdev.putc = logbuff_putc; /* 'putc' function */ - logdev.puts = logbuff_puts; /* 'puts' function */ - - rc = stdio_register(&logdev); + cmd_tbl_t *cp; - return (rc == 0) ? 1 : rc; -} + if (argc < 2) + return CMD_RET_USAGE; -static void logbuff_putc(struct stdio_dev *dev, const char c) -{ - char buf[2]; - buf[0] = c; - buf[1] = '\0'; - logbuff_printk(buf); -} + /* drop initial "log" arg */ + argc--; + argv++; -static void logbuff_puts(struct stdio_dev *dev, const char *s) -{ - logbuff_printk (s); -} + cp = find_cmd_tbl(argv[0], log_sub, ARRAY_SIZE(log_sub)); + if (cp) + return cp->cmd(cmdtp, flag, argc, argv); -void logbuff_log(char *msg) -{ - if ((gd->flags & GD_FLG_LOGINIT)) { - logbuff_printk(msg); - } else { - /* - * Can happen only for pre-relocated errors as logging - * at that stage should be disabled - */ - puts (msg); - } + return CMD_RET_USAGE; } -/* - * Subroutine: do_log - * - * Description: Handler for 'log' command.. - * - * Inputs: argv[1] contains the subcommand - * - * Return: None - * - */ -int do_log(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct stdio_dev *sdev = NULL; - char *s; - unsigned long i, start, size; - - if (strcmp(argv[1], "append") == 0) { - /* Log concatenation of all arguments separated by spaces */ - for (i = 2; i < argc; i++) { - logbuff_printk(argv[i]); - logbuff_putc(sdev, (i < argc - 1) ? ' ' : '\n'); - } - return 0; - } - - switch (argc) { - - case 2: - if (strcmp(argv[1], "show") == 0) { - if (log_version == 2) { - start = log->v2.start; - size = log->v2.end - log->v2.start; - } else { - start = log->v1.start; - size = log->v1.size; - } - if (size > LOGBUFF_LEN) - size = LOGBUFF_LEN; - for (i = 0; i < size; i++) { - s = lbuf + ((start + i) & LOGBUFF_MASK); - putc(*s); - } - return 0; - } else if (strcmp(argv[1], "reset") == 0) { - logbuff_reset(); - return 0; - } else if (strcmp(argv[1], "info") == 0) { - printf("Logbuffer at %08lx\n", (unsigned long)lbuf); - if (log_version == 2) { - printf("log_start = %08lx\n", - log->v2.start); - printf("log_end = %08lx\n", log->v2.end); - printf("log_con = %08lx\n", log->v2.con); - printf("logged_chars = %08lx\n", - log->v2.chars); - } - else { - printf("log_start = %08lx\n", - log->v1.start); - printf("log_size = %08lx\n", - log->v1.size); - printf("logged_chars = %08lx\n", - log->v1.chars); - } - return 0; - } - return CMD_RET_USAGE; - - default: - return CMD_RET_USAGE; - } -} +#ifdef CONFIG_SYS_LONGHELP +static char log_help_text[] = + "level - get/set log level\n" +#ifdef CONFIG_LOG_TEST + "log test - run log tests\n" +#endif + ; +#endif U_BOOT_CMD( - log, 255, 1, do_log, - "manipulate logbuffer", - "info - show pointer details\n" - "log reset - clear contents\n" - "log show - show contents\n" - "log append <msg> - append <msg> to the logbuffer" + log, CONFIG_SYS_MAXARGS, 1, do_log, + "log system", log_help_text ); - -static int logbuff_printk(const char *line) -{ - int i; - char *msg, *p, *buf_end; - int line_feed; - static signed char msg_level = -1; - - strcpy(buf + 3, line); - i = strlen(line); - buf_end = buf + 3 + i; - for (p = buf + 3; p < buf_end; p++) { - msg = p; - if (msg_level < 0) { - if ( - p[0] != '<' || - p[1] < '0' || - p[1] > '7' || - p[2] != '>' - ) { - p -= 3; - p[0] = '<'; - p[1] = default_message_loglevel + '0'; - p[2] = '>'; - } else { - msg += 3; - } - msg_level = p[1] - '0'; - } - line_feed = 0; - for (; p < buf_end; p++) { - if (log_version == 2) { - lbuf[log->v2.end & LOGBUFF_MASK] = *p; - log->v2.end++; - if (log->v2.end - log->v2.start > LOGBUFF_LEN) - log->v2.start++; - log->v2.chars++; - } else { - lbuf[(log->v1.start + log->v1.size) & - LOGBUFF_MASK] = *p; - if (log->v1.size < LOGBUFF_LEN) - log->v1.size++; - else - log->v1.start++; - log->v1.chars++; - } - if (*p == '\n') { - line_feed = 1; - break; - } - } - if (msg_level < console_loglevel) { - printf("%s", msg); - } - if (line_feed) - msg_level = -1; - } - return i; -} diff --git a/cmd/mtdparts.c b/cmd/mtdparts.c index 3169c33265c..9bc977450cf 100644 --- a/cmd/mtdparts.c +++ b/cmd/mtdparts.c @@ -873,15 +873,12 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_ return 1; } -#ifdef DEBUG pend = strchr(p, ';'); -#endif debug("dev type = %d (%s), dev num = %d, mtd-id = %s\n", id->type, MTD_DEV_TYPE(id->type), id->num, id->mtd_id); debug("parsing partitions %.*s\n", (int)(pend ? pend - p : strlen(p)), p); - /* parse partitions */ num_parts = 0; diff --git a/common/Kconfig b/common/Kconfig index c50d6ebb2ad..4da095a4fd7 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -420,6 +420,92 @@ config SYS_STDIO_DEREGISTER endmenu +menu "Logging" + +config LOG + bool "Enable logging support" + help + This enables support for logging of status and debug messages. These + can be displayed on the console, recorded in a memory buffer, or + discarded if not needed. Logging supports various categories and + levels of severity. + +config SPL_LOG + bool "Enable logging support in SPL" + help + This enables support for logging of status and debug messages. These + can be displayed on the console, recorded in a memory buffer, or + discarded if not needed. Logging supports various categories and + levels of severity. + +config LOG_MAX_LEVEL + int "Maximum log level to record" + depends on LOG + default 5 + help + This selects the maximum log level that will be recorded. Any value + higher than this will be ignored. If possible log statements below + this level will be discarded at build time. Levels: + + 0 - panic + 1 - critical + 2 - error + 3 - warning + 4 - note + 5 - info + 6 - detail + 7 - debug + +config SPL_LOG_MAX_LEVEL + int "Maximum log level to record in SPL" + depends on SPL_LOG + default 3 + help + This selects the maximum log level that will be recorded. Any value + higher than this will be ignored. If possible log statements below + this level will be discarded at build time. Levels: + + 0 - panic + 1 - critical + 2 - error + 3 - warning + 4 - note + 5 - info + 6 - detail + 7 - debug + +config LOG_CONSOLE + bool "Allow log output to the console" + depends on LOG + default y + help + Enables a log driver which writes log records to the console. + Generally the console is the serial port or LCD display. Only the + log message is shown - other details like level, category, file and + line number are omitted. + +config LOG_SPL_CONSOLE + bool "Allow log output to the console in SPL" + depends on LOG_SPL + default y + help + Enables a log driver which writes log records to the console. + Generally the console is the serial port or LCD display. Only the + log message is shown - other details like level, category, file and + line number are omitted. + +config LOG_TEST + bool "Provide a test for logging" + depends on LOG + default y if SANDBOX + help + This enables a 'log test' command to test logging. It is normally + executed from a pytest and simply outputs logging information + in various different ways to test that the logging system works + correctly with varoius settings. + +endmenu + config DEFAULT_FDT_FILE string "Default fdt file" help diff --git a/common/Makefile b/common/Makefile index cec506fe3e1..14166209fe4 100644 --- a/common/Makefile +++ b/common/Makefile @@ -128,5 +128,7 @@ obj-y += cli.o obj-$(CONFIG_FSL_DDR_INTERACTIVE) += cli_simple.o cli_readline.o obj-$(CONFIG_CMD_DFU) += dfu.o obj-y += command.o +obj-$(CONFIG_$(SPL_)LOG) += log.o +obj-$(CONFIG_$(SPL_)LOG_CONSOLE) += log_console.o obj-y += s_record.o obj-y += xyzModem.o diff --git a/common/board_f.c b/common/board_f.c index 9220815441e..e46eceda7d0 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -19,7 +19,6 @@ #include <i2c.h> #include <initcall.h> #include <init_helpers.h> -#include <logbuff.h> #include <malloc.h> #include <mapmem.h> #include <os.h> @@ -296,20 +295,6 @@ static int setup_dest_addr(void) return 0; } -#if defined(CONFIG_LOGBUFFER) -static int reserve_logbuffer(void) -{ -#ifndef CONFIG_ALT_LB_ADDR - /* reserve kernel log buffer */ - gd->relocaddr -= LOGBUFF_RESERVE; - debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, - gd->relocaddr); -#endif - - return 0; -} -#endif - #ifdef CONFIG_PRAM /* reserve protected RAM */ static int reserve_pram(void) @@ -766,6 +751,7 @@ static const init_fnc_t init_sequence_f[] = { trace_early_init, #endif initf_malloc, + log_init, initf_bootstage, /* uses its own timer, so does not need DM */ initf_console_record, #if defined(CONFIG_HAVE_FSP) @@ -846,9 +832,6 @@ static const init_fnc_t init_sequence_f[] = { * - board info struct */ setup_dest_addr, -#if defined(CONFIG_LOGBUFFER) - reserve_logbuffer, -#endif #ifdef CONFIG_PRAM reserve_pram, #endif @@ -950,8 +933,10 @@ void board_init_f_r(void) * The pre-relocation drivers may be using memory that has now gone * away. Mark serial as unavailable - this will fall back to the debug * UART if available. + * + * Do the same with log drivers since the memory may not be available. */ - gd->flags &= ~GD_FLG_SERIAL_READY; + gd->flags &= ~(GD_FLG_SERIAL_READY | GD_FLG_LOG_READY); #ifdef CONFIG_TIMER gd->timer = NULL; #endif diff --git a/common/board_r.c b/common/board_r.c index a3b9bfb8ee4..09167c13cc8 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -30,7 +30,6 @@ #if defined(CONFIG_CMD_KGDB) #include <kgdb.h> #endif -#include <logbuff.h> #include <malloc.h> #include <mapmem.h> #ifdef CONFIG_BITBANGMII @@ -200,19 +199,6 @@ static int initr_addr_map(void) } #endif -#ifdef CONFIG_LOGBUFFER -unsigned long logbuffer_base(void) -{ - return gd->ram_top - LOGBUFF_LEN; -} - -static int initr_logbuffer(void) -{ - logbuff_init_ptrs(); - return 0; -} -#endif - #ifdef CONFIG_POST static int initr_post_backlog(void) { @@ -628,7 +614,7 @@ static int initr_ide(void) } #endif -#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER) +#if defined(CONFIG_PRAM) /* * Export available size of memory for Linux, taking into account the * protected RAM at top of memory @@ -641,10 +627,6 @@ int initr_mem(void) # ifdef CONFIG_PRAM pram = env_get_ulong("pram", 10, CONFIG_PRAM); # endif -# if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR) - /* Also take the logbuffer into account (pram is in kB) */ - pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024; -# endif sprintf(memsz, "%ldk", (long int) ((gd->ram_size / 1024) - pram)); env_set("mem", memsz); @@ -709,6 +691,7 @@ static init_fnc_t init_sequence_r[] = { #endif initr_barrier, initr_malloc, + log_init, initr_bootstage, /* Needs malloc() but has its own timer */ initr_console_record, #ifdef CONFIG_SYS_NONCACHED_MEMORY @@ -753,9 +736,6 @@ static init_fnc_t init_sequence_r[] = { board_early_init_r, #endif INIT_FUNC_WATCHDOG_RESET -#ifdef CONFIG_LOGBUFFER - initr_logbuffer, -#endif #ifdef CONFIG_POST initr_post_backlog, #endif @@ -877,7 +857,7 @@ static init_fnc_t init_sequence_r[] = { INIT_FUNC_WATCHDOG_RESET initr_bedbug, #endif -#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER) +#if defined(CONFIG_PRAM) initr_mem, #endif #ifdef CONFIG_PS2KBD @@ -905,6 +885,7 @@ void board_init_r(gd_t *new_gd, ulong dest_addr) #if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) gd = new_gd; #endif + gd->flags &= ~GD_FLG_LOG_READY; #ifdef CONFIG_NEEDS_MANUAL_RELOC for (i = 0; i < ARRAY_SIZE(init_sequence_r); i++) diff --git a/common/console.c b/common/console.c index d763f2c6846..0e0295514b2 100644 --- a/common/console.c +++ b/common/console.c @@ -489,6 +489,13 @@ static inline void print_pre_console_buffer(int flushpoint) {} void putc(const char c) { +#ifdef CONFIG_SANDBOX + /* sandbox can send characters to stdout before it has a console */ + if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) { + os_putc(c); + return; + } +#endif #ifdef CONFIG_DEBUG_UART /* if we don't have a console yet, use the debug UART */ if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) { diff --git a/common/image.c b/common/image.c index 4ec4744589f..4bcf6b3128a 100644 --- a/common/image.c +++ b/common/image.c @@ -15,10 +15,6 @@ #include <status_led.h> #endif -#ifdef CONFIG_LOGBUFFER -#include <logbuff.h> -#endif - #include <rtc.h> #include <environment.h> @@ -1154,11 +1150,6 @@ int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, } -#ifdef CONFIG_LOGBUFFER - /* Prevent initrd from overwriting logbuffer */ - lmb_reserve(lmb, logbuffer_base() - LOGBUFF_OVERHEAD, LOGBUFF_RESERVE); -#endif - debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n", initrd_high, initrd_copy_to_ram); diff --git a/common/log.c b/common/log.c new file mode 100644 index 00000000000..45e46dd5209 --- /dev/null +++ b/common/log.c @@ -0,0 +1,245 @@ +/* + * Logging support + * + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <log.h> +#include <malloc.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct log_device *log_device_find_by_name(const char *drv_name) +{ + struct log_device *ldev; + + list_for_each_entry(ldev, &gd->log_head, sibling_node) { + if (!strcmp(drv_name, ldev->drv->name)) + return ldev; + } + + return NULL; +} + +/** + * log_has_cat() - check if a log category exists within a list + * + * @cat_list: List of categories to check, at most LOGF_MAX_CATEGORIES entries + * long, terminated by LC_END if fewer + * @cat: Category to search for + * @return true if @cat is in @cat_list, else false + */ +static bool log_has_cat(enum log_category_t cat_list[], enum log_category_t cat) +{ + int i; + + for (i = 0; i < LOGF_MAX_CATEGORIES && cat_list[i] != LOGC_END; i++) { + if (cat_list[i] == cat) + return true; + } + + return false; +} + +/** + * log_has_file() - check if a file is with a list + * + * @file_list: List of files to check, separated by comma + * @file: File to check for. This string is matched against the end of each + * file in the list, i.e. ignoring any preceding path. The list is + * intended to consist of relative pathnames, e.g. common/main.c,cmd/log.c + * @return true if @file is in @file_list, else false + */ +static bool log_has_file(const char *file_list, const char *file) +{ + int file_len = strlen(file); + const char *s, *p; + int substr_len; + + for (s = file_list; *s; s = p + (*p != '\0')) { + p = strchrnul(s, ','); + substr_len = p - s; + if (file_len >= substr_len && + !strncmp(file + file_len - substr_len, s, substr_len)) + return true; + } + + return false; +} + +/** + * log_passes_filters() - check if a log record passes the filters for a device + * + * @ldev: Log device to check + * @rec: Log record to check + * @return true if @rec is not blocked by the filters in @ldev, false if it is + */ +static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec) +{ + struct log_filter *filt; + + /* If there are no filters, filter on the default log level */ + if (list_empty(&ldev->filter_head)) { + if (rec->level > gd->default_log_level) + return false; + return true; + } + + list_for_each_entry(filt, &ldev->filter_head, sibling_node) { + if (rec->level > filt->max_level) + continue; + if ((filt->flags & LOGFF_HAS_CAT) && + !log_has_cat(filt->cat_list, rec->cat)) + continue; + if (filt->file_list && + !log_has_file(filt->file_list, rec->file)) + continue; + return true; + } + + return false; +} + +/** + * log_dispatch() - Send a log record to all log devices for processing + * + * The log record is sent to each log device in turn, skipping those which have + * filters which block the record + * + * @rec: Log record to dispatch + * @return 0 (meaning success) + */ +static int log_dispatch(struct log_rec *rec) +{ + struct log_device *ldev; + + list_for_each_entry(ldev, &gd->log_head, sibling_node) { + if (log_passes_filters(ldev, rec)) + ldev->drv->emit(ldev, rec); + } + + return 0; +} + +int _log(enum log_category_t cat, enum log_level_t level, const char *file, + int line, const char *func, const char *fmt, ...) +{ + char buf[CONFIG_SYS_CBSIZE]; + struct log_rec rec; + va_list args; + + rec.cat = cat; + rec.level = level; + rec.file = file; + rec.line = line; + rec.func = func; + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + rec.msg = buf; + if (!gd || !(gd->flags & GD_FLG_LOG_READY)) { + if (gd) + gd->log_drop_count++; + return -ENOSYS; + } + log_dispatch(&rec); + + return 0; +} + +int log_add_filter(const char *drv_name, enum log_category_t cat_list[], + enum log_level_t max_level, const char *file_list) +{ + struct log_filter *filt; + struct log_device *ldev; + int i; + + ldev = log_device_find_by_name(drv_name); + if (!ldev) + return -ENOENT; + filt = (struct log_filter *)calloc(1, sizeof(*filt)); + if (!filt) + return -ENOMEM; + + if (cat_list) { + filt->flags |= LOGFF_HAS_CAT; + for (i = 0; ; i++) { + if (i == ARRAY_SIZE(filt->cat_list)) + return -ENOSPC; + filt->cat_list[i] = cat_list[i]; + if (cat_list[i] == LOGC_END) + break; + } + } + filt->max_level = max_level; + if (file_list) { + filt->file_list = strdup(file_list); + if (!filt->file_list) + goto nomem; + } + filt->filter_num = ldev->next_filter_num++; + list_add_tail(&filt->sibling_node, &ldev->filter_head); + + return filt->filter_num; + +nomem: + free(filt); + return -ENOMEM; +} + +int log_remove_filter(const char *drv_name, int filter_num) +{ + struct log_filter *filt; + struct log_device *ldev; + + ldev = log_device_find_by_name(drv_name); + if (!ldev) + return -ENOENT; + + list_for_each_entry(filt, &ldev->filter_head, sibling_node) { + if (filt->filter_num == filter_num) { + list_del(&filt->sibling_node); + free(filt); + + return 0; + } + } + + return -ENOENT; +} + +int log_init(void) +{ + struct log_driver *drv = ll_entry_start(struct log_driver, log_driver); + const int count = ll_entry_count(struct log_driver, log_driver); + struct log_driver *end = drv + count; + + /* + * We cannot add runtime data to the driver since it is likely stored + * in rodata. Instead, set up a 'device' corresponding to each driver. + * We only support having a single device. + */ + INIT_LIST_HEAD((struct list_head *)&gd->log_head); + while (drv < end) { + struct log_device *ldev; + + ldev = calloc(1, sizeof(*ldev)); + if (!ldev) { + debug("%s: Cannot allocate memory\n", __func__); + return -ENOMEM; + } + INIT_LIST_HEAD(&ldev->filter_head); + ldev->drv = drv; + list_add_tail(&ldev->sibling_node, + (struct list_head *)&gd->log_head); + drv++; + } + gd->flags |= GD_FLG_LOG_READY; + gd->default_log_level = LOGL_INFO; + + return 0; +} diff --git a/common/log_console.c b/common/log_console.c new file mode 100644 index 00000000000..5af73bd8be4 --- /dev/null +++ b/common/log_console.c @@ -0,0 +1,23 @@ +/* + * Logging support + * + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <log.h> + +static int log_console_emit(struct log_device *ldev, struct log_rec *rec) +{ + puts(rec->msg); + + return 0; +} + +LOG_DRIVER(console) = { + .name = "console", + .emit = log_console_emit, +}; diff --git a/common/stdio.c b/common/stdio.c index ee4f0bda9ea..2e5143a0255 100644 --- a/common/stdio.c +++ b/common/stdio.c @@ -17,9 +17,6 @@ #include <malloc.h> #include <stdio_dev.h> #include <serial.h> -#ifdef CONFIG_LOGBUFFER -#include <logbuff.h> -#endif #if defined(CONFIG_SYS_I2C) #include <i2c.h> @@ -381,9 +378,6 @@ int stdio_add_devices(void) #if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD) drv_keyboard_init (); #endif -#ifdef CONFIG_LOGBUFFER - drv_logbuff_init (); -#endif drv_system_init (); serial_stdio_init (); #ifdef CONFIG_USB_TTY diff --git a/common/usb_hub.c b/common/usb_hub.c index 024dadb2774..b46dfa16ccf 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -625,7 +625,7 @@ static int usb_hub_configure(struct usb_device *dev) short hubCharacteristics; struct usb_hub_descriptor *descriptor; struct usb_hub_device *hub; - __maybe_unused struct usb_hub_status *hubsts; + struct usb_hub_status *hubsts; int ret; hub = usb_get_hub_device(dev); @@ -779,9 +779,7 @@ static int usb_hub_configure(struct usb_device *dev) return ret; } -#ifdef DEBUG hubsts = (struct usb_hub_status *)buffer; -#endif debug("get_hub_status returned status %X, change %X\n", le16_to_cpu(hubsts->wHubStatus), diff --git a/configs/ls1088aqds_qspi_SECURE_BOOT_defconfig b/configs/ls1088aqds_qspi_SECURE_BOOT_defconfig new file mode 100644 index 00000000000..529651be75a --- /dev/null +++ b/configs/ls1088aqds_qspi_SECURE_BOOT_defconfig @@ -0,0 +1,47 @@ +CONFIG_ARM=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PING=y +CONFIG_CMD_SF=y +CONFIG_CMD_USB=y +# CONFIG_SYS_MALLOC_F is not set +CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1088a-qds" +CONFIG_DM=y +CONFIG_DM_PCI=y +CONFIG_DM_PCI_COMPAT=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y +CONFIG_DM_USB=y +CONFIG_EFI_LOADER_BOUNCE_BUFFER=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_E1000=y +CONFIG_FIT_VERBOSE=y +CONFIG_FSL_CAAM=y +CONFIG_FSL_DSPI=y +CONFIG_FSL_LS_PPA=y +CONFIG_HUSH_PARSER=y +CONFIG_NETDEVICES=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_OF_CONTROL=y +CONFIG_OF_STDOUT_VIA_ALIAS=y +CONFIG_PCI=y +CONFIG_PCIE_LAYERSCAPE=y +CONFIG_RSA=y +CONFIG_RSA_SOFTWARE_EXP=y +CONFIG_SECURE_BOOT=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4, QSPI_BOOT" +CONFIG_SYS_NS16550=y +CONFIG_TARGET_LS1088AQDS=y +CONFIG_USB=y +CONFIG_USB_DWC3=y +CONFIG_USB_GADGET=y +CONFIG_USB_STORAGE=y +CONFIG_USB_XHCI_DWC3=y +CONFIG_USB_XHCI_HCD=y +# CONFIG_DISPLAY_BOARDINFO is not set +# CONFIG_USE_BOOTCOMMAND is not set diff --git a/configs/ls1088aqds_qspi_defconfig b/configs/ls1088aqds_qspi_defconfig index 850be3ebc9b..58276f7f3c1 100644 --- a/configs/ls1088aqds_qspi_defconfig +++ b/configs/ls1088aqds_qspi_defconfig @@ -8,6 +8,7 @@ CONFIG_OF_BOARD_SETUP=y CONFIG_OF_STDOUT_VIA_ALIAS=y CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4, QSPI_BOOT" # CONFIG_DISPLAY_BOARDINFO is not set +# CONFIG_USE_BOOTCOMMAND is not set CONFIG_HUSH_PARSER=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y diff --git a/configs/ls1088aqds_sdcard_qspi_defconfig b/configs/ls1088aqds_sdcard_qspi_defconfig index 214de5459db..8629800a2ba 100644 --- a/configs/ls1088aqds_sdcard_qspi_defconfig +++ b/configs/ls1088aqds_sdcard_qspi_defconfig @@ -14,6 +14,7 @@ CONFIG_PARTITIONS=y CONFIG_SYS_EXTRA_OPTIONS="SD_BOOT_QSPI" CONFIG_SD_BOOT=y # CONFIG_DISPLAY_BOARDINFO is not set +# CONFIG_USE_BOOTCOMMAND is not set CONFIG_SPL=y CONFIG_SPL_BUILD=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y diff --git a/configs/ls1088ardb_qspi_SECURE_BOOT_defconfig b/configs/ls1088ardb_qspi_SECURE_BOOT_defconfig new file mode 100644 index 00000000000..e800966e7e8 --- /dev/null +++ b/configs/ls1088ardb_qspi_SECURE_BOOT_defconfig @@ -0,0 +1,48 @@ +CONFIG_ARM=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PING=y +CONFIG_CMD_SF=y +CONFIG_CMD_USB=y +# CONFIG_SYS_MALLOC_F is not set +CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1088a-rdb" +CONFIG_DISTRO_DEFAULTS=y +CONFIG_DM=y +CONFIG_DM_PCI=y +CONFIG_DM_PCI_COMPAT=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y +CONFIG_DM_USB=y +CONFIG_EFI_LOADER_BOUNCE_BUFFER=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_E1000=y +CONFIG_FIT_VERBOSE=y +CONFIG_FSL_CAAM=y +CONFIG_FSL_DSPI=y +CONFIG_FSL_LS_PPA=y +CONFIG_HUSH_PARSER=y +CONFIG_NETDEVICES=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_OF_CONTROL=y +CONFIG_OF_STDOUT_VIA_ALIAS=y +CONFIG_PCI=y +CONFIG_PCIE_LAYERSCAPE=y +CONFIG_RSA=y +CONFIG_RSA_SOFTWARE_EXP=y +CONFIG_SECURE_BOOT=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4, QSPI_BOOT" +CONFIG_SYS_NS16550=y +CONFIG_TARGET_LS1088ARDB=y +CONFIG_USB=y +CONFIG_USB_DWC3=y +CONFIG_USB_GADGET=y +CONFIG_USB_STORAGE=y +CONFIG_USB_XHCI_DWC3=y +CONFIG_USB_XHCI_HCD=y +# CONFIG_DISPLAY_BOARDINFO is not set +# CONFIG_USE_BOOTCOMMAND is not set diff --git a/configs/ls1088ardb_qspi_defconfig b/configs/ls1088ardb_qspi_defconfig index 1f3d5812444..bb5e72cbcd7 100644 --- a/configs/ls1088ardb_qspi_defconfig +++ b/configs/ls1088ardb_qspi_defconfig @@ -9,6 +9,7 @@ CONFIG_OF_BOARD_SETUP=y CONFIG_OF_STDOUT_VIA_ALIAS=y CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4, QSPI_BOOT" # CONFIG_DISPLAY_BOARDINFO is not set +# CONFIG_USE_BOOTCOMMAND is not set CONFIG_HUSH_PARSER=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y diff --git a/configs/ls1088ardb_sdcard_qspi_defconfig b/configs/ls1088ardb_sdcard_qspi_defconfig index 8e5cf3bc5b2..7c143e9f917 100644 --- a/configs/ls1088ardb_sdcard_qspi_defconfig +++ b/configs/ls1088ardb_sdcard_qspi_defconfig @@ -15,6 +15,7 @@ CONFIG_PARTITIONS=y CONFIG_SYS_EXTRA_OPTIONS="SD_BOOT_QSPI" CONFIG_SD_BOOT=y # CONFIG_DISPLAY_BOARDINFO is not set +# CONFIG_USE_BOOTCOMMAND is not set CONFIG_SPL=y CONFIG_SPL_BUILD=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y diff --git a/configs/ls2080aqds_SECURE_BOOT_defconfig b/configs/ls2080aqds_SECURE_BOOT_defconfig index ee6043e704d..17a077d8d71 100644 --- a/configs/ls2080aqds_SECURE_BOOT_defconfig +++ b/configs/ls2080aqds_SECURE_BOOT_defconfig @@ -1,12 +1,13 @@ CONFIG_ARM=y CONFIG_TARGET_LS2080AQDS=y +CONFIG_FSL_LS_PPA=y CONFIG_SECURE_BOOT=y CONFIG_DEFAULT_DEVICE_TREE="fsl-ls2080a-qds" # CONFIG_SYS_MALLOC_F is not set -CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_STDOUT_VIA_ALIAS=y +CONFIG_ENV_IS_IN_FLASH=y CONFIG_BOOTDELAY=10 CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 root=/dev/ram0 earlycon=uart8250,mmio,0x21c0500 ramdisk_size=0x2000000 default_hugepagesz=2m hugepagesz=2m hugepages=256" @@ -28,6 +29,7 @@ CONFIG_CMD_DATE=y CONFIG_OF_CONTROL=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y +CONFIG_FSL_CAAM=y CONFIG_MTD_NOR_FLASH=y CONFIG_DM_SPI_FLASH=y CONFIG_PHYLIB=y @@ -47,6 +49,5 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y CONFIG_RSA=y -CONFIG_SPL_RSA=y CONFIG_RSA_SOFTWARE_EXP=y CONFIG_EFI_LOADER_BOUNCE_BUFFER=y diff --git a/configs/ls2080ardb_SECURE_BOOT_defconfig b/configs/ls2080ardb_SECURE_BOOT_defconfig index 01fc9e65b7d..37137f44259 100644 --- a/configs/ls2080ardb_SECURE_BOOT_defconfig +++ b/configs/ls2080ardb_SECURE_BOOT_defconfig @@ -1,12 +1,13 @@ CONFIG_ARM=y CONFIG_TARGET_LS2080ARDB=y +CONFIG_FSL_LS_PPA=y CONFIG_SECURE_BOOT=y CONFIG_DEFAULT_DEVICE_TREE="fsl-ls2080a-rdb" # CONFIG_SYS_MALLOC_F is not set -CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_STDOUT_VIA_ALIAS=y +CONFIG_ENV_IS_IN_FLASH=y CONFIG_BOOTDELAY=10 CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS1,115200 root=/dev/ram0 earlycon=uart8250,mmio,0x21c0600 ramdisk_size=0x2000000 default_hugepagesz=2m hugepagesz=2m hugepages=256" @@ -27,6 +28,7 @@ CONFIG_CMD_DATE=y CONFIG_OF_CONTROL=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y +CONFIG_FSL_CAAM=y CONFIG_MTD_NOR_FLASH=y CONFIG_DM_SPI_FLASH=y CONFIG_PHYLIB=y @@ -46,6 +48,5 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y CONFIG_RSA=y -CONFIG_SPL_RSA=y CONFIG_RSA_SOFTWARE_EXP=y CONFIG_EFI_LOADER_BOUNCE_BUFFER=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 08eec8ecc6f..7efb4ebf117 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -15,7 +15,9 @@ CONFIG_CONSOLE_RECORD=y CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 CONFIG_SILENT_CONSOLE=y CONFIG_PRE_CONSOLE_BUFFER=y -CONFIG_PRE_CON_BUF_ADDR=0 +CONFIG_PRE_CON_BUF_ADDR=0x100000 +CONFIG_LOG=y +CONFIG_LOG_MAX_LEVEL=6 CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y CONFIG_CMD_BOOTZ=y @@ -64,6 +66,7 @@ CONFIG_CMD_CBFS=y CONFIG_CMD_CRAMFS=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_MTDPARTS=y +CONFIG_CMD_LOG=y CONFIG_MAC_PARTITION=y CONFIG_AMIGA_PARTITION=y CONFIG_OF_CONTROL=y diff --git a/doc/README.log b/doc/README.log new file mode 100644 index 00000000000..f653fe7d797 --- /dev/null +++ b/doc/README.log @@ -0,0 +1,214 @@ +Logging in U-Boot +================= + +Introduction +------------ + +U-Boot's internal operation involves many different steps and actions. From +setting up the board to displaying a start-up screen to loading an Operating +System, there are many component parts each with many actions. + +Most of the time this internal detail is not useful. Displaying it on the +console would delay booting (U-Boot's primary purpose) and confuse users. + +But for digging into what is happening in a particular area, or for debugging +a problem it is often useful to see what U-Boot is doing in more detail than +is visible from the basic console output. + +U-Boot's logging feature aims to satisfy this goal for both users and +developers. + + +Logging levels +-------------- + +There are a number logging levels available, in increasing order of verbosity: + + LOGL_EMERG - Printed before U-Boot halts + LOGL_ALERT - Indicates action must be taken immediate or U-Boot will crash + LOGL_CRIT - Indicates a critical error that will cause boot failure + LOGL_ERR - Indicates an error that may cause boot failure + LOGL_WARNING - Warning about an unexpected condition + LOGL_NOTE - Important information about progress + LOGL_INFO - Information about normal boot progress + LOGL_DEBUG - Debug information (useful for debugging a driver or subsystem) + LOGL_DEBUG_CONTENT - Debug message showing full message content + LOGL_DEBUG_IO - Debug message showing hardware I/O access + + +Logging category +---------------- + +Logging can come from a wide variety of places within U-Boot. Each log message +has a category which is intended to allow messages to be filtered according to +their source. + +The following main categories are defined: + + LOGC_NONE - Unknown category (e.g. a debug() statement) + UCLASS_... - Related to a particular uclass (e.g. UCLASS_USB) + LOGC_ARCH - Related to architecture-specific code + LOGC_BOARD - Related to board-specific code + LOGC_CORE - Related to core driver-model support + LOGC_DT - Related to device tree control + + +Enabling logging +---------------- + +The following options are used to enable logging at compile time: + + CONFIG_LOG - Enables the logging system + CONFIG_MAX_LOG_LEVEL - Max log level to build (anything higher is compiled + out) + CONFIG_LOG_CONSOLE - Enable writing log records to the console + +If CONFIG_LOG is not set, then no logging will be available. + +The above have SPL versions also, e.g. CONFIG_SPL_MAX_LOG_LEVEL. + + +Using DEBUG +----------- + +U-Boot has traditionally used a #define called DEBUG to enable debugging on a +file-by-file basis. The debug() macro compiles to a printf() statement if +DEBUG is enabled, and an empty statement if not. + +With logging enabled, debug() statements are interpreted as logging output +with a level of LOGL_DEBUG and a category of LOGC_NONE. + +The logging facilities are intended to replace DEBUG, but if DEBUG is defined +at the top of a file, then it takes precedence. This means that debug() +statements will result in output to the console and this output will not be +logged. + + +Logging destinations +-------------------- + +If logging information goes nowhere then it serves no purpose. U-Boot provides +several possible determinations for logging information, all of which can be +enabled or disabled independently: + + console - goes to stdout + + +Filters +------- + +Filters are attached to log drivers to control what those drivers emit. Only +records that pass through the filter make it to the driver. + +Filters can be based on several criteria: + + - maximum log level + - in a set of categories + - in a set of files + +If no filters are attached to a driver then a default filter is used, which +limits output to records with a level less than CONFIG_LOG_MAX_LEVEL. + + +Logging statements +------------------ + +The main logging function is: + + log(category, level, format_string, ...) + +Also debug() and error() will generate log records - these use LOG_CATEGORY +as the category, so you should #define this right at the top of the source +file to ensure the category is correct. + + +Code size +--------- + +Code size impact depends largely on what is enabled. The following numbers are +for snow, which is a Thumb-2 board: + +This series: adds bss +20.0 data +4.0 rodata +4.0 text +44.0 +CONFIG_LOG: bss -52.0 data +92.0 rodata -635.0 text +1048.0 +CONFIG_LOG_MAX_LEVEL=7: bss +188.0 data +4.0 rodata +49183.0 text +98124.0 + +The last option turns every debug() statement into a logging call, which +bloats the code hugely. The advantage is that it is then possible to enable +all logging within U-Boot. + + +To Do +----- + +There are lots of useful additions that could be made. None of the below is +implemented! If you do one, please add a test in test/py/tests/test_log.py + +Convenience functions to support setting the category: + + log_arch(level, format_string, ...) - category LOGC_ARCH + log_board(level, format_string, ...) - category LOGC_BOARD + log_core(level, format_string, ...) - category LOGC_CORE + log_dt(level, format_string, ...) - category LOGC_DT + +Convenience functions to support a category defined for a single file, for +example: + + #define LOG_CATEGORY UCLASS_USB + +all of these can use LOG_CATEGORY as the category, and a log level +corresponding to the function name: + + logc(level, format_string, ...) + +More logging destinations: + + device - goes to a device (e.g. serial) + buffer - recorded in a memory buffer + +Convert debug() statements in the code to log() statements + +Support making printf() emit log statements a L_INFO level + +Convert error() statements in the code to log() statements + +Figure out what to do with BUG(), BUG_ON() and warn_non_spl() + +Figure out what to do with assert() + +Add a way to browse log records + +Add a way to record log records for browsing using an external tool + +Add commands to add and remove filters + +Add commands to add and remove log devices + +Allow sharing of printf format strings in log records to reduce storage size +for large numbers of log records + +Add a command-line option to sandbox to set the default logging level + +Convert core driver model code to use logging + +Convert uclasses to use logging with the correct category + +Consider making log() calls emit an automatic newline, perhaps with a logn() + function to avoid that + +Passing log records through to linux (e.g. via device tree /chosen) + +Provide a command to access the number of log records generated, and the +number dropped due to them being generated before the log system was ready. + +Add a printf() format string pragma so that log statements are checked properly + +Enhance the log console driver to show level / category / file / line +information + +Add a command to add new log records and delete existing records. + +Provide additional log() functions - e.g. logc() to specify the category + +-- +Simon Glass <sjg@chromium.org> +15-Sep-17 diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index cc370b9c57c..0630712e4a4 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -141,7 +141,12 @@ config SYS_I2C_MESON bool "Amlogic Meson I2C driver" depends on DM_I2C && ARCH_MESON help - Add support for the Amlogic Meson I2C driver. + Add support for the I2C controller available in Amlogic Meson + SoCs. The controller supports programmable bus speed including + standard (100kbits/s) and fast (400kbit/s) speed and allows the + software to define a flexible format of the bit streams. It has an + internal buffer holding up to 8 bytes for transfers and supports + both 7-bit and 10-bit addresses. config SYS_I2C_MXC bool "NXP i.MX I2C driver" diff --git a/drivers/i2c/at91_i2c.c b/drivers/i2c/at91_i2c.c index d394044f80d..7917ca12312 100644 --- a/drivers/i2c/at91_i2c.c +++ b/drivers/i2c/at91_i2c.c @@ -72,6 +72,8 @@ static int at91_i2c_xfer_msg(struct at91_i2c_bus *bus, struct i2c_msg *msg) } else { writel(msg->buf[0], ®->thr); + ret = at91_wait_for_xfer(bus, TWI_SR_TXRDY); + for (i = 1; !ret && (i < msg->len); i++) { writel(msg->buf[i], ®->thr); ret = at91_wait_for_xfer(bus, TWI_SR_TXRDY); @@ -199,27 +201,6 @@ static int at91_i2c_enable_clk(struct udevice *dev) return 0; } -static int at91_i2c_probe_chip(struct udevice *dev, uint chip, uint chip_flags) -{ - struct at91_i2c_bus *bus = dev_get_priv(dev); - struct at91_i2c_regs *reg = bus->regs; - int ret; - - ret = at91_i2c_enable_clk(dev); - if (ret) - return ret; - - writel(TWI_CR_SWRST, ®->cr); - - at91_calc_i2c_clock(dev, bus->clock_frequency); - - writel(bus->cwgr_val, ®->cwgr); - writel(TWI_CR_MSEN, ®->cr); - writel(TWI_CR_SVDIS, ®->cr); - - return 0; -} - static int at91_i2c_set_bus_speed(struct udevice *dev, unsigned int speed) { struct at91_i2c_bus *bus = dev_get_priv(dev); @@ -254,7 +235,6 @@ static int at91_i2c_ofdata_to_platdata(struct udevice *dev) static const struct dm_i2c_ops at91_i2c_ops = { .xfer = at91_i2c_xfer, - .probe_chip = at91_i2c_probe_chip, .set_bus_speed = at91_i2c_set_bus_speed, .get_bus_speed = at91_i2c_get_bus_speed, }; diff --git a/drivers/i2c/meson_i2c.c b/drivers/i2c/meson_i2c.c index 2434d9ed538..4f37d2f3168 100644 --- a/drivers/i2c/meson_i2c.c +++ b/drivers/i2c/meson_i2c.c @@ -9,7 +9,7 @@ #include <dm.h> #include <i2c.h> -#define I2C_TIMEOUT_MS 500 +#define I2C_TIMEOUT_MS 100 /* Control register fields */ #define REG_CTRL_START BIT(0) @@ -44,12 +44,12 @@ struct i2c_regs { struct meson_i2c { struct i2c_regs *regs; - struct i2c_msg *msg; - bool last; - uint count; - uint pos; - u32 tokens[2]; - uint num_tokens; + struct i2c_msg *msg; /* Current I2C message */ + bool last; /* Whether the message is the last */ + uint count; /* Number of bytes in the current transfer */ + uint pos; /* Position of current transfer in message */ + u32 tokens[2]; /* Sequence of tokens to be written */ + uint num_tokens; /* Number of tokens to be written */ }; static void meson_i2c_reset_tokens(struct meson_i2c *i2c) @@ -69,6 +69,10 @@ static void meson_i2c_add_token(struct meson_i2c *i2c, int token) i2c->num_tokens++; } +/* + * Retrieve data for the current transfer (which can be at most 8 + * bytes) from the device internal buffer. + */ static void meson_i2c_get_data(struct meson_i2c *i2c, u8 *buf, int len) { u32 rdata0, rdata1; @@ -86,6 +90,10 @@ static void meson_i2c_get_data(struct meson_i2c *i2c, u8 *buf, int len) *buf++ = (rdata1 >> (i - 4) * 8) & 0xff; } +/* + * Write data for the current transfer (which can be at most 8 bytes) + * to the device internal buffer. + */ static void meson_i2c_put_data(struct meson_i2c *i2c, u8 *buf, int len) { u32 wdata0 = 0, wdata1 = 0; @@ -103,6 +111,11 @@ static void meson_i2c_put_data(struct meson_i2c *i2c, u8 *buf, int len) debug("meson i2c: write data %08x %08x len %d\n", wdata0, wdata1, len); } +/* + * Prepare the next transfer: pick the next 8 bytes in the remaining + * part of message and write tokens and data (if needed) to the + * device. + */ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c) { bool write = !(i2c->msg->flags & I2C_M_RD); @@ -178,7 +191,7 @@ static int meson_i2c_xfer_msg(struct meson_i2c *i2c, struct i2c_msg *msg, if (readl(&i2c->regs->ctrl) & REG_CTRL_ERROR) { debug("meson i2c: error\n"); - return -ENXIO; + return -EREMOTEIO; } if ((msg->flags & I2C_M_RD) && i2c->count) { @@ -200,7 +213,7 @@ static int meson_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, for (i = 0; i < nmsgs; i++) { ret = meson_i2c_xfer_msg(i2c, msg + i, i == nmsgs - 1); if (ret) - return -EREMOTEIO; + return ret; } return 0; diff --git a/drivers/net/fsl-mc/dpbp.c b/drivers/net/fsl-mc/dpbp.c index ba9536d4050..a0552f44dc2 100644 --- a/drivers/net/fsl-mc/dpbp.c +++ b/drivers/net/fsl-mc/dpbp.c @@ -1,8 +1,8 @@ /* * Freescale Layerscape MC I/O wrapper * - * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -50,9 +50,10 @@ int dpbp_close(struct fsl_mc_io *mc_io, } int dpbp_create(struct fsl_mc_io *mc_io, + uint16_t dprc_token, uint32_t cmd_flags, const struct dpbp_cfg *cfg, - uint16_t *token) + uint32_t *obj_id) { struct mc_command cmd = { 0 }; int err; @@ -62,7 +63,7 @@ int dpbp_create(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE, cmd_flags, - 0); + dprc_token); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -70,21 +71,25 @@ int dpbp_create(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *token = MC_CMD_HDR_READ_TOKEN(cmd.header); + MC_CMD_READ_OBJ_ID(cmd, *obj_id); return 0; } int dpbp_destroy(struct fsl_mc_io *mc_io, + uint16_t dprc_token, uint32_t cmd_flags, - uint16_t token) + uint32_t obj_id) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY, cmd_flags, - token); + dprc_token); + + /* set object id to destroy */ + CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, obj_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -157,3 +162,26 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io, return 0; } + +int dpbp_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_API_VERSION, + cmd_flags, 0); + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + mc_cmd_read_api_version(&cmd, major_ver, minor_ver); + + return 0; +} diff --git a/drivers/net/fsl-mc/dpio/dpio.c b/drivers/net/fsl-mc/dpio/dpio.c index b61df52860e..ccac506e995 100644 --- a/drivers/net/fsl-mc/dpio/dpio.c +++ b/drivers/net/fsl-mc/dpio/dpio.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2015 Freescale Semiconductor + * Copyright (C) 2013-2016 Freescale Semiconductor + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -10,7 +11,7 @@ int dpio_open(struct fsl_mc_io *mc_io, uint32_t cmd_flags, - int dpio_id, + uint32_t dpio_id, uint16_t *token) { struct mc_command cmd = { 0 }; @@ -49,9 +50,10 @@ int dpio_close(struct fsl_mc_io *mc_io, } int dpio_create(struct fsl_mc_io *mc_io, + uint16_t dprc_token, uint32_t cmd_flags, const struct dpio_cfg *cfg, - uint16_t *token) + uint32_t *obj_id) { struct mc_command cmd = { 0 }; int err; @@ -59,7 +61,7 @@ int dpio_create(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPIO_CMDID_CREATE, cmd_flags, - 0); + dprc_token); DPIO_CMD_CREATE(cmd, cfg); /* send command to mc*/ @@ -68,21 +70,25 @@ int dpio_create(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *token = MC_CMD_HDR_READ_TOKEN(cmd.header); + MC_CMD_READ_OBJ_ID(cmd, *obj_id); return 0; } int dpio_destroy(struct fsl_mc_io *mc_io, + uint16_t dprc_token, uint32_t cmd_flags, - uint16_t token) + uint32_t obj_id) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPIO_CMDID_DESTROY, cmd_flags, - token); + dprc_token); + + /* set object id to destroy */ + CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, obj_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -156,3 +162,26 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io, return 0; } + +int dpio_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_API_VERSION, + cmd_flags, 0); + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + mc_cmd_read_api_version(&cmd, major_ver, minor_ver); + + return 0; +} diff --git a/drivers/net/fsl-mc/dpmac.c b/drivers/net/fsl-mc/dpmac.c index 072a90dcaee..a719ac12d48 100644 --- a/drivers/net/fsl-mc/dpmac.c +++ b/drivers/net/fsl-mc/dpmac.c @@ -1,7 +1,8 @@ /* * Freescale Layerscape MC I/O wrapper * - * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP * Author: Prabhakar Kushwaha <prabhakar@freescale.com> * * SPDX-License-Identifier: GPL-2.0+ @@ -51,9 +52,10 @@ int dpmac_close(struct fsl_mc_io *mc_io, } int dpmac_create(struct fsl_mc_io *mc_io, + uint16_t dprc_token, uint32_t cmd_flags, const struct dpmac_cfg *cfg, - uint16_t *token) + uint32_t *obj_id) { struct mc_command cmd = { 0 }; int err; @@ -61,7 +63,7 @@ int dpmac_create(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE, cmd_flags, - 0); + dprc_token); DPMAC_CMD_CREATE(cmd, cfg); /* send command to mc*/ @@ -70,21 +72,25 @@ int dpmac_create(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *token = MC_CMD_HDR_READ_TOKEN(cmd.header); + MC_CMD_READ_OBJ_ID(cmd, *obj_id); return 0; } int dpmac_destroy(struct fsl_mc_io *mc_io, + uint16_t dprc_token, uint32_t cmd_flags, - uint16_t token) + uint32_t obj_id) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY, cmd_flags, - token); + dprc_token); + + /* set object id to destroy */ + CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, obj_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -220,3 +226,26 @@ int dpmac_get_counter(struct fsl_mc_io *mc_io, return 0; } + +int dpmac_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_API_VERSION, + cmd_flags, 0); + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + mc_cmd_read_api_version(&cmd, major_ver, minor_ver); + + return 0; +} diff --git a/drivers/net/fsl-mc/dpni.c b/drivers/net/fsl-mc/dpni.c index 41bf56abf5b..481f9d882b0 100644 --- a/drivers/net/fsl-mc/dpni.c +++ b/drivers/net/fsl-mc/dpni.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2015 Freescale Semiconductor + * Copyright (C) 2013-2016 Freescale Semiconductor + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -8,22 +9,22 @@ #include <fsl-mc/fsl_mc_cmd.h> #include <fsl-mc/fsl_dpni.h> -int dpni_prepare_extended_cfg(const struct dpni_extended_cfg *cfg, - uint8_t *ext_cfg_buf) +int dpni_prepare_cfg(const struct dpni_cfg *cfg, + uint8_t *cfg_buf) { - uint64_t *ext_params = (uint64_t *)ext_cfg_buf; + uint64_t *params = (uint64_t *)cfg_buf; - DPNI_PREP_EXTENDED_CFG(ext_params, cfg); + DPNI_PREP_CFG(params, cfg); return 0; } -int dpni_extract_extended_cfg(struct dpni_extended_cfg *cfg, - const uint8_t *ext_cfg_buf) +int dpni_extract_cfg(struct dpni_cfg *cfg, + const uint8_t *cfg_buf) { - uint64_t *ext_params = (uint64_t *)ext_cfg_buf; + uint64_t *params = (uint64_t *)cfg_buf; - DPNI_EXT_EXTENDED_CFG(ext_params, cfg); + DPNI_EXT_CFG(params, cfg); return 0; } @@ -69,9 +70,10 @@ int dpni_close(struct fsl_mc_io *mc_io, } int dpni_create(struct fsl_mc_io *mc_io, + uint16_t dprc_token, uint32_t cmd_flags, const struct dpni_cfg *cfg, - uint16_t *token) + uint32_t *obj_id) { struct mc_command cmd = { 0 }; int err; @@ -79,7 +81,7 @@ int dpni_create(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CREATE, cmd_flags, - 0); + dprc_token); DPNI_CMD_CREATE(cmd, cfg); /* send command to mc*/ @@ -88,21 +90,25 @@ int dpni_create(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - *token = MC_CMD_HDR_READ_TOKEN(cmd.header); + MC_CMD_READ_OBJ_ID(cmd, *obj_id); return 0; } int dpni_destroy(struct fsl_mc_io *mc_io, + uint16_t dprc_token, uint32_t cmd_flags, - uint16_t token) + uint32_t obj_id) { struct mc_command cmd = { 0 }; /* prepare command */ cmd.header = mc_encode_cmd_header(DPNI_CMDID_DESTROY, cmd_flags, - token); + dprc_token); + + /* set object id to destroy */ + CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, obj_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -182,8 +188,6 @@ int dpni_get_attributes(struct fsl_mc_io *mc_io, cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_ATTR, cmd_flags, token); - DPNI_CMD_GET_ATTR(cmd, attr); - /* send command to mc*/ err = mc_send_command(mc_io, &cmd); if (err) @@ -212,124 +216,19 @@ int dpni_set_errors_behavior(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } -int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - struct dpni_buffer_layout *layout) -{ - struct mc_command cmd = { 0 }; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_BUFFER_LAYOUT, - cmd_flags, - token); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout); - - return 0; -} - -int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - const struct dpni_buffer_layout *layout) +int dpni_set_buffer_layout(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + const struct dpni_buffer_layout *layout, + enum dpni_queue_type type) { struct mc_command cmd = { 0 }; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_BUFFER_LAYOUT, + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_BUFFER_LAYOUT, cmd_flags, token); - DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - struct dpni_buffer_layout *layout) -{ - struct mc_command cmd = { 0 }; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_BUFFER_LAYOUT, - cmd_flags, - token); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout); - - return 0; -} - -int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - const struct dpni_buffer_layout *layout) -{ - struct mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_BUFFER_LAYOUT, - cmd_flags, - token); - DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - struct dpni_buffer_layout *layout) -{ - struct mc_command cmd = { 0 }; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT, - cmd_flags, - token); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout); - - return 0; -} - -int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - const struct dpni_buffer_layout *layout) -{ - struct mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT, - cmd_flags, - token); - DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout); + DPNI_CMD_SET_BUFFER_LAYOUT(cmd, layout, type); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -383,50 +282,6 @@ int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, return 0; } -int dpni_get_counter(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - enum dpni_counter counter, - uint64_t *value) -{ - struct mc_command cmd = { 0 }; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_COUNTER, - cmd_flags, - token); - DPNI_CMD_GET_COUNTER(cmd, counter); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - /* retrieve response parameters */ - DPNI_RSP_GET_COUNTER(cmd, *value); - - return 0; -} - -int dpni_set_counter(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - enum dpni_counter counter, - uint64_t value) -{ - struct mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_COUNTER, - cmd_flags, - token); - DPNI_CMD_SET_COUNTER(cmd, counter, value); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - int dpni_set_link_cfg(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, @@ -544,46 +399,64 @@ int dpni_remove_mac_addr(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } -int dpni_set_tx_flow(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint16_t *flow_id, - const struct dpni_tx_flow_cfg *cfg) +int dpni_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver) { struct mc_command cmd = { 0 }; int err; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_FLOW, - cmd_flags, - token); - DPNI_CMD_SET_TX_FLOW(cmd, *flow_id, cfg); + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_API_VERSION, + cmd_flags, 0); - /* send command to mc*/ + /* send command to mc */ err = mc_send_command(mc_io, &cmd); if (err) return err; /* retrieve response parameters */ - DPNI_RSP_SET_TX_FLOW(cmd, *flow_id); + mc_cmd_read_api_version(&cmd, major_ver, minor_ver); return 0; } -int dpni_get_tx_flow(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint16_t flow_id, - struct dpni_tx_flow_attr *attr) +int dpni_set_queue(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + enum dpni_queue_type type, + uint8_t tc, + uint8_t index, + const struct dpni_queue *queue) +{ + struct mc_command cmd = { 0 }; + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QUEUE, + cmd_flags, + token); + DPNI_CMD_SET_QUEUE(cmd, type, tc, index, queue); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_get_queue(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + enum dpni_queue_type type, + uint8_t tc, + uint8_t index, + struct dpni_queue *queue) { struct mc_command cmd = { 0 }; int err; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_FLOW, + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QUEUE, cmd_flags, token); - DPNI_CMD_GET_TX_FLOW(cmd, flow_id); + DPNI_CMD_GET_QUEUE(cmd, type, tc, index); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -591,44 +464,43 @@ int dpni_get_tx_flow(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - DPNI_RSP_GET_TX_FLOW(cmd, attr); - + DPNI_RSP_GET_QUEUE(cmd, queue); return 0; } -int dpni_set_rx_flow(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t tc_id, - uint16_t flow_id, - const struct dpni_queue_cfg *cfg) +int dpni_set_tx_confirmation_mode(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + enum dpni_confirmation_mode mode) { + struct dpni_tx_confirmation_mode *cmd_params; struct mc_command cmd = { 0 }; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_FLOW, + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONFIRMATION_MODE, cmd_flags, token); - DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg); + + cmd_params = (struct dpni_tx_confirmation_mode *)cmd.params; + cmd_params->confirmation_mode = mode; /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -int dpni_get_rx_flow(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t tc_id, - uint16_t flow_id, - struct dpni_queue_attr *attr) +int dpni_get_statistics(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t page, + struct dpni_statistics *stat) { struct mc_command cmd = { 0 }; int err; + /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_FLOW, - cmd_flags, - token); - DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id); + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_STATISTICS, + cmd_flags, token); + DPNI_CMD_GET_STATISTICS(cmd, page); /* send command to mc*/ err = mc_send_command(mc_io, &cmd); @@ -636,50 +508,22 @@ int dpni_get_rx_flow(struct fsl_mc_io *mc_io, return err; /* retrieve response parameters */ - DPNI_RSP_GET_RX_FLOW(cmd, attr); + DPNI_RSP_GET_STATISTICS(cmd, stat); return 0; } -int dpni_set_tx_conf(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint16_t flow_id, - const struct dpni_tx_conf_cfg *cfg) +int dpni_reset_statistics(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token) { struct mc_command cmd = { 0 }; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF, - cmd_flags, - token); - DPNI_CMD_SET_TX_CONF(cmd, flow_id, cfg); + cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET_STATISTICS, + cmd_flags, token); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } -int dpni_get_tx_conf(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint16_t flow_id, - struct dpni_tx_conf_attr *attr) -{ - struct mc_command cmd = { 0 }; - int err; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF, - cmd_flags, - token); - DPNI_CMD_GET_TX_CONF(cmd, flow_id); - - /* send command to mc*/ - err = mc_send_command(mc_io, &cmd); - if (err) - return err; - - DPNI_RSP_GET_TX_CONF(cmd, attr); - - return 0; -} diff --git a/drivers/net/fsl-mc/dprc.c b/drivers/net/fsl-mc/dprc.c index 7d34355b866..be02057b46e 100644 --- a/drivers/net/fsl-mc/dprc.c +++ b/drivers/net/fsl-mc/dprc.c @@ -1,8 +1,8 @@ /* * Freescale Layerscape MC I/O wrapper * - * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -353,3 +353,26 @@ int dprc_get_connection(struct fsl_mc_io *mc_io, return 0; } + +int dprc_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION, + cmd_flags, 0); + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + mc_cmd_read_api_version(&cmd, major_ver, minor_ver); + + return 0; +} diff --git a/drivers/net/fsl-mc/fsl_dpmng_cmd.h b/drivers/net/fsl-mc/fsl_dpmng_cmd.h index 33f84f39bb9..a91da2b52d3 100644 --- a/drivers/net/fsl-mc/fsl_dpmng_cmd.h +++ b/drivers/net/fsl-mc/fsl_dpmng_cmd.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. +/* Copyright 2013-2016 Freescale Semiconductor Inc. + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -6,7 +7,7 @@ #define __FSL_DPMNG_CMD_H /* Command IDs */ -#define DPMNG_CMDID_GET_VERSION 0x831 +#define DPMNG_CMDID_GET_VERSION 0x8311 /* cmd, param, offset, width, type, arg_name */ #define DPMNG_RSP_GET_VERSION(cmd, mc_ver_info) \ diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index c76f58253d6..f36fe06269d 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -854,21 +854,25 @@ int fsl_mc_ldpaa_init(bd_t *bis) static int dprc_version_check(struct fsl_mc_io *mc_io, uint16_t handle) { - struct dprc_attributes attr; int error; + uint16_t major_ver, minor_ver; - memset(&attr, 0, sizeof(struct dprc_attributes)); - error = dprc_get_attributes(mc_io, MC_CMD_NO_FLAGS, handle, &attr); - if (error == 0) { - if ((attr.version.major != DPRC_VER_MAJOR) || - (attr.version.minor != DPRC_VER_MINOR)) { - printf("DPRC version mismatch found %u.%u,", - attr.version.major, - attr.version.minor); - printf("supported version is %u.%u\n", - DPRC_VER_MAJOR, DPRC_VER_MINOR); - } + error = dprc_get_api_version(mc_io, 0, + &major_ver, + &minor_ver); + if (error < 0) { + printf("dprc_get_api_version() failed: %d\n", error); + return error; + } + + if (major_ver < DPRC_VER_MAJOR || (major_ver == DPRC_VER_MAJOR && + minor_ver < DPRC_VER_MINOR)) { + printf("DPRC version mismatch found %u.%u,", + major_ver, minor_ver); + printf("supported version is %u.%u\n", + DPRC_VER_MAJOR, DPRC_VER_MINOR); } + return error; } @@ -878,6 +882,7 @@ static int dpio_init(void) struct dpio_attr attr; struct dpio_cfg dpio_cfg; int err = 0; + uint16_t major_ver, minor_ver; dflt_dpio = (struct fsl_dpio_obj *)calloc( sizeof(struct fsl_dpio_obj), 1); @@ -886,18 +891,44 @@ static int dpio_init(void) err = -ENOMEM; goto err_calloc; } - dpio_cfg.channel_mode = DPIO_LOCAL_CHANNEL; dpio_cfg.num_priorities = 8; - err = dpio_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpio_cfg, - &dflt_dpio->dpio_handle); + err = dpio_create(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, + &dpio_cfg, + &dflt_dpio->dpio_id); if (err < 0) { printf("dpio_create() failed: %d\n", err); err = -ENODEV; goto err_create; } + err = dpio_get_api_version(dflt_mc_io, 0, + &major_ver, + &minor_ver); + if (err < 0) { + printf("dpio_get_api_version() failed: %d\n", err); + goto err_get_api_ver; + } + + if (major_ver < DPIO_VER_MAJOR || (major_ver == DPIO_VER_MAJOR && + minor_ver < DPIO_VER_MINOR)) { + printf("DPRC version mismatch found %u.%u,", + major_ver, + minor_ver); + } + + err = dpio_open(dflt_mc_io, + MC_CMD_NO_FLAGS, + dflt_dpio->dpio_id, + &dflt_dpio->dpio_handle); + if (err) { + printf("dpio_open() failed\n"); + goto err_open; + } + memset(&attr, 0, sizeof(struct dpio_attr)); err = dpio_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle, &attr); @@ -906,15 +937,11 @@ static int dpio_init(void) goto err_get_attr; } - if ((attr.version.major != DPIO_VER_MAJOR) || - (attr.version.minor != DPIO_VER_MINOR)) { - printf("DPIO version mismatch found %u.%u,", - attr.version.major, attr.version.minor); - printf("supported version is %u.%u\n", - DPIO_VER_MAJOR, DPIO_VER_MINOR); + if (dflt_dpio->dpio_id != attr.id) { + printf("dnpi object id and attribute id are not same\n"); + goto err_attr_not_same; } - dflt_dpio->dpio_id = attr.id; #ifdef DEBUG printf("Init: DPIO id=0x%d\n", dflt_dpio->dpio_id); #endif @@ -945,8 +972,14 @@ err_get_swp_init: dpio_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle); err_get_enable: err_get_attr: +err_attr_not_same: dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle); - dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle); +err_open: +err_get_api_ver: + dpio_destroy(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, + dflt_dpio->dpio_id); err_create: free(dflt_dpio); err_calloc: @@ -963,7 +996,16 @@ static int dpio_exit(void) goto err; } - err = dpio_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle); + dpio_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpio->dpio_handle); + if (err < 0) { + printf("dpio_close() failed: %d\n", err); + goto err; + } + + err = dpio_destroy(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, + dflt_dpio->dpio_id); if (err < 0) { printf("dpio_destroy() failed: %d\n", err); goto err; @@ -1040,6 +1082,7 @@ static int dprc_init(void) child_portal_id = MC_PORTAL_OFFSET_TO_PORTAL_ID(mc_portal_offset); dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(child_portal_id); + #ifdef DEBUG printf("MC portal of child DPRC container: %d, physical addr %p)\n", child_dprc_id, dflt_mc_io->mmio_regs); @@ -1110,6 +1153,7 @@ static int dpbp_init(void) int err; struct dpbp_attr dpbp_attr; struct dpbp_cfg dpbp_cfg; + uint16_t major_ver, minor_ver; dflt_dpbp = (struct fsl_dpbp_obj *)calloc( sizeof(struct fsl_dpbp_obj), 1); @@ -1121,8 +1165,11 @@ static int dpbp_init(void) dpbp_cfg.options = 512; - err = dpbp_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpbp_cfg, - &dflt_dpbp->dpbp_handle); + err = dpbp_create(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, + &dpbp_cfg, + &dflt_dpbp->dpbp_id); if (err < 0) { err = -ENODEV; @@ -1130,6 +1177,31 @@ static int dpbp_init(void) goto err_create; } + err = dpbp_get_api_version(dflt_mc_io, 0, + &major_ver, + &minor_ver); + if (err < 0) { + printf("dpbp_get_api_version() failed: %d\n", err); + goto err_get_api_ver; + } + + if (major_ver < DPBP_VER_MAJOR || (major_ver == DPBP_VER_MAJOR && + minor_ver < DPBP_VER_MINOR)) { + printf("DPBP version mismatch found %u.%u,", + major_ver, minor_ver); + printf("supported version is %u.%u\n", + DPBP_VER_MAJOR, DPBP_VER_MINOR); + } + + err = dpbp_open(dflt_mc_io, + MC_CMD_NO_FLAGS, + dflt_dpbp->dpbp_id, + &dflt_dpbp->dpbp_handle); + if (err) { + printf("dpbp_open() failed\n"); + goto err_open; + } + memset(&dpbp_attr, 0, sizeof(struct dpbp_attr)); err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle, @@ -1139,17 +1211,13 @@ static int dpbp_init(void) goto err_get_attr; } - if ((dpbp_attr.version.major != DPBP_VER_MAJOR) || - (dpbp_attr.version.minor != DPBP_VER_MINOR)) { - printf("DPBP version mismatch found %u.%u,", - dpbp_attr.version.major, dpbp_attr.version.minor); - printf("supported version is %u.%u\n", - DPBP_VER_MAJOR, DPBP_VER_MINOR); + if (dflt_dpbp->dpbp_id != dpbp_attr.id) { + printf("dpbp object id and attribute id are not same\n"); + goto err_attr_not_same; } - dflt_dpbp->dpbp_attr.id = dpbp_attr.id; #ifdef DEBUG - printf("Init: DPBP id=0x%d\n", dflt_dpbp->dpbp_attr.id); + printf("Init: DPBP id=0x%x\n", dflt_dpbp->dpbp_attr.id); #endif err = dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); @@ -1160,12 +1228,18 @@ static int dpbp_init(void) return 0; -err_close: - free(dflt_dpbp); err_get_attr: +err_attr_not_same: dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); - dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle); + dpbp_destroy(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, + dflt_dpbp->dpbp_id); +err_get_api_ver: +err_close: +err_open: err_create: + free(dflt_dpbp); err_calloc: return err; } @@ -1174,15 +1248,8 @@ static int dpbp_exit(void) { int err; - err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id, - &dflt_dpbp->dpbp_handle); - if (err < 0) { - printf("dpbp_open() failed: %d\n", err); - goto err; - } - - err = dpbp_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpbp->dpbp_handle); + err = dpbp_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS, + dflt_dpbp->dpbp_id); if (err < 0) { printf("dpbp_destroy() failed: %d\n", err); goto err; @@ -1203,10 +1270,9 @@ err: static int dpni_init(void) { int err; - struct dpni_attr dpni_attr; - uint8_t ext_cfg_buf[256] = {0}; - struct dpni_extended_cfg dpni_extended_cfg; + uint8_t cfg_buf[256] = {0}; struct dpni_cfg dpni_cfg; + uint16_t major_ver, minor_ver; dflt_dpni = (struct fsl_dpni_obj *)calloc( sizeof(struct fsl_dpni_obj), 1); @@ -1216,50 +1282,53 @@ static int dpni_init(void) goto err_calloc; } - memset(&dpni_extended_cfg, 0, sizeof(dpni_extended_cfg)); - err = dpni_prepare_extended_cfg(&dpni_extended_cfg, &ext_cfg_buf[0]); + memset(&dpni_cfg, 0, sizeof(dpni_cfg)); + err = dpni_prepare_cfg(&dpni_cfg, &cfg_buf[0]); if (err < 0) { err = -ENODEV; - printf("dpni_prepare_extended_cfg() failed: %d\n", err); - goto err_prepare_extended_cfg; + printf("dpni_prepare_cfg() failed: %d\n", err); + goto err_prepare_cfg; } - memset(&dpni_cfg, 0, sizeof(dpni_cfg)); - dpni_cfg.adv.options = DPNI_OPT_UNICAST_FILTER | - DPNI_OPT_MULTICAST_FILTER; - - dpni_cfg.adv.ext_cfg_iova = (uint64_t)&ext_cfg_buf[0]; - err = dpni_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpni_cfg, - &dflt_dpni->dpni_handle); - + err = dpni_create(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, + &dpni_cfg, + &dflt_dpni->dpni_id); if (err < 0) { err = -ENODEV; - printf("dpni_create() failed: %d\n", err); + printf("dpni create() failed: %d\n", err); goto err_create; } - memset(&dpni_attr, 0, sizeof(struct dpni_attr)); - err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - &dpni_attr); + err = dpni_get_api_version(dflt_mc_io, 0, + &major_ver, + &minor_ver); if (err < 0) { - printf("dpni_get_attributes() failed: %d\n", err); - goto err_get_attr; + printf("dpni_get_api_version() failed: %d\n", err); + goto err_get_version; } - if ((dpni_attr.version.major != DPNI_VER_MAJOR) || - (dpni_attr.version.minor != DPNI_VER_MINOR)) { + if (major_ver < DPNI_VER_MAJOR || (major_ver == DPNI_VER_MAJOR && + minor_ver < DPNI_VER_MINOR)) { printf("DPNI version mismatch found %u.%u,", - dpni_attr.version.major, dpni_attr.version.minor); + major_ver, minor_ver); printf("supported version is %u.%u\n", DPNI_VER_MAJOR, DPNI_VER_MINOR); } - dflt_dpni->dpni_id = dpni_attr.id; + err = dpni_open(dflt_mc_io, + MC_CMD_NO_FLAGS, + dflt_dpni->dpni_id, + &dflt_dpni->dpni_handle); + if (err) { + printf("dpni_open() failed\n"); + goto err_open; + } + #ifdef DEBUG printf("Init: DPNI id=0x%d\n", dflt_dpni->dpni_id); #endif - err = dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); if (err < 0) { printf("dpni_close() failed: %d\n", err); @@ -1269,11 +1338,15 @@ static int dpni_init(void) return 0; err_close: -err_get_attr: dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); - dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); +err_open: +err_get_version: + dpni_destroy(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, + dflt_dpni->dpni_id); err_create: -err_prepare_extended_cfg: +err_prepare_cfg: free(dflt_dpni); err_calloc: return err; @@ -1283,15 +1356,8 @@ static int dpni_exit(void) { int err; - err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id, - &dflt_dpni->dpni_handle); - if (err < 0) { - printf("dpni_open() failed: %d\n", err); - goto err; - } - - err = dpni_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle); + err = dpni_destroy(dflt_mc_io, dflt_dprc_handle, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_id); if (err < 0) { printf("dpni_destroy() failed: %d\n", err); goto err; @@ -1370,12 +1436,13 @@ int fsl_mc_ldpaa_exit(bd_t *bd) */ if (bd && mc_boot_status && !is_dpl_apply_status) { printf("fsl-mc: DPL not deployed, DPAA2 ethernet not work\n"); - return 0; + goto mc_obj_cleanup; } if (bd && mc_boot_status && is_dpl_apply_status) return 0; +mc_obj_cleanup: err = dpbp_exit(); if (err < 0) { printf("dpbp_exit() failed: %d\n", err); @@ -1420,6 +1487,7 @@ static int do_fsl_mc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #endif sub_cmd = argv[2][0]; + switch (sub_cmd) { case 'm': if (argc < 5) diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 21be79a58ad..109aba2f967 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2014 Freescale Semiconductor + * Copyright (C) 2014-2016 Freescale Semiconductor + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -42,80 +43,67 @@ static int init_phy(struct eth_device *dev) #endif #ifdef DEBUG -static void ldpaa_eth_get_dpni_counter(void) -{ - int err = 0; - u64 value; - - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_ING_FRAME, - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_ING_FRAME failed\n"); - return; - } - printf("DPNI_CNT_ING_FRAME=%lld\n", value); - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_ING_BYTE, - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_ING_BYTE failed\n"); - return; - } - printf("DPNI_CNT_ING_BYTE=%lld\n", value); - - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_ING_FRAME_DROP , - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DROP failed\n"); - return; - } - printf("DPNI_CNT_ING_FRAME_DROP =%lld\n", value); - - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_ING_FRAME_DISCARD, - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DISCARD failed\n"); - return; - } - printf("DPNI_CNT_ING_FRAME_DISCARD=%lld\n", value); - - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_EGR_FRAME, - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_EGR_FRAME failed\n"); - return; - } - printf("DPNI_CNT_EGR_FRAME=%lld\n", value); +#define DPNI_STATS_PER_PAGE 6 + +static const char *dpni_statistics[][DPNI_STATS_PER_PAGE] = { + { + "DPNI_CNT_ING_ALL_FRAMES", + "DPNI_CNT_ING_ALL_BYTES", + "DPNI_CNT_ING_MCAST_FRAMES", + "DPNI_CNT_ING_MCAST_BYTES", + "DPNI_CNT_ING_BCAST_FRAMES", + "DPNI_CNT_ING_BCAST_BYTES", + }, { + "DPNI_CNT_EGR_ALL_FRAMES", + "DPNI_CNT_EGR_ALL_BYTES", + "DPNI_CNT_EGR_MCAST_FRAMES", + "DPNI_CNT_EGR_MCAST_BYTES", + "DPNI_CNT_EGR_BCAST_FRAMES", + "DPNI_CNT_EGR_BCAST_BYTES", + }, { + "DPNI_CNT_ING_FILTERED_FRAMES", + "DPNI_CNT_ING_DISCARDED_FRAMES", + "DPNI_CNT_ING_NOBUFFER_DISCARDS", + "DPNI_CNT_EGR_DISCARDED_FRAMES", + "DPNI_CNT_EGR_CNF_FRAMES", + "" + }, +}; + +static void print_dpni_stats(const char *strings[], + struct dpni_statistics dpni_stats) +{ + uint64_t *stat; + int i; - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_EGR_BYTE , - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_EGR_BYTE failed\n"); - return; + stat = (uint64_t *)&dpni_stats; + for (i = 0; i < DPNI_STATS_PER_PAGE; i++) { + if (strcmp(strings[i], "\0") == 0) + break; + printf("%s= %llu\n", strings[i], *stat); + stat++; } - printf("DPNI_CNT_EGR_BYTE =%lld\n", value); +} - err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - DPNI_CNT_EGR_FRAME_DISCARD , - &value); - if (err < 0) { - printf("dpni_get_counter: DPNI_CNT_EGR_FRAME_DISCARD failed\n"); - return; +static void ldpaa_eth_get_dpni_counter(void) +{ + int err = 0; + unsigned int page = 0; + struct dpni_statistics dpni_stats; + + printf("DPNI counters ..\n"); + for (page = 0; page < 3; page++) { + err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, page, + &dpni_stats); + if (err < 0) { + printf("dpni_get_statistics: failed:"); + printf("%d for page[%d]\n", err, page); + return; + } + print_dpni_stats(dpni_statistics[page], dpni_stats); } - printf("DPNI_CNT_EGR_FRAME_DISCARD =%lld\n", value); } static void ldpaa_eth_get_dpmac_counter(struct eth_device *net_dev) @@ -132,6 +120,7 @@ static void ldpaa_eth_get_dpmac_counter(struct eth_device *net_dev) printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n"); return; } + printf("\nDPMAC counters ..\n"); printf("DPMAC_CNT_ING_BYTE=%lld\n", value); err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS, @@ -392,7 +381,6 @@ error: static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; - struct dpni_queue_attr rx_queue_attr; struct dpmac_link_state dpmac_link_state = { 0 }; #ifdef DEBUG struct dpni_link_state link_state; @@ -400,6 +388,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) int err = 0; struct mii_dev *bus; phy_interface_t enet_if; + struct dpni_queue d_queue; if (net_dev->state == ETH_STATE_ACTIVE) return 0; @@ -508,6 +497,10 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) } #ifdef DEBUG + printf("DPMAC link status: %d - ", dpmac_link_state.up); + dpmac_link_state.up == 0 ? printf("down\n") : + dpmac_link_state.up == 1 ? printf("up\n") : printf("error state\n"); + err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle, &link_state); if (err < 0) { @@ -515,20 +508,21 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) return err; } - printf("link status: %d - ", link_state.up); + printf("DPNI link status: %d - ", link_state.up); link_state.up == 0 ? printf("down\n") : link_state.up == 1 ? printf("up\n") : printf("error state\n"); #endif - /* TODO: support multiple Rx flows */ - err = dpni_get_rx_flow(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, 0, 0, &rx_queue_attr); + memset(&d_queue, 0, sizeof(struct dpni_queue)); + err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, DPNI_QUEUE_RX, + 0, 0, &d_queue); if (err) { - printf("dpni_get_rx_flow() failed\n"); - goto err_rx_flow; + printf("dpni_get_queue failed\n"); + goto err_get_queue; } - priv->rx_dflt_fqid = rx_queue_attr.fqid; + priv->rx_dflt_fqid = d_queue.fqid; err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle, &priv->tx_qdid); @@ -540,7 +534,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) return priv->phydev->link; err_qdid: -err_rx_flow: +err_get_queue: dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); err_dpni_bind: ldpaa_dpbp_free(); @@ -548,7 +542,10 @@ err_dpbp_setup: dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); err_dpni_setup: err_dpamc_bind: - dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); + dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); + dpmac_destroy(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, priv->dpmac_id); err_dpmac_setup: return err; } @@ -575,7 +572,14 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) if (err < 0) printf("dprc_disconnect() failed dpmac_endpoint\n"); - err = dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); + err = dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); + if (err < 0) + printf("dpmac_close() failed\n"); + + err = dpmac_destroy(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, + priv->dpmac_id); if (err < 0) printf("dpmac_destroy() failed\n"); @@ -593,9 +597,16 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) } #endif + /* Free DPBP handle and reset. */ ldpaa_dpbp_free(); + dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); + if (err < 0) + printf("dpni_reset() failed\n"); + dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); + if (err < 0) + printf("dpni_close() failed\n"); } static void ldpaa_dpbp_drain_cnt(int count) @@ -711,6 +722,7 @@ static int ldpaa_dpbp_setup(void) } err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid); + if (err) { printf("Buffer seeding failed for DPBP %d (bpid=%d)\n", dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid); @@ -739,21 +751,19 @@ static void ldpaa_dpbp_free(void) static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io, struct ldpaa_eth_priv *priv) { - struct dpmac_attr attr; int error; - - memset(&attr, 0, sizeof(struct dpmac_attr)); - error = dpmac_get_attributes(mc_io, MC_CMD_NO_FLAGS, - priv->dpmac_handle, - &attr); - if (error == 0) { - if ((attr.version.major != DPMAC_VER_MAJOR) || - (attr.version.minor != DPMAC_VER_MINOR)) { - printf("DPMAC version mismatch found %u.%u,", - attr.version.major, attr.version.minor); - printf("supported version is %u.%u\n", - DPMAC_VER_MAJOR, DPMAC_VER_MINOR); - } + uint16_t major_ver, minor_ver; + + error = dpmac_get_api_version(dflt_mc_io, 0, + &major_ver, + &minor_ver); + if ((major_ver < DPMAC_VER_MAJOR) || + (major_ver == DPMAC_VER_MAJOR && minor_ver < DPMAC_VER_MINOR)) { + printf("DPMAC version mismatch found %u.%u,", + major_ver, minor_ver); + printf("supported version is %u.%u\n", + DPMAC_VER_MAJOR, DPMAC_VER_MINOR); + return error; } return error; @@ -765,14 +775,36 @@ static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv) struct dpmac_cfg dpmac_cfg; dpmac_cfg.mac_id = priv->dpmac_id; - err = dpmac_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpmac_cfg, - &priv->dpmac_handle); + + err = dpmac_create(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, &dpmac_cfg, + &priv->dpmac_id); if (err) printf("dpmac_create() failed\n"); err = ldpaa_dpmac_version_check(dflt_mc_io, priv); - if (err < 0) + if (err < 0) { printf("ldpaa_dpmac_version_check() failed: %d\n", err); + goto err_version_check; + } + + err = dpmac_open(dflt_mc_io, + MC_CMD_NO_FLAGS, + priv->dpmac_id, + &priv->dpmac_handle); + if (err < 0) { + printf("dpmac_open() failed: %d\n", err); + goto err_open; + } + + return err; + +err_open: +err_version_check: + dpmac_destroy(dflt_mc_io, + dflt_dprc_handle, + MC_CMD_NO_FLAGS, priv->dpmac_id); return err; } @@ -838,7 +870,6 @@ static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv) printf("dpni_open() failed\n"); goto err_open; } - err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle, &dflt_dpni->dpni_attrs); @@ -857,12 +888,13 @@ static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv) dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE; /* HW erratum mandates data alignment in multiples of 256 */ dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN; + /* ...rx, ... */ - err = dpni_set_rx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - &dflt_dpni->buf_layout); + err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, + &dflt_dpni->buf_layout, DPNI_QUEUE_RX); if (err) { - printf("dpni_set_rx_buffer_layout() failed"); + printf("dpni_set_buffer_layout() failed"); goto err_buf_layout; } @@ -870,21 +902,22 @@ static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv) /* remove Rx-only options */ dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | DPNI_BUF_LAYOUT_OPT_PARSER_RESULT); - err = dpni_set_tx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - &dflt_dpni->buf_layout); + err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, + &dflt_dpni->buf_layout, DPNI_QUEUE_TX); if (err) { - printf("dpni_set_tx_buffer_layout() failed"); + printf("dpni_set_buffer_layout() failed"); goto err_buf_layout; } /* ... tx-confirm. */ dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; - err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - &dflt_dpni->buf_layout); + err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, + &dflt_dpni->buf_layout, + DPNI_QUEUE_TX_CONFIRM); if (err) { - printf("dpni_set_tx_conf_buffer_layout() failed"); + printf("dpni_set_buffer_layout() failed"); goto err_buf_layout; } @@ -919,8 +952,7 @@ err_open: static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv) { struct dpni_pools_cfg pools_params; - struct dpni_tx_flow_cfg dflt_tx_flow; - struct dpni_tx_conf_cfg tx_conf_cfg; + struct dpni_queue tx_queue; int err = 0; memset(&pools_params, 0, sizeof(pools_params)); @@ -934,26 +966,22 @@ static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv) return err; } - priv->tx_flow_id = DPNI_NEW_FLOW_ID; - memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow)); + memset(&tx_queue, 0, sizeof(struct dpni_queue)); + + err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, + DPNI_QUEUE_TX, 0, 0, &tx_queue); - dflt_tx_flow.use_common_tx_conf_queue = 0; - err = dpni_set_tx_flow(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, &priv->tx_flow_id, - &dflt_tx_flow); if (err) { - printf("dpni_set_tx_flow() failed\n"); + printf("dpni_set_queue() failed\n"); return err; } - memset(&tx_conf_cfg, 0, sizeof(struct dpni_tx_conf_cfg)); - tx_conf_cfg.errors_only = true; - /*Set tx-conf and error configuration*/ - err = dpni_set_tx_conf(dflt_mc_io, MC_CMD_NO_FLAGS, - dflt_dpni->dpni_handle, - priv->tx_flow_id, &tx_conf_cfg); + err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS, + dflt_dpni->dpni_handle, + DPNI_CONF_DISABLE); if (err) { - printf("dpni_set_tx_conf() failed\n"); + printf("dpni_set_tx_confirmation_mode() failed\n"); return err; } @@ -996,7 +1024,6 @@ int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if) struct ldpaa_eth_priv *priv = NULL; int err = 0; - /* Net device */ net_dev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!net_dev) { diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.h b/drivers/net/ldpaa_eth/ldpaa_eth.h index 3b161507359..1e26630043a 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.h +++ b/drivers/net/ldpaa_eth/ldpaa_eth.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2014 Freescale Semiconductor + * Copyright (C) 2014-2016 Freescale Semiconductor + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -117,7 +118,7 @@ struct ldpaa_fas { struct ldpaa_eth_priv { struct eth_device *net_dev; - int dpmac_id; + uint32_t dpmac_id; uint16_t dpmac_handle; uint16_t tx_data_offset; diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 944f58195ca..73e036d6fd4 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -36,7 +36,7 @@ typedef struct global_data { #if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) unsigned long fb_base; /* Base address of framebuffer mem */ #endif -#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) +#if defined(CONFIG_POST) unsigned long post_log_word; /* Record POST activities */ unsigned long post_log_res; /* success of POST test */ unsigned long post_init_f_time; /* When post_init_f started */ @@ -114,6 +114,11 @@ typedef struct global_data { struct bootstage_data *bootstage; /* Bootstage information */ struct bootstage_data *new_bootstage; /* Relocated bootstage info */ #endif +#ifdef CONFIG_LOG + int log_drop_count; /* Number of dropped log messages */ + int default_log_level; /* For devices with no filters */ + struct list_head log_head; /* List of struct log_device */ +#endif } gd_t; #endif @@ -141,5 +146,6 @@ typedef struct global_data { #define GD_FLG_RECORD 0x01000 /* Record console */ #define GD_FLG_ENV_DEFAULT 0x02000 /* Default variable flag */ #define GD_FLG_SPL_EARLY_INIT 0x04000 /* Early SPL init is done */ +#define GD_FLG_LOG_READY 0x08000 /* Log system is ready for use */ #endif /* __ASM_GENERIC_GBL_DATA_H */ diff --git a/include/charset.h b/include/charset.h index 37a32784998..2662c2f7c9a 100644 --- a/include/charset.h +++ b/include/charset.h @@ -9,6 +9,8 @@ #ifndef __CHARSET_H_ #define __CHARSET_H_ +#include <linux/types.h> + #define MAX_UTF8_PER_UTF16 3 /** @@ -62,4 +64,17 @@ uint16_t *utf16_strdup(const uint16_t *s); */ uint8_t *utf16_to_utf8(uint8_t *dest, const uint16_t *src, size_t size); +/** + * utf8_to_utf16() - Convert an utf8 string to utf16 + * + * Converts up to 'size' characters of the utf16 string 'src' to utf8 + * written to the 'dest' buffer. Stops at 0x00. + * + * @dest the destination buffer to write the utf8 characters + * @src the source utf16 string + * @size maximum number of utf16 characters to convert + * @return the pointer to the first unwritten byte in 'dest' + */ +uint16_t *utf8_to_utf16(uint16_t *dest, const uint8_t *src, size_t size); + #endif /* __CHARSET_H_ */ diff --git a/include/common.h b/include/common.h index 6e245451789..436200044f3 100644 --- a/include/common.h +++ b/include/common.h @@ -45,51 +45,7 @@ typedef volatile unsigned char vu_char; #define CONFIG_SYS_SUPPORT_64BIT_DATA #endif -#ifdef DEBUG -#define _DEBUG 1 -#else -#define _DEBUG 0 -#endif - -#ifdef CONFIG_SPL_BUILD -#define _SPL_BUILD 1 -#else -#define _SPL_BUILD 0 -#endif - -/* - * Output a debug text when condition "cond" is met. The "cond" should be - * computed by a preprocessor in the best case, allowing for the best - * optimization. - */ -#define debug_cond(cond, fmt, args...) \ - do { \ - if (cond) \ - printf(pr_fmt(fmt), ##args); \ - } while (0) - -/* Show a message if DEBUG is defined in a file */ -#define debug(fmt, args...) \ - debug_cond(_DEBUG, fmt, ##args) - -/* Show a message if not in SPL */ -#define warn_non_spl(fmt, args...) \ - debug_cond(!_SPL_BUILD, fmt, ##args) - -/* - * An assertion is run-time check done in debug mode only. If DEBUG is not - * defined then it is skipped. If DEBUG is defined and the assertion fails, - * then it calls panic*( which may or may not reset/halt U-Boot (see - * CONFIG_PANIC_HANG), It is hoped that all failing assertions are found - * before release, and after release it is hoped that they don't matter. But - * in any case these failing assertions cannot be fixed with a reset (which - * may just do the same assertion again). - */ -void __assert_fail(const char *assertion, const char *file, unsigned line, - const char *function); -#define assert(x) \ - ({ if (!(x) && _DEBUG) \ - __assert_fail(#x, __FILE__, __LINE__, __func__); }) +#include <log.h> typedef void (interrupt_handler_t)(void *); diff --git a/include/configs/ls1012a_common.h b/include/configs/ls1012a_common.h index d2fa50a8be7..57cae9498cb 100644 --- a/include/configs/ls1012a_common.h +++ b/include/configs/ls1012a_common.h @@ -65,7 +65,7 @@ #define CONFIG_ENV_OVERWRITE #define CONFIG_ENV_SIZE 0x40000 /* 256KB */ -#define CONFIG_ENV_OFFSET 0x200000 /* 2MB */ +#define CONFIG_ENV_OFFSET 0x300000 /* 3MB */ #define CONFIG_ENV_SECT_SIZE 0x40000 #endif @@ -94,7 +94,7 @@ "kernel_addr=0x100000\0" \ "fdt_high=0xffffffffffffffff\0" \ "initrd_high=0xffffffffffffffff\0" \ - "kernel_start=0xa00000\0" \ + "kernel_start=0x1000000\0" \ "kernel_load=0xa0000000\0" \ "kernel_size=0x2800000\0" \ diff --git a/include/configs/ls1012afrdm.h b/include/configs/ls1012afrdm.h index efb4c00cd91..5b4bf288e75 100644 --- a/include/configs/ls1012afrdm.h +++ b/include/configs/ls1012afrdm.h @@ -27,7 +27,7 @@ "kernel_addr=0x100000\0" \ "fdt_high=0xffffffffffffffff\0" \ "initrd_high=0xffffffffffffffff\0" \ - "kernel_start=0xa00000\0" \ + "kernel_start=0x1000000\0" \ "kernel_load=0x96000000\0" \ "kernel_size=0x2800000\0" diff --git a/include/configs/ls1021atwr.h b/include/configs/ls1021atwr.h index 5be61ad7b6b..3db7ef12b07 100644 --- a/include/configs/ls1021atwr.h +++ b/include/configs/ls1021atwr.h @@ -420,16 +420,22 @@ "initrd_high=0xffffffff\0" \ "fdt_high=0xffffffff\0" \ "fdt_addr=0x64f00000\0" \ - "kernel_addr=0x65000000\0" \ + "kernel_addr=0x61000000\0" \ + "kernelheader_addr=0x60800000\0" \ "scriptaddr=0x80000000\0" \ "scripthdraddr=0x80080000\0" \ "fdtheader_addr_r=0x80100000\0" \ "kernelheader_addr_r=0x80200000\0" \ "kernel_addr_r=0x81000000\0" \ + "kernelheader_size=0x40000\0" \ "fdt_addr_r=0x90000000\0" \ "ramdisk_addr_r=0xa0000000\0" \ "load_addr=0xa0000000\0" \ "kernel_size=0x2800000\0" \ + "kernel_addr_sd=0x8000\0" \ + "kernel_size_sd=0x14000\0" \ + "kernelhdr_addr_sd=0x4000\0" \ + "kernelhdr_size_sd=0x10\0" \ BOOTENV \ "boot_scripts=ls1021atwr_boot.scr\0" \ "boot_script_hdr=hdr_ls1021atwr_bs.out\0" \ @@ -460,26 +466,35 @@ "source ${scriptaddr}\0" \ "qspi_bootcmd=echo Trying load from qspi..;" \ "sf probe && sf read $load_addr " \ - "$kernel_addr $kernel_size && bootm $load_addr#$board\0" \ + "$kernel_addr $kernel_size; env exists secureboot " \ + "&& sf read $kernelheader_addr_r $kernelheader_addr " \ + "$kernelheader_size && esbc_validate ${kernelheader_addr_r}; " \ + "bootm $load_addr#$board\0" \ "nor_bootcmd=echo Trying load from nor..;" \ "cp.b $kernel_addr $load_addr " \ - "$kernel_size && bootm $load_addr#$board\0" \ + "$kernel_size; env exists secureboot " \ + "&& cp.b $kernelheader_addr $kernelheader_addr_r " \ + "$kernelheader_size && esbc_validate ${kernelheader_addr_r}; " \ + "bootm $load_addr#$board\0" \ "sd_bootcmd=echo Trying load from SD ..;" \ "mmcinfo && mmc read $load_addr " \ "$kernel_addr_sd $kernel_size_sd && " \ + "env exists secureboot && mmc read $kernelheader_addr_r " \ + "$kernelhdr_addr_sd $kernelhdr_size_sd " \ + " && esbc_validate ${kernelheader_addr_r};" \ "bootm $load_addr#$board\0" #endif #undef CONFIG_BOOTCOMMAND #if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI) -#define CONFIG_BOOTCOMMAND "run distro_bootcmd; env exists secureboot" \ - "&& esbc_halt; run qspi_bootcmd;" +#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run qspi_bootcmd" \ + "env exists secureboot && esbc_halt" #elif defined(CONFIG_SD_BOOT) -#define CONFIG_BOOTCOMMAND "run distro_bootcmd; env exists secureboot" \ - "&& esbc_halt; run sd_bootcmd;" +#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run sd_bootcmd; " \ + "env exists secureboot && esbc_halt;" #else -#define CONFIG_BOOTCOMMAND "run distro_bootcmd; env exists secureboot" \ - "&& esbc_halt; run nor_bootcmd;" +#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run nor_bootcmd;" \ + "env exists secureboot && esbc_halt;" #endif /* diff --git a/include/configs/ls1043a_common.h b/include/configs/ls1043a_common.h index a4cd09aa90d..67b5ea715e8 100644 --- a/include/configs/ls1043a_common.h +++ b/include/configs/ls1043a_common.h @@ -252,7 +252,7 @@ "fdt_high=0xffffffffffffffff\0" \ "initrd_high=0xffffffffffffffff\0" \ "fdt_addr=0x64f00000\0" \ - "kernel_addr=0x65000000\0" \ + "kernel_addr=0x61000000\0" \ "scriptaddr=0x80000000\0" \ "scripthdraddr=0x80080000\0" \ "fdtheader_addr_r=0x80100000\0" \ @@ -260,9 +260,13 @@ "kernel_addr_r=0x81000000\0" \ "fdt_addr_r=0x90000000\0" \ "load_addr=0xa0000000\0" \ + "kernelheader_addr=0x60800000\0" \ "kernel_size=0x2800000\0" \ + "kernelheader_size=0x40000\0" \ "kernel_addr_sd=0x8000\0" \ "kernel_size_sd=0x14000\0" \ + "kernelhdr_addr_sd=0x4000\0" \ + "kernelhdr_size_sd=0x10\0" \ "console=ttyS0,115200\0" \ "boot_os=y\0" \ "mtdparts=" CONFIG_MTDPARTS_DEFAULT "\0" \ @@ -295,26 +299,35 @@ "source ${scriptaddr}\0" \ "qspi_bootcmd=echo Trying load from qspi..;" \ "sf probe && sf read $load_addr " \ - "$kernel_addr $kernel_size && bootm $load_addr#$board\0" \ + "$kernel_addr $kernel_size; env exists secureboot " \ + "&& sf read $kernelheader_addr_r $kernelheader_addr " \ + "$kernelheader_size && esbc_validate ${kernelheader_addr_r}; " \ + "bootm $load_addr#$board\0" \ "nor_bootcmd=echo Trying load from nor..;" \ "cp.b $kernel_addr $load_addr " \ - "$kernel_size && bootm $load_addr#$board\0" \ + "$kernel_size; env exists secureboot " \ + "&& cp.b $kernelheader_addr $kernelheader_addr_r " \ + "$kernelheader_size && esbc_validate ${kernelheader_addr_r}; " \ + "bootm $load_addr#$board\0" \ "sd_bootcmd=echo Trying load from SD ..;" \ "mmcinfo; mmc read $load_addr " \ "$kernel_addr_sd $kernel_size_sd && " \ + "env exists secureboot && mmc read $kernelheader_addr_r " \ + "$kernelhdr_addr_sd $kernelhdr_size_sd " \ + " && esbc_validate ${kernelheader_addr_r};" \ "bootm $load_addr#$board\0" #undef CONFIG_BOOTCOMMAND #if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI) -#define CONFIG_BOOTCOMMAND "run distro_bootcmd; env exists secureboot" \ - "&& esbc_halt; run qspi_bootcmd;" +#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run qspi_bootcmd; " \ + "env exists secureboot && esbc_halt;" #elif defined(CONFIG_SD_BOOT) -#define CONFIG_BOOTCOMMAND "run distro_bootcmd; env exists secureboot" \ - "&& esbc_halt; run sd_bootcmd;" +#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run sd_bootcmd; " \ + "env exists secureboot && esbc_halt;" #else -#define CONFIG_BOOTCOMMAND "run distro_bootcmd; env exists secureboot" \ - "&& esbc_halt; run nor_bootcmd;" +#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run nor_bootcmd; " \ + "env exists secureboot && esbc_halt;" #endif #endif diff --git a/include/configs/ls1046a_common.h b/include/configs/ls1046a_common.h index 11f2a28743e..e208f7d2de7 100644 --- a/include/configs/ls1046a_common.h +++ b/include/configs/ls1046a_common.h @@ -225,10 +225,14 @@ "fdt_addr_r=0x90000000\0" \ "ramdisk_addr_r=0xa0000000\0" \ "kernel_start=0x1000000\0" \ + "kernelheader_start=0x800000\0" \ "kernel_load=0xa0000000\0" \ "kernel_size=0x2800000\0" \ + "kernelheader_size=0x40000\0" \ "kernel_addr_sd=0x8000\0" \ "kernel_size_sd=0x14000\0" \ + "kernelhdr_addr_sd=0x4000\0" \ + "kernelhdr_size_sd=0x10\0" \ "console=ttyS0,115200\0" \ CONFIG_MTDPARTS_DEFAULT "\0" \ BOOTENV \ @@ -261,10 +265,16 @@ "source ${scriptaddr}\0" \ "qspi_bootcmd=echo Trying load from qspi..;" \ "sf probe && sf read $load_addr " \ - "$kernel_start $kernel_size && bootm $load_addr#$board\0" \ + "$kernel_start $kernel_size; env exists secureboot " \ + "&& sf read $kernelheader_addr_r $kernelheader_start " \ + "$kernelheader_size && esbc_validate ${kernelheader_addr_r}; " \ + "bootm $load_addr#$board\0" \ "sd_bootcmd=echo Trying load from SD ..;" \ "mmcinfo; mmc read $load_addr " \ "$kernel_addr_sd $kernel_size_sd && " \ + "env exists secureboot && mmc read $kernelheader_addr_r " \ + "$kernelhdr_addr_sd $kernelhdr_size_sd " \ + " && esbc_validate ${kernelheader_addr_r};" \ "bootm $load_addr#$board\0" #endif diff --git a/include/configs/ls1046ardb.h b/include/configs/ls1046ardb.h index d001b802701..5afd5c64bbb 100644 --- a/include/configs/ls1046ardb.h +++ b/include/configs/ls1046ardb.h @@ -226,11 +226,11 @@ #ifndef SPL_NO_MISC #undef CONFIG_BOOTCOMMAND #if defined(CONFIG_QSPI_BOOT) -#define CONFIG_BOOTCOMMAND "run distro_bootcmd; env exists secureboot" \ - "&& esbc_halt; run qspi_bootcmd;" +#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run qspi_bootcmd; " \ + "env exists secureboot && esbc_halt;;" #elif defined(CONFIG_SD_BOOT) -#define CONFIG_BOOTCOMMAND "run distro_bootcmd; env exists secureboot" \ - "&& esbc_halt; run sd_bootcmd;" +#define CONFIG_BOOTCOMMAND "run distro_bootcmd;run sd_bootcmd; " \ + "env exists secureboot && esbc_halt;" #endif #endif diff --git a/include/configs/ls1088a_common.h b/include/configs/ls1088a_common.h index 6b71d47c5ac..b99257e547a 100644 --- a/include/configs/ls1088a_common.h +++ b/include/configs/ls1088a_common.h @@ -144,9 +144,6 @@ unsigned long long get_qixis_addr(void); #if defined(CONFIG_FSL_MC_ENET) #define CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE (512UL * 1024 * 1024) #endif - -#define CONFIG_FSL_CAAM /* Enable SEC/CAAM */ - /* Command line configuration */ #define CONFIG_CMD_GREPENV #define CONFIG_CMD_CACHE diff --git a/include/configs/ls1088aqds.h b/include/configs/ls1088aqds.h index 310e8fd59f3..e7e3afefd9a 100644 --- a/include/configs/ls1088aqds.h +++ b/include/configs/ls1088aqds.h @@ -335,6 +335,26 @@ unsigned long get_board_ddr_clk(void); QIXIS_SDID_MASK) != QIXIS_ESDHC_NO_ADAPTER) /* Initial environment variables */ +#ifdef CONFIG_SECURE_BOOT +#undef CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS \ + "hwconfig=fsl_ddr:bank_intlv=auto\0" \ + "loadaddr=0x90100000\0" \ + "kernel_addr=0x100000\0" \ + "ramdisk_addr=0x800000\0" \ + "ramdisk_size=0x2000000\0" \ + "fdt_high=0xa0000000\0" \ + "initrd_high=0xffffffffffffffff\0" \ + "kernel_start=0x1000000\0" \ + "kernel_load=0xa0000000\0" \ + "kernel_size=0x2800000\0" \ + "mcinitcmd=sf probe 0:0;sf read 0xa0a00000 0xa00000 0x100000;" \ + "sf read 0xa0700000 0x700000 0x4000; esbc_validate 0xa0700000;" \ + "sf read 0xa0e00000 0xe00000 0x100000;" \ + "sf read 0xa0740000 0x740000 0x4000;esbc_validate 0xa0740000;" \ + "fsl_mc start mc 0xa0a00000 0xa0e00000\0" \ + "mcmemsize=0x70000000 \0" +#else /* if !(CONFIG_SECURE_BOOT) */ #if defined(CONFIG_QSPI_BOOT) #undef CONFIG_EXTRA_ENV_SETTINGS #define CONFIG_EXTRA_ENV_SETTINGS \ @@ -385,6 +405,7 @@ unsigned long get_board_ddr_clk(void); "mcinitcmd=fsl_mc start mc 0x580A00000 0x580E00000\0" \ "mcmemsize=0x70000000 \0" #endif +#endif /* CONFIG_SECURE_BOOT */ #ifdef CONFIG_FSL_MC_ENET #define CONFIG_FSL_MEMAC diff --git a/include/configs/ls1088ardb.h b/include/configs/ls1088ardb.h index e6bf2b8d873..1da8153a4e9 100644 --- a/include/configs/ls1088ardb.h +++ b/include/configs/ls1088ardb.h @@ -95,6 +95,7 @@ #define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE } #endif #endif +#define CONFIG_NAND_FSL_IFC #define CONFIG_SYS_NAND_MAX_ECCPOS 256 #define CONFIG_SYS_NAND_MAX_OOBFREE 2 @@ -132,6 +133,7 @@ #define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_MTD_NAND_VERIFY_WRITE +#define CONFIG_CMD_NAND #define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024) @@ -261,13 +263,23 @@ #define MC_INIT_CMD \ "mcinitcmd=sf probe 0:0;sf read 0x80000000 0xA00000 0x100000;" \ "sf read 0x80100000 0xE00000 0x100000;" \ - "fsl_mc start mc 0x80000000 0x80100000\0" \ + "env exists secureboot && " \ + "sf read 0x80700000 0x700000 0x40000 && " \ + "sf read 0x80740000 0x740000 0x40000 && " \ + "esbc_validate 0x80700000 && " \ + "esbc_validate 0x80740000 ;" \ + "fsl_mc start mc 0x80000000 0x80100000\0" \ "mcmemsize=0x70000000\0" #elif defined(CONFIG_SD_BOOT) #define MC_INIT_CMD \ "mcinitcmd=mmcinfo;mmc read 0x80000000 0x5000 0x800;" \ "mmc read 0x80100000 0x7000 0x800;" \ - "fsl_mc start mc 0x80000000 0x80100000\0" \ + "env exists secureboot && " \ + "mmc read 0x80700000 0x3800 0x10 && " \ + "mmc read 0x80740000 0x3A00 0x10 && " \ + "esbc_validate 0x80700000 && " \ + "esbc_validate 0x80740000 ;" \ + "fsl_mc start mc 0x80000000 0x80100000\0" \ "mcmemsize=0x70000000\0" #endif @@ -282,6 +294,7 @@ "fdt_addr=0x64f00000\0" \ "kernel_addr=0x1000000\0" \ "kernel_addr_sd=0x8000\0" \ + "kernelhdr_addr_sd=0x4000\0" \ "kernel_start=0x580100000\0" \ "kernelheader_start=0x580800000\0" \ "scriptaddr=0x80000000\0" \ @@ -295,6 +308,7 @@ "load_addr=0xa0000000\0" \ "kernel_size=0x2800000\0" \ "kernel_size_sd=0x14000\0" \ + "kernelhdr_size_sd=0x10\0" \ MC_INIT_CMD \ BOOTENV \ "boot_scripts=ls1088ardb_boot.scr\0" \ @@ -331,29 +345,41 @@ "bootm $load_addr#ls1088ardb\0" \ "qspi_bootcmd=echo Trying load from qspi..;" \ "sf probe && sf read $load_addr " \ - "$kernel_addr $kernel_size &&" \ + "$kernel_addr $kernel_size ; env exists secureboot " \ + "&& sf read $kernelheader_addr_r $kernelheader_addr " \ + "$kernelheader_size && esbc_validate ${kernelheader_addr_r}; "\ "bootm $load_addr#$BOARD\0" \ - "sd_bootcmd=echo Trying load from sd card..;" \ + "sd_bootcmd=echo Trying load from sd card..;" \ "mmcinfo; mmc read $load_addr " \ "$kernel_addr_sd $kernel_size_sd ;" \ + "env exists secureboot && mmc read $kernelheader_addr_r "\ + "$kernelhdr_addr_sd $kernelhdr_size_sd " \ + " && esbc_validate ${kernelheader_addr_r};" \ "bootm $load_addr#$BOARD\0" #undef CONFIG_BOOTCOMMAND #if defined(CONFIG_QSPI_BOOT) /* Try to boot an on-QSPI kernel first, then do normal distro boot */ #define CONFIG_BOOTCOMMAND \ - "env exists mcinitcmd && run mcinitcmd && " \ - "sf read 0x80200000 0xd00000 0x100000;" \ - " fsl_mc apply dpl 0x80200000;" \ - "run distro_bootcmd;run qspi_bootcmd" + "sf read 0x80200000 0xd00000 0x100000;" \ + "env exists mcinitcmd && env exists secureboot " \ + " && sf read 0x80780000 0x780000 0x100000 " \ + "&& esbc_validate 0x80780000;env exists mcinitcmd " \ + "&& fsl_mc apply dpl 0x80200000;" \ + "run distro_bootcmd;run qspi_bootcmd;" \ + "env exists secureboot && esbc_halt;" + /* Try to boot an on-SD kernel first, then do normal distro boot */ #elif defined(CONFIG_SD_BOOT) #define CONFIG_BOOTCOMMAND \ - "env exists mcinitcmd && run mcinitcmd ;" \ - "&& env exists mcinitcmd && mmcinfo; " \ - "mmc read 0x88000000 0x6800 0x800; " \ - "&& fsl_mc apply dpl 0x88000000;" \ - "run distro_bootcmd;run sd_bootcmd" + "env exists mcinitcmd && mmcinfo; " \ + "mmc read 0x80200000 0x6800 0x800; " \ + "env exists mcinitcmd && env exists secureboot " \ + " && mmc read 0x80780000 0x3800 0x10 " \ + "&& esbc_validate 0x80780000;env exists mcinitcmd " \ + "&& fsl_mc apply dpl 0x80200000;" \ + "run distro_bootcmd;run sd_bootcmd;" \ + "env exists secureboot && esbc_halt;" #endif /* MAC/PHY configuration */ diff --git a/include/efi.h b/include/efi.h index dc8edc8743a..2f0be9c86cb 100644 --- a/include/efi.h +++ b/include/efi.h @@ -227,9 +227,9 @@ struct efi_time_cap { }; enum efi_locate_search_type { - all_handles, - by_register_notify, - by_protocol + ALL_HANDLES, + BY_REGISTER_NOTIFY, + BY_PROTOCOL }; struct efi_open_protocol_info_entry { diff --git a/include/efi_api.h b/include/efi_api.h index fcd7483ab21..584016dc302 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -28,8 +28,7 @@ enum efi_timer_delay { EFI_TIMER_RELATIVE = 2 }; -#define UINTN size_t -typedef long INTN; +#define efi_uintn_t size_t typedef uint16_t *efi_string_t; #define EVT_TIMER 0x80000000 @@ -49,20 +48,22 @@ struct efi_event; /* EFI Boot Services table */ struct efi_boot_services { struct efi_table_hdr hdr; - efi_status_t (EFIAPI *raise_tpl)(UINTN new_tpl); - void (EFIAPI *restore_tpl)(UINTN old_tpl); + efi_status_t (EFIAPI *raise_tpl)(efi_uintn_t new_tpl); + void (EFIAPI *restore_tpl)(efi_uintn_t old_tpl); - efi_status_t (EFIAPI *allocate_pages)(int, int, unsigned long, + efi_status_t (EFIAPI *allocate_pages)(int, int, efi_uintn_t, efi_physical_addr_t *); - efi_status_t (EFIAPI *free_pages)(efi_physical_addr_t, unsigned long); - efi_status_t (EFIAPI *get_memory_map)(unsigned long *memory_map_size, - struct efi_mem_desc *desc, unsigned long *key, - unsigned long *desc_size, u32 *desc_version); - efi_status_t (EFIAPI *allocate_pool)(int, unsigned long, void **); + efi_status_t (EFIAPI *free_pages)(efi_physical_addr_t, efi_uintn_t); + efi_status_t (EFIAPI *get_memory_map)(efi_uintn_t *memory_map_size, + struct efi_mem_desc *desc, + efi_uintn_t *key, + efi_uintn_t *desc_size, + u32 *desc_version); + efi_status_t (EFIAPI *allocate_pool)(int, efi_uintn_t, void **); efi_status_t (EFIAPI *free_pool)(void *); efi_status_t (EFIAPI *create_event)(uint32_t type, - UINTN notify_tpl, + efi_uintn_t notify_tpl, void (EFIAPI *notify_function) ( struct efi_event *event, void *context), @@ -70,8 +71,9 @@ struct efi_boot_services { efi_status_t (EFIAPI *set_timer)(struct efi_event *event, enum efi_timer_delay type, uint64_t trigger_time); - efi_status_t (EFIAPI *wait_for_event)(unsigned long number_of_events, - struct efi_event **event, size_t *index); + efi_status_t (EFIAPI *wait_for_event)(efi_uintn_t number_of_events, + struct efi_event **event, + efi_uintn_t *index); efi_status_t (EFIAPI *signal_event)(struct efi_event *event); efi_status_t (EFIAPI *close_event)(struct efi_event *event); efi_status_t (EFIAPI *check_event)(struct efi_event *event); @@ -94,7 +96,7 @@ struct efi_boot_services { efi_status_t (EFIAPI *locate_handle)( enum efi_locate_search_type search_type, const efi_guid_t *protocol, void *search_key, - unsigned long *buffer_size, efi_handle_t *buffer); + efi_uintn_t *buffer_size, efi_handle_t *buffer); efi_status_t (EFIAPI *locate_device_path)(const efi_guid_t *protocol, struct efi_device_path **device_path, efi_handle_t *device); @@ -141,14 +143,14 @@ struct efi_boot_services { efi_status_t(EFIAPI *open_protocol_information)(efi_handle_t handle, const efi_guid_t *protocol, struct efi_open_protocol_info_entry **entry_buffer, - unsigned long *entry_count); + efi_uintn_t *entry_count); efi_status_t (EFIAPI *protocols_per_handle)(efi_handle_t handle, efi_guid_t ***protocol_buffer, - unsigned long *protocols_buffer_count); + efi_uintn_t *protocols_buffer_count); efi_status_t (EFIAPI *locate_handle_buffer) ( enum efi_locate_search_type search_type, const efi_guid_t *protocol, void *search_key, - unsigned long *no_handles, efi_handle_t **buffer); + efi_uintn_t *no_handles, efi_handle_t **buffer); efi_status_t (EFIAPI *locate_protocol)(const efi_guid_t *protocol, void *registration, void **protocol_interface); efi_status_t (EFIAPI *install_multiple_protocol_interfaces)( @@ -249,7 +251,7 @@ struct efi_system_table { struct efi_simple_text_output_protocol *std_err; struct efi_runtime_services *runtime; struct efi_boot_services *boottime; - unsigned long nr_tables; + efi_uintn_t nr_tables; struct efi_configuration_table *tables; }; @@ -583,14 +585,14 @@ struct efi_gop_mode struct efi_gop { efi_status_t (EFIAPI *query_mode)(struct efi_gop *this, u32 mode_number, - unsigned long *size_of_info, + efi_uintn_t *size_of_info, struct efi_gop_mode_info **info); efi_status_t (EFIAPI *set_mode)(struct efi_gop *this, u32 mode_number); efi_status_t (EFIAPI *blt)(struct efi_gop *this, void *buffer, - unsigned long operation, unsigned long sx, - unsigned long sy, unsigned long dx, - unsigned long dy, unsigned long width, - unsigned long height, unsigned long delta); + u32 operation, efi_uintn_t sx, + efi_uintn_t sy, efi_uintn_t dx, + efi_uintn_t dy, efi_uintn_t width, + efi_uintn_t height, efi_uintn_t delta); struct efi_gop_mode *mode; }; diff --git a/include/efi_loader.h b/include/efi_loader.h index 1b92edbd77c..c0caabddb12 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -6,6 +6,9 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#ifndef _EFI_LOADER_H +#define _EFI_LOADER_H 1 + #include <common.h> #include <part_efi.h> #include <efi_api.h> @@ -75,9 +78,9 @@ const char *__efi_nesting_dec(void); extern struct efi_runtime_services efi_runtime_services; extern struct efi_system_table systab; -extern const struct efi_simple_text_output_protocol efi_con_out; +extern struct efi_simple_text_output_protocol efi_con_out; extern struct efi_simple_input_interface efi_con_in; -extern const struct efi_console_control_protocol efi_console_control; +extern struct efi_console_control_protocol efi_console_control; extern const struct efi_device_path_to_text_protocol efi_device_path_to_text; uint16_t *efi_dp_str(struct efi_device_path *dp); @@ -98,6 +101,8 @@ extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; * interface (usually a struct with callback functions), this struct maps the * protocol GUID to the respective protocol interface */ struct efi_handler { + /* Link to the list of protocols of a handle */ + struct list_head link; const efi_guid_t *guid; void *protocol_interface; }; @@ -112,20 +117,12 @@ struct efi_handler { struct efi_object { /* Every UEFI object is part of a global object list */ struct list_head link; - /* We support up to 16 "protocols" an object can be accessed through */ - struct efi_handler protocols[16]; + /* The list of protocols */ + struct list_head protocols; /* The object spawner can either use this for data or as identifier */ void *handle; }; -#define EFI_PROTOCOL_OBJECT(_guid, _protocol) (struct efi_object){ \ - .protocols = {{ \ - .guid = &(_guid), \ - .protocol_interface = (void *)(_protocol), \ - }}, \ - .handle = (void *)(_protocol), \ -} - /** * struct efi_event * @@ -141,7 +138,7 @@ struct efi_object { */ struct efi_event { uint32_t type; - UINTN notify_tpl; + efi_uintn_t notify_tpl; void (EFIAPI *notify_function)(struct efi_event *event, void *context); void *notify_context; u64 trigger_next; @@ -163,6 +160,8 @@ int efi_disk_register(void); int efi_gop_register(void); /* Called by bootefi to make the network interface available */ int efi_net_register(void); +/* Called by bootefi to make the watchdog available */ +int efi_watchdog_register(void); /* Called by bootefi to make SMBIOS tables available */ void efi_smbios_register(void); @@ -171,6 +170,8 @@ efi_fs_from_path(struct efi_device_path *fp); /* Called by networking code to memorize the dhcp ack package */ void efi_net_set_dhcp_ack(void *pkt, int len); +/* Called by efi_set_watchdog_timer to reset the timer */ +efi_status_t efi_set_watchdog(unsigned long timeout); /* Called from places to check whether a timer expired */ void efi_timer_check(void); @@ -185,8 +186,26 @@ void efi_restore_gd(void); void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map); /* Call this to set the current device name */ void efi_set_bootdev(const char *dev, const char *devnr, const char *path); +/* Add a new object to the object list. */ +void efi_add_handle(struct efi_object *obj); +/* Create handle */ +efi_status_t efi_create_handle(void **handle); +/* Call this to validate a handle and find the EFI object for it */ +struct efi_object *efi_search_obj(const void *handle); +/* Find a protocol on a handle */ +efi_status_t efi_search_protocol(const void *handle, + const efi_guid_t *protocol_guid, + struct efi_handler **handler); +/* Install new protocol on a handle */ +efi_status_t efi_add_protocol(const void *handle, const efi_guid_t *protocol, + void *protocol_interface); +/* Delete protocol from a handle */ +efi_status_t efi_remove_protocol(const void *handle, const efi_guid_t *protocol, + void *protocol_interface); +/* Delete all protocols from a handle */ +efi_status_t efi_remove_all_protocols(const void *handle); /* Call this to create an event */ -efi_status_t efi_create_event(uint32_t type, UINTN notify_tpl, +efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, void (EFIAPI *notify_function) ( struct efi_event *event, void *context), @@ -208,20 +227,20 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp); /* Generic EFI memory allocator, call this to get memory */ void *efi_alloc(uint64_t len, int memory_type); /* More specific EFI memory allocator, called by EFI payloads */ -efi_status_t efi_allocate_pages(int type, int memory_type, unsigned long pages, +efi_status_t efi_allocate_pages(int type, int memory_type, efi_uintn_t pages, uint64_t *memory); /* EFI memory free function. */ -efi_status_t efi_free_pages(uint64_t memory, unsigned long pages); +efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages); /* EFI memory allocator for small allocations */ -efi_status_t efi_allocate_pool(int pool_type, unsigned long size, +efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer); /* EFI pool memory free function. */ efi_status_t efi_free_pool(void *buffer); /* Returns the EFI memory map */ -efi_status_t efi_get_memory_map(unsigned long *memory_map_size, +efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, struct efi_mem_desc *memory_map, - unsigned long *map_key, - unsigned long *descriptor_size, + efi_uintn_t *map_key, + efi_uintn_t *descriptor_size, uint32_t *descriptor_version); /* Adds a range into the EFI memory map */ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, @@ -243,7 +262,8 @@ extern void *efi_bounce_buffer; struct efi_device_path *efi_dp_next(const struct efi_device_path *dp); -int efi_dp_match(struct efi_device_path *a, struct efi_device_path *b); +int efi_dp_match(const struct efi_device_path *a, + const struct efi_device_path *b); struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, struct efi_device_path **rem); unsigned efi_dp_size(const struct efi_device_path *dp); @@ -341,4 +361,6 @@ static inline void efi_set_bootdev(const char *dev, const char *devnr, const char *path) { } static inline void efi_net_set_dhcp_ack(void *pkt, int len) { } -#endif +#endif /* CONFIG_EFI_LOADER && !CONFIG_SPL_BUILD */ + +#endif /* _EFI_LOADER_H */ diff --git a/include/efi_selftest.h b/include/efi_selftest.h index 7ec42a0406b..be5ba4bfa91 100644 --- a/include/efi_selftest.h +++ b/include/efi_selftest.h @@ -12,6 +12,7 @@ #include <common.h> #include <efi.h> #include <efi_api.h> +#include <efi_loader.h> #include <linker_lists.h> #define EFI_ST_SUCCESS 0 @@ -27,6 +28,15 @@ efi_st_printf(__VA_ARGS__)) \ /* + * Prints a TODO message. + * + * @... format string followed by fields to print + */ +#define efi_st_todo(...) \ + (efi_st_printf("%s(%u):\nTODO: ", __FILE__, __LINE__), \ + efi_st_printf(__VA_ARGS__)) \ + +/* * A test may be setup and executed at boottime, * it may be setup at boottime and executed at runtime, * or it may be setup and executed at runtime. @@ -72,6 +82,15 @@ void efi_st_printf(const char *fmt, ...) int efi_st_memcmp(const void *buf1, const void *buf2, size_t length); /* + * Compare an u16 string to a char string. + * + * @buf1: u16 string + * @buf2: char string + * @return: 0 if both buffers contain the same bytes + */ +int efi_st_strcmp_16_8(const u16 *buf1, const char *buf2); + +/* * Reads an Unicode character from the input device. * * @return: Unicode character @@ -88,6 +107,7 @@ u16 efi_st_get_key(void); * @setup: set up the unit test * @teardown: tear down the unit test * @execute: execute the unit test + * @on_request: test is only executed on request */ struct efi_unit_test { const char *name; @@ -96,6 +116,7 @@ struct efi_unit_test { const struct efi_system_table *systable); int (*execute)(void); int (*teardown)(void); + bool on_request; }; /* Declare a new EFI unit test */ diff --git a/include/fsl-mc/fsl_dpbp.h b/include/fsl-mc/fsl_dpbp.h index b1ad46ee45e..5401e861f0f 100644 --- a/include/fsl-mc/fsl_dpbp.h +++ b/include/fsl-mc/fsl_dpbp.h @@ -1,8 +1,8 @@ /* * Freescale Layerscape MC I/O wrapper * - * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -14,19 +14,21 @@ #define __FSL_DPBP_H /* DPBP Version */ -#define DPBP_VER_MAJOR 2 -#define DPBP_VER_MINOR 2 +#define DPBP_VER_MAJOR 3 +#define DPBP_VER_MINOR 3 /* Command IDs */ -#define DPBP_CMDID_CLOSE 0x800 -#define DPBP_CMDID_OPEN 0x804 -#define DPBP_CMDID_CREATE 0x904 -#define DPBP_CMDID_DESTROY 0x900 - -#define DPBP_CMDID_ENABLE 0x002 -#define DPBP_CMDID_DISABLE 0x003 -#define DPBP_CMDID_GET_ATTR 0x004 -#define DPBP_CMDID_RESET 0x005 +#define DPBP_CMDID_CLOSE 0x8001 +#define DPBP_CMDID_OPEN 0x8041 +#define DPBP_CMDID_CREATE 0x9041 +#define DPBP_CMDID_DESTROY 0x9841 +#define DPBP_CMDID_GET_API_VERSION 0xa041 + +#define DPBP_CMDID_ENABLE 0x0021 +#define DPBP_CMDID_DISABLE 0x0031 +#define DPBP_CMDID_GET_ATTR 0x0041 +#define DPBP_CMDID_RESET 0x0051 +#define DPBP_CMDID_IS_ENABLED 0x0061 /* cmd, param, offset, width, type, arg_name */ #define DPBP_CMD_OPEN(cmd, dpbp_id) \ @@ -37,8 +39,6 @@ do { \ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->bpid); \ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ - MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ - MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ } while (0) /* Data Path Buffer Pool API @@ -114,9 +114,10 @@ struct dpbp_cfg { * Return: '0' on Success; Error code otherwise. */ int dpbp_create(struct fsl_mc_io *mc_io, + uint16_t dprc_token, uint32_t cmd_flags, const struct dpbp_cfg *cfg, - uint16_t *token); + uint32_t *obj_id); /** * dpbp_destroy() - Destroy the DPBP object and release all its resources. @@ -127,8 +128,9 @@ int dpbp_create(struct fsl_mc_io *mc_io, * Return: '0' on Success; error code otherwise. */ int dpbp_destroy(struct fsl_mc_io *mc_io, + uint16_t dprc_token, uint32_t cmd_flags, - uint16_t token); + uint32_t obj_id); /** * dpbp_enable() - Enable the DPBP. @@ -189,16 +191,7 @@ int dpbp_reset(struct fsl_mc_io *mc_io, * acquire/release operations on buffers */ struct dpbp_attr { - int id; - /** - * struct version - Structure representing DPBP version - * @major: DPBP major version - * @minor: DPBP minor version - */ - struct { - uint16_t major; - uint16_t minor; - } version; + uint32_t id; uint16_t bpid; }; @@ -217,6 +210,21 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io, uint16_t token, struct dpbp_attr *attr); +/** + * dpbp_get_api_version - Retrieve DPBP Major and Minor version info. + * + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @major_ver: DPBP major version + * @minor_ver: DPBP minor version + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver); + /** @} */ #endif /* __FSL_DPBP_H */ diff --git a/include/fsl-mc/fsl_dpio.h b/include/fsl-mc/fsl_dpio.h index d8c458fb4fc..86251e222f8 100644 --- a/include/fsl-mc/fsl_dpio.h +++ b/include/fsl-mc/fsl_dpio.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2015 Freescale Semiconductor + * Copyright (C) 2013-2016 Freescale Semiconductor + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -8,19 +9,20 @@ #define _FSL_DPIO_H /* DPIO Version */ -#define DPIO_VER_MAJOR 3 +#define DPIO_VER_MAJOR 4 #define DPIO_VER_MINOR 2 /* Command IDs */ -#define DPIO_CMDID_CLOSE 0x800 -#define DPIO_CMDID_OPEN 0x803 -#define DPIO_CMDID_CREATE 0x903 -#define DPIO_CMDID_DESTROY 0x900 +#define DPIO_CMDID_CLOSE 0x8001 +#define DPIO_CMDID_OPEN 0x8031 +#define DPIO_CMDID_CREATE 0x9031 +#define DPIO_CMDID_DESTROY 0x9831 +#define DPIO_CMDID_GET_API_VERSION 0xa031 -#define DPIO_CMDID_ENABLE 0x002 -#define DPIO_CMDID_DISABLE 0x003 -#define DPIO_CMDID_GET_ATTR 0x004 -#define DPIO_CMDID_RESET 0x005 +#define DPIO_CMDID_ENABLE 0x0021 +#define DPIO_CMDID_DISABLE 0x0031 +#define DPIO_CMDID_GET_ATTR 0x0041 +#define DPIO_CMDID_RESET 0x0051 /* cmd, param, offset, width, type, arg_name */ #define DPIO_CMD_OPEN(cmd, dpio_id) \ @@ -43,8 +45,6 @@ do { \ MC_RSP_OP(cmd, 0, 56, 4, enum dpio_channel_mode, attr->channel_mode);\ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->qbman_portal_ce_offset);\ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, attr->qbman_portal_ci_offset);\ - MC_RSP_OP(cmd, 3, 0, 16, uint16_t, attr->version.major);\ - MC_RSP_OP(cmd, 3, 16, 16, uint16_t, attr->version.minor);\ MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->qbman_version);\ } while (0) @@ -73,7 +73,7 @@ struct fsl_mc_io; */ int dpio_open(struct fsl_mc_io *mc_io, uint32_t cmd_flags, - int dpio_id, + uint32_t dpio_id, uint16_t *token); /** @@ -114,9 +114,10 @@ struct dpio_cfg { /** * dpio_create() - Create the DPIO object. * @mc_io: Pointer to MC portal's I/O object + * @token: Authentication token. * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @cfg: Configuration structure - * @token: Returned token; use in subsequent API calls + * @obj_id: Returned obj_id; use in subsequent API calls * * Create the DPIO object, allocate required resources and * perform required initialization. @@ -134,21 +135,24 @@ struct dpio_cfg { * Return: '0' on Success; Error code otherwise. */ int dpio_create(struct fsl_mc_io *mc_io, + uint16_t token, uint32_t cmd_flags, const struct dpio_cfg *cfg, - uint16_t *token); + uint32_t *obj_id); /** * dpio_destroy() - Destroy the DPIO object and release all its resources. * @mc_io: Pointer to MC portal's I/O object + * @token: Authentication token. * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPIO object + * @obj_id: Object ID of DPIO * * Return: '0' on Success; Error code otherwise */ int dpio_destroy(struct fsl_mc_io *mc_io, + uint16_t token, uint32_t cmd_flags, - uint16_t token); + uint32_t obj_id); /** * dpio_enable() - Enable the DPIO, allow I/O portal operations. @@ -199,16 +203,7 @@ int dpio_reset(struct fsl_mc_io *mc_io, * @qbman_version: QBMAN version */ struct dpio_attr { - int id; - /** - * struct version - DPIO version - * @major: DPIO major version - * @minor: DPIO minor version - */ - struct { - uint16_t major; - uint16_t minor; - } version; + uint32_t id; uint64_t qbman_portal_ce_offset; uint64_t qbman_portal_ci_offset; uint16_t qbman_portal_id; @@ -231,4 +226,19 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io, uint16_t token, struct dpio_attr *attr); +/** + * dpio_get_api_version - Retrieve DPIO Major and Minor version info. + * + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @major_ver: DPIO major version + * @minor_ver: DPIO minor version + * + * Return: '0' on Success; Error code otherwise. + */ +int dpio_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver); + #endif /* _FSL_DPIO_H */ diff --git a/include/fsl-mc/fsl_dpmac.h b/include/fsl-mc/fsl_dpmac.h index 296f3aed245..36a5cca69ce 100644 --- a/include/fsl-mc/fsl_dpmac.h +++ b/include/fsl-mc/fsl_dpmac.h @@ -1,7 +1,8 @@ /* * Freescale Layerscape MC I/O wrapper * - * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP * Author: Prabhakar Kushwaha <prabhakar@freescale.com> * * SPDX-License-Identifier: GPL-2.0+ @@ -11,27 +12,28 @@ #define __FSL_DPMAC_H /* DPMAC Version */ -#define DPMAC_VER_MAJOR 3 +#define DPMAC_VER_MAJOR 4 #define DPMAC_VER_MINOR 2 /* Command IDs */ -#define DPMAC_CMDID_CLOSE 0x800 -#define DPMAC_CMDID_OPEN 0x80c -#define DPMAC_CMDID_CREATE 0x90c -#define DPMAC_CMDID_DESTROY 0x900 +#define DPMAC_CMDID_CLOSE 0x8001 +#define DPMAC_CMDID_OPEN 0x80c1 +#define DPMAC_CMDID_CREATE 0x90c1 +#define DPMAC_CMDID_DESTROY 0x98c1 +#define DPMAC_CMDID_GET_API_VERSION 0xa0c1 -#define DPMAC_CMDID_GET_ATTR 0x004 -#define DPMAC_CMDID_RESET 0x005 +#define DPMAC_CMDID_GET_ATTR 0x0041 +#define DPMAC_CMDID_RESET 0x0051 -#define DPMAC_CMDID_MDIO_READ 0x0c0 -#define DPMAC_CMDID_MDIO_WRITE 0x0c1 -#define DPMAC_CMDID_GET_LINK_CFG 0x0c2 -#define DPMAC_CMDID_SET_LINK_STATE 0x0c3 -#define DPMAC_CMDID_GET_COUNTER 0x0c4 +#define DPMAC_CMDID_MDIO_READ 0x0c01 +#define DPMAC_CMDID_MDIO_WRITE 0x0c11 +#define DPMAC_CMDID_GET_LINK_CFG 0x0c21 +#define DPMAC_CMDID_SET_LINK_STATE 0x0c31 +#define DPMAC_CMDID_GET_COUNTER 0x0c41 /* cmd, param, offset, width, type, arg_name */ #define DPMAC_CMD_CREATE(cmd, cfg) \ - MC_CMD_OP(cmd, 0, 0, 32, int, cfg->mac_id) + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->mac_id) /* cmd, param, offset, width, type, arg_name */ #define DPMAC_CMD_OPEN(cmd, dpmac_id) \ @@ -42,8 +44,6 @@ do { \ MC_RSP_OP(cmd, 0, 0, 32, int, attr->phy_id);\ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ - MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ - MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ MC_RSP_OP(cmd, 1, 32, 8, enum dpmac_link_type, attr->link_type);\ MC_RSP_OP(cmd, 1, 40, 8, enum dpmac_eth_if, attr->eth_if);\ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->max_rate);\ @@ -85,7 +85,7 @@ do { \ /* cmd, param, offset, width, type, arg_name */ #define DPMAC_CMD_GET_COUNTER(cmd, type) \ - MC_CMD_OP(cmd, 0, 0, 8, enum dpmac_counter, type) + MC_CMD_OP(cmd, 1, 0, 64, enum dpmac_counter, type) /* cmd, param, offset, width, type, arg_name */ #define DPMAC_RSP_GET_COUNTER(cmd, counter) \ @@ -187,9 +187,10 @@ struct dpmac_cfg { /** * dpmac_create() - Create the DPMAC object. * @mc_io: Pointer to MC portal's I/O object + * @token: Authentication token. * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @cfg: Configuration structure - * @token: Returned token; use in subsequent API calls + * @obj_id: Returned obj_id; use in subsequent API calls * * Create the DPMAC object, allocate required resources and * perform required initialization. @@ -206,21 +207,24 @@ struct dpmac_cfg { * Return: '0' on Success; Error code otherwise. */ int dpmac_create(struct fsl_mc_io *mc_io, + uint16_t token, uint32_t cmd_flags, const struct dpmac_cfg *cfg, - uint16_t *token); + uint32_t *obj_id); /** * dpmac_destroy() - Destroy the DPMAC object and release all its resources. * @mc_io: Pointer to MC portal's I/O object + * @token: Authentication token. * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPMAC object + * @obj_id: DPMAC object id * * Return: '0' on Success; error code otherwise. */ int dpmac_destroy(struct fsl_mc_io *mc_io, + uint16_t token, uint32_t cmd_flags, - uint16_t token); + uint32_t obj_id); /* DPMAC IRQ Index and Events */ @@ -246,15 +250,6 @@ struct dpmac_attr { enum dpmac_link_type link_type; enum dpmac_eth_if eth_if; uint32_t max_rate; - /** - * struct version - Structure representing DPMAC version - * @major: DPMAC major version - * @minor: DPMAC minor version - */ - struct { - uint16_t major; - uint16_t minor; - } version; }; /** @@ -464,5 +459,19 @@ int dpmac_get_counter(struct fsl_mc_io *mc_io, uint16_t token, enum dpmac_counter type, uint64_t *counter); +/** + * dpmac_get_api_version - Retrieve DPMAC Major and Minor version info. + * + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @major_ver: DPMAC major version + * @minor_ver: DPMAC minor version + * + * Return: '0' on Success; Error code otherwise. + */ +int dpmac_get_api_version(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t *major_ver, + uint16_t *minor_ver); #endif /* __FSL_DPMAC_H */ diff --git a/include/fsl-mc/fsl_dpni.h b/include/fsl-mc/fsl_dpni.h index f396dc304fe..5b80b6f8e0c 100644 --- a/include/fsl-mc/fsl_dpni.h +++ b/include/fsl-mc/fsl_dpni.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2015 Freescale Semiconductor + * Copyright (C) 2013-2016 Freescale Semiconductor + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -7,134 +8,80 @@ #define _FSL_DPNI_H /* DPNI Version */ -#define DPNI_VER_MAJOR 6 -#define DPNI_VER_MINOR 0 +#define DPNI_VER_MAJOR 7 +#define DPNI_VER_MINOR 3 /* Command IDs */ -#define DPNI_CMDID_OPEN 0x801 -#define DPNI_CMDID_CLOSE 0x800 -#define DPNI_CMDID_CREATE 0x901 -#define DPNI_CMDID_DESTROY 0x900 - -#define DPNI_CMDID_ENABLE 0x002 -#define DPNI_CMDID_DISABLE 0x003 -#define DPNI_CMDID_GET_ATTR 0x004 -#define DPNI_CMDID_RESET 0x005 - -#define DPNI_CMDID_SET_POOLS 0x200 -#define DPNI_CMDID_GET_RX_BUFFER_LAYOUT 0x201 -#define DPNI_CMDID_SET_RX_BUFFER_LAYOUT 0x202 -#define DPNI_CMDID_GET_TX_BUFFER_LAYOUT 0x203 -#define DPNI_CMDID_SET_TX_BUFFER_LAYOUT 0x204 -#define DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT 0x205 -#define DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT 0x206 -#define DPNI_CMDID_SET_ERRORS_BEHAVIOR 0x20B - -#define DPNI_CMDID_GET_QDID 0x210 -#define DPNI_CMDID_GET_TX_DATA_OFFSET 0x212 -#define DPNI_CMDID_GET_COUNTER 0x213 -#define DPNI_CMDID_SET_COUNTER 0x214 -#define DPNI_CMDID_GET_LINK_STATE 0x215 -#define DPNI_CMDID_SET_LINK_CFG 0x21A - -#define DPNI_CMDID_SET_PRIM_MAC 0x224 -#define DPNI_CMDID_GET_PRIM_MAC 0x225 -#define DPNI_CMDID_ADD_MAC_ADDR 0x226 -#define DPNI_CMDID_REMOVE_MAC_ADDR 0x227 - -#define DPNI_CMDID_SET_TX_FLOW 0x236 -#define DPNI_CMDID_GET_TX_FLOW 0x237 -#define DPNI_CMDID_SET_RX_FLOW 0x238 -#define DPNI_CMDID_GET_RX_FLOW 0x239 -#define DPNI_CMDID_SET_TX_CONF 0x257 -#define DPNI_CMDID_GET_TX_CONF 0x258 +#define DPNI_CMDID_OPEN 0x8011 +#define DPNI_CMDID_CLOSE 0x8001 +#define DPNI_CMDID_CREATE 0x9011 +#define DPNI_CMDID_DESTROY 0x9811 +#define DPNI_CMDID_GET_API_VERSION 0xa011 + +#define DPNI_CMDID_ENABLE 0x0021 +#define DPNI_CMDID_DISABLE 0x0031 +#define DPNI_CMDID_GET_ATTR 0x0041 +#define DPNI_CMDID_RESET 0x0051 + +#define DPNI_CMDID_SET_POOLS 0x2002 +#define DPNI_CMDID_SET_BUFFER_LAYOUT 0x2651 +#define DPNI_CMDID_GET_BUFFER_LAYOUT 0x2641 +#define DPNI_CMDID_SET_ERRORS_BEHAVIOR 0x20B1 + +#define DPNI_CMDID_GET_QDID 0x2101 +#define DPNI_CMDID_GET_TX_DATA_OFFSET 0x2121 +#define DPNI_CMDID_GET_LINK_STATE 0x2151 +#define DPNI_CMDID_SET_LINK_CFG 0x21A1 + +#define DPNI_CMDID_SET_PRIM_MAC 0x2241 +#define DPNI_CMDID_GET_PRIM_MAC 0x2251 +#define DPNI_CMDID_ADD_MAC_ADDR 0x2261 +#define DPNI_CMDID_REMOVE_MAC_ADDR 0x2271 + +#define DPNI_CMDID_GET_STATISTICS 0x25D1 +#define DPNI_CMDID_RESET_STATISTICS 0x25E1 +#define DPNI_CMDID_GET_QUEUE 0x25F1 +#define DPNI_CMDID_SET_QUEUE 0x2601 +#define DPNI_CMDID_SET_TX_CONFIRMATION_MODE 0x2661 /* cmd, param, offset, width, type, arg_name */ #define DPNI_CMD_OPEN(cmd, dpni_id) \ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id) -#define DPNI_PREP_EXTENDED_CFG(ext, cfg) \ +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_PREP_CFG(param, cfg) \ do { \ - MC_PREP_OP(ext, 0, 0, 16, uint16_t, cfg->tc_cfg[0].max_dist); \ - MC_PREP_OP(ext, 0, 16, 16, uint16_t, cfg->tc_cfg[0].max_fs_entries); \ - MC_PREP_OP(ext, 0, 32, 16, uint16_t, cfg->tc_cfg[1].max_dist); \ - MC_PREP_OP(ext, 0, 48, 16, uint16_t, cfg->tc_cfg[1].max_fs_entries); \ - MC_PREP_OP(ext, 1, 0, 16, uint16_t, cfg->tc_cfg[2].max_dist); \ - MC_PREP_OP(ext, 1, 16, 16, uint16_t, cfg->tc_cfg[2].max_fs_entries); \ - MC_PREP_OP(ext, 1, 32, 16, uint16_t, cfg->tc_cfg[3].max_dist); \ - MC_PREP_OP(ext, 1, 48, 16, uint16_t, cfg->tc_cfg[3].max_fs_entries); \ - MC_PREP_OP(ext, 2, 0, 16, uint16_t, cfg->tc_cfg[4].max_dist); \ - MC_PREP_OP(ext, 2, 16, 16, uint16_t, cfg->tc_cfg[4].max_fs_entries); \ - MC_PREP_OP(ext, 2, 32, 16, uint16_t, cfg->tc_cfg[5].max_dist); \ - MC_PREP_OP(ext, 2, 48, 16, uint16_t, cfg->tc_cfg[5].max_fs_entries); \ - MC_PREP_OP(ext, 3, 0, 16, uint16_t, cfg->tc_cfg[6].max_dist); \ - MC_PREP_OP(ext, 3, 16, 16, uint16_t, cfg->tc_cfg[6].max_fs_entries); \ - MC_PREP_OP(ext, 3, 32, 16, uint16_t, cfg->tc_cfg[7].max_dist); \ - MC_PREP_OP(ext, 3, 48, 16, uint16_t, cfg->tc_cfg[7].max_fs_entries); \ - MC_PREP_OP(ext, 4, 0, 16, uint16_t, \ - cfg->ipr_cfg.max_open_frames_ipv4); \ - MC_PREP_OP(ext, 4, 16, 16, uint16_t, \ - cfg->ipr_cfg.max_open_frames_ipv6); \ - MC_PREP_OP(ext, 4, 32, 16, uint16_t, \ - cfg->ipr_cfg.max_reass_frm_size); \ - MC_PREP_OP(ext, 5, 0, 16, uint16_t, \ - cfg->ipr_cfg.min_frag_size_ipv4); \ - MC_PREP_OP(ext, 5, 16, 16, uint16_t, \ - cfg->ipr_cfg.min_frag_size_ipv6); \ + MC_PREP_OP(param, 0, 0, 32, uint16_t, cfg->adv.options); \ + MC_PREP_OP(param, 0, 32, 8, uint16_t, cfg->adv.num_queues); \ + MC_PREP_OP(param, 0, 40, 8, uint16_t, cfg->adv.num_tcs); \ + MC_PREP_OP(param, 0, 48, 8, uint16_t, cfg->adv.mac_entries); \ + MC_PREP_OP(param, 1, 0, 8, uint16_t, cfg->adv.vlan_entries); \ + MC_PREP_OP(param, 1, 16, 8, uint16_t, cfg->adv.qos_entries); \ + MC_PREP_OP(param, 1, 32, 16, uint16_t, cfg->adv.fs_entries); \ } while (0) -#define DPNI_EXT_EXTENDED_CFG(ext, cfg) \ +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_EXT_CFG(param, cfg) \ do { \ - MC_EXT_OP(ext, 0, 0, 16, uint16_t, cfg->tc_cfg[0].max_dist); \ - MC_EXT_OP(ext, 0, 16, 16, uint16_t, cfg->tc_cfg[0].max_fs_entries); \ - MC_EXT_OP(ext, 0, 32, 16, uint16_t, cfg->tc_cfg[1].max_dist); \ - MC_EXT_OP(ext, 0, 48, 16, uint16_t, cfg->tc_cfg[1].max_fs_entries); \ - MC_EXT_OP(ext, 1, 0, 16, uint16_t, cfg->tc_cfg[2].max_dist); \ - MC_EXT_OP(ext, 1, 16, 16, uint16_t, cfg->tc_cfg[2].max_fs_entries); \ - MC_EXT_OP(ext, 1, 32, 16, uint16_t, cfg->tc_cfg[3].max_dist); \ - MC_EXT_OP(ext, 1, 48, 16, uint16_t, cfg->tc_cfg[3].max_fs_entries); \ - MC_EXT_OP(ext, 2, 0, 16, uint16_t, cfg->tc_cfg[4].max_dist); \ - MC_EXT_OP(ext, 2, 16, 16, uint16_t, cfg->tc_cfg[4].max_fs_entries); \ - MC_EXT_OP(ext, 2, 32, 16, uint16_t, cfg->tc_cfg[5].max_dist); \ - MC_EXT_OP(ext, 2, 48, 16, uint16_t, cfg->tc_cfg[5].max_fs_entries); \ - MC_EXT_OP(ext, 3, 0, 16, uint16_t, cfg->tc_cfg[6].max_dist); \ - MC_EXT_OP(ext, 3, 16, 16, uint16_t, cfg->tc_cfg[6].max_fs_entries); \ - MC_EXT_OP(ext, 3, 32, 16, uint16_t, cfg->tc_cfg[7].max_dist); \ - MC_EXT_OP(ext, 3, 48, 16, uint16_t, cfg->tc_cfg[7].max_fs_entries); \ - MC_EXT_OP(ext, 4, 0, 16, uint16_t, \ - cfg->ipr_cfg.max_open_frames_ipv4); \ - MC_EXT_OP(ext, 4, 16, 16, uint16_t, \ - cfg->ipr_cfg.max_open_frames_ipv6); \ - MC_EXT_OP(ext, 4, 32, 16, uint16_t, \ - cfg->ipr_cfg.max_reass_frm_size); \ - MC_EXT_OP(ext, 5, 0, 16, uint16_t, \ - cfg->ipr_cfg.min_frag_size_ipv4); \ - MC_EXT_OP(ext, 5, 16, 16, uint16_t, \ - cfg->ipr_cfg.min_frag_size_ipv6); \ + MC_EXT_OP(param, 0, 0, 32, uint16_t, cfg->adv.options); \ + MC_EXT_OP(param, 0, 32, 8, uint16_t, cfg->adv.num_queues); \ + MC_EXT_OP(param, 0, 40, 8, uint16_t, cfg->adv.num_tcs); \ + MC_EXT_OP(param, 0, 48, 8, uint16_t, cfg->adv.mac_entries); \ + MC_EXT_OP(param, 1, 0, 8, uint16_t, cfg->adv.vlan_entries); \ + MC_EXT_OP(param, 1, 16, 8, uint16_t, cfg->adv.qos_entries); \ + MC_EXT_OP(param, 1, 32, 16, uint16_t, cfg->adv.fs_entries); \ } while (0) /* cmd, param, offset, width, type, arg_name */ #define DPNI_CMD_CREATE(cmd, cfg) \ do { \ - MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->adv.max_tcs); \ - MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->adv.max_senders); \ - MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]); \ - MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]); \ - MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]); \ - MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]); \ - MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]); \ - MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]); \ - MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->adv.options); \ - MC_CMD_OP(cmd, 2, 0, 8, uint8_t, cfg->adv.max_unicast_filters); \ - MC_CMD_OP(cmd, 2, 8, 8, uint8_t, cfg->adv.max_multicast_filters); \ - MC_CMD_OP(cmd, 2, 16, 8, uint8_t, cfg->adv.max_vlan_filters); \ - MC_CMD_OP(cmd, 2, 24, 8, uint8_t, cfg->adv.max_qos_entries); \ - MC_CMD_OP(cmd, 2, 32, 8, uint8_t, cfg->adv.max_qos_key_size); \ - MC_CMD_OP(cmd, 2, 48, 8, uint8_t, cfg->adv.max_dist_key_size); \ - MC_CMD_OP(cmd, 2, 56, 8, enum net_prot, cfg->adv.start_hdr); \ - MC_CMD_OP(cmd, 4, 48, 8, uint8_t, cfg->adv.max_policers); \ - MC_CMD_OP(cmd, 4, 56, 8, uint8_t, cfg->adv.max_congestion_ctrl); \ - MC_CMD_OP(cmd, 5, 0, 64, uint64_t, cfg->adv.ext_cfg_iova); \ + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, cfg->adv.options); \ + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->adv.num_queues); \ + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->adv.num_tcs); \ + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->adv.mac_entries); \ + MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->adv.vlan_entries); \ + MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->adv.qos_entries); \ + MC_CMD_OP(cmd, 1, 32, 16, uint8_t, cfg->adv.fs_entries); \ } while (0) /* cmd, param, offset, width, type, arg_name */ @@ -168,27 +115,18 @@ do { \ } while (0) /* cmd, param, offset, width, type, arg_name */ -#define DPNI_CMD_GET_ATTR(cmd, attr) \ - MC_CMD_OP(cmd, 6, 0, 64, uint64_t, attr->ext_cfg_iova) - -/* cmd, param, offset, width, type, arg_name */ #define DPNI_RSP_GET_ATTR(cmd, attr) \ do { \ - MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ - MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->max_tcs); \ - MC_RSP_OP(cmd, 0, 40, 8, uint8_t, attr->max_senders); \ - MC_RSP_OP(cmd, 0, 48, 8, enum net_prot, attr->start_hdr); \ - MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options); \ - MC_RSP_OP(cmd, 2, 0, 8, uint8_t, attr->max_unicast_filters); \ - MC_RSP_OP(cmd, 2, 8, 8, uint8_t, attr->max_multicast_filters);\ - MC_RSP_OP(cmd, 2, 16, 8, uint8_t, attr->max_vlan_filters); \ - MC_RSP_OP(cmd, 2, 24, 8, uint8_t, attr->max_qos_entries); \ - MC_RSP_OP(cmd, 2, 32, 8, uint8_t, attr->max_qos_key_size); \ - MC_RSP_OP(cmd, 2, 40, 8, uint8_t, attr->max_dist_key_size); \ - MC_RSP_OP(cmd, 4, 48, 8, uint8_t, attr->max_policers); \ - MC_RSP_OP(cmd, 4, 56, 8, uint8_t, attr->max_congestion_ctrl); \ - MC_RSP_OP(cmd, 5, 32, 16, uint16_t, attr->version.major);\ - MC_RSP_OP(cmd, 5, 48, 16, uint16_t, attr->version.minor);\ + MC_RSP_OP(cmd, 0, 0, 32, int, attr->options);\ + MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->max_num_queues); \ + MC_RSP_OP(cmd, 0, 40, 8, uint8_t, attr->max_num_tcs); \ + MC_RSP_OP(cmd, 0, 48, 8, uint8_t, attr->max_mac_entries); \ + MC_RSP_OP(cmd, 1, 0, 8, uint8_t, attr->max_vlan_entries); \ + MC_RSP_OP(cmd, 1, 16, 8, uint8_t, attr->max_qos_entries); \ + MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->max_fs_entries); \ + MC_RSP_OP(cmd, 2, 0, 8, uint8_t, attr->max_qos_key_size); \ + MC_RSP_OP(cmd, 2, 8, 8, uint8_t, attr->max_fs_key_size); \ + MC_RSP_OP(cmd, 2, 16, 16, uint16_t, attr->wriop_version); \ } while (0) /* cmd, param, offset, width, type, arg_name */ @@ -200,78 +138,17 @@ do { \ } while (0) /* cmd, param, offset, width, type, arg_name */ -#define DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout) \ -do { \ - MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ - MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ - MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ - MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ - MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ - MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ - MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ -} while (0) - -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout) \ -do { \ - MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ - MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ - MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ - MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ - MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ - MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ - MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ - MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ -} while (0) - -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout) \ -do { \ - MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ - MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ - MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ - MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ - MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ - MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ - MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ -} while (0) - -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout) \ -do { \ - MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ - MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ - MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ - MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ - MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ - MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ - MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ - MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ -} while (0) - -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout) \ -do { \ - MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ - MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ - MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ - MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ - MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ - MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ - MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ -} while (0) - -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout) \ +#define DPNI_CMD_SET_BUFFER_LAYOUT(cmd, layout, queue) \ do { \ - MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ - MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ - MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ - MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ - MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ - MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ - MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ - MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ + MC_CMD_OP(cmd, 0, 0, 8, enum dpni_queue_type, queue); \ + MC_CMD_OP(cmd, 1, 0, 16, uint16_t, layout->private_data_size); \ + MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_align); \ + MC_CMD_OP(cmd, 0, 32, 16, uint16_t, layout->options); \ + MC_CMD_OP(cmd, 0, 48, 1, int, layout->pass_timestamp); \ + MC_CMD_OP(cmd, 0, 49, 1, int, layout->pass_parser_result); \ + MC_CMD_OP(cmd, 0, 50, 1, int, layout->pass_frame_status); \ + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_head_room); \ + MC_CMD_OP(cmd, 1, 48, 16, uint16_t, layout->data_tail_room); \ } while (0) /* cmd, param, offset, width, type, arg_name */ @@ -283,21 +160,6 @@ do { \ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, data_offset) /* cmd, param, offset, width, type, arg_name */ -#define DPNI_CMD_GET_COUNTER(cmd, counter) \ - MC_CMD_OP(cmd, 0, 0, 16, enum dpni_counter, counter) - -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_RSP_GET_COUNTER(cmd, value) \ - MC_RSP_OP(cmd, 1, 0, 64, uint64_t, value) - -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_CMD_SET_COUNTER(cmd, counter, value) \ -do { \ - MC_CMD_OP(cmd, 0, 0, 16, enum dpni_counter, counter); \ - MC_CMD_OP(cmd, 1, 0, 64, uint64_t, value); \ -} while (0) - -/* cmd, param, offset, width, type, arg_name */ #define DPNI_CMD_SET_LINK_CFG(cmd, cfg) \ do { \ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\ @@ -358,129 +220,54 @@ do { \ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ } while (0) -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_CMD_SET_TX_FLOW(cmd, flow_id, cfg) \ +#define DPNI_CMD_GET_QUEUE(cmd, type, tc, index) \ do { \ - MC_CMD_OP(cmd, 0, 43, 1, int, cfg->l3_chksum_gen);\ - MC_CMD_OP(cmd, 0, 44, 1, int, cfg->l4_chksum_gen);\ - MC_CMD_OP(cmd, 0, 45, 1, int, cfg->use_common_tx_conf_queue);\ - MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id);\ - MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ + MC_CMD_OP(cmd, 0, 0, 8, enum dpni_queue_type, type); \ + MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc); \ + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, index); \ } while (0) -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_RSP_SET_TX_FLOW(cmd, flow_id) \ - MC_RSP_OP(cmd, 0, 48, 16, uint16_t, flow_id) - -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_CMD_GET_TX_FLOW(cmd, flow_id) \ - MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id) - -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_RSP_GET_TX_FLOW(cmd, attr) \ +#define DPNI_RSP_GET_QUEUE(cmd, queue) \ do { \ - MC_RSP_OP(cmd, 0, 43, 1, int, attr->l3_chksum_gen);\ - MC_RSP_OP(cmd, 0, 44, 1, int, attr->l4_chksum_gen);\ - MC_RSP_OP(cmd, 0, 45, 1, int, attr->use_common_tx_conf_queue);\ + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, (queue)->destination.id); \ + MC_RSP_OP(cmd, 1, 56, 4, enum dpni_dest, (queue)->destination.type); \ + MC_RSP_OP(cmd, 1, 62, 1, char, (queue)->destination.stash_ctrl); \ + MC_RSP_OP(cmd, 1, 63, 1, char, (queue)->destination.hold_active); \ + MC_RSP_OP(cmd, 2, 0, 64, uint64_t, (queue)->flc); \ + MC_RSP_OP(cmd, 3, 0, 64, uint64_t, (queue)->user_context); \ + MC_RSP_OP(cmd, 4, 0, 32, uint32_t, (queue)->fqid); \ + MC_RSP_OP(cmd, 4, 32, 16, uint16_t, (queue)->qdbin); \ } while (0) -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg) \ +#define DPNI_CMD_SET_QUEUE(cmd, type, tc, index, queue) \ do { \ - MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ - MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority);\ - MC_CMD_OP(cmd, 0, 40, 2, enum dpni_dest, cfg->dest_cfg.dest_type);\ - MC_CMD_OP(cmd, 0, 42, 1, int, cfg->order_preservation_en);\ - MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ - MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ - MC_CMD_OP(cmd, 2, 16, 8, uint8_t, tc_id); \ - MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->options); \ - MC_CMD_OP(cmd, 3, 0, 4, enum dpni_flc_type, cfg->flc_cfg.flc_type); \ - MC_CMD_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ - cfg->flc_cfg.frame_data_size);\ - MC_CMD_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ - cfg->flc_cfg.flow_context_size);\ - MC_CMD_OP(cmd, 3, 32, 32, uint32_t, cfg->flc_cfg.options);\ - MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->flc_cfg.flow_context);\ - MC_CMD_OP(cmd, 5, 0, 32, uint32_t, cfg->tail_drop_threshold); \ + MC_CMD_OP(cmd, 0, 0, 8, enum dpni_queue_type, type); \ + MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc); \ + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, index); \ + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, (queue)->options); \ + MC_CMD_OP(cmd, 1, 0, 32, uint32_t, (queue)->destination.id); \ + MC_CMD_OP(cmd, 1, 56, 4, enum dpni_dest, (queue)->destination.type); \ + MC_CMD_OP(cmd, 1, 62, 1, char, (queue)->destination.stash_ctrl); \ + MC_CMD_OP(cmd, 1, 63, 1, char, (queue)->destination.hold_active); \ + MC_CMD_OP(cmd, 1, 0, 32, uint32_t, (queue)->destination.id); \ + MC_CMD_OP(cmd, 2, 0, 64, uint64_t, (queue)->flc); \ + MC_CMD_OP(cmd, 3, 0, 64, uint64_t, (queue)->user_context); \ } while (0) -/* cmd, param, offset, width, type, arg_name */ -#define DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id) \ -do { \ - MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ - MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ -} while (0) +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_GET_STATISTICS(cmd, page) \ + MC_CMD_OP(cmd, 0, 0, 8, uint8_t, page) /* cmd, param, offset, width, type, arg_name */ -#define DPNI_RSP_GET_RX_FLOW(cmd, attr) \ +#define DPNI_RSP_GET_STATISTICS(cmd, stat) \ do { \ - MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id); \ - MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ - MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, attr->dest_cfg.dest_type); \ - MC_RSP_OP(cmd, 0, 42, 1, int, attr->order_preservation_en);\ - MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx); \ - MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->tail_drop_threshold); \ - MC_RSP_OP(cmd, 2, 32, 32, uint32_t, attr->fqid); \ - MC_RSP_OP(cmd, 3, 0, 4, enum dpni_flc_type, attr->flc_cfg.flc_type); \ - MC_RSP_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ - attr->flc_cfg.frame_data_size);\ - MC_RSP_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ - attr->flc_cfg.flow_context_size);\ - MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->flc_cfg.options);\ - MC_RSP_OP(cmd, 4, 0, 64, uint64_t, attr->flc_cfg.flow_context);\ -} while (0) - -#define DPNI_CMD_SET_TX_CONF(cmd, flow_id, cfg) \ -do { \ - MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->queue_cfg.dest_cfg.priority); \ - MC_CMD_OP(cmd, 0, 40, 2, enum dpni_dest, \ - cfg->queue_cfg.dest_cfg.dest_type); \ - MC_CMD_OP(cmd, 0, 42, 1, int, cfg->errors_only); \ - MC_CMD_OP(cmd, 0, 46, 1, int, cfg->queue_cfg.order_preservation_en); \ - MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ - MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->queue_cfg.user_ctx); \ - MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->queue_cfg.options); \ - MC_CMD_OP(cmd, 2, 32, 32, int, cfg->queue_cfg.dest_cfg.dest_id); \ - MC_CMD_OP(cmd, 3, 0, 32, uint32_t, \ - cfg->queue_cfg.tail_drop_threshold); \ - MC_CMD_OP(cmd, 4, 0, 4, enum dpni_flc_type, \ - cfg->queue_cfg.flc_cfg.flc_type); \ - MC_CMD_OP(cmd, 4, 4, 4, enum dpni_stash_size, \ - cfg->queue_cfg.flc_cfg.frame_data_size); \ - MC_CMD_OP(cmd, 4, 8, 4, enum dpni_stash_size, \ - cfg->queue_cfg.flc_cfg.flow_context_size); \ - MC_CMD_OP(cmd, 4, 32, 32, uint32_t, cfg->queue_cfg.flc_cfg.options); \ - MC_CMD_OP(cmd, 5, 0, 64, uint64_t, \ - cfg->queue_cfg.flc_cfg.flow_context); \ -} while (0) - -#define DPNI_CMD_GET_TX_CONF(cmd, flow_id) \ - MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id) - -#define DPNI_RSP_GET_TX_CONF(cmd, attr) \ -do { \ - MC_RSP_OP(cmd, 0, 32, 8, uint8_t, \ - attr->queue_attr.dest_cfg.priority); \ - MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, \ - attr->queue_attr.dest_cfg.dest_type); \ - MC_RSP_OP(cmd, 0, 42, 1, int, attr->errors_only); \ - MC_RSP_OP(cmd, 0, 46, 1, int, \ - attr->queue_attr.order_preservation_en); \ - MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->queue_attr.user_ctx); \ - MC_RSP_OP(cmd, 2, 32, 32, int, attr->queue_attr.dest_cfg.dest_id); \ - MC_RSP_OP(cmd, 3, 0, 32, uint32_t, \ - attr->queue_attr.tail_drop_threshold); \ - MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->queue_attr.fqid); \ - MC_RSP_OP(cmd, 4, 0, 4, enum dpni_flc_type, \ - attr->queue_attr.flc_cfg.flc_type); \ - MC_RSP_OP(cmd, 4, 4, 4, enum dpni_stash_size, \ - attr->queue_attr.flc_cfg.frame_data_size); \ - MC_RSP_OP(cmd, 4, 8, 4, enum dpni_stash_size, \ - attr->queue_attr.flc_cfg.flow_context_size); \ - MC_RSP_OP(cmd, 4, 32, 32, uint32_t, attr->queue_attr.flc_cfg.options); \ - MC_RSP_OP(cmd, 5, 0, 64, uint64_t, \ - attr->queue_attr.flc_cfg.flow_context); \ + MC_RSP_OP(cmd, 0, 0, 64, uint64_t, (stat)->counter0); \ + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, (stat)->counter1); \ + MC_RSP_OP(cmd, 2, 0, 64, uint64_t, (stat)->counter2); \ + MC_RSP_OP(cmd, 3, 0, 64, uint64_t, (stat)->counter3); \ + MC_RSP_OP(cmd, 4, 0, 64, uint64_t, (stat)->counter4); \ + MC_RSP_OP(cmd, 5, 0, 64, uint64_t, (stat)->counter5); \ + MC_RSP_OP(cmd, 6, 0, 64, uint64_t, (stat)->counter6); \ } while (0) enum net_prot { @@ -645,6 +432,33 @@ int dpni_close(struct fsl_mc_io *mc_io, #define DPNI_OPT_FS_MASK_SUPPORT 0x00040000 /** + * enum dpni_queue_type - Identifies a type of queue targeted by the command + * @DPNI_QUEUE_RX: Rx queue + * @DPNI_QUEUE_TX: Tx queue + * @DPNI_QUEUE_TX_CONFIRM: Tx confirmation queue + * @DPNI_QUEUE_RX_ERR: Rx error queue + */ +enum dpni_queue_type { + DPNI_QUEUE_RX, + DPNI_QUEUE_TX, + DPNI_QUEUE_TX_CONFIRM, + DPNI_QUEUE_RX_ERR, +}; + +struct dpni_cfg { + uint8_t mac_addr[6]; + struct { + uint32_t options; + uint16_t fs_entries; + uint8_t num_queues; + uint8_t num_tcs; + uint8_t mac_entries; + uint8_t vlan_entries; + uint8_t qos_entries; + } adv; +}; + +/** * struct dpni_extended_cfg - Structure representing extended DPNI configuration * @tc_cfg: TCs configuration * @ipr_cfg: IP reassembly configuration @@ -685,78 +499,21 @@ struct dpni_extended_cfg { }; /** - * dpni_prepare_extended_cfg() - function prepare extended parameters - * @cfg: extended structure - * @ext_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA + * dpni_prepare_cfg() - function prepare parameters + * @cfg: cfg structure + * @cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA * * This function has to be called before dpni_create() */ -int dpni_prepare_extended_cfg(const struct dpni_extended_cfg *cfg, - uint8_t *ext_cfg_buf); - -/** - * struct dpni_cfg - Structure representing DPNI configuration - * @mac_addr: Primary MAC address - * @adv: Advanced parameters; default is all zeros; - * use this structure to change default settings - */ -struct dpni_cfg { - uint8_t mac_addr[6]; - /** - * struct adv - Advanced parameters - * @options: Mask of available options; use 'DPNI_OPT_<X>' values - * @start_hdr: Selects the packet starting header for parsing; - * 'NET_PROT_NONE' is treated as default: 'NET_PROT_ETH' - * @max_senders: Maximum number of different senders; used as the number - * of dedicated Tx flows; Non-power-of-2 values are rounded - * up to the next power-of-2 value as hardware demands it; - * '0' will be treated as '1' - * @max_tcs: Maximum number of traffic classes (for both Tx and Rx); - * '0' will e treated as '1' - * @max_unicast_filters: Maximum number of unicast filters; - * '0' is treated as '16' - * @max_multicast_filters: Maximum number of multicast filters; - * '0' is treated as '64' - * @max_qos_entries: if 'max_tcs > 1', declares the maximum entries in - * the QoS table; '0' is treated as '64' - * @max_qos_key_size: Maximum key size for the QoS look-up; - * '0' is treated as '24' which is enough for IPv4 - * 5-tuple - * @max_dist_key_size: Maximum key size for the distribution; - * '0' is treated as '24' which is enough for IPv4 5-tuple - * @max_policers: Maximum number of policers; - * should be between '0' and max_tcs - * @max_congestion_ctrl: Maximum number of congestion control groups - * (CGs); covers early drop and congestion notification - * requirements; - * should be between '0' and ('max_tcs' + 'max_senders') - * @ext_cfg_iova: I/O virtual address of 256 bytes DMA-able memory - * filled with the extended configuration by calling - * dpni_prepare_extended_cfg() - */ - struct { - uint32_t options; - enum net_prot start_hdr; - uint8_t max_senders; - uint8_t max_tcs; - uint8_t max_unicast_filters; - uint8_t max_multicast_filters; - uint8_t max_vlan_filters; - uint8_t max_qos_entries; - uint8_t max_qos_key_size; - uint8_t max_dist_key_size; - uint8_t max_policers; - uint8_t max_congestion_ctrl; - uint64_t ext_cfg_iova; - } adv; -}; - +int dpni_prepare_cfg(const struct dpni_cfg *cfg, + uint8_t *cfg_buf); /** * dpni_create() - Create the DPNI object * @mc_io: Pointer to MC portal's I/O object + * @token: Authentication token. * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @cfg: Configuration structure - * @token: Returned token; use in subsequent API calls + * @obj_id: Returned obj_id; use in subsequent API calls * * Create the DPNI object, allocate required resources and * perform required initialization. @@ -774,21 +531,24 @@ struct dpni_cfg { * Return: '0' on Success; Error code otherwise. */ int dpni_create(struct fsl_mc_io *mc_io, + uint16_t token, uint32_t cmd_flags, const struct dpni_cfg *cfg, - uint16_t *token); + uint32_t *obj_id); /** * dpni_destroy() - Destroy the DPNI object and release all its resources. * @mc_io: Pointer to MC portal's I/O object + * @token: Authentication token. * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object + * @obj_id: Returned obj_id; use in subsequent API calls * * Return: '0' on Success; error code otherwise. */ int dpni_destroy(struct fsl_mc_io *mc_io, + uint16_t token, uint32_t cmd_flags, - uint16_t token); + uint32_t obj_id); /** * struct dpni_pools_cfg - Structure representing buffer pools configuration @@ -867,49 +627,32 @@ int dpni_reset(struct fsl_mc_io *mc_io, /** * struct dpni_attr - Structure representing DPNI attributes - * @id: DPNI object ID - * @version: DPNI version - * @start_hdr: Indicates the packet starting header for parsing * @options: Mask of available options; reflects the value as was given in * object's creation - * @max_senders: Maximum number of different senders; used as the number - * of dedicated Tx flows; - * @max_tcs: Maximum number of traffic classes (for both Tx and Rx) + * @max_num_queues: Number of queues available (for both Tx and Rx) + * @max_num_tcs: Maximum number of traffic classes (for both Tx and Rx) + * @max_mac_entries: Maximum number of traffic classes (for both Tx and Rx) * @max_unicast_filters: Maximum number of unicast filters * @max_multicast_filters: Maximum number of multicast filters - * @max_vlan_filters: Maximum number of VLAN filters + * @max_vlan_entries: Maximum number of VLAN filters * @max_qos_entries: if 'max_tcs > 1', declares the maximum entries in QoS table + * @max_fs_entries: declares the maximum entries in flow steering table * @max_qos_key_size: Maximum key size for the QoS look-up - * @max_dist_key_size: Maximum key size for the distribution look-up - * @max_policers: Maximum number of policers; - * @max_congestion_ctrl: Maximum number of congestion control groups (CGs); - * @ext_cfg_iova: I/O virtual address of 256 bytes DMA-able memory; - * call dpni_extract_extended_cfg() to extract the extended configuration + * @max_fs_key_size: Maximum key size for the flow steering + * @wriop_version: Indicates revision of WRIOP hardware block */ struct dpni_attr { - int id; - /** - * struct version - DPNI version - * @major: DPNI major version - * @minor: DPNI minor version - */ - struct { - uint16_t major; - uint16_t minor; - } version; - enum net_prot start_hdr; + uint32_t id; uint32_t options; - uint8_t max_senders; - uint8_t max_tcs; - uint8_t max_unicast_filters; - uint8_t max_multicast_filters; - uint8_t max_vlan_filters; + uint8_t max_num_queues; + uint8_t max_num_tcs; + uint8_t max_mac_entries; + uint8_t max_vlan_entries; uint8_t max_qos_entries; + uint16_t max_fs_entries; uint8_t max_qos_key_size; - uint8_t max_dist_key_size; - uint8_t max_policers; - uint8_t max_congestion_ctrl; - uint64_t ext_cfg_iova; + uint8_t max_fs_key_size; + uint16_t wriop_version; }; /** @@ -927,14 +670,14 @@ int dpni_get_attributes(struct fsl_mc_io *mc_io, struct dpni_attr *attr); /** - * dpni_extract_extended_cfg() - extract the extended parameters - * @cfg: extended structure - * @ext_cfg_buf: 256 bytes of DMA-able memory + * dpni_extract_cfg() - extract the parameters + * @cfg: cfg structure + * @cfg_buf: 256 bytes of DMA-able memory * * This function has to be called after dpni_get_attributes() */ -int dpni_extract_extended_cfg(struct dpni_extended_cfg *cfg, - const uint8_t *ext_cfg_buf); +int dpni_extract_cfg(struct dpni_cfg *cfg, + const uint8_t *cfg_buf); /** * DPNI errors @@ -1037,7 +780,7 @@ int dpni_set_errors_behavior(struct fsl_mc_io *mc_io, * @data_tail_room: Data tail room */ struct dpni_buffer_layout { - uint32_t options; + uint16_t options; int pass_timestamp; int pass_parser_result; int pass_frame_status; @@ -1048,96 +791,38 @@ struct dpni_buffer_layout { }; /** - * dpni_get_rx_buffer_layout() - Retrieve Rx buffer layout attributes. + * dpni_get_buffer_layout() - Retrieve buffer layout attributes. * @mc_io: Pointer to MC portal's I/O object * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @token: Token of DPNI object * @layout: Returns buffer layout attributes + * @type: DPNI queue type * * Return: '0' on Success; Error code otherwise. */ -int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - struct dpni_buffer_layout *layout); +int dpni_get_buffer_layout(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + const struct dpni_buffer_layout *layout, + enum dpni_queue_type type); /** - * dpni_set_rx_buffer_layout() - Set Rx buffer layout configuration. + * dpni_set_buffer_layout() - Set buffer layout configuration. * @mc_io: Pointer to MC portal's I/O object * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @token: Token of DPNI object * @layout: Buffer layout configuration + * @type: DPNI queue type * * Return: '0' on Success; Error code otherwise. * * @warning Allowed only when DPNI is disabled */ -int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - const struct dpni_buffer_layout *layout); - -/** - * dpni_get_tx_buffer_layout() - Retrieve Tx buffer layout attributes. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @layout: Returns buffer layout attributes - * - * Return: '0' on Success; Error code otherwise. - */ -int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - struct dpni_buffer_layout *layout); - -/** - * dpni_set_tx_buffer_layout() - Set Tx buffer layout configuration. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @layout: Buffer layout configuration - * - * Return: '0' on Success; Error code otherwise. - * - * @warning Allowed only when DPNI is disabled - */ -int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - const struct dpni_buffer_layout *layout); - -/** - * dpni_get_tx_conf_buffer_layout() - Retrieve Tx confirmation buffer layout - * attributes. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @layout: Returns buffer layout attributes - * - * Return: '0' on Success; Error code otherwise. - */ -int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - struct dpni_buffer_layout *layout); - -/** - * dpni_set_tx_conf_buffer_layout() - Set Tx confirmation buffer layout - * configuration. - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @layout: Buffer layout configuration - * - * Return: '0' on Success; Error code otherwise. - * - * @warning Allowed only when DPNI is disabled - */ -int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - const struct dpni_buffer_layout *layout); +int dpni_set_buffer_layout(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + const struct dpni_buffer_layout *layout, + enum dpni_queue_type type); /** * dpni_get_qdid() - Get the Queuing Destination ID (QDID) that should be used @@ -1169,68 +854,6 @@ int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, uint16_t token, uint16_t *data_offset); -/** - * enum dpni_counter - DPNI counter types - * @DPNI_CNT_ING_FRAME: Counts ingress frames - * @DPNI_CNT_ING_BYTE: Counts ingress bytes - * @DPNI_CNT_ING_FRAME_DROP: Counts ingress frames dropped due to explicit - * 'drop' setting - * @DPNI_CNT_ING_FRAME_DISCARD: Counts ingress frames discarded due to errors - * @DPNI_CNT_ING_MCAST_FRAME: Counts ingress multicast frames - * @DPNI_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes - * @DPNI_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames - * @DPNI_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes - * @DPNI_CNT_EGR_FRAME: Counts egress frames - * @DPNI_CNT_EGR_BYTE: Counts egress bytes - * @DPNI_CNT_EGR_FRAME_DISCARD: Counts egress frames discarded due to errors - */ -enum dpni_counter { - DPNI_CNT_ING_FRAME = 0x0, - DPNI_CNT_ING_BYTE = 0x1, - DPNI_CNT_ING_FRAME_DROP = 0x2, - DPNI_CNT_ING_FRAME_DISCARD = 0x3, - DPNI_CNT_ING_MCAST_FRAME = 0x4, - DPNI_CNT_ING_MCAST_BYTE = 0x5, - DPNI_CNT_ING_BCAST_FRAME = 0x6, - DPNI_CNT_ING_BCAST_BYTES = 0x7, - DPNI_CNT_EGR_FRAME = 0x8, - DPNI_CNT_EGR_BYTE = 0x9, - DPNI_CNT_EGR_FRAME_DISCARD = 0xa -}; - -/** - * dpni_get_counter() - Read a specific DPNI counter - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @counter: The requested counter - * @value: Returned counter's current value - * - * Return: '0' on Success; Error code otherwise. - */ -int dpni_get_counter(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - enum dpni_counter counter, - uint64_t *value); - -/** - * dpni_set_counter() - Set (or clear) a specific DPNI counter - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @counter: The requested counter - * @value: New counter value; typically pass '0' for resetting - * the counter. - * - * Return: '0' on Success; Error code otherwise. - */ -int dpni_set_counter(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - enum dpni_counter counter, - uint64_t value); - /* Enable auto-negotiation */ #define DPNI_LINK_OPT_AUTONEG 0x0000000000000001ULL /* Enable half-duplex mode */ @@ -1506,183 +1129,199 @@ struct dpni_queue_attr { #define DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN 0x00000020 /** - * struct dpni_tx_flow_cfg - Structure representing Tx flow configuration - * @options: Flags representing the suggested modifications to the Tx flow; - * Use any combination 'DPNI_TX_FLOW_OPT_<X>' flags - * @use_common_tx_conf_queue: Set to '1' to use the common (default) Tx - * confirmation and error queue; Set to '0' to use the private - * Tx confirmation and error queue; valid only if - * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' wasn't set at DPNI creation - * and 'DPNI_TX_FLOW_OPT_TX_CONF_ERROR' is contained in 'options' - * @l3_chksum_gen: Set to '1' to enable L3 checksum generation; '0' to disable; - * valid only if 'DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN' is contained in 'options' - * @l4_chksum_gen: Set to '1' to enable L4 checksum generation; '0' to disable; - * valid only if 'DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN' is contained in 'options' - */ -struct dpni_tx_flow_cfg { - uint32_t options; - int use_common_tx_conf_queue; - int l3_chksum_gen; - int l4_chksum_gen; -}; - -/** - * dpni_set_tx_flow() - Set Tx flow configuration + * dpni_get_api_version - Retrieve DPNI Major and Minor version info. + * * @mc_io: Pointer to MC portal's I/O object * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @flow_id: Provides (or returns) the sender's flow ID; - * for each new sender set (*flow_id) to 'DPNI_NEW_FLOW_ID' to generate - * a new flow_id; this ID should be used as the QDBIN argument - * in enqueue operations - * @cfg: Tx flow configuration + * @major_ver: DPNI major version + * @minor_ver: DPNI minor version * - * Return: '0' on Success; Error code otherwise. - */ -int dpni_set_tx_flow(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint16_t *flow_id, - const struct dpni_tx_flow_cfg *cfg); - -/** - * struct dpni_tx_flow_attr - Structure representing Tx flow attributes - * @use_common_tx_conf_queue: '1' if using common (default) Tx confirmation and - * error queue; '0' if using private Tx confirmation and error queue - * @l3_chksum_gen: '1' if L3 checksum generation is enabled; '0' if disabled - * @l4_chksum_gen: '1' if L4 checksum generation is enabled; '0' if disabled - */ -struct dpni_tx_flow_attr { - int use_common_tx_conf_queue; - int l3_chksum_gen; - int l4_chksum_gen; + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver); + +/** + * enum dpni_confirmation_mode - Defines DPNI options supported for Tx + * confirmation + * @DPNI_CONF_AFFINE: For each Tx queue set associated with a sender there is + * an affine Tx Confirmation queue + * @DPNI_CONF_SINGLE: All Tx queues are associated with a single Tx + * confirmation queue + * @DPNI_CONF_DISABLE: Tx frames are not confirmed. This must be associated + * with proper FD set-up to have buffers release to a Buffer Pool, otherwise + * buffers will be leaked. + */ +enum dpni_confirmation_mode { + DPNI_CONF_AFFINE, + DPNI_CONF_SINGLE, + DPNI_CONF_DISABLE, }; -/** - * dpni_get_tx_flow() - Get Tx flow attributes - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @flow_id: The sender's flow ID, as returned by the - * dpni_set_tx_flow() function - * @attr: Returned Tx flow attributes - * - * Return: '0' on Success; Error code otherwise. - */ -int dpni_get_tx_flow(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint16_t flow_id, - struct dpni_tx_flow_attr *attr); +struct dpni_tx_confirmation_mode { + uint32_t pad; + uint8_t confirmation_mode; +}; /** - * struct dpni_tx_conf_cfg - Structure representing Tx conf configuration - * @errors_only: Set to '1' to report back only error frames; - * Set to '0' to confirm transmission/error for all transmitted frames; - * @queue_cfg: Queue configuration + * struct dpni_queue - Queue structure + * @fqid: FQID used for enqueueing to and/or configuration of this specific FQ + * @qdbin: Queueing bin, used to enqueue using QDID, DQBIN, QPRI. Only relevant + * for Tx queues. + * @flc: FLC value for traffic dequeued from this queue. + * @user_context: User data, presented to the user along with any frames + * from this queue. Not relevant for Tx queues. */ -struct dpni_tx_conf_cfg { - int errors_only; - struct dpni_queue_cfg queue_cfg; +struct dpni_queue { + /** + * struct destination - Destination structure + * @id: ID of the destination, only relevant if DEST_TYPE is > 0. + * Identifies either a DPIO or a DPCON object. Not relevant for Tx + * queues. + * @type: May be one of the following: + * 0 - No destination, queue can be manually queried, but won't + * push traffic or notifications to a DPIO; + * 1 - The destination is DPIO. When traffic becomes available in + * the queue a FQDAN (FQ data available notification) will be + * generated to selected DPIO; + * 2 - The destination is a DPCON. The queue is associated with a + * DPCON object for purpose of scheduling between multiple + * queues. The DPCON may be independently configured to + * generate notifications. Not relevant for Tx queues. + * @hold_active: Hold active + */ + struct { + uint32_t id; + enum dpni_dest type; + char hold_active; + char stash_ctrl; + } destination; + uint8_t options; + uint32_t fqid; + uint16_t qdbin; + uint64_t flc; + uint64_t user_context; }; /** - * dpni_set_tx_conf() - Set Tx confirmation and error queue configuration - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @flow_id: The sender's flow ID, as returned by the - * dpni_set_tx_flow() function; - * use 'DPNI_COMMON_TX_CONF' for common tx-conf - * @cfg: Queue configuration + * dpni_set_queue() - Set queue parameters + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPNI object + * @type: Type of queue + * @tc: Traffic class, in range 0 to NUM_TCS - 1 + * @index: Selects the specific queue out of the set allocated for the same + * TC. Value must be in range 0 to NUM_QUEUES - 1 + * @queue: Queue structure * - * If either 'DPNI_OPT_TX_CONF_DISABLED' or - * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation, - * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF'; - * i.e. only serve the common tx-conf-err queue; - * if 'DPNI_OPT_TX_CONF_DISABLED' was selected, only error frames are reported - * back - successfully transmitted frames are not confirmed. Otherwise, all - * transmitted frames are sent for confirmation. + * Return: '0' on Success; Error code otherwise. + */ +int dpni_set_queue(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + enum dpni_queue_type type, + uint8_t tc, + uint8_t index, + const struct dpni_queue *queue); + +/** + * dpni_get_queue() - Get queue parameters + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPNI object + * @type: Type of queue + * @tc: Traffic class, in range 0 to NUM_TCS - 1 + * @index: Selects the specific queue out of the set allocated for the same + * TC. Value must be in range 0 to NUM_QUEUES - 1 + * @queue: Queue structure * - * Return: '0' on Success; Error code otherwise. + * Return: '0' on Success; Error code otherwise. */ -int dpni_set_tx_conf(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint16_t flow_id, - const struct dpni_tx_conf_cfg *cfg); +int dpni_get_queue(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + enum dpni_queue_type type, + uint8_t tc, + uint8_t index, + struct dpni_queue *queue); /** - * struct dpni_tx_conf_attr - Structure representing Tx conf attributes - * @errors_only: '1' if only error frames are reported back; '0' if all - * transmitted frames are confirmed - * @queue_attr: Queue attributes + * dpni_set_tx_confirmation_mode() - Set TX conf mode + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPNI object + * @mode: DPNI confirmation mode type + * + * Return: '0' on Success; Error code otherwise. */ -struct dpni_tx_conf_attr { - int errors_only; - struct dpni_queue_attr queue_attr; +int dpni_set_tx_confirmation_mode(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + enum dpni_confirmation_mode mode); +struct dpni_statistics { + /** + * Page_0 statistics structure + * @ingress_all_frames: Ingress frame count + * @ingress_all_bytes: Ingress byte count + * @ingress_multicast_frames: Ingress multicast frame count + * @ingress_multicast_bytes: Ingress multicast byte count + * @ingress_broadcast_frames: Ingress broadcast frame count + * @ingress_broadcast_bytes: Ingress broadcast byte count + * + * Page_1 statistics structure + * @egress_all_frames: Egress frame count + * @egress_all_bytes: Egress byte count + * @egress_multicast_frames: Egress multicast frame count + * @egress_multicast_bytes: Egress multicast byte count + * @egress_broadcast_frames: Egress broadcast frame count + * @egress_broadcast_bytes: Egress broadcast byte count + * + * Page_2 statistics structure + * @ingress_filtered_frames: Ingress filtered frame count + * @ingress_discarded_frames: Ingress discarded frame count + * @ingress_nobuffer_discards: Ingress discarded frame count due to + * lack of buffers. + * @egress_discarded_frames: Egress discarded frame count + * @egress_confirmed_frames: Egress confirmed frame count + */ + + uint64_t counter0; + uint64_t counter1; + uint64_t counter2; + uint64_t counter3; + uint64_t counter4; + uint64_t counter5; + uint64_t counter6; }; /** - * dpni_get_tx_conf() - Get Tx confirmation and error queue attributes + * dpni_get_statistics() - Get DPNI statistics * @mc_io: Pointer to MC portal's I/O object * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @token: Token of DPNI object - * @flow_id: The sender's flow ID, as returned by the - * dpni_set_tx_flow() function; - * use 'DPNI_COMMON_TX_CONF' for common tx-conf - * @attr: Returned tx-conf attributes - * - * If either 'DPNI_OPT_TX_CONF_DISABLED' or - * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation, - * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF'; - * i.e. only serve the common tx-conf-err queue; + * @page: Selects the statistics page to retrieve, see DPNI_GET_STATISTICS + * output. Pages are numbered 0 to 2. + * @stat: Structure containing the statistics * * Return: '0' on Success; Error code otherwise. */ -int dpni_get_tx_conf(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint16_t flow_id, - struct dpni_tx_conf_attr *attr); -/** - * dpni_set_rx_flow() - Set Rx flow configuration - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @tc_id: Traffic class selection (0-7); - * use 'DPNI_ALL_TCS' to set all TCs and all flows - * @flow_id: Rx flow id within the traffic class; use - * 'DPNI_ALL_TC_FLOWS' to set all flows within - * this tc_id; ignored if tc_id is set to - * 'DPNI_ALL_TCS'; - * @cfg: Rx flow configuration - * - * Return: '0' on Success; Error code otherwise. - */ -int dpni_set_rx_flow(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t tc_id, - uint16_t flow_id, - const struct dpni_queue_cfg *cfg); +int dpni_get_statistics(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t page, + struct dpni_statistics *stat); /** - * dpni_get_rx_flow() - Get Rx flow attributes + * dpni_reset_statistics() - Clears DPNI statistics * @mc_io: Pointer to MC portal's I/O object * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' * @token: Token of DPNI object - * @tc_id: Traffic class selection (0-7) - * @flow_id: Rx flow id within the traffic class - * @attr: Returned Rx flow attributes * * Return: '0' on Success; Error code otherwise. */ -int dpni_get_rx_flow(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t tc_id, - uint16_t flow_id, - struct dpni_queue_attr *attr); - +int dpni_reset_statistics(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token); #endif /* _FSL_DPNI_H */ diff --git a/include/fsl-mc/fsl_dprc.h b/include/fsl-mc/fsl_dprc.h index 535c789c95e..8ad01d4f511 100644 --- a/include/fsl-mc/fsl_dprc.h +++ b/include/fsl-mc/fsl_dprc.h @@ -1,8 +1,8 @@ /* * Freescale Layerscape MC I/O wrapper * - * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. - * Author: German Rivera <German.Rivera@freescale.com> + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -10,29 +10,30 @@ #define _FSL_DPRC_H /* DPRC Version */ -#define DPRC_VER_MAJOR 5 +#define DPRC_VER_MAJOR 6 #define DPRC_VER_MINOR 1 /* Command IDs */ -#define DPRC_CMDID_CLOSE 0x800 -#define DPRC_CMDID_OPEN 0x805 -#define DPRC_CMDID_CREATE 0x905 - -#define DPRC_CMDID_GET_ATTR 0x004 -#define DPRC_CMDID_RESET_CONT 0x005 - -#define DPRC_CMDID_CREATE_CONT 0x151 -#define DPRC_CMDID_DESTROY_CONT 0x152 -#define DPRC_CMDID_GET_CONT_ID 0x830 -#define DPRC_CMDID_GET_OBJ_COUNT 0x159 -#define DPRC_CMDID_GET_OBJ 0x15A -#define DPRC_CMDID_GET_RES_COUNT 0x15B -#define DPRC_CMDID_GET_RES_IDS 0x15C -#define DPRC_CMDID_GET_OBJ_REG 0x15E - -#define DPRC_CMDID_CONNECT 0x167 -#define DPRC_CMDID_DISCONNECT 0x168 -#define DPRC_CMDID_GET_CONNECTION 0x16C +#define DPRC_CMDID_CLOSE 0x8001 +#define DPRC_CMDID_OPEN 0x8051 +#define DPRC_CMDID_CREATE 0x9051 + +#define DPRC_CMDID_GET_ATTR 0x0041 +#define DPRC_CMDID_RESET_CONT 0x0051 +#define DPRC_CMDID_GET_API_VERSION 0xa051 + +#define DPRC_CMDID_CREATE_CONT 0x1511 +#define DPRC_CMDID_DESTROY_CONT 0x1521 +#define DPRC_CMDID_GET_CONT_ID 0x8301 +#define DPRC_CMDID_GET_OBJ_COUNT 0x1591 +#define DPRC_CMDID_GET_OBJ 0x15A1 +#define DPRC_CMDID_GET_RES_COUNT 0x15B1 +#define DPRC_CMDID_GET_RES_IDS 0x15C1 +#define DPRC_CMDID_GET_OBJ_REG 0x15E1 + +#define DPRC_CMDID_CONNECT 0x1671 +#define DPRC_CMDID_DISCONNECT 0x1681 +#define DPRC_CMDID_GET_CONNECTION 0x16C1 /* cmd, param, offset, width, type, arg_name */ #define DPRC_RSP_GET_CONTAINER_ID(cmd, container_id) \ @@ -88,8 +89,6 @@ do { \ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->icid); \ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options);\ MC_RSP_OP(cmd, 1, 32, 32, int, attr->portal_id); \ - MC_RSP_OP(cmd, 2, 0, 16, uint16_t, attr->version.major);\ - MC_RSP_OP(cmd, 2, 16, 16, uint16_t, attr->version.minor);\ } while (0) /* cmd, param, offset, width, type, arg_name */ @@ -345,9 +344,9 @@ do { \ #define DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2, cfg) \ do { \ MC_CMD_OP(cmd, 0, 0, 32, int, endpoint1->id); \ - MC_CMD_OP(cmd, 0, 32, 16, uint16_t, endpoint1->if_id); \ + MC_CMD_OP(cmd, 0, 32, 32, int, endpoint1->if_id); \ MC_CMD_OP(cmd, 1, 0, 32, int, endpoint2->id); \ - MC_CMD_OP(cmd, 1, 32, 16, uint16_t, endpoint2->if_id); \ + MC_CMD_OP(cmd, 1, 32, 32, int, endpoint2->if_id); \ MC_CMD_OP(cmd, 2, 0, 8, char, endpoint1->type[0]); \ MC_CMD_OP(cmd, 2, 8, 8, char, endpoint1->type[1]); \ MC_CMD_OP(cmd, 2, 16, 8, char, endpoint1->type[2]); \ @@ -410,8 +409,8 @@ do { \ /* cmd, param, offset, width, type, arg_name */ #define DPRC_CMD_GET_CONNECTION(cmd, endpoint1) \ do { \ - MC_CMD_OP(cmd, 0, 0, 32, int, endpoint1->id); \ - MC_CMD_OP(cmd, 0, 32, 16, uint16_t, endpoint1->if_id); \ + MC_CMD_OP(cmd, 0, 0, 32, int, endpoint1->id); \ + MC_CMD_OP(cmd, 0, 32, 32, int, endpoint1->if_id); \ MC_CMD_OP(cmd, 1, 0, 8, char, endpoint1->type[0]); \ MC_CMD_OP(cmd, 1, 8, 8, char, endpoint1->type[1]); \ MC_CMD_OP(cmd, 1, 16, 8, char, endpoint1->type[2]); \ @@ -657,15 +656,6 @@ struct dprc_attributes { uint16_t icid; int portal_id; uint64_t options; - /** - * struct version - DPRC version - * @major: DPRC major version - * @minor: DPRC minor version - */ - struct { - uint16_t major; - uint16_t minor; - } version; }; /** @@ -950,4 +940,19 @@ int dprc_get_connection(struct fsl_mc_io *mc_io, struct dprc_endpoint *endpoint2, int *state); +/** + * dprc_get_api_version - Retrieve DPRC Major and Minor version info. + * + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @major_ver: DPRC major version + * @minor_ver: DPRC minor version + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_api_version(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 *major_ver, + u16 *minor_ver); + #endif /* _FSL_DPRC_H */ diff --git a/include/fsl-mc/fsl_mc_cmd.h b/include/fsl-mc/fsl_mc_cmd.h index f3d1498cc0f..1ec67b54916 100644 --- a/include/fsl-mc/fsl_mc_cmd.h +++ b/include/fsl-mc/fsl_mc_cmd.h @@ -1,4 +1,5 @@ -/* Copyright 2013-2015 Freescale Semiconductor Inc. +/* Copyright 2013-2016 Freescale Semiconductor Inc. + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -24,6 +25,15 @@ struct mc_command { uint64_t params[MC_CMD_NUM_OF_PARAMS]; }; +struct mc_rsp_create { + __le32 object_id; +}; + +struct mc_rsp_api_ver { + __le16 major_ver; + __le16 minor_ver; +}; + enum mc_cmd_status { MC_CMD_STATUS_OK = 0x0, /*!< Completed successfully */ MC_CMD_STATUS_READY = 0x1, /*!< Ready to be processed */ @@ -51,15 +61,15 @@ enum mc_cmd_status { #define MC_CMD_FLAG_INTR_DIS 0x01000000 -#define MC_CMD_HDR_CMDID_O 52 /* Command ID field offset */ -#define MC_CMD_HDR_CMDID_S 12 /* Command ID field size */ +#define MC_CMD_HDR_CMDID_O 48 /* Command ID field offset */ +#define MC_CMD_HDR_CMDID_S 16 /* Command ID field size */ #define MC_CMD_HDR_STATUS_O 16 /* Status field offset */ -#define MC_CMD_HDR_TOKEN_O 38 /* Token field offset */ -#define MC_CMD_HDR_TOKEN_S 10 /* Token field size */ +#define MC_CMD_HDR_TOKEN_O 32 /* Token field offset */ +#define MC_CMD_HDR_TOKEN_S 16 /* Token field size */ #define MC_CMD_HDR_STATUS_S 8 /* Status field size*/ #define MC_CMD_HDR_FLAGS_O 0 /* Flags field offset */ #define MC_CMD_HDR_FLAGS_S 32 /* Flags field size*/ -#define MC_CMD_HDR_FLAGS_MASK 0xFF00FF00 /* Command flags mask */ +#define MC_CMD_HDR_FLAGS_MASK 0x0000FFFF /* Command flags mask */ #define MC_CMD_HDR_READ_STATUS(_hdr) \ ((enum mc_cmd_status)mc_dec((_hdr), \ @@ -80,11 +90,19 @@ enum mc_cmd_status { #define MC_RSP_OP(_cmd, _param, _offset, _width, _type, _arg) \ (_arg = (_type)mc_dec(_cmd.params[_param], (_offset), (_width))) +/* cmd, param, offset, width, type, arg_name */ +#define MC_CMD_READ_OBJ_ID(cmd, obj_id) \ + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, obj_id) + +/* cmd, param, offset, width, type, arg_name */ +#define CMD_DESTROY_SET_OBJ_ID_PARAM0(cmd, object_id) \ + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, object_id) + static inline uint64_t mc_encode_cmd_header(uint16_t cmd_id, uint32_t cmd_flags, uint16_t token) { - uint64_t hdr; + uint64_t hdr = 0; hdr = mc_enc(MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S, cmd_id); hdr |= mc_enc(MC_CMD_HDR_FLAGS_O, MC_CMD_HDR_FLAGS_S, @@ -144,4 +162,22 @@ static inline enum mc_cmd_status mc_read_response( return status; } +/** + * mc_read_version - read version of the given cmd + * + * @cmd: pointer to a filled command + * @major_version: major version value for the given cmd + * @minor_version: minor version value for the given cmd + */ +static inline void mc_cmd_read_api_version(struct mc_command *cmd, + u16 *major_ver, + u16 *minor_ver) +{ + struct mc_rsp_api_ver *rsp_params; + + rsp_params = (struct mc_rsp_api_ver *)cmd->params; + *major_ver = le16_to_cpu(rsp_params->major_ver); + *minor_ver = le16_to_cpu(rsp_params->minor_ver); +} + #endif /* __FSL_MC_CMD_H */ diff --git a/include/fsl-mc/fsl_mc_private.h b/include/fsl-mc/fsl_mc_private.h index 17e06119640..2932d9d5619 100644 --- a/include/fsl-mc/fsl_mc_private.h +++ b/include/fsl-mc/fsl_mc_private.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2014 Freescale Semiconductor + * Copyright (C) 2014-2016 Freescale Semiconductor + * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -29,6 +30,7 @@ extern struct fsl_mc_io *dflt_mc_io; * @struct dpbp_attr: DPBP attribute */ struct fsl_dpbp_obj { + uint32_t dpbp_id; uint16_t dpbp_handle; struct dpbp_attr dpbp_attr; }; @@ -41,7 +43,7 @@ extern struct fsl_dpbp_obj *dflt_dpbp; * @struct qbman_swp *sw_portal: SW portal object */ struct fsl_dpio_obj { - int dpio_id; + uint32_t dpio_id; uint16_t dpio_handle; struct qbman_swp *sw_portal; /** SW portal object */ }; @@ -56,7 +58,7 @@ extern struct fsl_dpio_obj *dflt_dpio; * @struct dpni_buffer_layout: DPNI buffer layout */ struct fsl_dpni_obj { - int dpni_id; + uint32_t dpni_id; uint16_t dpni_handle; struct dpni_attr dpni_attrs; struct dpni_buffer_layout buf_layout; diff --git a/include/log.h b/include/log.h new file mode 100644 index 00000000000..8083b64831d --- /dev/null +++ b/include/log.h @@ -0,0 +1,304 @@ +/* + * Logging support + * + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __LOG_H +#define __LOG_H + +#include <dm/uclass-id.h> +#include <linux/list.h> + +/** Log levels supported, ranging from most to least important */ +enum log_level_t { + LOGL_EMERG = 0, /*U-Boot is unstable */ + LOGL_ALERT, /* Action must be taken immediately */ + LOGL_CRIT, /* Critical conditions */ + LOGL_ERR, /* Error that prevents something from working */ + LOGL_WARNING, /* Warning may prevent optimial operation */ + LOGL_NOTICE, /* Normal but significant condition, printf() */ + LOGL_INFO, /* General information message */ + LOGL_DEBUG, /* Basic debug-level message */ + LOGL_DEBUG_CONTENT, /* Debug message showing full message content */ + LOGL_DEBUG_IO, /* Debug message showing hardware I/O access */ + + LOGL_COUNT, + LOGL_FIRST = LOGL_EMERG, + LOGL_MAX = LOGL_DEBUG, +}; + +/** + * Log categories supported. Most of these correspond to uclasses (i.e. + * enum uclass_id) but there are also some more generic categories + */ +enum log_category_t { + LOGC_FIRST = 0, /* First part mirrors UCLASS_... */ + + LOGC_NONE = UCLASS_COUNT, + LOGC_ARCH, + LOGC_BOARD, + LOGC_CORE, + LOGC_DT, + + LOGC_COUNT, + LOGC_END, +}; + +/* Helper to cast a uclass ID to a log category */ +static inline int log_uc_cat(enum uclass_id id) +{ + return (enum log_category_t)id; +} + +/** + * _log() - Internal function to emit a new log record + * + * @cat: Category of log record (indicating which subsystem generated it) + * @level: Level of log record (indicating its severity) + * @file: File name of file where log record was generated + * @line: Line number in file where log record was generated + * @func: Function where log record was generated + * @fmt: printf() format string for log record + * @...: Optional parameters, according to the format string @fmt + * @return 0 if log record was emitted, -ve on error + */ +int _log(enum log_category_t cat, enum log_level_t level, const char *file, + int line, const char *func, const char *fmt, ...); + +/* Define this at the top of a file to add a prefix to debug messages */ +#ifndef pr_fmt +#define pr_fmt(fmt) fmt +#endif + +/* Use a default category if this file does not supply one */ +#ifndef LOG_CATEGORY +#define LOG_CATEGORY LOGC_NONE +#endif + +/* + * This header may be including when CONFIG_LOG is disabled, in which case + * CONFIG_LOG_MAX_LEVEL is not defined. Add a check for this. + */ +#if CONFIG_IS_ENABLED(LOG) +#define _LOG_MAX_LEVEL CONFIG_VAL(LOG_MAX_LEVEL) +#else +#define _LOG_MAX_LEVEL LOGL_INFO +#endif + +/* Emit a log record if the level is less that the maximum */ +#define log(_cat, _level, _fmt, _args...) ({ \ + int _l = _level; \ + if (_l <= _LOG_MAX_LEVEL) \ + _log((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \ + __func__, \ + pr_fmt(_fmt), ##_args); \ + }) + +#ifdef DEBUG +#define _DEBUG 1 +#else +#define _DEBUG 0 +#endif + +#ifdef CONFIG_SPL_BUILD +#define _SPL_BUILD 1 +#else +#define _SPL_BUILD 0 +#endif + +#if !_DEBUG && CONFIG_IS_ENABLED(LOG) + +#define debug_cond(cond, fmt, args...) \ + do { \ + if (1) \ + log(LOG_CATEGORY, LOGL_DEBUG, fmt, ##args); \ + } while (0) + +#else /* _DEBUG */ + +/* + * Output a debug text when condition "cond" is met. The "cond" should be + * computed by a preprocessor in the best case, allowing for the best + * optimization. + */ +#define debug_cond(cond, fmt, args...) \ + do { \ + if (cond) \ + printf(pr_fmt(fmt), ##args); \ + } while (0) + +#endif /* _DEBUG */ + +/* Show a message if DEBUG is defined in a file */ +#define debug(fmt, args...) \ + debug_cond(_DEBUG, fmt, ##args) + +/* Show a message if not in SPL */ +#define warn_non_spl(fmt, args...) \ + debug_cond(!_SPL_BUILD, fmt, ##args) + +/* + * An assertion is run-time check done in debug mode only. If DEBUG is not + * defined then it is skipped. If DEBUG is defined and the assertion fails, + * then it calls panic*( which may or may not reset/halt U-Boot (see + * CONFIG_PANIC_HANG), It is hoped that all failing assertions are found + * before release, and after release it is hoped that they don't matter. But + * in any case these failing assertions cannot be fixed with a reset (which + * may just do the same assertion again). + */ +void __assert_fail(const char *assertion, const char *file, unsigned int line, + const char *function); +#define assert(x) \ + ({ if (!(x) && _DEBUG) \ + __assert_fail(#x, __FILE__, __LINE__, __func__); }) + +/** + * struct log_rec - a single log record + * + * Holds information about a single record in the log + * + * Members marked as 'not allocated' are stored as pointers and the caller is + * responsible for making sure that the data pointed to is not overwritten. + * Memebers marked as 'allocated' are allocated (e.g. via strdup()) by the log + * system. + * + * @cat: Category, representing a uclass or part of U-Boot + * @level: Severity level, less severe is higher + * @file: Name of file where the log record was generated (not allocated) + * @line: Line number where the log record was generated + * @func: Function where the log record was generated (not allocated) + * @msg: Log message (allocated) + */ +struct log_rec { + enum log_category_t cat; + enum log_level_t level; + const char *file; + int line; + const char *func; + const char *msg; +}; + +struct log_device; + +/** + * struct log_driver - a driver which accepts and processes log records + * + * @name: Name of driver + */ +struct log_driver { + const char *name; + /** + * emit() - emit a log record + * + * Called by the log system to pass a log record to a particular driver + * for processing. The filter is checked before calling this function. + */ + int (*emit)(struct log_device *ldev, struct log_rec *rec); +}; + +/** + * struct log_device - an instance of a log driver + * + * Since drivers are set up at build-time we need to have a separate device for + * the run-time aspects of drivers (currently just a list of filters to apply + * to records send to this device). + * + * @next_filter_num: Seqence number of next filter filter added (0=no filters + * yet). This increments with each new filter on the device, but never + * decrements + * @drv: Pointer to driver for this device + * @filter_head: List of filters for this device + * @sibling_node: Next device in the list of all devices + */ +struct log_device { + int next_filter_num; + struct log_driver *drv; + struct list_head filter_head; + struct list_head sibling_node; +}; + +enum { + LOGF_MAX_CATEGORIES = 5, /* maximum categories per filter */ +}; + +enum log_filter_flags { + LOGFF_HAS_CAT = 1 << 0, /* Filter has a category list */ +}; + +/** + * struct log_filter - criterial to filter out log messages + * + * @filter_num: Sequence number of this filter. This is returned when adding a + * new filter, and must be provided when removing a previously added + * filter. + * @flags: Flags for this filter (LOGFF_...) + * @cat_list: List of categories to allow (terminated by LOGC_none). If empty + * then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries + * can be provided + * @max_level: Maximum log level to allow + * @file_list: List of files to allow, separated by comma. If NULL then all + * files are permitted + * @sibling_node: Next filter in the list of filters for this log device + */ +struct log_filter { + int filter_num; + int flags; + enum log_category_t cat_list[LOGF_MAX_CATEGORIES]; + enum log_level_t max_level; + const char *file_list; + struct list_head sibling_node; +}; + +#define LOG_DRIVER(_name) \ + ll_entry_declare(struct log_driver, _name, log_driver) + +/* Handle the 'log test' command */ +int do_log_test(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); + +/** + * log_add_filter() - Add a new filter to a log device + * + * @drv_name: Driver name to add the filter to (since each driver only has a + * single device) + * @cat_list: List of categories to allow (terminated by LOGC_none). If empty + * then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries + * can be provided + * @max_level: Maximum log level to allow + * @file_list: List of files to allow, separated by comma. If NULL then all + * files are permitted + * @return the sequence number of the new filter (>=0) if the filter was added, + * or a -ve value on error + */ +int log_add_filter(const char *drv_name, enum log_category_t cat_list[], + enum log_level_t max_level, const char *file_list); + +/** + * log_remove_filter() - Remove a filter from a log device + * + * @drv_name: Driver name to remove the filter from (since each driver only has + * a single device) + * @filter_num: Filter number to remove (as returned by log_add_filter()) + * @return 0 if the filter was removed, -ENOENT if either the driver or the + * filter number was not found + */ +int log_remove_filter(const char *drv_name, int filter_num); + +#if CONFIG_IS_ENABLED(LOG) +/** + * log_init() - Set up the log system ready for use + * + * @return 0 if OK, -ENOMEM if out of memory + */ +int log_init(void); +#else +static inline int log_init(void) +{ + return 0; +} +#endif + +#endif diff --git a/include/logbuff.h b/include/logbuff.h deleted file mode 100644 index 625feb9f95a..00000000000 --- a/include/logbuff.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * (C) Copyright 2002-2007 - * Detlev Zundel, dzu@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#ifndef _LOGBUFF_H -#define _LOGBUFF_H - -#ifdef CONFIG_LOGBUFFER - -#define LOGBUFF_MAGIC 0xc0de4ced /* Forced by code, eh! */ -#define LOGBUFF_LEN (16384) /* Must be 16k right now */ -#define LOGBUFF_MASK (LOGBUFF_LEN-1) -#define LOGBUFF_OVERHEAD (4096) /* Logbuffer overhead for extra info */ -#define LOGBUFF_RESERVE (LOGBUFF_LEN+LOGBUFF_OVERHEAD) - -/* The mapping used here has to be the same as in setup_ext_logbuff () - in linux/kernel/printk */ - -typedef struct { - union { - struct { - unsigned long tag; - unsigned long start; - unsigned long con; - unsigned long end; - unsigned long chars; - } v2; - struct { - unsigned long dummy; - unsigned long tag; - unsigned long start; - unsigned long size; - unsigned long chars; - } v1; - }; - unsigned char buf[0]; -} logbuff_t; - -int drv_logbuff_init (void); -void logbuff_init_ptrs (void); -void logbuff_log(char *msg); -void logbuff_reset (void); -unsigned long logbuffer_base (void); - -#endif /* CONFIG_LOGBUFFER */ - -#endif /* _LOGBUFF_H */ diff --git a/include/os.h b/include/os.h index 2bf4bdb1b83..049b248c5b0 100644 --- a/include/os.h +++ b/include/os.h @@ -241,6 +241,26 @@ const char *os_dirent_get_typename(enum os_dirent_t type); int os_get_filesize(const char *fname, loff_t *size); /** + * Write a character to the controlling OS terminal + * + * This bypasses the U-Boot console support and writes directly to the OS + * stdout file descriptor. + * + * @param ch Character to write + */ +void os_putc(int ch); + +/** + * Write a string to the controlling OS terminal + * + * This bypasses the U-Boot console support and writes directly to the OS + * stdout file descriptor. + * + * @param str String to write (note that \n is not appended) + */ +void os_puts(const char *str); + +/** * Write the sandbox RAM buffer to a existing file * * @param fname Filename to write memory to (simple binary format) diff --git a/include/post.h b/include/post.h index d5278111e85..b41a6c81272 100644 --- a/include/post.h +++ b/include/post.h @@ -15,7 +15,7 @@ #include <common.h> #include <asm/io.h> -#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) +#if defined(CONFIG_POST) #ifndef CONFIG_POST_EXTERNAL_WORD_FUNCS #ifdef CONFIG_SYS_POST_WORD_ADDR @@ -58,7 +58,7 @@ extern ulong post_word_load(void); extern void post_word_store(ulong value); #endif /* CONFIG_POST_EXTERNAL_WORD_FUNCS */ -#endif /* defined (CONFIG_POST) || defined(CONFIG_LOGBUFFER) */ +#endif /* defined (CONFIG_POST) */ #endif /* __ASSEMBLY__ */ #ifdef CONFIG_POST diff --git a/lib/charset.c b/lib/charset.c index ff76e88c776..8cd17ea1cb7 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -6,7 +6,6 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#include <common.h> #include <charset.h> #include <malloc.h> @@ -99,3 +98,59 @@ uint8_t *utf16_to_utf8(uint8_t *dest, const uint16_t *src, size_t size) return dest; } + +uint16_t *utf8_to_utf16(uint16_t *dest, const uint8_t *src, size_t size) +{ + while (size--) { + int extension_bytes; + uint32_t code; + + extension_bytes = 0; + if (*src <= 0x7f) { + code = *src++; + /* Exit on zero byte */ + if (!code) + size = 0; + } else if (*src <= 0xbf) { + /* Illegal code */ + code = '?'; + } else if (*src <= 0xdf) { + code = *src++ & 0x1f; + extension_bytes = 1; + } else if (*src <= 0xef) { + code = *src++ & 0x0f; + extension_bytes = 2; + } else if (*src <= 0xf7) { + code = *src++ & 0x07; + extension_bytes = 3; + } else { + /* Illegal code */ + code = '?'; + } + + for (; extension_bytes && size; --size, --extension_bytes) { + if ((*src & 0xc0) == 0x80) { + code <<= 6; + code |= *src++ & 0x3f; + } else { + /* Illegal code */ + code = '?'; + ++src; + --size; + break; + } + } + + if (code < 0x10000) { + *dest++ = code; + } else { + /* + * Simplified expression for + * (((code - 0x10000) >> 10) & 0x3ff) | 0xd800 + */ + *dest++ = (code >> 10) + 0xd7c0; + *dest++ = (code & 0x3ff) | 0xdc00; + } + } + return dest; +} diff --git a/lib/efi/efi_stub.c b/lib/efi/efi_stub.c index 18149605728..2e8d409d31a 100644 --- a/lib/efi/efi_stub.c +++ b/lib/efi/efi_stub.c @@ -277,7 +277,7 @@ efi_status_t efi_main(efi_handle_t image, struct efi_system_table *sys_table) struct efi_boot_services *boot = sys_table->boottime; struct efi_mem_desc *desc; struct efi_entry_memmap map; - ulong key, desc_size, size; + efi_uintn_t key, desc_size, size; efi_status_t ret; u32 version; int cs32; diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index ddb978f650f..2722265ee3d 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -7,8 +7,8 @@ # This file only gets included with CONFIG_EFI_LOADER set, so all # object inclusion implicitly depends on it -CFLAGS_helloworld.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI) +CFLAGS_helloworld.o := $(CFLAGS_EFI) -Os -ffreestanding +CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI) -Os ifneq ($(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),) always += helloworld.efi @@ -17,7 +17,7 @@ endif obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o obj-y += efi_memory.o efi_device_path_to_text.o efi_device_path.o -obj-y += efi_file.o efi_variable.o efi_bootmgr.o +obj-y += efi_file.o efi_variable.o efi_bootmgr.o efi_watchdog.o obj-$(CONFIG_LCD) += efi_gop.o obj-$(CONFIG_DM_VIDEO) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 743b84864fc..a37fb25638c 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -21,7 +21,7 @@ DECLARE_GLOBAL_DATA_PTR; /* Task priority level */ -static UINTN efi_tpl = TPL_APPLICATION; +static efi_uintn_t efi_tpl = TPL_APPLICATION; /* This list contains all the EFI objects our payload has access to */ LIST_HEAD(efi_obj_list); @@ -156,18 +156,6 @@ void efi_signal_event(struct efi_event *event) } /* - * Write a debug message for an EPI API service that is not implemented yet. - * - * @funcname function that is not yet implemented - * @return EFI_UNSUPPORTED - */ -static efi_status_t efi_unsupported(const char *funcname) -{ - debug("EFI: App called into unimplemented function %s\n", funcname); - return EFI_EXIT(EFI_UNSUPPORTED); -} - -/* * Raise the task priority level. * * This function implements the RaiseTpl service. @@ -177,9 +165,9 @@ static efi_status_t efi_unsupported(const char *funcname) * @new_tpl new value of the task priority level * @return old value of the task priority level */ -static unsigned long EFIAPI efi_raise_tpl(UINTN new_tpl) +static unsigned long EFIAPI efi_raise_tpl(efi_uintn_t new_tpl) { - UINTN old_tpl = efi_tpl; + efi_uintn_t old_tpl = efi_tpl; EFI_ENTRY("0x%zx", new_tpl); @@ -202,7 +190,7 @@ static unsigned long EFIAPI efi_raise_tpl(UINTN new_tpl) * * @old_tpl value of the task priority level to be restored */ -static void EFIAPI efi_restore_tpl(UINTN old_tpl) +static void EFIAPI efi_restore_tpl(efi_uintn_t old_tpl) { EFI_ENTRY("0x%zx", old_tpl); @@ -229,12 +217,12 @@ static void EFIAPI efi_restore_tpl(UINTN old_tpl) * @return status code */ static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type, - unsigned long pages, + efi_uintn_t pages, uint64_t *memory) { efi_status_t r; - EFI_ENTRY("%d, %d, 0x%lx, %p", type, memory_type, pages, memory); + EFI_ENTRY("%d, %d, 0x%zx, %p", type, memory_type, pages, memory); r = efi_allocate_pages(type, memory_type, pages, memory); return EFI_EXIT(r); } @@ -251,11 +239,11 @@ static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type, * @return status code */ static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory, - unsigned long pages) + efi_uintn_t pages) { efi_status_t r; - EFI_ENTRY("%"PRIx64", 0x%lx", memory, pages); + EFI_ENTRY("%"PRIx64", 0x%zx", memory, pages); r = efi_free_pages(memory, pages); return EFI_EXIT(r); } @@ -276,10 +264,10 @@ static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory, * @return status code */ static efi_status_t EFIAPI efi_get_memory_map_ext( - unsigned long *memory_map_size, + efi_uintn_t *memory_map_size, struct efi_mem_desc *memory_map, - unsigned long *map_key, - unsigned long *descriptor_size, + efi_uintn_t *map_key, + efi_uintn_t *descriptor_size, uint32_t *descriptor_version) { efi_status_t r; @@ -304,12 +292,12 @@ static efi_status_t EFIAPI efi_get_memory_map_ext( * @return status code */ static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type, - unsigned long size, + efi_uintn_t size, void **buffer) { efi_status_t r; - EFI_ENTRY("%d, %ld, %p", pool_type, size, buffer); + EFI_ENTRY("%d, %zd, %p", pool_type, size, buffer); r = efi_allocate_pool(pool_type, size, buffer); return EFI_EXIT(r); } @@ -333,7 +321,30 @@ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer) return EFI_EXIT(r); } -static efi_status_t efi_create_handle(void **handle) +/* + * Add a new object to the object list. + * + * The protocols list is initialized. + * The object handle is set. + * + * @obj object to be added + */ +void efi_add_handle(struct efi_object *obj) +{ + if (!obj) + return; + INIT_LIST_HEAD(&obj->protocols); + obj->handle = obj; + list_add_tail(&obj->link, &efi_obj_list); +} + +/* + * Create handle. + * + * @handle new handle + * @return status code + */ +efi_status_t efi_create_handle(void **handle) { struct efi_object *obj; efi_status_t r; @@ -343,10 +354,8 @@ static efi_status_t efi_create_handle(void **handle) (void **)&obj); if (r != EFI_SUCCESS) return r; - memset(obj, 0, sizeof(struct efi_object)); - obj->handle = obj; - list_add_tail(&obj->link, &efi_obj_list); - *handle = obj; + efi_add_handle(obj); + *handle = obj->handle; return r; } @@ -371,7 +380,7 @@ static struct efi_event efi_events[16]; * @event created event * @return status code */ -efi_status_t efi_create_event(uint32_t type, UINTN notify_tpl, +efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, void (EFIAPI *notify_function) ( struct efi_event *event, void *context), @@ -421,7 +430,7 @@ efi_status_t efi_create_event(uint32_t type, UINTN notify_tpl, * @return status code */ static efi_status_t EFIAPI efi_create_event_ext( - uint32_t type, UINTN notify_tpl, + uint32_t type, efi_uintn_t notify_tpl, void (EFIAPI *notify_function) ( struct efi_event *event, void *context), @@ -551,13 +560,13 @@ static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event, * @index index of the event that was signaled * @return status code */ -static efi_status_t EFIAPI efi_wait_for_event(unsigned long num_events, +static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events, struct efi_event **event, - size_t *index) + efi_uintn_t *index) { int i, j; - EFI_ENTRY("%ld, %p, %p", num_events, event, index); + EFI_ENTRY("%zd, %p, %p", num_events, event, index); /* Check parameters */ if (!num_events || !event) @@ -691,75 +700,137 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) } /* - * Install protocol interface. + * Find the internal EFI object for a handle. + * + * @handle handle to find + * @return EFI object + */ +struct efi_object *efi_search_obj(const void *handle) +{ + struct efi_object *efiobj; + + list_for_each_entry(efiobj, &efi_obj_list, link) { + if (efiobj->handle == handle) + return efiobj; + } + + return NULL; +} + +/* + * Find a protocol on a handle. * - * This is the function for internal calls. For the API implementation of the - * InstallProtocolInterface service see function - * efi_install_protocol_interface_ext. + * @handle handle + * @protocol_guid GUID of the protocol + * @handler reference to the protocol + * @return status code + */ +efi_status_t efi_search_protocol(const void *handle, + const efi_guid_t *protocol_guid, + struct efi_handler **handler) +{ + struct efi_object *efiobj; + struct list_head *lhandle; + + if (!handle || !protocol_guid) + return EFI_INVALID_PARAMETER; + efiobj = efi_search_obj(handle); + if (!efiobj) + return EFI_INVALID_PARAMETER; + list_for_each(lhandle, &efiobj->protocols) { + struct efi_handler *protocol; + + protocol = list_entry(lhandle, struct efi_handler, link); + if (!guidcmp(protocol->guid, protocol_guid)) { + if (handler) + *handler = protocol; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + +/* + * Install new protocol on a handle. * * @handle handle on which the protocol shall be installed * @protocol GUID of the protocol to be installed - * @protocol_interface_type type of the interface to be installed, - * always EFI_NATIVE_INTERFACE * @protocol_interface interface of the protocol implementation * @return status code */ -static efi_status_t EFIAPI efi_install_protocol_interface(void **handle, - const efi_guid_t *protocol, int protocol_interface_type, - void *protocol_interface) +efi_status_t efi_add_protocol(const void *handle, const efi_guid_t *protocol, + void *protocol_interface) { - struct list_head *lhandle; - int i; - efi_status_t r; + struct efi_object *efiobj; + struct efi_handler *handler; + efi_status_t ret; - if (!handle || !protocol || - protocol_interface_type != EFI_NATIVE_INTERFACE) { - r = EFI_INVALID_PARAMETER; - goto out; - } + efiobj = efi_search_obj(handle); + if (!efiobj) + return EFI_INVALID_PARAMETER; + ret = efi_search_protocol(handle, protocol, NULL); + if (ret != EFI_NOT_FOUND) + return EFI_INVALID_PARAMETER; + handler = calloc(1, sizeof(struct efi_handler)); + if (!handler) + return EFI_OUT_OF_RESOURCES; + handler->guid = protocol; + handler->protocol_interface = protocol_interface; + list_add_tail(&handler->link, &efiobj->protocols); + return EFI_SUCCESS; +} - /* Create new handle if requested. */ - if (!*handle) { - r = efi_create_handle(handle); - if (r != EFI_SUCCESS) - goto out; - } - /* Find object. */ - list_for_each(lhandle, &efi_obj_list) { - struct efi_object *efiobj; - efiobj = list_entry(lhandle, struct efi_object, link); +/* + * Delete protocol from a handle. + * + * @handle handle from which the protocol shall be deleted + * @protocol GUID of the protocol to be deleted + * @protocol_interface interface of the protocol implementation + * @return status code + */ +efi_status_t efi_remove_protocol(const void *handle, const efi_guid_t *protocol, + void *protocol_interface) +{ + struct efi_handler *handler; + efi_status_t ret; - if (efiobj->handle != *handle) - continue; - /* Check if protocol is already installed on the handle. */ - for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { - struct efi_handler *handler = &efiobj->protocols[i]; - - if (!handler->guid) - continue; - if (!guidcmp(handler->guid, protocol)) { - r = EFI_INVALID_PARAMETER; - goto out; - } - } - /* Install protocol in first empty slot. */ - for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { - struct efi_handler *handler = &efiobj->protocols[i]; + ret = efi_search_protocol(handle, protocol, &handler); + if (ret != EFI_SUCCESS) + return ret; + if (guidcmp(handler->guid, protocol)) + return EFI_INVALID_PARAMETER; + list_del(&handler->link); + free(handler); + return EFI_SUCCESS; +} - if (handler->guid) - continue; +/* + * Delete all protocols from a handle. + * + * @handle handle from which the protocols shall be deleted + * @return status code + */ +efi_status_t efi_remove_all_protocols(const void *handle) +{ + struct efi_object *efiobj; + struct list_head *lhandle; + struct list_head *pos; - handler->guid = protocol; - handler->protocol_interface = protocol_interface; - r = EFI_SUCCESS; - goto out; - } - r = EFI_OUT_OF_RESOURCES; - goto out; + efiobj = efi_search_obj(handle); + if (!efiobj) + return EFI_INVALID_PARAMETER; + list_for_each_safe(lhandle, pos, &efiobj->protocols) { + struct efi_handler *protocol; + efi_status_t ret; + + protocol = list_entry(lhandle, struct efi_handler, link); + + ret = efi_remove_protocol(handle, protocol->guid, + protocol->protocol_interface); + if (ret != EFI_SUCCESS) + return ret; } - r = EFI_INVALID_PARAMETER; -out: - return r; + return EFI_SUCCESS; } /* @@ -776,16 +847,36 @@ out: * @protocol_interface interface of the protocol implementation * @return status code */ -static efi_status_t EFIAPI efi_install_protocol_interface_ext(void **handle, - const efi_guid_t *protocol, int protocol_interface_type, - void *protocol_interface) +static efi_status_t EFIAPI efi_install_protocol_interface( + void **handle, const efi_guid_t *protocol, + int protocol_interface_type, void *protocol_interface) { + efi_status_t r; + EFI_ENTRY("%p, %pUl, %d, %p", handle, protocol, protocol_interface_type, protocol_interface); - return EFI_EXIT(efi_install_protocol_interface(handle, protocol, - protocol_interface_type, - protocol_interface)); + if (!handle || !protocol || + protocol_interface_type != EFI_NATIVE_INTERFACE) { + r = EFI_INVALID_PARAMETER; + goto out; + } + + /* Create new handle if requested. */ + if (!*handle) { + r = efi_create_handle(handle); + if (r != EFI_SUCCESS) + goto out; + debug("%sEFI: new handle %p\n", indent_string(nesting_level), + *handle); + } else { + debug("%sEFI: handle %p\n", indent_string(nesting_level), + *handle); + } + /* Add new protocol */ + r = efi_add_protocol(*handle, protocol, protocol_interface); +out: + return EFI_EXIT(r); } /* @@ -814,75 +905,41 @@ static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle, /* * Uninstall protocol interface. * - * This is the function for internal calls. For the API implementation of the - * UninstallProtocolInterface service see function - * efi_uninstall_protocol_interface_ext. + * This function implements the UninstallProtocolInterface service. + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. * * @handle handle from which the protocol shall be removed * @protocol GUID of the protocol to be removed * @protocol_interface interface to be removed * @return status code */ -static efi_status_t EFIAPI efi_uninstall_protocol_interface(void *handle, - const efi_guid_t *protocol, void *protocol_interface) +static efi_status_t EFIAPI efi_uninstall_protocol_interface( + void *handle, const efi_guid_t *protocol, + void *protocol_interface) { - struct list_head *lhandle; - int i; - efi_status_t r = EFI_NOT_FOUND; + struct efi_handler *handler; + efi_status_t r; + + EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface); if (!handle || !protocol) { r = EFI_INVALID_PARAMETER; goto out; } - list_for_each(lhandle, &efi_obj_list) { - struct efi_object *efiobj; - efiobj = list_entry(lhandle, struct efi_object, link); - - if (efiobj->handle != handle) - continue; - - for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { - struct efi_handler *handler = &efiobj->protocols[i]; - const efi_guid_t *hprotocol = handler->guid; - - if (!hprotocol) - continue; - if (!guidcmp(hprotocol, protocol)) { - if (handler->protocol_interface) { - r = EFI_ACCESS_DENIED; - } else { - handler->guid = 0; - r = EFI_SUCCESS; - } - goto out; - } - } + /* Find the protocol on the handle */ + r = efi_search_protocol(handle, protocol, &handler); + if (r != EFI_SUCCESS) + goto out; + if (handler->protocol_interface) { + /* TODO disconnect controllers */ + r = EFI_ACCESS_DENIED; + } else { + r = efi_remove_protocol(handle, protocol, protocol_interface); } - out: - return r; -} - -/* - * Uninstall protocol interface. - * - * This function implements the UninstallProtocolInterface service. - * See the Unified Extensible Firmware Interface (UEFI) specification - * for details. - * - * @handle handle from which the protocol shall be removed - * @protocol GUID of the protocol to be removed - * @protocol_interface interface to be removed - * @return status code - */ -static efi_status_t EFIAPI efi_uninstall_protocol_interface_ext(void *handle, - const efi_guid_t *protocol, void *protocol_interface) -{ - EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface); - - return EFI_EXIT(efi_uninstall_protocol_interface(handle, protocol, - protocol_interface)); + return EFI_EXIT(r); } /* @@ -922,23 +979,21 @@ static int efi_search(enum efi_locate_search_type search_type, const efi_guid_t *protocol, void *search_key, struct efi_object *efiobj) { - int i; + efi_status_t ret; switch (search_type) { - case all_handles: + case ALL_HANDLES: return 0; - case by_register_notify: + case BY_REGISTER_NOTIFY: + /* TODO: RegisterProtocolNotify is not implemented yet */ return -1; - case by_protocol: - for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { - const efi_guid_t *guid = efiobj->protocols[i].guid; - if (guid && !guidcmp(guid, protocol)) - return 0; - } + case BY_PROTOCOL: + ret = efi_search_protocol(efiobj->handle, protocol, NULL); + return (ret != EFI_SUCCESS); + default: + /* Invalid search type */ return -1; } - - return -1; } /* @@ -957,18 +1012,40 @@ static int efi_search(enum efi_locate_search_type search_type, static efi_status_t efi_locate_handle( enum efi_locate_search_type search_type, const efi_guid_t *protocol, void *search_key, - unsigned long *buffer_size, efi_handle_t *buffer) + efi_uintn_t *buffer_size, efi_handle_t *buffer) { - struct list_head *lhandle; - unsigned long size = 0; + struct efi_object *efiobj; + efi_uintn_t size = 0; + + /* Check parameters */ + switch (search_type) { + case ALL_HANDLES: + break; + case BY_REGISTER_NOTIFY: + if (!search_key) + return EFI_INVALID_PARAMETER; + /* RegisterProtocolNotify is not implemented yet */ + return EFI_UNSUPPORTED; + case BY_PROTOCOL: + if (!protocol) + return EFI_INVALID_PARAMETER; + break; + default: + return EFI_INVALID_PARAMETER; + } + + /* + * efi_locate_handle_buffer uses this function for + * the calculation of the necessary buffer size. + * So do not require a buffer for buffersize == 0. + */ + if (!buffer_size || (*buffer_size && !buffer)) + return EFI_INVALID_PARAMETER; /* Count how much space we need */ - list_for_each(lhandle, &efi_obj_list) { - struct efi_object *efiobj; - efiobj = list_entry(lhandle, struct efi_object, link); - if (!efi_search(search_type, protocol, search_key, efiobj)) { + list_for_each_entry(efiobj, &efi_obj_list, link) { + if (!efi_search(search_type, protocol, search_key, efiobj)) size += sizeof(void*); - } } if (*buffer_size < size) { @@ -981,12 +1058,9 @@ static efi_status_t efi_locate_handle( return EFI_NOT_FOUND; /* Then fill the array */ - list_for_each(lhandle, &efi_obj_list) { - struct efi_object *efiobj; - efiobj = list_entry(lhandle, struct efi_object, link); - if (!efi_search(search_type, protocol, search_key, efiobj)) { - *(buffer++) = efiobj->handle; - } + list_for_each_entry(efiobj, &efi_obj_list, link) { + if (!efi_search(search_type, protocol, search_key, efiobj)) + *buffer++ = efiobj->handle; } return EFI_SUCCESS; @@ -1009,7 +1083,7 @@ static efi_status_t efi_locate_handle( static efi_status_t EFIAPI efi_locate_handle_ext( enum efi_locate_search_type search_type, const efi_guid_t *protocol, void *search_key, - unsigned long *buffer_size, efi_handle_t *buffer) + efi_uintn_t *buffer_size, efi_handle_t *buffer) { EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key, buffer_size, buffer); @@ -1018,36 +1092,6 @@ static efi_status_t EFIAPI efi_locate_handle_ext( buffer_size, buffer)); } -/* - * Get the device path and handle of an device implementing a protocol. - * - * This function implements the LocateDevicePath service. - * See the Unified Extensible Firmware Interface (UEFI) specification - * for details. - * - * @protocol GUID of the protocol - * @device_path device path - * @device handle of the device - * @return status code - */ -static efi_status_t EFIAPI efi_locate_device_path( - const efi_guid_t *protocol, - struct efi_device_path **device_path, - efi_handle_t *device) -{ - struct efi_object *efiobj; - - EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device); - - efiobj = efi_dp_find_obj(*device_path, device_path); - if (!efiobj) - return EFI_EXIT(EFI_NOT_FOUND); - - *device = efiobj->handle; - - return EFI_EXIT(EFI_SUCCESS); -} - /* Collapses configuration table entries, removing index i */ static void efi_remove_configuration_table(int i) { @@ -1131,34 +1175,47 @@ void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *ob struct efi_device_path *device_path, struct efi_device_path *file_path) { + efi_status_t ret; + + /* Add internal object to object list */ + efi_add_handle(obj); + /* efi_exit() assumes that the handle points to the info */ obj->handle = info; + info->file_path = file_path; + if (device_path) + info->device_handle = efi_dp_find_obj(device_path, NULL); + /* * When asking for the device path interface, return * bootefi_device_path */ - obj->protocols[0].guid = &efi_guid_device_path; - obj->protocols[0].protocol_interface = device_path; + ret = efi_add_protocol(obj->handle, &efi_guid_device_path, device_path); + if (ret != EFI_SUCCESS) + goto failure; /* * When asking for the loaded_image interface, just * return handle which points to loaded_image_info */ - obj->protocols[1].guid = &efi_guid_loaded_image; - obj->protocols[1].protocol_interface = info; - - obj->protocols[2].guid = &efi_guid_console_control; - obj->protocols[2].protocol_interface = (void *)&efi_console_control; + ret = efi_add_protocol(obj->handle, &efi_guid_loaded_image, info); + if (ret != EFI_SUCCESS) + goto failure; - obj->protocols[3].guid = &efi_guid_device_path_to_text_protocol; - obj->protocols[3].protocol_interface = - (void *)&efi_device_path_to_text; + ret = efi_add_protocol(obj->handle, &efi_guid_console_control, + (void *)&efi_console_control); + if (ret != EFI_SUCCESS) + goto failure; - info->file_path = file_path; - if (device_path) - info->device_handle = efi_dp_find_obj(device_path, NULL); + ret = efi_add_protocol(obj->handle, + &efi_guid_device_path_to_text_protocol, + (void *)&efi_device_path_to_text); + if (ret != EFI_SUCCESS) + goto failure; - list_add_tail(&obj->link, &efi_obj_list); + return; +failure: + printf("ERROR: Failure to install protocols for loaded image\n"); } /* @@ -1273,7 +1330,9 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, return EFI_EXIT(EFI_UNSUPPORTED); } - *image_handle = info; + info->system_table = &systab; + info->parent_handle = parent_image; + *image_handle = obj->handle; return EFI_EXIT(EFI_SUCCESS); } @@ -1335,6 +1394,17 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, efi_status_t exit_status, unsigned long exit_data_size, int16_t *exit_data) { + /* + * We require that the handle points to the original loaded + * image protocol interface. + * + * For getting the longjmp address this is safer than locating + * the protocol because the protocol may have been reinstalled + * pointing to another memory location. + * + * TODO: We should call the unload procedure of the loaded + * image protocol. + */ struct efi_loaded_image *loaded_image_info = (void*)image_handle; EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status, @@ -1356,26 +1426,6 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, } /* - * Find the internal EFI object for a handle. - * - * @handle handle to find - * @return EFI object - */ -static struct efi_object *efi_search_obj(void *handle) -{ - struct list_head *lhandle; - - list_for_each(lhandle, &efi_obj_list) { - struct efi_object *efiobj; - efiobj = list_entry(lhandle, struct efi_object, link); - if (efiobj->handle == handle) - return efiobj; - } - - return NULL; -} - -/* * Unload an EFI image. * * This function implements the UnloadImage service. @@ -1450,6 +1500,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle, bootm_disable_interrupts(); /* Give the payload some time to boot */ + efi_set_watchdog(0); WATCHDOG_RESET(); return EFI_EXIT(EFI_SUCCESS); @@ -1493,7 +1544,7 @@ static efi_status_t EFIAPI efi_stall(unsigned long microseconds) /* * Reset the watchdog timer. * - * This function implements the WatchdogTimer service. + * This function implements the SetWatchdogTimer service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * @@ -1510,7 +1561,7 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout, { EFI_ENTRY("%ld, 0x%"PRIx64", %ld, %p", timeout, watchdog_code, data_size, watchdog_data); - return efi_unsupported(__func__); + return EFI_EXIT(efi_set_watchdog(timeout)); } /* @@ -1597,7 +1648,7 @@ static efi_status_t EFIAPI efi_close_protocol(void *handle, static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle, const efi_guid_t *protocol, struct efi_open_protocol_info_entry **entry_buffer, - unsigned long *entry_count) + efi_uintn_t *entry_count) { EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, entry_buffer, entry_count); @@ -1618,12 +1669,11 @@ static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle, */ static efi_status_t EFIAPI efi_protocols_per_handle(void *handle, efi_guid_t ***protocol_buffer, - unsigned long *protocol_buffer_count) + efi_uintn_t *protocol_buffer_count) { unsigned long buffer_size; struct efi_object *efiobj; - unsigned long i, j; - struct list_head *lhandle; + struct list_head *protocol_handle; efi_status_t r; EFI_ENTRY("%p, %p, %p", handle, protocol_buffer, @@ -1634,36 +1684,33 @@ static efi_status_t EFIAPI efi_protocols_per_handle(void *handle, *protocol_buffer = NULL; *protocol_buffer_count = 0; - list_for_each(lhandle, &efi_obj_list) { - efiobj = list_entry(lhandle, struct efi_object, link); - if (efiobj->handle != handle) - continue; + efiobj = efi_search_obj(handle); + if (!efiobj) + return EFI_EXIT(EFI_INVALID_PARAMETER); - /* Count protocols */ - for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { - if (efiobj->protocols[i].guid) - ++*protocol_buffer_count; - } - /* Copy guids */ - if (*protocol_buffer_count) { - buffer_size = sizeof(efi_guid_t *) * - *protocol_buffer_count; - r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, - buffer_size, - (void **)protocol_buffer); - if (r != EFI_SUCCESS) - return EFI_EXIT(r); - j = 0; - for (i = 0; i < ARRAY_SIZE(efiobj->protocols); ++i) { - if (efiobj->protocols[i].guid) { - (*protocol_buffer)[j] = (void *) - efiobj->protocols[i].guid; - ++j; - } - } + /* Count protocols */ + list_for_each(protocol_handle, &efiobj->protocols) { + ++*protocol_buffer_count; + } + + /* Copy guids */ + if (*protocol_buffer_count) { + size_t j = 0; + + buffer_size = sizeof(efi_guid_t *) * *protocol_buffer_count; + r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, buffer_size, + (void **)protocol_buffer); + if (r != EFI_SUCCESS) + return EFI_EXIT(r); + list_for_each(protocol_handle, &efiobj->protocols) { + struct efi_handler *protocol; + + protocol = list_entry(protocol_handle, + struct efi_handler, link); + (*protocol_buffer)[j] = (void *)protocol->guid; + ++j; } - break; } return EFI_EXIT(EFI_SUCCESS); @@ -1686,10 +1733,10 @@ static efi_status_t EFIAPI efi_protocols_per_handle(void *handle, static efi_status_t EFIAPI efi_locate_handle_buffer( enum efi_locate_search_type search_type, const efi_guid_t *protocol, void *search_key, - unsigned long *no_handles, efi_handle_t **buffer) + efi_uintn_t *no_handles, efi_handle_t **buffer) { efi_status_t r; - unsigned long buffer_size = 0; + efi_uintn_t buffer_size = 0; EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key, no_handles, buffer); @@ -1733,29 +1780,23 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, void **protocol_interface) { struct list_head *lhandle; - int i; + efi_status_t ret; EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface); if (!protocol || !protocol_interface) return EFI_EXIT(EFI_INVALID_PARAMETER); - EFI_PRINT_GUID("protocol", protocol); - list_for_each(lhandle, &efi_obj_list) { struct efi_object *efiobj; + struct efi_handler *handler; efiobj = list_entry(lhandle, struct efi_object, link); - for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { - struct efi_handler *handler = &efiobj->protocols[i]; - - if (!handler->guid) - continue; - if (!guidcmp(handler->guid, protocol)) { - *protocol_interface = - handler->protocol_interface; - return EFI_EXIT(EFI_SUCCESS); - } + + ret = efi_search_protocol(efiobj->handle, protocol, &handler); + if (ret == EFI_SUCCESS) { + *protocol_interface = handler->protocol_interface; + return EFI_EXIT(EFI_SUCCESS); } } *protocol_interface = NULL; @@ -1764,6 +1805,82 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, } /* + * Get the device path and handle of an device implementing a protocol. + * + * This function implements the LocateDevicePath service. + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @protocol GUID of the protocol + * @device_path device path + * @device handle of the device + * @return status code + */ +static efi_status_t EFIAPI efi_locate_device_path( + const efi_guid_t *protocol, + struct efi_device_path **device_path, + efi_handle_t *device) +{ + struct efi_device_path *dp; + size_t i; + struct efi_handler *handler; + efi_handle_t *handles; + size_t len, len_dp; + size_t len_best = 0; + efi_uintn_t no_handles; + u8 *remainder; + efi_status_t ret; + + EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device); + + if (!protocol || !device_path || !*device_path || !device) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + /* Find end of device path */ + len = efi_dp_size(*device_path); + + /* Get all handles implementing the protocol */ + ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL, + &no_handles, &handles)); + if (ret != EFI_SUCCESS) + goto out; + + for (i = 0; i < no_handles; ++i) { + /* Find the device path protocol */ + ret = efi_search_protocol(handles[i], &efi_guid_device_path, + &handler); + if (ret != EFI_SUCCESS) + continue; + dp = (struct efi_device_path *)handler->protocol_interface; + len_dp = efi_dp_size(dp); + /* + * This handle can only be a better fit + * if its device path length is longer than the best fit and + * if its device path length is shorter of equal the searched + * device path. + */ + if (len_dp <= len_best || len_dp > len) + continue; + /* Check if dp is a subpath of device_path */ + if (memcmp(*device_path, dp, len_dp)) + continue; + *device = handles[i]; + len_best = len_dp; + } + if (len_best) { + remainder = (u8 *)*device_path + len_best; + *device_path = (struct efi_device_path *)remainder; + ret = EFI_SUCCESS; + } else { + ret = EFI_NOT_FOUND; + } +out: + return EFI_EXIT(ret); +} + +/* * Install multiple protocol interfaces. * * This function implements the MultipleProtocolInterfaces service. @@ -1795,9 +1912,10 @@ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces( if (!protocol) break; protocol_interface = va_arg(argptr, void*); - r = efi_install_protocol_interface(handle, protocol, - EFI_NATIVE_INTERFACE, - protocol_interface); + r = EFI_CALL(efi_install_protocol_interface( + handle, protocol, + EFI_NATIVE_INTERFACE, + protocol_interface)); if (r != EFI_SUCCESS) break; i++; @@ -1806,13 +1924,13 @@ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces( if (r == EFI_SUCCESS) return EFI_EXIT(r); - /* If an error occured undo all changes. */ + /* If an error occurred undo all changes. */ va_start(argptr, handle); for (; i; --i) { protocol = va_arg(argptr, efi_guid_t*); protocol_interface = va_arg(argptr, void*); - efi_uninstall_protocol_interface(handle, protocol, - protocol_interface); + EFI_CALL(efi_uninstall_protocol_interface(handle, protocol, + protocol_interface)); } va_end(argptr); @@ -1835,7 +1953,45 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces( void *handle, ...) { EFI_ENTRY("%p", handle); - return EFI_EXIT(EFI_INVALID_PARAMETER); + + va_list argptr; + const efi_guid_t *protocol; + void *protocol_interface; + efi_status_t r = EFI_SUCCESS; + size_t i = 0; + + if (!handle) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + va_start(argptr, handle); + for (;;) { + protocol = va_arg(argptr, efi_guid_t*); + if (!protocol) + break; + protocol_interface = va_arg(argptr, void*); + r = EFI_CALL(efi_uninstall_protocol_interface( + handle, protocol, + protocol_interface)); + if (r != EFI_SUCCESS) + break; + i++; + } + va_end(argptr); + if (r == EFI_SUCCESS) + return EFI_EXIT(r); + + /* If an error occurred undo all changes. */ + va_start(argptr, handle); + for (; i; --i) { + protocol = va_arg(argptr, efi_guid_t*); + protocol_interface = va_arg(argptr, void*); + EFI_CALL(efi_install_protocol_interface(&handle, protocol, + EFI_NATIVE_INTERFACE, + protocol_interface)); + } + va_end(argptr); + + return EFI_EXIT(r); } /* @@ -1916,8 +2072,7 @@ static efi_status_t EFIAPI efi_open_protocol( void **protocol_interface, void *agent_handle, void *controller_handle, uint32_t attributes) { - struct list_head *lhandle; - int i; + struct efi_handler *handler; efi_status_t r = EFI_INVALID_PARAMETER; EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol, @@ -1930,8 +2085,6 @@ static efi_status_t EFIAPI efi_open_protocol( goto out; } - EFI_PRINT_GUID("protocol", protocol); - switch (attributes) { case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL: case EFI_OPEN_PROTOCOL_GET_PROTOCOL: @@ -1952,33 +2105,12 @@ static efi_status_t EFIAPI efi_open_protocol( goto out; } - list_for_each(lhandle, &efi_obj_list) { - struct efi_object *efiobj; - efiobj = list_entry(lhandle, struct efi_object, link); - - if (efiobj->handle != handle) - continue; - - for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { - struct efi_handler *handler = &efiobj->protocols[i]; - const efi_guid_t *hprotocol = handler->guid; - if (!hprotocol) - continue; - if (!guidcmp(hprotocol, protocol)) { - if (attributes != - EFI_OPEN_PROTOCOL_TEST_PROTOCOL) { - *protocol_interface = - handler->protocol_interface; - } - r = EFI_SUCCESS; - goto out; - } - } - goto unsupported; - } + r = efi_search_protocol(handle, protocol, &handler); + if (r != EFI_SUCCESS) + goto out; -unsupported: - r = EFI_UNSUPPORTED; + if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) + *protocol_interface = handler->protocol_interface; out: return EFI_EXIT(r); } @@ -2020,9 +2152,9 @@ static const struct efi_boot_services efi_boot_services = { .signal_event = efi_signal_event_ext, .close_event = efi_close_event, .check_event = efi_check_event, - .install_protocol_interface = efi_install_protocol_interface_ext, + .install_protocol_interface = efi_install_protocol_interface, .reinstall_protocol_interface = efi_reinstall_protocol_interface, - .uninstall_protocol_interface = efi_uninstall_protocol_interface_ext, + .uninstall_protocol_interface = efi_uninstall_protocol_interface, .handle_protocol = efi_handle_protocol, .reserved = NULL, .register_protocol_notify = efi_register_protocol_notify, diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 01732aafead..98497db612e 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -46,6 +46,10 @@ static struct cout_mode efi_cout_modes[] = { }; const efi_guid_t efi_guid_console_control = CONSOLE_CONTROL_GUID; +const efi_guid_t efi_guid_text_output_protocol = + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID; +const efi_guid_t efi_guid_text_input_protocol = + EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID; #define cESC '\x1b' #define ESC "\x1b" @@ -81,7 +85,7 @@ static efi_status_t EFIAPI efi_cin_lock_std_in( return EFI_EXIT(EFI_UNSUPPORTED); } -const struct efi_console_control_protocol efi_console_control = { +struct efi_console_control_protocol efi_console_control = { .get_mode = efi_cin_get_mode, .set_mode = efi_cin_set_mode, .lock_std_in = efi_cin_lock_std_in, @@ -374,7 +378,7 @@ static efi_status_t EFIAPI efi_cout_enable_cursor( return EFI_EXIT(EFI_SUCCESS); } -const struct efi_simple_text_output_protocol efi_con_out = { +struct efi_simple_text_output_protocol efi_con_out = { .reset = efi_cout_reset, .output_string = efi_cout_output_string, .test_string = efi_cout_test_string, @@ -490,23 +494,38 @@ static void EFIAPI efi_console_timer_notify(struct efi_event *event, } -static struct efi_object efi_console_control_obj = - EFI_PROTOCOL_OBJECT(efi_guid_console_control, &efi_console_control); -static struct efi_object efi_console_output_obj = - EFI_PROTOCOL_OBJECT(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID, &efi_con_out); -static struct efi_object efi_console_input_obj = - EFI_PROTOCOL_OBJECT(EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID, &efi_con_in); - /* This gets called from do_bootefi_exec(). */ int efi_console_register(void) { efi_status_t r; + struct efi_object *efi_console_control_obj; + struct efi_object *efi_console_output_obj; + struct efi_object *efi_console_input_obj; - /* Hook up to the device list */ - list_add_tail(&efi_console_control_obj.link, &efi_obj_list); - list_add_tail(&efi_console_output_obj.link, &efi_obj_list); - list_add_tail(&efi_console_input_obj.link, &efi_obj_list); + /* Create handles */ + r = efi_create_handle((void **)&efi_console_control_obj); + if (r != EFI_SUCCESS) + goto out_of_memory; + r = efi_add_protocol(efi_console_control_obj->handle, + &efi_guid_console_control, &efi_console_control); + if (r != EFI_SUCCESS) + goto out_of_memory; + r = efi_create_handle((void **)&efi_console_output_obj); + if (r != EFI_SUCCESS) + goto out_of_memory; + r = efi_add_protocol(efi_console_output_obj->handle, + &efi_guid_text_output_protocol, &efi_con_out); + if (r != EFI_SUCCESS) + goto out_of_memory; + r = efi_create_handle((void **)&efi_console_input_obj); + if (r != EFI_SUCCESS) + goto out_of_memory; + r = efi_add_protocol(efi_console_input_obj->handle, + &efi_guid_text_input_protocol, &efi_con_in); + if (r != EFI_SUCCESS) + goto out_of_memory; + /* Create console events */ r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify, NULL, &efi_con_in.wait_for_key); if (r != EFI_SUCCESS) { @@ -525,4 +544,7 @@ int efi_console_register(void) if (r != EFI_SUCCESS) printf("ERROR: Failed to set console timer\n"); return r; +out_of_memory: + printf("ERROR: Out of meemory\n"); + return r; } diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index f6e368e029b..b4e2f933cb6 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -68,7 +68,8 @@ struct efi_device_path *efi_dp_next(const struct efi_device_path *dp) * representing a device with one representing a file on the device, or * a device with a parent device. */ -int efi_dp_match(struct efi_device_path *a, struct efi_device_path *b) +int efi_dp_match(const struct efi_device_path *a, + const struct efi_device_path *b) { while (1) { int ret; @@ -127,32 +128,27 @@ static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, struct efi_object *efiobj; list_for_each_entry(efiobj, &efi_obj_list, link) { - int i; - - for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { - struct efi_handler *handler = &efiobj->protocols[i]; - struct efi_device_path *obj_dp; - - if (!handler->guid) - break; - - if (guidcmp(handler->guid, &efi_guid_device_path)) - continue; - - obj_dp = handler->protocol_interface; - - do { - if (efi_dp_match(dp, obj_dp) == 0) { - if (rem) { - *rem = ((void *)dp) + - efi_dp_size(obj_dp); - } - return efiobj; + struct efi_handler *handler; + struct efi_device_path *obj_dp; + efi_status_t ret; + + ret = efi_search_protocol(efiobj->handle, + &efi_guid_device_path, &handler); + if (ret != EFI_SUCCESS) + continue; + obj_dp = handler->protocol_interface; + + do { + if (efi_dp_match(dp, obj_dp) == 0) { + if (rem) { + *rem = ((void *)dp) + + efi_dp_size(obj_dp); } + return efiobj; + } - obj_dp = shorten_path(efi_dp_next(obj_dp)); - } while (short_path && obj_dp); - } + obj_dp = shorten_path(efi_dp_next(obj_dp)); + } while (short_path && obj_dp); } return NULL; @@ -427,10 +423,27 @@ static void *dp_part_fill(void *buf, struct blk_desc *desc, int part) hddp->partmap_type = 2; else hddp->partmap_type = 1; - hddp->signature_type = desc->sig_type; - if (hddp->signature_type != 0) + + switch (desc->sig_type) { + case SIG_TYPE_NONE: + default: + hddp->signature_type = 0; + memset(hddp->partition_signature, 0, + sizeof(hddp->partition_signature)); + break; + case SIG_TYPE_MBR: + hddp->signature_type = 1; + memset(hddp->partition_signature, 0, + sizeof(hddp->partition_signature)); + memcpy(hddp->partition_signature, &desc->mbr_sig, + sizeof(desc->mbr_sig)); + break; + case SIG_TYPE_GUID: + hddp->signature_type = 2; memcpy(hddp->partition_signature, &desc->guid_sig, sizeof(hddp->partition_signature)); + break; + } buf = &hddp[1]; } diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 62771338f03..7159c974d4d 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -12,12 +12,31 @@ #define MAC_OUTPUT_LEN 22 #define UNKNOWN_OUTPUT_LEN 23 +#define MAX_NODE_LEN 512 +#define MAX_PATH_LEN 1024 + const efi_guid_t efi_guid_device_path_to_text_protocol = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; +static u16 *efi_str_to_u16(char *str) +{ + efi_uintn_t len; + u16 *out; + efi_status_t ret; + + len = strlen(str) + 1; + ret = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, len * sizeof(u16), + (void **)&out); + if (ret != EFI_SUCCESS) + return NULL; + ascii2unicode(out, str); + out[len - 1] = 0; + return out; +} + static char *dp_unknown(char *s, struct efi_device_path *dp) { - s += sprintf(s, "/UNKNOWN(%04x,%04x)", dp->type, dp->sub_type); + s += sprintf(s, "UNKNOWN(%04x,%04x)", dp->type, dp->sub_type); return s; } @@ -27,7 +46,7 @@ static char *dp_hardware(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_MEMORY: { struct efi_device_path_memory *mdp = (struct efi_device_path_memory *)dp; - s += sprintf(s, "/MemoryMapped(0x%x,0x%llx,0x%llx)", + s += sprintf(s, "MemoryMapped(0x%x,0x%llx,0x%llx)", mdp->memory_type, mdp->start_address, mdp->end_address); @@ -36,7 +55,7 @@ static char *dp_hardware(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_VENDOR: { struct efi_device_path_vendor *vdp = (struct efi_device_path_vendor *)dp; - s += sprintf(s, "/VenHw(%pUl)", &vdp->guid); + s += sprintf(s, "VenHw(%pUl)", &vdp->guid); break; } default: @@ -52,7 +71,7 @@ static char *dp_acpi(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_ACPI_DEVICE: { struct efi_device_path_acpi_path *adp = (struct efi_device_path_acpi_path *)dp; - s += sprintf(s, "/Acpi(PNP%04x", EISA_PNP_NUM(adp->hid)); + s += sprintf(s, "Acpi(PNP%04x", EISA_PNP_NUM(adp->hid)); if (adp->uid) s += sprintf(s, ",%d", adp->uid); s += sprintf(s, ")"); @@ -71,7 +90,7 @@ static char *dp_msging(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_MSG_USB: { struct efi_device_path_usb *udp = (struct efi_device_path_usb *)dp; - s += sprintf(s, "/Usb(0x%x,0x%x)", udp->parent_port_number, + s += sprintf(s, "Usb(0x%x,0x%x)", udp->parent_port_number, udp->usb_interface); break; } @@ -82,7 +101,7 @@ static char *dp_msging(char *s, struct efi_device_path *dp) if (mdp->if_type != 0 && mdp->if_type != 1) break; - s += sprintf(s, "/MAC(%02x%02x%02x%02x%02x%02x,0x%1x)", + s += sprintf(s, "MAC(%02x%02x%02x%02x%02x%02x,0x%1x)", mdp->mac.addr[0], mdp->mac.addr[1], mdp->mac.addr[2], mdp->mac.addr[3], mdp->mac.addr[4], mdp->mac.addr[5], @@ -94,7 +113,7 @@ static char *dp_msging(char *s, struct efi_device_path *dp) struct efi_device_path_usb_class *ucdp = (struct efi_device_path_usb_class *)dp; - s += sprintf(s, "/USBClass(%x,%x,%x,%x,%x)", + s += sprintf(s, "USBClass(%x,%x,%x,%x,%x)", ucdp->vendor_id, ucdp->product_id, ucdp->device_class, ucdp->device_subclass, ucdp->device_protocol); @@ -108,7 +127,7 @@ static char *dp_msging(char *s, struct efi_device_path *dp) "SDCard" : "MMC"; struct efi_device_path_sd_mmc_path *sddp = (struct efi_device_path_sd_mmc_path *)dp; - s += sprintf(s, "/%s(Slot%u)", typename, sddp->slot_number); + s += sprintf(s, "%s(Slot%u)", typename, sddp->slot_number); break; } default: @@ -128,17 +147,19 @@ static char *dp_media(char *s, struct efi_device_path *dp) switch (hddp->signature_type) { case SIG_TYPE_MBR: - s += sprintf(s, "/HD(Part%d,Sig%08x)", + s += sprintf(s, "HD(Part%d,Sig%08x)", hddp->partition_number, *(uint32_t *)sig); break; case SIG_TYPE_GUID: - s += sprintf(s, "/HD(Part%d,Sig%pUl)", + s += sprintf(s, "HD(Part%d,Sig%pUl)", hddp->partition_number, sig); + break; default: - s += sprintf(s, "/HD(Part%d,MBRType=%02x,SigType=%02x)", + s += sprintf(s, "HD(Part%d,MBRType=%02x,SigType=%02x)", hddp->partition_number, hddp->partmap_type, hddp->signature_type); + break; } break; @@ -146,14 +167,16 @@ static char *dp_media(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_CDROM_PATH: { struct efi_device_path_cdrom_path *cddp = (struct efi_device_path_cdrom_path *)dp; - s += sprintf(s, "/CDROM(0x%x)", cddp->boot_entry); + s += sprintf(s, "CDROM(0x%x)", cddp->boot_entry); break; } case DEVICE_PATH_SUB_TYPE_FILE_PATH: { struct efi_device_path_file_path *fp = (struct efi_device_path_file_path *)dp; int slen = (dp->length - sizeof(*dp)) / 2; - s += sprintf(s, "/%-*ls", slen, fp->str); + if (slen > MAX_NODE_LEN - 2) + slen = MAX_NODE_LEN - 2; + s += sprintf(s, "%-.*ls", slen, fp->str); break; } default: @@ -163,95 +186,119 @@ static char *dp_media(char *s, struct efi_device_path *dp) return s; } -static uint16_t *efi_convert_device_node_to_text( - struct efi_device_path *dp, - bool display_only, - bool allow_shortcuts) +/* + * Converts a single node to a char string. + * + * @buffer output buffer + * @dp device path or node + * @return end of string + */ +static char *efi_convert_single_device_node_to_text( + char *buffer, + struct efi_device_path *dp) { - unsigned long len; - efi_status_t r; - char buf[512]; /* this ought be be big enough for worst case */ - char *str = buf; - uint16_t *out; - - while (dp) { - switch (dp->type) { - case DEVICE_PATH_TYPE_HARDWARE_DEVICE: - str = dp_hardware(str, dp); - break; - case DEVICE_PATH_TYPE_ACPI_DEVICE: - str = dp_acpi(str, dp); - break; - case DEVICE_PATH_TYPE_MESSAGING_DEVICE: - str = dp_msging(str, dp); - break; - case DEVICE_PATH_TYPE_MEDIA_DEVICE: - str = dp_media(str, dp); - break; - default: - str = dp_unknown(str, dp); - } + char *str = buffer; - dp = efi_dp_next(dp); + switch (dp->type) { + case DEVICE_PATH_TYPE_HARDWARE_DEVICE: + str = dp_hardware(str, dp); + break; + case DEVICE_PATH_TYPE_ACPI_DEVICE: + str = dp_acpi(str, dp); + break; + case DEVICE_PATH_TYPE_MESSAGING_DEVICE: + str = dp_msging(str, dp); + break; + case DEVICE_PATH_TYPE_MEDIA_DEVICE: + str = dp_media(str, dp); + break; + default: + str = dp_unknown(str, dp); } - *str++ = '\0'; - - len = str - buf; - r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, 2 * len, (void **)&out); - if (r != EFI_SUCCESS) - return NULL; - - ascii2unicode(out, buf); - out[len - 1] = 0; - - return out; + *str = '\0'; + return str; } -/* helper for debug prints.. efi_free_pool() the result. */ -uint16_t *efi_dp_str(struct efi_device_path *dp) -{ - return efi_convert_device_node_to_text(dp, true, true); -} - - -static uint16_t EFIAPI *efi_convert_device_node_to_text_ext( +/* + * This function implements the ConvertDeviceNodeToText service of the + * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * device_node device node to be converted + * display_only true if the shorter text represenation shall be used + * allow_shortcuts true if shortcut forms may be used + * @return text represenation of the device path + * NULL if out of memory of device_path is NULL + */ +static uint16_t EFIAPI *efi_convert_device_node_to_text( struct efi_device_path *device_node, bool display_only, bool allow_shortcuts) { - uint16_t *buffer; + char str[MAX_NODE_LEN]; + uint16_t *text = NULL; EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts); - buffer = efi_convert_device_node_to_text(device_node, display_only, - allow_shortcuts); + if (!device_node) + goto out; + efi_convert_single_device_node_to_text(str, device_node); + + text = efi_str_to_u16(str); +out: EFI_EXIT(EFI_SUCCESS); - return buffer; + return text; } +/* + * This function implements the ConvertDevicePathToText service of the + * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * device_path device path to be converted + * display_only true if the shorter text represenation shall be used + * allow_shortcuts true if shortcut forms may be used + * @return text represenation of the device path + * NULL if out of memory of device_path is NULL + */ static uint16_t EFIAPI *efi_convert_device_path_to_text( struct efi_device_path *device_path, bool display_only, bool allow_shortcuts) { - uint16_t *buffer; + uint16_t *text = NULL; + char buffer[MAX_PATH_LEN]; + char *str = buffer; EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts); - /* - * Our device paths are all of depth one. So its is sufficient to - * to convert the first node. - */ - buffer = efi_convert_device_node_to_text(device_path, display_only, - allow_shortcuts); + if (!device_path) + goto out; + while (device_path && + str + MAX_NODE_LEN < buffer + MAX_PATH_LEN) { + *str++ = '/'; + str = efi_convert_single_device_node_to_text(str, device_path); + device_path = efi_dp_next(device_path); + } + + text = efi_str_to_u16(buffer); +out: EFI_EXIT(EFI_SUCCESS); - return buffer; + return text; +} + +/* helper for debug prints.. efi_free_pool() the result. */ +uint16_t *efi_dp_str(struct efi_device_path *dp) +{ + return EFI_CALL(efi_convert_device_path_to_text(dp, true, true)); } const struct efi_device_path_to_text_protocol efi_device_path_to_text = { - .convert_device_node_to_text = efi_convert_device_node_to_text_ext, + .convert_device_node_to_text = efi_convert_device_node_to_text, .convert_device_path_to_text = efi_convert_device_path_to_text, }; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index e61dbc80580..4e457a841bd 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -196,6 +196,15 @@ efi_fs_from_path(struct efi_device_path *fp) return diskobj->volume; } +/* + * Create a device for a disk + * + * @name not used + * @if_typename interface name for block device + * @desc internal block device + * @dev_index device index for block device + * @offset offset into disk for simple partitions + */ static void efi_disk_add_dev(const char *name, const char *if_typename, struct blk_desc *desc, @@ -204,29 +213,39 @@ static void efi_disk_add_dev(const char *name, unsigned int part) { struct efi_disk_obj *diskobj; + efi_status_t ret; /* Don't add empty devices */ if (!desc->lba) return; diskobj = calloc(1, sizeof(*diskobj)); + if (!diskobj) + goto out_of_memory; + + /* Hook up to the device list */ + efi_add_handle(&diskobj->parent); /* Fill in object data */ diskobj->dp = efi_dp_from_part(desc, part); diskobj->part = part; - diskobj->parent.protocols[0].guid = &efi_block_io_guid; - diskobj->parent.protocols[0].protocol_interface = &diskobj->ops; - diskobj->parent.protocols[1].guid = &efi_guid_device_path; - diskobj->parent.protocols[1].protocol_interface = diskobj->dp; + ret = efi_add_protocol(diskobj->parent.handle, &efi_block_io_guid, + &diskobj->ops); + if (ret != EFI_SUCCESS) + goto out_of_memory; + ret = efi_add_protocol(diskobj->parent.handle, &efi_guid_device_path, + diskobj->dp); + if (ret != EFI_SUCCESS) + goto out_of_memory; if (part >= 1) { diskobj->volume = efi_simple_file_system(desc, part, diskobj->dp); - diskobj->parent.protocols[2].guid = - &efi_simple_file_system_protocol_guid; - diskobj->parent.protocols[2].protocol_interface = - diskobj->volume; + ret = efi_add_protocol(diskobj->parent.handle, + &efi_simple_file_system_protocol_guid, + &diskobj->volume); + if (ret != EFI_SUCCESS) + goto out_of_memory; } - diskobj->parent.handle = diskobj; diskobj->ops = block_io_disk_template; diskobj->ifname = if_typename; diskobj->dev_index = dev_index; @@ -240,26 +259,22 @@ static void efi_disk_add_dev(const char *name, diskobj->media.io_align = desc->blksz; diskobj->media.last_block = desc->lba - offset; diskobj->ops.media = &diskobj->media; - - /* Hook up to the device list */ - list_add_tail(&diskobj->parent.link, &efi_obj_list); + return; +out_of_memory: + printf("ERROR: Out of memory\n"); } -static int efi_disk_create_eltorito(struct blk_desc *desc, - const char *if_typename, - int diskid, - const char *pdevname) +static int efi_disk_create_partitions(struct blk_desc *desc, + const char *if_typename, + int diskid, + const char *pdevname) { int disks = 0; -#if CONFIG_IS_ENABLED(ISO_PARTITION) char devname[32] = { 0 }; /* dp->str is u16[32] long */ disk_partition_t info; int part; - if (desc->part_type != PART_TYPE_ISO) - return 0; - - /* and devices for each partition: */ + /* Add devices for each partition */ for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { if (part_get_info(desc, part, &info)) continue; @@ -270,10 +285,6 @@ static int efi_disk_create_eltorito(struct blk_desc *desc, disks++; } - /* ... and add block device: */ - efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0); -#endif - return disks; } @@ -299,31 +310,18 @@ int efi_disk_register(void) uclass_next_device_check(&dev)) { struct blk_desc *desc = dev_get_uclass_platdata(dev); const char *if_typename = dev->driver->name; - disk_partition_t info; - int part; printf("Scanning disk %s...\n", dev->name); - /* add devices for each partition: */ - for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { - if (part_get_info(desc, part, &info)) - continue; - efi_disk_add_dev(dev->name, if_typename, desc, - desc->devnum, 0, part); - } - - /* ... and add block device: */ + /* Add block device for the full device */ efi_disk_add_dev(dev->name, if_typename, desc, desc->devnum, 0, 0); disks++; - /* - * El Torito images show up as block devices in an EFI world, - * so let's create them here - */ - disks += efi_disk_create_eltorito(desc, if_typename, - desc->devnum, dev->name); + /* Partitions show up as block devices in EFI */ + disks += efi_disk_create_partitions(desc, if_typename, + desc->devnum, dev->name); } #else int i, if_type; @@ -342,8 +340,6 @@ int efi_disk_register(void) for (i = 0; i < 4; i++) { struct blk_desc *desc; char devname[32] = { 0 }; /* dp->str is u16[32] long */ - disk_partition_t info; - int part; desc = blk_get_devnum_by_type(if_type, i); if (!desc) @@ -354,24 +350,13 @@ int efi_disk_register(void) snprintf(devname, sizeof(devname), "%s%d", if_typename, i); - /* add devices for each partition: */ - for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { - if (part_get_info(desc, part, &info)) - continue; - efi_disk_add_dev(devname, if_typename, desc, - i, 0, part); - } - - /* ... and add block device: */ + /* Add block device for the full device */ efi_disk_add_dev(devname, if_typename, desc, i, 0, 0); disks++; - /* - * El Torito images show up as block devices - * in an EFI world, so let's create them here - */ - disks += efi_disk_create_eltorito(desc, if_typename, - i, devname); + /* Partitions show up as block devices in EFI */ + disks += efi_disk_create_partitions(desc, if_typename, + i, devname); } } #endif diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index 411a8c92261..3caddd5f844 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -32,7 +32,7 @@ struct efi_gop_obj { }; static efi_status_t EFIAPI gop_query_mode(struct efi_gop *this, u32 mode_number, - unsigned long *size_of_info, + efi_uintn_t *size_of_info, struct efi_gop_mode_info **info) { struct efi_gop_obj *gopobj; @@ -56,17 +56,17 @@ static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number) return EFI_EXIT(EFI_SUCCESS); } -static efi_status_t EFIAPI gop_blt(struct efi_gop *this, void *buffer, - unsigned long operation, unsigned long sx, - unsigned long sy, unsigned long dx, - unsigned long dy, unsigned long width, - unsigned long height, unsigned long delta) +efi_status_t EFIAPI gop_blt(struct efi_gop *this, void *buffer, + u32 operation, efi_uintn_t sx, + efi_uintn_t sy, efi_uintn_t dx, + efi_uintn_t dy, efi_uintn_t width, + efi_uintn_t height, efi_uintn_t delta) { struct efi_gop_obj *gopobj = container_of(this, struct efi_gop_obj, ops); int i, j, line_len16, line_len32; void *fb; - EFI_ENTRY("%p, %p, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx", this, + EFI_ENTRY("%p, %p, %u, %zu, %zu, %zu, %zu, %zu, %zu, %zu", this, buffer, operation, sx, sy, dx, dy, width, height, delta); if (operation != EFI_BLT_BUFFER_TO_VIDEO) @@ -132,6 +132,7 @@ int efi_gop_register(void) u32 bpix, col, row; u64 fb_base, fb_size; void *fb; + efi_status_t ret; #ifdef CONFIG_DM_VIDEO struct udevice *vdev; @@ -173,11 +174,21 @@ int efi_gop_register(void) } gopobj = calloc(1, sizeof(*gopobj)); + if (!gopobj) { + printf("ERROR: Out of memory\n"); + return 1; + } + + /* Hook up to the device list */ + efi_add_handle(&gopobj->parent); /* Fill in object data */ - gopobj->parent.protocols[0].guid = &efi_gop_guid; - gopobj->parent.protocols[0].protocol_interface = &gopobj->ops; - gopobj->parent.handle = &gopobj->ops; + ret = efi_add_protocol(gopobj->parent.handle, &efi_gop_guid, + &gopobj->ops); + if (ret != EFI_SUCCESS) { + printf("ERROR: Out of memory\n"); + return 1; + } gopobj->ops.query_mode = gop_query_mode; gopobj->ops.set_mode = gop_set_mode; gopobj->ops.blt = gop_blt; @@ -206,8 +217,5 @@ int efi_gop_register(void) gopobj->bpix = bpix; gopobj->fb = fb; - /* Hook up to the device list */ - list_add_tail(&gopobj->parent.link, &efi_obj_list); - return 0; } diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index d47759e08ed..0aa3e0881d4 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -276,7 +276,7 @@ static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr) } efi_status_t efi_allocate_pages(int type, int memory_type, - unsigned long pages, uint64_t *memory) + efi_uintn_t pages, uint64_t *memory) { u64 len = pages << EFI_PAGE_SHIFT; efi_status_t r = EFI_SUCCESS; @@ -338,7 +338,7 @@ void *efi_alloc(uint64_t len, int memory_type) return NULL; } -efi_status_t efi_free_pages(uint64_t memory, unsigned long pages) +efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages) { uint64_t r = 0; @@ -351,7 +351,7 @@ efi_status_t efi_free_pages(uint64_t memory, unsigned long pages) return EFI_NOT_FOUND; } -efi_status_t efi_allocate_pool(int pool_type, unsigned long size, +efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer) { efi_status_t r; @@ -392,16 +392,16 @@ efi_status_t efi_free_pool(void *buffer) return r; } -efi_status_t efi_get_memory_map(unsigned long *memory_map_size, - struct efi_mem_desc *memory_map, - unsigned long *map_key, - unsigned long *descriptor_size, - uint32_t *descriptor_version) +efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, + struct efi_mem_desc *memory_map, + efi_uintn_t *map_key, + efi_uintn_t *descriptor_size, + uint32_t *descriptor_version) { - ulong map_size = 0; + efi_uintn_t map_size = 0; int map_entries = 0; struct list_head *lhandle; - unsigned long provided_map_size = *memory_map_size; + efi_uintn_t provided_map_size = *memory_map_size; list_for_each(lhandle, &efi_mem) map_entries++; diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 432d9a99a2b..8c5d5b492ca 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -292,16 +292,25 @@ int efi_net_register(void) /* We only expose the "active" eth device, so one is enough */ netobj = calloc(1, sizeof(*netobj)); + if (!netobj) + goto out_of_memory; + + /* Hook net up to the device list */ + efi_add_handle(&netobj->parent); /* Fill in object data */ - netobj->parent.protocols[0].guid = &efi_net_guid; - netobj->parent.protocols[0].protocol_interface = &netobj->net; - netobj->parent.protocols[1].guid = &efi_guid_device_path; - netobj->parent.protocols[1].protocol_interface = - efi_dp_from_eth(); - netobj->parent.protocols[2].guid = &efi_pxe_guid; - netobj->parent.protocols[2].protocol_interface = &netobj->pxe; - netobj->parent.handle = &netobj->net; + r = efi_add_protocol(netobj->parent.handle, &efi_net_guid, + &netobj->net); + if (r != EFI_SUCCESS) + goto out_of_memory; + r = efi_add_protocol(netobj->parent.handle, &efi_guid_device_path, + efi_dp_from_eth()); + if (r != EFI_SUCCESS) + goto out_of_memory; + r = efi_add_protocol(netobj->parent.handle, &efi_pxe_guid, + &netobj->pxe); + if (r != EFI_SUCCESS) + goto out_of_memory; netobj->net.revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; netobj->net.start = efi_net_start; netobj->net.stop = efi_net_stop; @@ -326,9 +335,6 @@ int efi_net_register(void) if (dhcp_ack) netobj->pxe_mode.dhcp_ack = *dhcp_ack; - /* Hook net up to the device list */ - list_add_tail(&netobj->parent.link, &efi_obj_list); - /* * Create WaitForPacket event. */ @@ -361,4 +367,7 @@ int efi_net_register(void) } return 0; +out_of_memory: + printf("ERROR: Out of memory\n"); + return 1; } diff --git a/lib/efi_loader/efi_watchdog.c b/lib/efi_loader/efi_watchdog.c new file mode 100644 index 00000000000..35a45dedf84 --- /dev/null +++ b/lib/efi_loader/efi_watchdog.c @@ -0,0 +1,89 @@ +/* + * EFI watchdog + * + * Copyright (c) 2017 Heinrich Schuchardt + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <efi_loader.h> + +/* Conversion factor from seconds to multiples of 100ns */ +#define EFI_SECONDS_TO_100NS 10000000ULL + +static struct efi_event *watchdog_timer_event; + +/* + * Reset the system when the watchdog event is notified. + * + * @event: the watchdog event + * @context: not used + */ +static void EFIAPI efi_watchdog_timer_notify(struct efi_event *event, + void *context) +{ + EFI_ENTRY("%p, %p", event, context); + + printf("\nEFI: Watchdog timeout\n"); + EFI_CALL_VOID(efi_runtime_services.reset_system(EFI_RESET_COLD, + EFI_SUCCESS, 0, NULL)); + + EFI_EXIT(EFI_UNSUPPORTED); +} + +/* + * Reset the watchdog timer. + * + * This function is used by the SetWatchdogTimer service. + * + * @timeout: seconds before reset by watchdog + * @return: status code + */ +efi_status_t efi_set_watchdog(unsigned long timeout) +{ + efi_status_t r; + + if (timeout) + /* Reset watchdog */ + r = efi_set_timer(watchdog_timer_event, EFI_TIMER_RELATIVE, + EFI_SECONDS_TO_100NS * timeout); + else + /* Deactivate watchdog */ + r = efi_set_timer(watchdog_timer_event, EFI_TIMER_STOP, 0); + return r; +} + +/* + * Initialize the EFI watchdog. + * + * This function is called by efi_init_obj_list() + */ +int efi_watchdog_register(void) +{ + efi_status_t r; + + /* + * Create a timer event. + */ + r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, + efi_watchdog_timer_notify, NULL, + &watchdog_timer_event); + if (r != EFI_SUCCESS) { + printf("ERROR: Failed to register watchdog event\n"); + return r; + } + /* + * The UEFI standard requires that the watchdog timer is set to five + * minutes when invoking an EFI boot option. + * + * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A + * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer + */ + r = efi_set_watchdog(300); + if (r != EFI_SUCCESS) { + printf("ERROR: Failed to set watchdog timer\n"); + return r; + } + return 0; +} diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c index 03e65ab1336..e59c24c7881 100644 --- a/lib/efi_loader/helloworld.c +++ b/lib/efi_loader/helloworld.c @@ -5,20 +5,52 @@ * Written by Simon Glass <sjg@chromium.org> * * SPDX-License-Identifier: GPL-2.0+ + * + * This program demonstrates calling a boottime service. + * It writes a greeting and the load options to the console. */ #include <common.h> -#include <part_efi.h> #include <efi_api.h> +/* + * Entry point of the EFI application. + * + * @handle handle of the loaded image + * @systable system table + * @return status code + */ efi_status_t EFIAPI efi_main(efi_handle_t handle, struct efi_system_table *systable) { struct efi_simple_text_output_protocol *con_out = systable->con_out; struct efi_boot_services *boottime = systable->boottime; + struct efi_loaded_image *loaded_image; + const efi_guid_t loaded_image_guid = LOADED_IMAGE_GUID; + efi_status_t ret; con_out->output_string(con_out, L"Hello, world!\n"); - boottime->exit(handle, 0, 0, NULL); - return EFI_SUCCESS; + /* Get the loaded image protocol */ + ret = boottime->handle_protocol(handle, &loaded_image_guid, + (void **)&loaded_image); + if (ret != EFI_SUCCESS) { + con_out->output_string(con_out, + L"Cannot open loaded image protocol\n"); + goto out; + } + /* Output the load options */ + con_out->output_string(con_out, L"Load options: "); + if (loaded_image->load_options_size && loaded_image->load_options) + con_out->output_string(con_out, + (u16 *)loaded_image->load_options); + else + con_out->output_string(con_out, L"<none>"); + con_out->output_string(con_out, L"\n"); + +out: + boottime->exit(handle, ret, 0, NULL); + + /* We should never arrive here */ + return ret; } diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index e446046e022..837e86228ea 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -7,26 +7,16 @@ # This file only gets included with CONFIG_EFI_LOADER set, so all # object inclusion implicitly depends on it -CFLAGS_efi_selftest.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_console.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_console.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_events.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_events.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_exitbootservices.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_exitbootservices.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_snp.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_snp.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_tpl.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_tpl.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_util.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_util.o := $(CFLAGS_NON_EFI) - obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += \ efi_selftest.o \ efi_selftest_console.o \ +efi_selftest_devicepath.o \ efi_selftest_events.o \ efi_selftest_exitbootservices.o \ +efi_selftest_gop.o \ +efi_selftest_manageprotocols.o \ efi_selftest_snp.o \ +efi_selftest_textoutput.o \ efi_selftest_tpl.o \ -efi_selftest_util.o +efi_selftest_util.o \ +efi_selftest_watchdog.o diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c index 45d8d3d384c..4e5a12c47ca 100644 --- a/lib/efi_selftest/efi_selftest.c +++ b/lib/efi_selftest/efi_selftest.c @@ -9,6 +9,13 @@ #include <efi_selftest.h> #include <vsprintf.h> +/* + * Constants for test step bitmap + */ +#define EFI_ST_SETUP 1 +#define EFI_ST_EXECUTE 2 +#define EFI_ST_TEARDOWN 4 + static const struct efi_system_table *systable; static const struct efi_boot_services *boottime; static const struct efi_runtime_services *runtime; @@ -25,9 +32,9 @@ static u16 reset_message[] = L"Selftest completed"; */ void efi_st_exit_boot_services(void) { - unsigned long map_size = 0; - unsigned long map_key; - unsigned long desc_size; + efi_uintn_t map_size = 0; + efi_uintn_t map_key; + efi_uintn_t desc_size; u32 desc_version; efi_status_t ret; struct efi_mem_desc *memory_map; @@ -134,6 +141,70 @@ static int teardown(struct efi_unit_test *test, unsigned int *failures) } /* + * Check that a test exists. + * + * @testname: name of the test + * @return: test + */ +static struct efi_unit_test *find_test(const u16 *testname) +{ + struct efi_unit_test *test; + + for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); + test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { + if (!efi_st_strcmp_16_8(testname, test->name)) + return test; + } + efi_st_printf("\nTest '%ps' not found\n", testname); + return NULL; +} + +/* + * List all available tests. + */ +static void list_all_tests(void) +{ + struct efi_unit_test *test; + + /* List all tests */ + efi_st_printf("\nAvailable tests:\n"); + for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); + test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { + efi_st_printf("'%s'%s\n", test->name, + test->on_request ? " - on request" : ""); + } +} + +/* + * Execute test steps of one phase. + * + * @testname name of a single selected test or NULL + * @phase test phase + * @steps steps to execute + * failures returns EFI_ST_SUCCESS if all test steps succeeded + */ +void efi_st_do_tests(const u16 *testname, unsigned int phase, + unsigned int steps, unsigned int *failures) +{ + struct efi_unit_test *test; + + for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); + test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { + if (testname ? + efi_st_strcmp_16_8(testname, test->name) : test->on_request) + continue; + if (test->phase != phase) + continue; + if (steps & EFI_ST_SETUP) + setup(test, failures); + if (steps & EFI_ST_EXECUTE) + execute(test, failures); + if (steps & EFI_ST_TEARDOWN) + teardown(test, failures); + } +} + +/* * Execute selftest of the EFI API * * This is the main entry point of the EFI selftest application. @@ -153,8 +224,10 @@ static int teardown(struct efi_unit_test *test, unsigned int *failures) efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle, struct efi_system_table *systab) { - struct efi_unit_test *test; unsigned int failures = 0; + const u16 *testname = NULL; + struct efi_loaded_image *loaded_image; + efi_status_t ret; systable = systab; boottime = systable->boottime; @@ -163,47 +236,59 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle, con_out = systable->con_out; con_in = systable->con_in; - efi_st_printf("\nTesting EFI API implementation\n"); + ret = boottime->handle_protocol(image_handle, &efi_guid_loaded_image, + (void **)&loaded_image); + if (ret != EFI_SUCCESS) { + efi_st_error("Cannot open loaded image protocol\n"); + return ret; + } - efi_st_printf("\nNumber of tests to execute: %u\n", - ll_entry_count(struct efi_unit_test, efi_unit_test)); + if (loaded_image->load_options) + testname = (u16 *)loaded_image->load_options; - /* Execute boottime tests */ - for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); - test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { - if (test->phase == EFI_EXECUTE_BEFORE_BOOTTIME_EXIT) { - setup(test, &failures); - execute(test, &failures); - teardown(test, &failures); + if (testname) { + if (!efi_st_strcmp_16_8(testname, "list") || + !find_test(testname)) { + list_all_tests(); + /* + * TODO: + * Once the Exit boottime service is correctly + * implemented we should call + * boottime->exit(image_handle, EFI_SUCCESS, 0, NULL); + * here, cf. + * https://lists.denx.de/pipermail/u-boot/2017-October/308720.html + */ + return EFI_SUCCESS; } } + efi_st_printf("\nTesting EFI API implementation\n"); + + if (testname) + efi_st_printf("\nSelected test: '%ps'\n", testname); + else + efi_st_printf("\nNumber of tests to execute: %u\n", + ll_entry_count(struct efi_unit_test, + efi_unit_test)); + + /* Execute boottime tests */ + efi_st_do_tests(testname, EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN, + &failures); + /* Execute mixed tests */ - for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); - test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { - if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT) - setup(test, &failures); - } + efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT, + EFI_ST_SETUP, &failures); efi_st_exit_boot_services(); - for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); - test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { - if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT) { - execute(test, &failures); - teardown(test, &failures); - } - } + efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT, + EFI_ST_EXECUTE | EFI_ST_TEARDOWN, &failures); /* Execute runtime tests */ - for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); - test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { - if (test->phase == EFI_SETUP_AFTER_BOOTTIME_EXIT) { - setup(test, &failures); - execute(test, &failures); - teardown(test, &failures); - } - } + efi_st_do_tests(testname, EFI_SETUP_AFTER_BOOTTIME_EXIT, + EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN, + &failures); /* Give feedback */ efi_st_printf("\nSummary: %u failures\n\n", failures); diff --git a/lib/efi_selftest/efi_selftest_console.c b/lib/efi_selftest/efi_selftest_console.c index 840e2290c60..6a7fd20da5c 100644 --- a/lib/efi_selftest/efi_selftest_console.c +++ b/lib/efi_selftest/efi_selftest_console.c @@ -142,6 +142,7 @@ void efi_st_printf(const char *fmt, ...) const char *c; u16 *pos = buf; const char *s; + const u16 *u; va_start(args, fmt); @@ -179,9 +180,18 @@ void efi_st_printf(const char *fmt, ...) case 'p': ++c; switch (*c) { + /* MAC address */ case 'm': mac(va_arg(args, void*), &pos); break; + + /* u16 string */ + case 's': + u = va_arg(args, u16*); + /* Ensure string fits into buffer */ + for (; *u && pos < buf + 120; ++u) + *pos++ = *u; + break; default: --c; pointer(va_arg(args, void*), &pos); diff --git a/lib/efi_selftest/efi_selftest_devicepath.c b/lib/efi_selftest/efi_selftest_devicepath.c new file mode 100644 index 00000000000..1ab54ebb371 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_devicepath.c @@ -0,0 +1,390 @@ +/* + * efi_selftest_devicepath + * + * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This unit test checks the following protocol services: + * DevicePathToText + */ + +#include <efi_selftest.h> + +static struct efi_boot_services *boottime; + +static efi_handle_t handle1; +static efi_handle_t handle2; +static efi_handle_t handle3; + +struct interface { + void (EFIAPI * inc)(void); +} interface; + +static efi_guid_t guid_device_path = DEVICE_PATH_GUID; + +static efi_guid_t guid_device_path_to_text_protocol = + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; + +static efi_guid_t guid_protocol = + EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, + 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0x7d); + +static efi_guid_t guid_vendor1 = + EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, + 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xb1); + +static efi_guid_t guid_vendor2 = + EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, + 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xa2); + +static efi_guid_t guid_vendor3 = + EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, + 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xc3); + +static u8 *dp1; +static u8 *dp2; +static u8 *dp3; + +struct efi_device_path_to_text_protocol *device_path_to_text; + +/* + * Setup unit test. + * + * Create three handles. Install a new protocol on two of them and + * provice device paths. + * + * handle1 + * guid interface + * handle2 + * guid interface + * handle3 + * + * @handle: handle of the loaded image + * @systable: system table + */ +static int setup(const efi_handle_t img_handle, + const struct efi_system_table *systable) +{ + struct efi_device_path_vendor vendor_node; + struct efi_device_path end_node; + efi_status_t ret; + + boottime = systable->boottime; + + ret = boottime->locate_protocol(&guid_device_path_to_text_protocol, + NULL, (void **)&device_path_to_text); + if (ret != EFI_SUCCESS) { + device_path_to_text = NULL; + efi_st_error( + "Device path to text protocol is not available.\n"); + return EFI_ST_FAILURE; + } + + ret = boottime->allocate_pool(EFI_LOADER_DATA, + sizeof(struct efi_device_path_vendor) + + sizeof(struct efi_device_path), + (void **)&dp1); + if (ret != EFI_SUCCESS) + goto out_of_memory; + + ret = boottime->allocate_pool(EFI_LOADER_DATA, 2 * + sizeof(struct efi_device_path_vendor) + + sizeof(struct efi_device_path), + (void **)&dp2); + if (ret != EFI_SUCCESS) + goto out_of_memory; + + ret = boottime->allocate_pool(EFI_LOADER_DATA, 3 * + sizeof(struct efi_device_path_vendor) + + sizeof(struct efi_device_path), + (void **)&dp3); + if (ret != EFI_SUCCESS) + goto out_of_memory; + + vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; + vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; + vendor_node.dp.length = sizeof(struct efi_device_path_vendor); + + boottime->copy_mem(&vendor_node.guid, &guid_vendor1, + sizeof(efi_guid_t)); + boottime->copy_mem(dp1, &vendor_node, + sizeof(struct efi_device_path_vendor)); + boottime->copy_mem(dp2, &vendor_node, + sizeof(struct efi_device_path_vendor)); + boottime->copy_mem(dp3, &vendor_node, + sizeof(struct efi_device_path_vendor)); + + boottime->copy_mem(&vendor_node.guid, &guid_vendor2, + sizeof(efi_guid_t)); + boottime->copy_mem(dp2 + sizeof(struct efi_device_path_vendor), + &vendor_node, sizeof(struct efi_device_path_vendor)); + boottime->copy_mem(dp3 + sizeof(struct efi_device_path_vendor), + &vendor_node, sizeof(struct efi_device_path_vendor)); + + boottime->copy_mem(&vendor_node.guid, &guid_vendor3, + sizeof(efi_guid_t)); + boottime->copy_mem(dp3 + 2 * sizeof(struct efi_device_path_vendor), + &vendor_node, sizeof(struct efi_device_path_vendor)); + + end_node.type = DEVICE_PATH_TYPE_END; + end_node.sub_type = DEVICE_PATH_SUB_TYPE_END; + end_node.length = sizeof(struct efi_device_path); + boottime->copy_mem(dp1 + sizeof(struct efi_device_path_vendor), + &end_node, sizeof(struct efi_device_path)); + boottime->copy_mem(dp2 + 2 * sizeof(struct efi_device_path_vendor), + &end_node, sizeof(struct efi_device_path)); + boottime->copy_mem(dp3 + 3 * sizeof(struct efi_device_path_vendor), + &end_node, sizeof(struct efi_device_path)); + + ret = boottime->install_protocol_interface(&handle1, + &guid_device_path, + EFI_NATIVE_INTERFACE, + dp1); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + ret = boottime->install_protocol_interface(&handle1, + &guid_protocol, + EFI_NATIVE_INTERFACE, + &interface); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + ret = boottime->install_protocol_interface(&handle2, + &guid_device_path, + EFI_NATIVE_INTERFACE, + dp2); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + ret = boottime->install_protocol_interface(&handle2, + &guid_protocol, + EFI_NATIVE_INTERFACE, + &interface); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + ret = boottime->install_protocol_interface(&handle3, + &guid_device_path, + EFI_NATIVE_INTERFACE, + dp3); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; + +out_of_memory: + efi_st_error("Out of memory\n"); + return EFI_ST_FAILURE; +} + +/* + * Tear down unit test. + * + */ +static int teardown(void) +{ + efi_status_t ret; + + ret = boottime->uninstall_protocol_interface(&handle1, + &guid_device_path, + dp1); + if (ret != EFI_SUCCESS) + efi_st_todo("UninstallProtocolInterface failed\n"); + ret = boottime->uninstall_protocol_interface(&handle1, + &guid_protocol, + &interface); + if (ret != EFI_SUCCESS) + efi_st_todo("UninstallProtocolInterface failed\n"); + ret = boottime->uninstall_protocol_interface(&handle2, + &guid_device_path, + dp2); + if (ret != EFI_SUCCESS) + efi_st_todo("UninstallProtocolInterface failed\n"); + ret = boottime->uninstall_protocol_interface(&handle2, + &guid_protocol, + &interface); + if (ret != EFI_SUCCESS) + efi_st_todo("UninstallProtocolInterface failed\n"); + ret = boottime->uninstall_protocol_interface(&handle3, + &guid_device_path, + dp3); + if (ret != EFI_SUCCESS) + efi_st_todo("UninstallProtocolInterface failed\n"); + if (dp1) { + ret = boottime->free_pool(dp1); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + } + if (dp2) { + ret = boottime->free_pool(dp2); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + } + if (dp3) { + ret = boottime->free_pool(dp3); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + } + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + */ +static int execute(void) +{ + struct efi_device_path *remaining_dp; + void *handle; + /* + * This device path node ends with the letter 't' of 'u-boot'. + * The following '.bin' does not belong to the node but is + * helps to test the correct truncation. + */ + struct { + struct efi_device_path dp; + u16 text[12]; + } __packed dp_node = { + { DEVICE_PATH_TYPE_MEDIA_DEVICE, + DEVICE_PATH_SUB_TYPE_FILE_PATH, + sizeof(struct efi_device_path) + 12}, + L"u-boot.bin", + }; + u16 *string; + efi_status_t ret; + efi_uintn_t i, no_handles; + efi_handle_t *handles; + struct efi_device_path *dp; + + /* Display all available device paths */ + ret = boottime->locate_handle_buffer(BY_PROTOCOL, + &guid_device_path, + NULL, &no_handles, &handles); + if (ret != EFI_SUCCESS) { + efi_st_error("Cannot retrieve device path protocols.\n"); + return EFI_ST_FAILURE; + } + + efi_st_printf("Installed device path protocols:\n"); + for (i = 0; i < no_handles; ++i) { + ret = boottime->open_protocol(handles[i], &guid_device_path, + (void **)&dp, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) { + efi_st_error("Cannot open device path protocol.\n"); + return EFI_ST_FAILURE; + } + string = device_path_to_text->convert_device_path_to_text( + dp, true, false); + if (!string) { + efi_st_error("ConvertDevicePathToText failed\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("%ps\n", string); + ret = boottime->free_pool(string); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + ret = boottime->close_protocol(handles[i], &guid_device_path, + NULL, NULL); + if (ret != EFI_SUCCESS) + efi_st_todo("Cannot close device path protocol.\n"); + } + ret = boottime->free_pool(handles); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("\n"); + + /* Test ConvertDevicePathToText */ + string = device_path_to_text->convert_device_path_to_text( + (struct efi_device_path *)dp2, true, false); + if (!string) { + efi_st_error("ConvertDevicePathToText failed\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("dp2: %ps\n", string); + if (efi_st_strcmp_16_8( + string, + "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbb1)/VenHw(dbca4c98-6cb0-694d-0872-819c650cbba2)") + ) { + efi_st_error("Incorrect text from ConvertDevicePathToText\n"); + return EFI_ST_FAILURE; + } + + ret = boottime->free_pool(string); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + + /* Test ConvertDeviceNodeToText */ + string = device_path_to_text->convert_device_node_to_text( + (struct efi_device_path *)&dp_node, true, false); + if (!string) { + efi_st_error("ConvertDeviceNodeToText failed\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("dp_node: %ps\n", string); + ret = boottime->free_pool(string); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + if (efi_st_strcmp_16_8(string, "u-boot")) { + efi_st_error( + "Incorrect conversion by ConvertDeviceNodeToText\n"); + return EFI_ST_FAILURE; + } + + /* Test LocateDevicePath */ + remaining_dp = (struct efi_device_path *)dp3; + ret = boottime->locate_device_path(&guid_protocol, &remaining_dp, + &handle); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateDevicePath failed\n"); + return EFI_ST_FAILURE; + } + if (handle != handle2) { + efi_st_error("LocateDevicePath returned wrong handle\n"); + return EFI_ST_FAILURE; + } + string = device_path_to_text->convert_device_path_to_text(remaining_dp, + true, false); + if (!string) { + efi_st_error("ConvertDevicePathToText failed\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("remaining device path: %ps\n", string); + if (efi_st_strcmp_16_8(string, + "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbc3)") + ) { + efi_st_error("LocateDevicePath: wrong remaining device path\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(devicepath) = { + .name = "device path", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, + .teardown = teardown, +}; diff --git a/lib/efi_selftest/efi_selftest_events.c b/lib/efi_selftest/efi_selftest_events.c index 081f31257fb..ad9490bd250 100644 --- a/lib/efi_selftest/efi_selftest_events.c +++ b/lib/efi_selftest/efi_selftest_events.c @@ -108,7 +108,7 @@ static int teardown(void) */ static int execute(void) { - size_t index; + efi_uintn_t index; efi_status_t ret; /* Set 10 ms timer */ diff --git a/lib/efi_selftest/efi_selftest_gop.c b/lib/efi_selftest/efi_selftest_gop.c new file mode 100644 index 00000000000..2a0553b115a --- /dev/null +++ b/lib/efi_selftest/efi_selftest_gop.c @@ -0,0 +1,95 @@ +/* + * efi_selftest_gop + * + * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Test the graphical output protocol. + */ + +#include <efi_selftest.h> + +static struct efi_boot_services *boottime; +static efi_guid_t efi_gop_guid = EFI_GOP_GUID; +static struct efi_gop *gop; + +/* + * Setup unit test. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup(const efi_handle_t handle, + const struct efi_system_table *systable) +{ + efi_status_t ret; + + boottime = systable->boottime; + + ret = boottime->locate_protocol(&efi_gop_guid, NULL, (void **)&gop); + if (ret != EFI_SUCCESS) { + gop = NULL; + efi_st_printf("Graphical output protocol is not available.\n"); + } + + return EFI_ST_SUCCESS; +} + +/* + * Tear down unit test. + * + * @return: EFI_ST_SUCCESS for success + */ +static int teardown(void) +{ + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + efi_status_t ret; + u32 i, max_mode; + efi_uintn_t size; + struct efi_gop_mode_info *info; + + if (!gop) + return EFI_ST_SUCCESS; + + if (!gop->mode) { + efi_st_error("EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE missing\n"); + return EFI_ST_FAILURE; + } + max_mode = gop->mode->max_mode; + if (!max_mode) { + efi_st_error("No graphical mode available\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("Number of available modes: %u\n", max_mode); + + for (i = 0; i < max_mode; ++i) { + ret = gop->query_mode(gop, i, &size, &info); + if (ret != EFI_SUCCESS) { + efi_st_printf("Could not query mode %u\n", i); + return EFI_ST_FAILURE; + } + efi_st_printf("Mode %u: %u x %u\n", + i, info->width, info->height); + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(gop) = { + .name = "graphical output", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, + .teardown = teardown, +}; diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c new file mode 100644 index 00000000000..f20f1528d47 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_manageprotocols.c @@ -0,0 +1,354 @@ +/* + * efi_selftest_manageprotocols + * + * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This unit test checks the following protocol services: + * InstallProtocolInterface, UninstallProtocolInterface, + * InstallMultipleProtocolsInterfaces, UninstallMultipleProtocolsInterfaces, + * HandleProtocol, ProtocolsPerHandle, + * LocateHandle, LocateHandleBuffer. + */ + +#include <efi_selftest.h> + +/* + * The test currently does not actually call the interface function. + * So this is just a dummy structure. + */ +struct interface { + void (EFIAPI * inc)(void); +}; + +static struct efi_boot_services *boottime; +static efi_guid_t guid1 = + EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a, + 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf); +static efi_guid_t guid2 = + EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77, + 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f); +static efi_guid_t guid3 = + EFI_GUID(0x06d641a3, 0xf4e7, 0xe0c9, + 0xe7, 0x8d, 0x41, 0x2d, 0x72, 0xa6, 0xb1, 0x24); +static efi_handle_t handle1; +static efi_handle_t handle2; +static struct interface interface1; +static struct interface interface2; +static struct interface interface3; +static struct interface interface4; + +/* + * Find a handle in an array. + * + * @handle: handle to find + * @count: number of entries in the array + * @buffer: array to search + */ +efi_status_t find_in_buffer(efi_handle_t handle, size_t count, + efi_handle_t *buffer) +{ + size_t i; + + for (i = 0; i < count; ++i) { + if (buffer[i] == handle) + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} + +/* + * Setup unit test. + * + * Create two handles and install two out of three protocol interfaces on each + * of them: + * + * handle1 + * guid1 interface1 + * guid3 interface3 + * handle2 + * guid1 interface4 + * guid2 interface2 + * + * @handle: handle of the loaded image + * @systable: system table + */ +static int setup(const efi_handle_t img_handle, + const struct efi_system_table *systable) +{ + efi_status_t ret; + efi_handle_t handle; + + boottime = systable->boottime; + + ret = boottime->install_protocol_interface(&handle1, &guid3, + EFI_NATIVE_INTERFACE, + &interface3); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + if (!handle1) { + efi_st_error("InstallProtocolInterface failed to create handle\n"); + return EFI_ST_FAILURE; + } + handle = handle1; + ret = boottime->install_protocol_interface(&handle1, &guid1, + EFI_NATIVE_INTERFACE, + &interface1); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + if (handle != handle1) { + efi_st_error("InstallProtocolInterface failed to use handle\n"); + return EFI_ST_FAILURE; + } + ret = boottime->install_multiple_protocol_interfaces(&handle2, + &guid1, &interface4, &guid2, &interface2, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallMultipleProtocolInterfaces failed\n"); + return EFI_ST_FAILURE; + } + if (!handle2 || handle1 == handle2) { + efi_st_error("InstallMultipleProtocolInterfaces failed to create handle\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +/* + * Tear down unit test. + * + */ +static int teardown(void) +{ + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + */ +static int execute(void) +{ + struct interface *interface; + efi_status_t ret; + efi_handle_t *buffer; + size_t buffer_size; + efi_uintn_t count = 0; + efi_guid_t **prot_buffer; + efi_uintn_t prot_count; + + /* + * Test HandleProtocol + */ + ret = boottime->handle_protocol(handle1, &guid3, (void **)&interface); + if (ret != EFI_SUCCESS) { + efi_st_error("HandleProtocol failed to retrieve interface\n"); + return EFI_ST_FAILURE; + } + if (interface != &interface3) { + efi_st_error("HandleProtocol returned wrong interface\n"); + return EFI_ST_FAILURE; + } + ret = boottime->handle_protocol(handle1, &guid2, (void **)&interface); + if (ret == EFI_SUCCESS) { + efi_st_error("HandleProtocol returned not installed interface\n"); + return EFI_ST_FAILURE; + } + + /* + * Test LocateHandleBuffer with AllHandles + */ + ret = boottime->locate_handle_buffer(ALL_HANDLES, NULL, NULL, + &count, &buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer with AllHandles failed\n"); + return EFI_ST_FAILURE; + } + buffer_size = count; + ret = find_in_buffer(handle1, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed to locate new handle\n"); + return EFI_ST_FAILURE; + } + ret = find_in_buffer(handle2, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed to locate new handle\n"); + return EFI_ST_FAILURE; + } + boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0); + + /* + * Test error handling in UninstallMultipleProtocols + * + * Try to uninstall more protocols than there are installed. + */ + ret = boottime->uninstall_multiple_protocol_interfaces( + handle2, + &guid1, &interface4, + &guid2, &interface2, + &guid3, &interface3, + NULL); + if (ret == EFI_SUCCESS) { + efi_st_todo("UninstallMultipleProtocolInterfaces did not catch error\n"); + return EFI_ST_FAILURE; + } + + /* + * Test LocateHandleBuffer with ByProtocol + */ + count = buffer_size; + ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL, + &count, &buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed to locate new handles\n"); + return EFI_ST_FAILURE; + } + if (count != 2) { + efi_st_error("LocateHandleBuffer failed to locate new handles\n"); + return EFI_ST_FAILURE; + } + ret = find_in_buffer(handle1, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed to locate new handle\n"); + return EFI_ST_FAILURE; + } + ret = find_in_buffer(handle2, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed to locate new handle\n"); + return EFI_ST_FAILURE; + } + boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0); + + /* + * Test LocateHandle with ByProtocol + */ + count = buffer_size * sizeof(efi_handle_t); + ret = boottime->locate_handle(BY_PROTOCOL, &guid1, NULL, + &count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandle with ByProtocol failed\n"); + return EFI_ST_FAILURE; + } + if (count / sizeof(efi_handle_t) != 2) { + efi_st_error("LocateHandle failed to locate new handles\n"); + return EFI_ST_FAILURE; + } + buffer_size = count; + ret = find_in_buffer(handle1, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandle failed to locate new handles\n"); + return EFI_ST_FAILURE; + } + ret = find_in_buffer(handle2, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandle failed to locate new handles\n"); + return EFI_ST_FAILURE; + } + boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0); + + /* + * Test LocateProtocol + */ + ret = boottime->locate_protocol(&guid1, NULL, (void **)&interface); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateProtocol failed\n"); + return EFI_ST_FAILURE; + } + if (interface != &interface1 && interface != &interface4) { + efi_st_error("LocateProtocol failed to locate protocol\n"); + return EFI_ST_FAILURE; + } + + /* + * Test UninstallMultipleProtocols + */ + ret = boottime->uninstall_multiple_protocol_interfaces( + handle2, + &guid1, &interface4, + &guid2, &interface2, + NULL); + if (ret != EFI_SUCCESS) { + efi_st_todo("UninstallMultipleProtocolInterfaces failed\n"); + /* This test is known to fail due to missing implementation */ + } + /* + * Check that the protocols are really uninstalled. + */ + count = buffer_size; + ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL, + &count, &buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed\n"); + return EFI_ST_FAILURE; + } + if (count != 1) { + efi_st_todo("UninstallMultipleProtocolInterfaces failed to uninstall protocols\n"); + /* This test is known to fail due to missing implementation */ + } + ret = find_in_buffer(handle1, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to locate new handle\n"); + return EFI_ST_FAILURE; + } + boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0); + + /* + * Test ProtocolsPerHandle + */ + ret = boottime->protocols_per_handle(handle1, + &prot_buffer, &prot_count); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to get protocols per handle\n"); + return EFI_ST_FAILURE; + } + if (prot_count != 2) { + efi_st_error("Failed to get protocols per handle\n"); + return EFI_ST_FAILURE; + } + if (efi_st_memcmp(prot_buffer[0], &guid1, 16) && + efi_st_memcmp(prot_buffer[1], &guid1, 16)) { + efi_st_error("Failed to get protocols per handle\n"); + return EFI_ST_FAILURE; + } + if (efi_st_memcmp(prot_buffer[0], &guid3, 16) && + efi_st_memcmp(prot_buffer[1], &guid3, 16)) { + efi_st_error("Failed to get protocols per handle\n"); + return EFI_ST_FAILURE; + } + + /* + * Uninstall remaining protocols + */ + ret = boottime->uninstall_protocol_interface(handle1, &guid1, + &interface1); + if (ret != EFI_SUCCESS) { + efi_st_todo("UninstallProtocolInterface failed\n"); + /* This test is known to fail due to missing implementation */ + } + ret = boottime->handle_protocol(handle1, &guid1, (void **)&interface); + if (ret == EFI_SUCCESS) { + efi_st_todo("UninstallProtocolInterface failed\n"); + /* This test is known to fail due to missing implementation */ + } + ret = boottime->uninstall_protocol_interface(handle1, &guid3, + &interface1); + if (ret != EFI_SUCCESS) { + efi_st_todo("UninstallProtocolInterface failed\n"); + /* This test is known to fail due to missing implementation */ + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(protserv) = { + .name = "manage protocols", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, + .teardown = teardown, +}; diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index bdd6ce20da6..cc0705fb59f 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -260,7 +260,7 @@ static int execute(void) { efi_status_t ret; struct efi_event *events[2]; - size_t index; + efi_uintn_t index; union { struct dhcp p; u8 b[PKTSIZE]; diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c new file mode 100644 index 00000000000..6e8c90cc8bc --- /dev/null +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -0,0 +1,53 @@ +/* + * efi_selftest_textoutput + * + * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Test the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. + * + * The following services are tested: + * OutputString, TestString, SetAttribute. + */ + +#include <efi_selftest.h> + +/* + * Execute unit test. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + size_t foreground; + size_t background; + size_t attrib; + efi_status_t ret; + + /* SetAttribute */ + efi_st_printf("\nColor palette\n"); + for (foreground = 0; foreground < 0x10; ++foreground) { + for (background = 0; background < 0x80; background += 0x10) { + attrib = foreground | background; + con_out->set_attribute(con_out, attrib); + efi_st_printf("%p", (void *)attrib); + } + con_out->set_attribute(con_out, 0); + efi_st_printf("\n"); + } + /* TestString */ + ret = con_out->test_string(con_out, + L" !\"#$%&'()*+,-./0-9:;<=>?@A-Z[\\]^_`a-z{|}~\n"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("TestString failed for ANSI characters\n"); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(textoutput) = { + .name = "text output", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .execute = execute, +}; diff --git a/lib/efi_selftest/efi_selftest_tpl.c b/lib/efi_selftest/efi_selftest_tpl.c index ddb67ed268b..6ea0bb7177f 100644 --- a/lib/efi_selftest/efi_selftest_tpl.c +++ b/lib/efi_selftest/efi_selftest_tpl.c @@ -111,9 +111,9 @@ static int teardown(void) */ static int execute(void) { - size_t index; + efi_uintn_t index; efi_status_t ret; - UINTN old_tpl; + efi_uintn_t old_tpl; /* Set 10 ms timer */ notification_count = 0; diff --git a/lib/efi_selftest/efi_selftest_util.c b/lib/efi_selftest/efi_selftest_util.c index 5cffe383d8d..1b17bf4d4bc 100644 --- a/lib/efi_selftest/efi_selftest_util.c +++ b/lib/efi_selftest/efi_selftest_util.c @@ -21,5 +21,14 @@ int efi_st_memcmp(const void *buf1, const void *buf2, size_t length) ++pos1; ++pos2; } - return EFI_ST_SUCCESS; + return 0; +} + +int efi_st_strcmp_16_8(const u16 *buf1, const char *buf2) +{ + for (; *buf1 || *buf2; ++buf1, ++buf2) { + if (*buf1 != *buf2) + return *buf1 - *buf2; + } + return 0; } diff --git a/lib/efi_selftest/efi_selftest_watchdog.c b/lib/efi_selftest/efi_selftest_watchdog.c new file mode 100644 index 00000000000..e4af38407fd --- /dev/null +++ b/lib/efi_selftest/efi_selftest_watchdog.c @@ -0,0 +1,231 @@ +/* + * efi_selftest_watchdog + * + * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * The 'watchdog timer' unit test checks that the watchdog timer + * will not cause a system restart during the timeout period after + * a timer reset. + * + * The 'watchdog reboot' unit test checks that the watchdog timer + * actually reboots the system after a timeout. The test is only + * executed on explicit request. Use the following commands: + * + * setenv efi_selftest watchdog reboot + * bootefi selftest + */ + +#include <efi_selftest.h> + +/* + * This is the communication structure for the notification function. + */ +struct notify_context { + /* Status code returned when resetting watchdog */ + efi_status_t status; + /* Number of invocations of the notification function */ + unsigned int timer_ticks; +}; + +static struct efi_event *event_notify; +static struct efi_event *event_wait; +static struct efi_boot_services *boottime; +static struct notify_context notification_context; +static bool watchdog_reset; + +/* + * Notification function, increments the notfication count if parameter + * context is provided. + * + * @event notified event + * @context pointer to the timeout + */ +static void EFIAPI notify(struct efi_event *event, void *context) +{ + struct notify_context *notify_context = context; + efi_status_t ret = EFI_SUCCESS; + + if (!notify_context) + return; + + /* Reset watchdog timer to one second */ + ret = boottime->set_watchdog_timer(1, 0, 0, NULL); + if (ret != EFI_SUCCESS) + notify_context->status = ret; + /* Count number of calls */ + notify_context->timer_ticks++; +} + +/* + * Setup unit test. + * + * Create two timer events. + * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup(const efi_handle_t handle, + const struct efi_system_table *systable) +{ + efi_status_t ret; + + boottime = systable->boottime; + + notification_context.status = EFI_SUCCESS; + notification_context.timer_ticks = 0; + ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, notify, + (void *)¬ification_context, + &event_notify); + if (ret != EFI_SUCCESS) { + efi_st_error("could not create event\n"); + return EFI_ST_FAILURE; + } + ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT, + TPL_CALLBACK, notify, NULL, &event_wait); + if (ret != EFI_SUCCESS) { + efi_st_error("could not create event\n"); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; +} + +/* + * Execute the test resetting the watchdog in a timely manner. No reboot occurs. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup_timer(const efi_handle_t handle, + const struct efi_system_table *systable) +{ + watchdog_reset = true; + return setup(handle, systable); +} + +/* + * Execute the test without resetting the watchdog. A system reboot occurs. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup_reboot(const efi_handle_t handle, + const struct efi_system_table *systable) +{ + watchdog_reset = false; + return setup(handle, systable); +} + +/* + * Tear down unit test. + * + * Close the events created in setup. + * + * @return: EFI_ST_SUCCESS for success + */ +static int teardown(void) +{ + efi_status_t ret; + + /* Set the watchdog timer to the five minute default value */ + ret = boottime->set_watchdog_timer(300, 0, 0, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("Setting watchdog timer failed\n"); + return EFI_ST_FAILURE; + } + if (event_notify) { + ret = boottime->close_event(event_notify); + event_notify = NULL; + if (ret != EFI_SUCCESS) { + efi_st_error("Could not close event\n"); + return EFI_ST_FAILURE; + } + } + if (event_wait) { + ret = boottime->close_event(event_wait); + event_wait = NULL; + if (ret != EFI_SUCCESS) { + efi_st_error("Could not close event\n"); + return EFI_ST_FAILURE; + } + } + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + * Run a 600 ms periodic timer that resets the watchdog to one second + * on every timer tick. + * + * Run a 1350 ms single shot timer and check that the 600ms timer has + * been called 2 times. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + size_t index; + efi_status_t ret; + + /* Set the watchdog timeout to one second */ + ret = boottime->set_watchdog_timer(1, 0, 0, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("Setting watchdog timer failed\n"); + return EFI_ST_FAILURE; + } + if (watchdog_reset) { + /* Set 600 ms timer */ + ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, + 6000000); + if (ret != EFI_SUCCESS) { + efi_st_error("Could not set timer\n"); + return EFI_ST_FAILURE; + } + } + /* Set 1350 ms timer */ + ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 13500000); + if (ret != EFI_SUCCESS) { + efi_st_error("Could not set timer\n"); + return EFI_ST_FAILURE; + } + + ret = boottime->wait_for_event(1, &event_wait, &index); + if (ret != EFI_SUCCESS) { + efi_st_error("Could not wait for event\n"); + return EFI_ST_FAILURE; + } + if (notification_context.status != EFI_SUCCESS) { + efi_st_error("Setting watchdog timer failed\n"); + return EFI_ST_FAILURE; + } + if (notification_context.timer_ticks != 2) { + efi_st_error("The timer was called %u times, expected 2.\n", + notification_context.timer_ticks); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(watchdog1) = { + .name = "watchdog timer", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup_timer, + .execute = execute, + .teardown = teardown, +}; + +EFI_UNIT_TEST(watchdog2) = { + .name = "watchdog reboot", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup_reboot, + .execute = execute, + .teardown = teardown, + .on_request = true, +}; diff --git a/post/post.c b/post/post.c index 8fef0c34127..6c7902ad0c7 100644 --- a/post/post.c +++ b/post/post.c @@ -15,10 +15,6 @@ #include <asm/gpio.h> #endif -#ifdef CONFIG_LOGBUFFER -#include <logbuff.h> -#endif - DECLARE_GLOBAL_DATA_PTR; #define POST_MAX_NUMBER 32 @@ -407,13 +403,8 @@ int post_log(char *format, ...) vsprintf(printbuffer, format, args); va_end(args); -#ifdef CONFIG_LOGBUFFER - /* Send to the logbuffer */ - logbuff_log(printbuffer); -#else /* Send to the stdout file */ puts(printbuffer); -#endif return 0; } diff --git a/post/tests.c b/post/tests.c index bc8e3980515..473c0ea1e1d 100644 --- a/post/tests.c +++ b/post/tests.c @@ -3,10 +3,6 @@ * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * SPDX-License-Identifier: GPL-2.0+ - * - * Be sure to mark tests to be run before relocation as such with the - * CONFIG_SYS_POST_PREREL flag so that logging is done correctly if the - * logbuffer support is enabled. */ #include <common.h> diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index c2fe81e5520..d5ae1f46855 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -1258,7 +1258,6 @@ CONFIG_LMS283GF05 CONFIG_LOADADDR CONFIG_LOADCMD CONFIG_LOADS_ECHO -CONFIG_LOGBUFFER CONFIG_LOWPOWER_ADDR CONFIG_LOWPOWER_FLAG CONFIG_LOW_MCFCLK diff --git a/test/Makefile b/test/Makefile index 6305afb2119..40f2244b79b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_SANDBOX) += command_ut.o obj-$(CONFIG_SANDBOX) += compression.o obj-$(CONFIG_SANDBOX) += print_ut.o obj-$(CONFIG_UT_TIME) += time_ut.o +obj-$(CONFIG_$(SPL_)LOG) += log/ diff --git a/test/log/Makefile b/test/log/Makefile new file mode 100644 index 00000000000..b0da8dee282 --- /dev/null +++ b/test/log/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (c) 2017 Google, Inc +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_LOG_TEST) += log_test.o diff --git a/test/log/log_test.c b/test/log/log_test.c new file mode 100644 index 00000000000..2c6227703fa --- /dev/null +++ b/test/log/log_test.c @@ -0,0 +1,205 @@ +/* + * Logging support test program + * + * Copyright (c) 2017 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +/* emit some sample log records in different ways, for testing */ +static int log_run(enum uclass_id cat, const char *file) +{ + int i; + + debug("debug\n"); + for (i = LOGL_FIRST; i < LOGL_COUNT; i++) { + log(cat, i, "log %d\n", i); + _log(log_uc_cat(cat), i, file, 100 + i, "func", "_log %d\n", + i); + } + + return 0; +} + +static int log_test(int testnum) +{ + int ret; + + printf("test %d\n", testnum); + switch (testnum) { + case 0: { + /* Check a category filter using the first category */ + enum log_category_t cat_list[] = { + log_uc_cat(UCLASS_MMC), log_uc_cat(UCLASS_SPI), + LOGC_NONE, LOGC_END + }; + + ret = log_add_filter("console", cat_list, LOGL_MAX, NULL); + if (ret < 0) + return ret; + log_run(UCLASS_MMC, "file"); + ret = log_remove_filter("console", ret); + if (ret < 0) + return ret; + break; + } + case 1: { + /* Check a category filter using the second category */ + enum log_category_t cat_list[] = { + log_uc_cat(UCLASS_MMC), log_uc_cat(UCLASS_SPI), LOGC_END + }; + + ret = log_add_filter("console", cat_list, LOGL_MAX, NULL); + if (ret < 0) + return ret; + log_run(UCLASS_SPI, "file"); + ret = log_remove_filter("console", ret); + if (ret < 0) + return ret; + break; + } + case 2: { + /* Check a category filter that should block log entries */ + enum log_category_t cat_list[] = { + log_uc_cat(UCLASS_MMC), LOGC_NONE, LOGC_END + }; + + ret = log_add_filter("console", cat_list, LOGL_MAX, NULL); + if (ret < 0) + return ret; + log_run(UCLASS_SPI, "file"); + ret = log_remove_filter("console", ret); + if (ret < 0) + return ret; + break; + } + case 3: { + /* Check a passing file filter */ + ret = log_add_filter("console", NULL, LOGL_MAX, "file"); + if (ret < 0) + return ret; + log_run(UCLASS_SPI, "file"); + ret = log_remove_filter("console", ret); + if (ret < 0) + return ret; + break; + } + case 4: { + /* Check a failing file filter */ + ret = log_add_filter("console", NULL, LOGL_MAX, "file"); + if (ret < 0) + return ret; + log_run(UCLASS_SPI, "file2"); + ret = log_remove_filter("console", ret); + if (ret < 0) + return ret; + break; + } + case 5: { + /* Check a passing file filter (second in list) */ + ret = log_add_filter("console", NULL, LOGL_MAX, "file,file2"); + if (ret < 0) + return ret; + log_run(UCLASS_SPI, "file2"); + ret = log_remove_filter("console", ret); + if (ret < 0) + return ret; + break; + } + case 6: { + /* Check a passing file filter */ + ret = log_add_filter("console", NULL, LOGL_MAX, + "file,file2,log/log_test.c"); + if (ret < 0) + return ret; + log_run(UCLASS_SPI, "file2"); + ret = log_remove_filter("console", ret); + if (ret < 0) + return ret; + break; + } + case 7: { + /* Check a log level filter */ + ret = log_add_filter("console", NULL, LOGL_WARNING, NULL); + if (ret < 0) + return ret; + log_run(UCLASS_SPI, "file"); + ret = log_remove_filter("console", ret); + if (ret < 0) + return ret; + break; + } + case 8: { + /* Check two filters, one of which passes everything */ + int filt1, filt2; + + ret = log_add_filter("console", NULL, LOGL_WARNING, NULL); + if (ret < 0) + return ret; + filt1 = ret; + ret = log_add_filter("console", NULL, LOGL_MAX, NULL); + if (ret < 0) + return ret; + filt2 = ret; + log_run(UCLASS_SPI, "file"); + ret = log_remove_filter("console", filt1); + if (ret < 0) + return ret; + ret = log_remove_filter("console", filt2); + if (ret < 0) + return ret; + break; + } + case 9: { + /* Check three filters, which together pass everything */ + int filt1, filt2, filt3; + + ret = log_add_filter("console", NULL, LOGL_MAX, "file)"); + if (ret < 0) + return ret; + filt1 = ret; + ret = log_add_filter("console", NULL, LOGL_MAX, "file2"); + if (ret < 0) + return ret; + filt2 = ret; + ret = log_add_filter("console", NULL, LOGL_MAX, + "log/log_test.c"); + if (ret < 0) + return ret; + filt3 = ret; + log_run(UCLASS_SPI, "file2"); + ret = log_remove_filter("console", filt1); + if (ret < 0) + return ret; + ret = log_remove_filter("console", filt2); + if (ret < 0) + return ret; + ret = log_remove_filter("console", filt3); + if (ret < 0) + return ret; + break; + } + } + + return 0; +} + +#ifdef CONFIG_LOG_TEST +int do_log_test(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int testnum = 0; + int ret; + + if (argc > 1) + testnum = simple_strtoul(argv[1], NULL, 10); + + ret = log_test(testnum); + if (ret) + printf("Test failure (err=%d)\n", ret); + + return ret ? CMD_RET_FAILURE : 0; +} +#endif diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py index 5d7f5dbfb23..906ef2feaaa 100644 --- a/test/py/tests/test_efi_loader.py +++ b/test/py/tests/test_efi_loader.py @@ -12,7 +12,7 @@ import u_boot_utils """ Note: This test relies on boardenv_* containing configuration values to define -which the network environment available for testing. Without this, the parts +which network environment is available for testing. Without this, the parts that rely on network will be automatically skipped. For example: @@ -154,6 +154,8 @@ def test_efi_helloworld_net(u_boot_console): output = u_boot_console.run_command('bootefi %x' % addr) expected_text = 'Hello, world' assert expected_text in output + expected_text = '## Application terminated, r = 0' + assert expected_text in output @pytest.mark.buildconfigspec('cmd_bootefi_hello') def test_efi_helloworld_builtin(u_boot_console): diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py index 76e282a6c72..66b799bed66 100644 --- a/test/py/tests/test_efi_selftest.py +++ b/test/py/tests/test_efi_selftest.py @@ -1,4 +1,3 @@ -# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. # Copyright (c) 2017, Heinrich Schuchardt <xypron.glpk@gmx.de> # # SPDX-License-Identifier: GPL-2.0 @@ -14,6 +13,7 @@ def test_efi_selftest(u_boot_console): Run bootefi selftest """ + u_boot_console.run_command(cmd='setenv efi_selftest') u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False) m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key']) if m != 0: @@ -23,3 +23,15 @@ def test_efi_selftest(u_boot_console): if m != 0: raise Exception('Reset failed during the EFI selftest') u_boot_console.restart_uboot(); + +@pytest.mark.buildconfigspec('cmd_bootefi_selftest') +def test_efi_selftest_watchdog_reboot(u_boot_console): + u_boot_console.run_command(cmd='setenv efi_selftest list') + output = u_boot_console.run_command('bootefi selftest') + assert '\'watchdog reboot\'' in output + u_boot_console.run_command(cmd='setenv efi_selftest watchdog reboot') + u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False) + m = u_boot_console.p.expect(['resetting', 'U-Boot']) + if m != 0: + raise Exception('Reset failed in \'watchdog reboot\' test') + u_boot_console.restart_uboot(); diff --git a/test/py/tests/test_log.py b/test/py/tests/test_log.py new file mode 100644 index 00000000000..fa9a25e8dc0 --- /dev/null +++ b/test/py/tests/test_log.py @@ -0,0 +1,101 @@ +# Copyright (c) 2016, Google Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# +# U-Boot Verified Boot Test + +""" +This tests U-Boot logging. It uses the 'log test' command with various options +and checks that the output is correct. +""" + +import pytest + +LOGL_FIRST, LOGL_WARNING, LOGL_INFO = (0, 4, 6) + +@pytest.mark.buildconfigspec('log') +def test_log(u_boot_console): + """Test that U-Boot logging works correctly.""" + def check_log_entries(lines, mask, max_level=LOGL_INFO): + """Check that the expected log records appear in the output + + Args: + lines: iterator containing lines to check + mask: bit mask to select which lines to check for: + bit 0: standard log line + bit 1: _log line + max_level: maximum log level to expect in the output + """ + for i in range(max_level): + if mask & 1: + assert 'log %d' % i == lines.next() + if mask & 3: + assert '_log %d' % i == lines.next() + + def run_test(testnum): + """Run a particular test number (the 'log test' command) + + Args: + testnum: Test number to run + Returns: + iterator containing the lines output from the command + """ + + with cons.log.section('basic'): + output = u_boot_console.run_command('log test %d' % testnum) + split = output.replace('\r', '').splitlines() + lines = iter(split) + assert 'test %d' % testnum == lines.next() + return lines + + def test0(): + lines = run_test(0) + check_log_entries(lines, 3) + + def test1(): + lines = run_test(1) + check_log_entries(lines, 3) + + def test2(): + lines = run_test(2) + + def test3(): + lines = run_test(3) + check_log_entries(lines, 2) + + def test4(): + lines = run_test(4) + assert next(lines, None) == None + + def test5(): + lines = run_test(5) + check_log_entries(lines, 2) + + def test6(): + lines = run_test(6) + check_log_entries(lines, 3) + + def test7(): + lines = run_test(7) + check_log_entries(lines, 3, LOGL_WARNING) + + def test8(): + lines = run_test(8) + check_log_entries(lines, 3) + + def test9(): + lines = run_test(9) + check_log_entries(lines, 3) + + # TODO(sjg@chromium.org): Consider structuring this as separate tests + cons = u_boot_console + test0() + test1() + test2() + test3() + test4() + test5() + test6() + test7() + test8() + test9() diff --git a/tools/omapimage.c b/tools/omapimage.c index e31b94ae4f7..e7c46388f4f 100644 --- a/tools/omapimage.c +++ b/tools/omapimage.c @@ -20,6 +20,8 @@ #include "gpheader.h" #include "omapimage.h" +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + /* Header size is CH header rounded up to 512 bytes plus GP header */ #define OMAP_CH_HDR_SIZE 512 #define OMAP_FILE_HDR_SIZE (OMAP_CH_HDR_SIZE + GPIMAGE_HDR_SIZE) @@ -150,8 +152,10 @@ static void omapimage_set_header(void *ptr, struct stat *sbuf, int ifd, do_swap32 = 1; int swapped = 0; uint32_t *data = (uint32_t *)ptr; + const off_t size_in_words = + DIV_ROUND_UP(sbuf->st_size, sizeof(uint32_t)); - while (swapped <= (sbuf->st_size / sizeof(uint32_t))) { + while (swapped < size_in_words) { *data = cpu_to_be32(*data); swapped++; data++; |