diff options
45 files changed, 1618 insertions, 1094 deletions
@@ -1209,7 +1209,23 @@ The following options need to be configured: If this option is set, the driver enables cache flush. - TPM Support: - CONFIG_GENERIC_LPC_TPM + CONFIG_TPM + Support TPM devices. + + CONFIG_TPM_TIS_I2C + Support for i2c bus TPM devices. Only one device + per system is supported at this time. + + CONFIG_TPM_TIS_I2C_BUS_NUMBER + Define the the i2c bus number for the TPM device + + CONFIG_TPM_TIS_I2C_SLAVE_ADDRESS + Define the TPM's address on the i2c bus + + CONFIG_TPM_TIS_I2C_BURST_LIMITATION + Define the burst count bytes upper limit + + CONFIG_TPM_TIS_LPC Support for generic parallel port TPM devices. Only one device per system is supported at this time. diff --git a/arch/arm/cpu/armv7/omap-common/boot-common.c b/arch/arm/cpu/armv7/omap-common/boot-common.c index bff7e9c..76ae1b6 100644 --- a/arch/arm/cpu/armv7/omap-common/boot-common.c +++ b/arch/arm/cpu/armv7/omap-common/boot-common.c @@ -25,6 +25,45 @@ DECLARE_GLOBAL_DATA_PTR; +void save_omap_boot_params(void) +{ + u32 rom_params = *((u32 *)OMAP_SRAM_SCRATCH_BOOT_PARAMS); + u8 boot_device; + u32 dev_desc, dev_data; + + if ((rom_params < NON_SECURE_SRAM_START) || + (rom_params > NON_SECURE_SRAM_END)) + return; + + /* + * rom_params can be type casted to omap_boot_parameters and + * used. But it not correct to assume that romcode structure + * encoding would be same as u-boot. So use the defined offsets. + */ + gd->arch.omap_boot_params.omap_bootdevice = boot_device = + *((u8 *)(rom_params + BOOT_DEVICE_OFFSET)); + + gd->arch.omap_boot_params.ch_flags = + *((u8 *)(rom_params + CH_FLAGS_OFFSET)); + + if ((boot_device >= MMC_BOOT_DEVICES_START) && + (boot_device <= MMC_BOOT_DEVICES_END)) { +#if !defined(CONFIG_AM33XX) && !defined(CONFIG_TI81XX) + if ((omap_hw_init_context() == + OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL)) { + gd->arch.omap_boot_params.omap_bootmode = + *((u8 *)(rom_params + BOOT_MODE_OFFSET)); + } else +#endif + { + dev_desc = *((u32 *)(rom_params + DEV_DESC_PTR_OFFSET)); + dev_data = *((u32 *)(dev_desc + DEV_DATA_PTR_OFFSET)); + gd->arch.omap_boot_params.omap_bootmode = + *((u32 *)(dev_data + BOOT_MODE_OFFSET)); + } + } +} + #ifdef CONFIG_SPL_BUILD u32 spl_boot_device(void) { diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c index 1645120..0776d5c 100644 --- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c +++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c @@ -84,7 +84,7 @@ u32 cortex_rev(void) return rev; } -void omap_rev_string(void) +static void omap_rev_string(void) { u32 omap_rev = omap_revision(); u32 soc_variant = (omap_rev & 0xF0000000) >> 28; @@ -111,42 +111,6 @@ void __weak srcomp_enable(void) { } -static void save_omap_boot_params(void) -{ - u32 rom_params = *((u32 *)OMAP_SRAM_SCRATCH_BOOT_PARAMS); - u8 boot_device; - u32 dev_desc, dev_data; - - if ((rom_params < NON_SECURE_SRAM_START) || - (rom_params > NON_SECURE_SRAM_END)) - return; - - /* - * rom_params can be type casted to omap_boot_parameters and - * used. But it not correct to assume that romcode structure - * encoding would be same as u-boot. So use the defined offsets. - */ - gd->arch.omap_boot_params.omap_bootdevice = boot_device = - *((u8 *)(rom_params + BOOT_DEVICE_OFFSET)); - - gd->arch.omap_boot_params.ch_flags = - *((u8 *)(rom_params + CH_FLAGS_OFFSET)); - - if ((boot_device >= MMC_BOOT_DEVICES_START) && - (boot_device <= MMC_BOOT_DEVICES_END)) { - if ((omap_hw_init_context() == - OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL)) { - gd->arch.omap_boot_params.omap_bootmode = - *((u8 *)(rom_params + BOOT_MODE_OFFSET)); - } else { - dev_desc = *((u32 *)(rom_params + DEV_DESC_PTR_OFFSET)); - dev_data = *((u32 *)(dev_desc + DEV_DATA_PTR_OFFSET)); - gd->arch.omap_boot_params.omap_bootmode = - *((u32 *)(dev_data + BOOT_MODE_OFFSET)); - } - } -} - #ifdef CONFIG_ARCH_CPU_INIT /* * SOC specific cpu init diff --git a/arch/arm/include/asm/arch-am33xx/omap.h b/arch/arm/include/asm/arch-am33xx/omap.h index 7e3bb9c..e7576c1 100644 --- a/arch/arm/include/asm/arch-am33xx/omap.h +++ b/arch/arm/include/asm/arch-am33xx/omap.h @@ -29,10 +29,12 @@ * at 0x40304000(EMU base) so that our code works for both EMU and GP */ #ifdef CONFIG_AM33XX -#define NON_SECURE_SRAM_START 0x40304000 -#define NON_SECURE_SRAM_END 0x4030E000 +#define NON_SECURE_SRAM_START 0x402F0400 +#define NON_SECURE_SRAM_END 0x40310000 +#define SRAM_SCRATCH_SPACE_ADDR 0x4030C000 #elif defined(CONFIG_TI814X) #define NON_SECURE_SRAM_START 0x40300000 #define NON_SECURE_SRAM_END 0x40320000 +#define SRAM_SCRATCH_SPACE_ADDR 0x4031B800 #endif #endif diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h index c913b5f..fedc674 100644 --- a/arch/arm/include/asm/arch-am33xx/sys_proto.h +++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h @@ -30,6 +30,7 @@ int print_cpuinfo(void); extern struct ctrl_stat *cstat; u32 get_device_type(void); +void save_omap_boot_params(void); void setup_clocks_for_console(void); void ddr_pll_config(unsigned int ddrpll_M); diff --git a/arch/arm/include/asm/arch-omap4/omap.h b/arch/arm/include/asm/arch-omap4/omap.h index e9a6ffe..44353a4 100644 --- a/arch/arm/include/asm/arch-omap4/omap.h +++ b/arch/arm/include/asm/arch-omap4/omap.h @@ -141,6 +141,7 @@ struct s32ktimer { */ #define NON_SECURE_SRAM_START 0x40304000 #define NON_SECURE_SRAM_END 0x4030E000 /* Not inclusive */ +#define SRAM_SCRATCH_SPACE_ADDR NON_SECURE_SRAM_START /* base address for indirect vectors (internal boot mode) */ #define SRAM_ROM_VECT_BASE 0x4030D000 #endif diff --git a/arch/arm/include/asm/arch-omap4/sys_proto.h b/arch/arm/include/asm/arch-omap4/sys_proto.h index 039a1f2..ef85594 100644 --- a/arch/arm/include/asm/arch-omap4/sys_proto.h +++ b/arch/arm/include/asm/arch-omap4/sys_proto.h @@ -54,6 +54,7 @@ void cancel_out(u32 *num, u32 *den, u32 den_limit); void sdram_init(void); u32 omap_sdram_size(void); u32 cortex_rev(void); +void save_omap_boot_params(void); void init_omap_revision(void); void do_io_settings(void); void omap_vc_init(u16 speed_khz); diff --git a/arch/arm/include/asm/arch-omap5/omap.h b/arch/arm/include/asm/arch-omap5/omap.h index 4f43a90..04af227 100644 --- a/arch/arm/include/asm/arch-omap5/omap.h +++ b/arch/arm/include/asm/arch-omap5/omap.h @@ -188,6 +188,7 @@ struct s32ktimer { */ #define NON_SECURE_SRAM_START 0x40300000 #define NON_SECURE_SRAM_END 0x40320000 /* Not inclusive */ +#define SRAM_SCRATCH_SPACE_ADDR NON_SECURE_SRAM_START /* base address for indirect vectors (internal boot mode) */ #define SRAM_ROM_VECT_BASE 0x4031F000 diff --git a/arch/arm/include/asm/arch-omap5/sys_proto.h b/arch/arm/include/asm/arch-omap5/sys_proto.h index b79161d..4d99db9 100644 --- a/arch/arm/include/asm/arch-omap5/sys_proto.h +++ b/arch/arm/include/asm/arch-omap5/sys_proto.h @@ -58,6 +58,7 @@ void cancel_out(u32 *num, u32 *den, u32 den_limit); void sdram_init(void); u32 omap_sdram_size(void); u32 cortex_rev(void); +void save_omap_boot_params(void); void init_omap_revision(void); void do_io_settings(void); void omap_vc_init(u16 speed_khz); diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h index ee7b188..baeef4e 100644 --- a/arch/arm/include/asm/omap_common.h +++ b/arch/arm/include/asm/omap_common.h @@ -591,7 +591,6 @@ static inline u32 omap_revision(void) /* * SRAM scratch space entries */ -#define SRAM_SCRATCH_SPACE_ADDR NON_SECURE_SRAM_START #define OMAP_SRAM_SCRATCH_OMAP_REV SRAM_SCRATCH_SPACE_ADDR #define OMAP_SRAM_SCRATCH_EMIF_SIZE (SRAM_SCRATCH_SPACE_ADDR + 0x4) #define OMAP_SRAM_SCRATCH_EMIF_T_NUM (SRAM_SCRATCH_SPACE_ADDR + 0xC) diff --git a/board/isee/igep0033/board.c b/board/isee/igep0033/board.c index d315516..826cead 100644 --- a/board/isee/igep0033/board.c +++ b/board/isee/igep0033/board.c @@ -105,6 +105,15 @@ static struct emif_regs ddr3_emif_reg_data = { */ void s_init(void) { + /* + * Save the boot parameters passed from romcode. + * We cannot delay the saving further than this, + * to prevent overwrites. + */ +#ifdef CONFIG_SPL_BUILD + save_omap_boot_params(); +#endif + /* WDT1 is already running when the bootloader gets control * Disable it to avoid "random" resets */ diff --git a/board/phytec/pcm051/board.c b/board/phytec/pcm051/board.c index 43d7b6e..93c611d 100644 --- a/board/phytec/pcm051/board.c +++ b/board/phytec/pcm051/board.c @@ -115,6 +115,15 @@ static struct emif_regs ddr3_emif_reg_data = { void s_init(void) { /* + * Save the boot parameters passed from romcode. + * We cannot delay the saving further than this, + * to prevent overwrites. + */ +#ifdef CONFIG_SPL_BUILD + save_omap_boot_params(); +#endif + + /* * WDT1 is already running when the bootloader gets control * Disable it to avoid "random" resets */ diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index b371376..ebddf0c 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -304,6 +304,15 @@ static struct emif_regs ddr3_evm_emif_reg_data = { */ void s_init(void) { + /* + * Save the boot parameters passed from romcode. + * We cannot delay the saving further than this, + * to prevent overwrites. + */ +#ifdef CONFIG_SPL_BUILD + save_omap_boot_params(); +#endif + /* WDT1 is already running when the bootloader gets control * Disable it to avoid "random" resets */ diff --git a/board/ti/ti814x/evm.c b/board/ti/ti814x/evm.c index 7adb524..4759b16 100644 --- a/board/ti/ti814x/evm.c +++ b/board/ti/ti814x/evm.c @@ -149,6 +149,15 @@ static const struct ddr_data evm_ddr2_data = { void s_init(void) { #ifdef CONFIG_SPL_BUILD + /* + * Save the boot parameters passed from romcode. + * We cannot delay the saving further than this, + * to prevent overwrites. + */ +#ifdef CONFIG_SPL_BUILD + save_omap_boot_params(); +#endif + /* WDT1 is already running when the bootloader gets control * Disable it to avoid "random" resets */ diff --git a/common/board_f.c b/common/board_f.c index 81edbdf..9fa7363 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -851,12 +851,6 @@ static init_fnc_t init_sequence_f[] = { #ifdef CONFIG_ARM timer_init, /* initialize timer */ #endif -#ifdef CONFIG_BOARD_POSTCLK_INIT - board_postclk_init, -#endif -#ifdef CONFIG_FSL_ESDHC - get_clocks, -#endif #ifdef CONFIG_SYS_ALLOC_DPRAM #if !defined(CONFIG_CPM2) dpram_init, @@ -865,6 +859,9 @@ static init_fnc_t init_sequence_f[] = { #if defined(CONFIG_BOARD_POSTCLK_INIT) board_postclk_init, #endif +#ifdef CONFIG_FSL_ESDHC + get_clocks, +#endif env_init, /* initialize environment */ #if defined(CONFIG_8xx_CPUCLK_DEFAULT) /* get CPU and bus clocks according to the environment variable */ diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 15f4599..05130b6 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -93,11 +93,6 @@ static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); static void fixup_silent_linux(void); #endif -static image_header_t *image_get_kernel(ulong img_addr, int verify); -#if defined(CONFIG_FIT) -static int fit_check_kernel(const void *fit, int os_noffset, int verify); -#endif - static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len); @@ -306,7 +301,7 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] #if defined(CONFIG_OF_LIBFDT) /* find flattened device tree */ - ret = boot_get_fdt(flag, argc, argv, &images, + ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images, &images.ft_addr, &images.ft_len); if (ret) { puts("Could not find a valid device tree\n"); @@ -336,12 +331,15 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) ulong image_len = os.image_len; __maybe_unused uint unc_len = CONFIG_SYS_BOOTM_LEN; int no_overlap = 0; + void *load_buf, *image_buf; #if defined(CONFIG_LZMA) || defined(CONFIG_LZO) int ret; #endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */ const char *type_name = genimg_get_type_name(os.type); + load_buf = map_sysmem(load, image_len); + image_buf = map_sysmem(image_start, image_len); switch (comp) { case IH_COMP_NONE: if (load == blob_start || load == image_start) { @@ -349,8 +347,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) no_overlap = 1; } else { printf(" Loading %s ... ", type_name); - memmove_wd((void *)load, (void *)image_start, - image_len, CHUNKSZ); + memmove_wd(load_buf, image_buf, image_len, CHUNKSZ); } *load_end = load + image_len; puts("OK\n"); @@ -358,8 +355,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) #ifdef CONFIG_GZIP case IH_COMP_GZIP: printf(" Uncompressing %s ... ", type_name); - if (gunzip((void *)load, unc_len, - (uchar *)image_start, &image_len) != 0) { + if (gunzip(load_buf, unc_len, image_buf, &image_len) != 0) { puts("GUNZIP: uncompress, out-of-mem or overwrite " "error - must RESET board to recover\n"); if (boot_progress) @@ -378,9 +374,9 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) * use slower decompression algorithm which requires * at most 2300 KB of memory. */ - int i = BZ2_bzBuffToBuffDecompress((char *)load, - &unc_len, (char *)image_start, image_len, - CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); + int i = BZ2_bzBuffToBuffDecompress(load_buf, &unc_len, + image_buf, image_len, + CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { printf("BUNZIP2: uncompress or overwrite error %d " "- must RESET board to recover\n", i); @@ -397,9 +393,8 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) SizeT lzma_len = unc_len; printf(" Uncompressing %s ... ", type_name); - ret = lzmaBuffToBuffDecompress( - (unsigned char *)load, &lzma_len, - (unsigned char *)image_start, image_len); + ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len, + image_buf, image_len); unc_len = lzma_len; if (ret != SZ_OK) { printf("LZMA: uncompress or overwrite error %d " @@ -415,9 +410,8 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) case IH_COMP_LZO: printf(" Uncompressing %s ... ", type_name); - ret = lzop_decompress((const unsigned char *)image_start, - image_len, (unsigned char *)load, - &unc_len); + ret = lzop_decompress(image_buf, image_len, load_buf, + &unc_len); if (ret != LZO_E_OK) { printf("LZO: uncompress or overwrite error %d " "- must RESET board to recover\n", ret); @@ -797,54 +791,6 @@ static image_header_t *image_get_kernel(ulong img_addr, int verify) } /** - * fit_check_kernel - verify FIT format kernel subimage - * @fit_hdr: pointer to the FIT image header - * os_noffset: kernel subimage node offset within FIT image - * @verify: data CRC verification flag - * - * fit_check_kernel() verifies integrity of the kernel subimage and from - * specified FIT image. - * - * returns: - * 1, on success - * 0, on failure - */ -#if defined(CONFIG_FIT) -static int fit_check_kernel(const void *fit, int os_noffset, int verify) -{ - fit_image_print(fit, os_noffset, " "); - - if (verify) { - puts(" Verifying Hash Integrity ... "); - if (!fit_image_verify(fit, os_noffset)) { - puts("Bad Data Hash\n"); - bootstage_error(BOOTSTAGE_ID_FIT_CHECK_HASH); - return 0; - } - puts("OK\n"); - } - bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_ARCH); - - if (!fit_image_check_target_arch(fit, os_noffset)) { - puts("Unsupported Architecture\n"); - bootstage_error(BOOTSTAGE_ID_FIT_CHECK_ARCH); - return 0; - } - - bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_KERNEL); - if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL) && - !fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL_NOLOAD)) { - puts("Not a kernel image\n"); - bootstage_error(BOOTSTAGE_ID_FIT_CHECK_KERNEL); - return 0; - } - - bootstage_mark(BOOTSTAGE_ID_FIT_CHECKED); - return 1; -} -#endif /* CONFIG_FIT */ - -/** * boot_get_kernel - find kernel image * @os_data: pointer to a ulong variable, will hold os data start address * @os_len: pointer to a ulong variable, will hold os data length @@ -864,12 +810,8 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, ulong img_addr; const void *buf; #if defined(CONFIG_FIT) - const void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; - const void *data; - size_t len; - int cfg_noffset; int os_noffset; #endif @@ -946,84 +888,16 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - fit_hdr = buf; - printf("## Booting kernel from FIT Image at %08lx ...\n", - img_addr); - - if (!fit_check_format(fit_hdr)) { - puts("Bad FIT kernel image format!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_FORMAT); + os_noffset = fit_image_load(images, FIT_KERNEL_PROP, + img_addr, + &fit_uname_kernel, fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_KERNEL, + BOOTSTAGE_ID_FIT_KERNEL_START, + FIT_LOAD_IGNORED, os_data, os_len); + if (os_noffset < 0) return NULL; - } - bootstage_mark(BOOTSTAGE_ID_FIT_FORMAT); - - if (!fit_uname_kernel) { - /* - * no kernel image node unit name, try to get config - * node first. If config unit node name is NULL - * fit_conf_get_node() will try to find default config - * node - */ - bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); -#ifdef CONFIG_FIT_BEST_MATCH - if (fit_uname_config) - cfg_noffset = - fit_conf_get_node(fit_hdr, - fit_uname_config); - else - cfg_noffset = - fit_conf_find_compat(fit_hdr, - gd->fdt_blob); -#else - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); -#endif - if (cfg_noffset < 0) { - bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); - return NULL; - } - /* save configuration uname provided in the first - * bootm argument - */ - images->fit_uname_cfg = fdt_get_name(fit_hdr, - cfg_noffset, - NULL); - printf(" Using '%s' configuration\n", - images->fit_uname_cfg); - bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); - - os_noffset = fit_conf_get_kernel_node(fit_hdr, - cfg_noffset); - fit_uname_kernel = fit_get_name(fit_hdr, os_noffset, - NULL); - } else { - /* get kernel component image node offset */ - bootstage_mark(BOOTSTAGE_ID_FIT_UNIT_NAME); - os_noffset = fit_image_get_node(fit_hdr, - fit_uname_kernel); - } - if (os_noffset < 0) { - bootstage_error(BOOTSTAGE_ID_FIT_CONFIG); - return NULL; - } - - printf(" Trying '%s' kernel subimage\n", fit_uname_kernel); - - bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE); - if (!fit_check_kernel(fit_hdr, os_noffset, images->verify)) - return NULL; - - /* get kernel image data address and length */ - if (fit_image_get_data(fit_hdr, os_noffset, &data, &len)) { - puts("Could not find kernel subimage data!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR); - return NULL; - } - bootstage_mark(BOOTSTAGE_ID_FIT_KERNEL_INFO); - *os_len = len; - *os_data = (ulong)data; - images->fit_hdr_os = (void *)fit_hdr; + images->fit_hdr_os = map_sysmem(img_addr, 0); images->fit_uname_os = fit_uname_kernel; images->fit_noffset_os = os_noffset; break; @@ -1820,7 +1694,7 @@ static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc, #if defined(CONFIG_OF_LIBFDT) /* find flattened device tree */ - ret = boot_get_fdt(flag, argc, argv, images, + ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images, &images->ft_addr, &images->ft_len); if (ret) { puts("Could not find a valid device tree\n"); diff --git a/common/cmd_fitupd.c b/common/cmd_fitupd.c index 7a3789e..618ff7c 100644 --- a/common/cmd_fitupd.c +++ b/common/cmd_fitupd.c @@ -8,13 +8,12 @@ #include <common.h> #include <command.h> +#include <net.h> #if !defined(CONFIG_UPDATE_TFTP) #error "CONFIG_UPDATE_TFTP required" #endif -extern int update_tftp(ulong addr); - static int do_fitupd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong addr = 0UL; diff --git a/common/image-fdt.c b/common/image-fdt.c index 158c9cf..0d421d9 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -211,51 +211,11 @@ error: return 1; } -#if defined(CONFIG_FIT) -/** - * fit_check_fdt - verify FIT format FDT subimage - * @fit_hdr: pointer to the FIT header - * fdt_noffset: FDT subimage node offset within FIT image - * @verify: data CRC verification flag - * - * fit_check_fdt() verifies integrity of the FDT subimage and from - * specified FIT image. - * - * returns: - * 1, on success - * 0, on failure - */ -static int fit_check_fdt(const void *fit, int fdt_noffset, int verify) -{ - fit_image_print(fit, fdt_noffset, " "); - - if (verify) { - puts(" Verifying Hash Integrity ... "); - if (!fit_image_verify(fit, fdt_noffset)) { - fdt_error("Bad Data Hash"); - return 0; - } - puts("OK\n"); - } - - if (!fit_image_check_type(fit, fdt_noffset, IH_TYPE_FLATDT)) { - fdt_error("Not a FDT image"); - return 0; - } - - if (!fit_image_check_comp(fit, fdt_noffset, IH_COMP_NONE)) { - fdt_error("FDT image is compressed"); - return 0; - } - - return 1; -} -#endif - /** * boot_get_fdt - main fdt handling routine * @argc: command argument count * @argv: command argument list + * @arch: architecture (IH_ARCH_...) * @images: pointer to the bootm images structure * @of_flat_tree: pointer to a char* variable, will hold fdt start address * @of_size: pointer to a ulong variable, will hold fdt length @@ -273,24 +233,20 @@ static int fit_check_fdt(const void *fit, int fdt_noffset, int verify) * 1, if fdt image is found but corrupted * of_flat_tree and of_size are set to 0 if no fdt exists */ -int boot_get_fdt(int flag, int argc, char * const argv[], +int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, bootm_headers_t *images, char **of_flat_tree, ulong *of_size) { const image_header_t *fdt_hdr; ulong fdt_addr; char *fdt_blob = NULL; ulong image_start, image_data, image_end; - ulong load_start, load_end; + ulong load, load_end; void *buf; #if defined(CONFIG_FIT) - void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_fdt = NULL; ulong default_addr; - int cfg_noffset; int fdt_noffset; - const void *data; - size_t size; #endif *of_flat_tree = NULL; @@ -333,31 +289,15 @@ int boot_get_fdt(int flag, int argc, char * const argv[], * command argument */ fdt_addr = map_to_sysmem(images->fit_hdr_os); - fit_uname_config = images->fit_uname_cfg; - debug("* fdt: using config '%s' from image at 0x%08lx\n", - fit_uname_config, fdt_addr); - - /* - * Check whether configuration has FDT blob defined, - * if not quit silently. - */ - fit_hdr = images->fit_hdr_os; - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - if (cfg_noffset < 0) { - debug("* fdt: no such config\n"); + fdt_noffset = fit_get_node_from_config(images, + FIT_FDT_PROP, + fdt_addr); + if (fdt_noffset == -ENOLINK) return 0; - } - - fdt_noffset = fit_conf_get_fdt_node(fit_hdr, - cfg_noffset); - if (fdt_noffset < 0) { - debug("* fdt: no fdt in config\n"); - return 0; - } + else if (fdt_noffset < 0) + return 1; } #endif - debug("## Checking for 'FDT'/'FDT Image' at %08lx\n", fdt_addr); @@ -387,29 +327,28 @@ int boot_get_fdt(int flag, int argc, char * const argv[], image_data = (ulong)image_get_data(fdt_hdr); image_end = image_get_image_end(fdt_hdr); - load_start = image_get_load(fdt_hdr); - load_end = load_start + image_get_data_size(fdt_hdr); + load = image_get_load(fdt_hdr); + load_end = load + image_get_data_size(fdt_hdr); - if (load_start == image_start || - load_start == image_data) { + if (load == image_start || + load == image_data) { fdt_blob = (char *)image_data; break; } - if ((load_start < image_end) && - (load_end > image_start)) { + if ((load < image_end) && (load_end > image_start)) { fdt_error("fdt overwritten"); goto error; } debug(" Loading FDT from 0x%08lx to 0x%08lx\n", - image_data, load_start); + image_data, load); - memmove((void *)load_start, + memmove((void *)load, (void *)image_data, image_get_data_size(fdt_hdr)); - fdt_blob = (char *)load_start; + fdt_addr = load; break; case IMAGE_FORMAT_FIT: /* @@ -420,107 +359,20 @@ int boot_get_fdt(int flag, int argc, char * const argv[], #if defined(CONFIG_FIT) /* check FDT blob vs FIT blob */ if (fit_check_format(buf)) { - /* - * FIT image - */ - fit_hdr = buf; - printf("## Flattened Device Tree from FIT Image at %08lx\n", - fdt_addr); - - if (!fit_uname_fdt) { - /* - * no FDT blob image node unit name, - * try to get config node first. If - * config unit node name is NULL - * fit_conf_get_node() will try to - * find default config node - */ - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - - if (cfg_noffset < 0) { - fdt_error("Could not find configuration node\n"); - goto error; - } - - fit_uname_config = fdt_get_name(fit_hdr, - cfg_noffset, NULL); - printf(" Using '%s' configuration\n", - fit_uname_config); - - fdt_noffset = fit_conf_get_fdt_node( - fit_hdr, - cfg_noffset); - fit_uname_fdt = fit_get_name(fit_hdr, - fdt_noffset, NULL); - } else { - /* - * get FDT component image node - * offset - */ - fdt_noffset = fit_image_get_node( - fit_hdr, - fit_uname_fdt); - } - if (fdt_noffset < 0) { - fdt_error("Could not find subimage node\n"); - goto error; - } - - printf(" Trying '%s' FDT blob subimage\n", - fit_uname_fdt); - - if (!fit_check_fdt(fit_hdr, fdt_noffset, - images->verify)) - goto error; - - /* get ramdisk image data address and length */ - if (fit_image_get_data(fit_hdr, fdt_noffset, - &data, &size)) { - fdt_error("Could not find FDT subimage data"); - goto error; - } + ulong load, len; - /* - * verify that image data is a proper FDT - * blob - */ - if (fdt_check_header((char *)data) != 0) { - fdt_error("Subimage data is not a FTD"); - goto error; - } - - /* - * move image data to the load address, - * make sure we don't overwrite initial image - */ - image_start = (ulong)fit_hdr; - image_end = fit_get_end(fit_hdr); - - if (fit_image_get_load(fit_hdr, fdt_noffset, - &load_start) == 0) { - load_end = load_start + size; + fdt_noffset = fit_image_load(images, + FIT_FDT_PROP, + fdt_addr, &fit_uname_fdt, + fit_uname_config, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_OPTIONAL, &load, &len); - if ((load_start < image_end) && - (load_end > image_start)) { - fdt_error("FDT overwritten"); - goto error; - } - - printf(" Loading FDT from 0x%08lx to 0x%08lx\n", - (ulong)data, load_start); - - memmove((void *)load_start, - (void *)data, size); - - fdt_blob = (char *)load_start; - } else { - fdt_blob = (char *)data; - } - - images->fit_hdr_fdt = fit_hdr; + images->fit_hdr_fdt = map_sysmem(fdt_addr, 0); images->fit_uname_fdt = fit_uname_fdt; images->fit_noffset_fdt = fdt_noffset; + fdt_addr = load; break; } else #endif @@ -528,7 +380,6 @@ int boot_get_fdt(int flag, int argc, char * const argv[], /* * FDT blob */ - fdt_blob = buf; debug("* fdt: raw FDT blob\n"); printf("## Flattened Device Tree blob at %08lx\n", (long)fdt_addr); @@ -539,8 +390,8 @@ int boot_get_fdt(int flag, int argc, char * const argv[], goto error; } - printf(" Booting using the fdt blob at 0x%p\n", fdt_blob); - + printf(" Booting using the fdt blob at %#08lx\n", fdt_addr); + fdt_blob = map_sysmem(fdt_addr, 0); } else if (images->legacy_hdr_valid && image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { diff --git a/common/image-fit.c b/common/image-fit.c index 254feec..7bf82d3 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -31,6 +31,9 @@ #include <time.h> #else #include <common.h> +#include <errno.h> +#include <asm/io.h> +DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ #include <bootstage.h> @@ -348,10 +351,13 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) #ifndef USE_HOSTCC printf("%s Data Start: ", p); - if (ret) + if (ret) { printf("unavailable\n"); - else - printf("0x%08lx\n", (ulong)data); + } else { + void *vdata = (void *)data; + + printf("0x%08lx\n", (ulong)map_to_sysmem(vdata)); + } #endif printf("%s Data Size: ", p); @@ -1349,63 +1355,6 @@ int fit_conf_get_prop_node(const void *fit, int noffset, } /** - * fit_conf_get_kernel_node - get kernel image node offset that corresponds to - * a given configuration - * @fit: pointer to the FIT format image header - * @noffset: configuration node offset - * - * fit_conf_get_kernel_node() retrives kernel image node unit name from - * configuration FIT_KERNEL_PROP property and translates it to the node - * offset. - * - * returns: - * image node offset when found (>=0) - * negative number on failure (FDT_ERR_* code) - */ -int fit_conf_get_kernel_node(const void *fit, int noffset) -{ - return fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP); -} - -/** - * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to - * a given configuration - * @fit: pointer to the FIT format image header - * @noffset: configuration node offset - * - * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from - * configuration FIT_KERNEL_PROP property and translates it to the node - * offset. - * - * returns: - * image node offset when found (>=0) - * negative number on failure (FDT_ERR_* code) - */ -int fit_conf_get_ramdisk_node(const void *fit, int noffset) -{ - return fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP); -} - -/** - * fit_conf_get_fdt_node - get fdt image node offset that corresponds to - * a given configuration - * @fit: pointer to the FIT format image header - * @noffset: configuration node offset - * - * fit_conf_get_fdt_node() retrives fdt image node unit name from - * configuration FIT_KERNEL_PROP property and translates it to the node - * offset. - * - * returns: - * image node offset when found (>=0) - * negative number on failure (FDT_ERR_* code) - */ -int fit_conf_get_fdt_node(const void *fit, int noffset) -{ - return fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP); -} - -/** * fit_conf_print - prints out the FIT configuration details * @fit: pointer to the FIT format image header * @noffset: offset of the configuration node @@ -1448,22 +1397,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p) printf("%s FDT: %s\n", p, uname); } -/** - * fit_check_ramdisk - verify FIT format ramdisk subimage - * @fit_hdr: pointer to the FIT ramdisk header - * @rd_noffset: ramdisk subimage node offset within FIT image - * @arch: requested ramdisk image architecture type - * @verify: data CRC verification flag - * - * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from - * specified FIT image. - * - * returns: - * 1, on success - * 0, on failure - */ -int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch, - int verify) +int fit_image_select(const void *fit, int rd_noffset, int verify) { fit_image_print(fit, rd_noffset, " "); @@ -1471,22 +1405,222 @@ int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch, puts(" Verifying Hash Integrity ... "); if (!fit_image_verify(fit, rd_noffset)) { puts("Bad Data Hash\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH); - return 0; + return -EACCES; } puts("OK\n"); } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL); - if (!fit_image_check_os(fit, rd_noffset, IH_OS_LINUX) || - !fit_image_check_arch(fit, rd_noffset, arch) || - !fit_image_check_type(fit, rd_noffset, IH_TYPE_RAMDISK)) { - printf("No Linux %s Ramdisk Image\n", - genimg_get_arch_name(arch)); - bootstage_error(BOOTSTAGE_ID_FIT_RD_CHECK_ALL); - return 0; + return 0; +} + +int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, + ulong addr) +{ + int cfg_noffset; + void *fit_hdr; + int noffset; + + debug("* %s: using config '%s' from image at 0x%08lx\n", + prop_name, images->fit_uname_cfg, addr); + + /* Check whether configuration has this property defined */ + fit_hdr = map_sysmem(addr, 0); + cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg); + if (cfg_noffset < 0) { + debug("* %s: no such config\n", prop_name); + return -ENOENT; } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK); - return 1; + noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name); + if (noffset < 0) { + debug("* %s: no '%s' in config\n", prop_name, prop_name); + return -ENOLINK; + } + + return noffset; +} + +int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, + const char **fit_unamep, const char *fit_uname_config, + int arch, int image_type, int bootstage_id, + enum fit_load_op load_op, ulong *datap, ulong *lenp) +{ + int cfg_noffset, noffset; + const char *fit_uname; + const void *fit; + const void *buf; + size_t size; + int type_ok, os_ok; + ulong load, data, len; + int ret; + + fit = map_sysmem(addr, 0); + fit_uname = fit_unamep ? *fit_unamep : NULL; + printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); + if (!fit_check_format(fit)) { + printf("Bad FIT %s image format!\n", prop_name); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT); + return -ENOEXEC; + } + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); + if (fit_uname) { + /* get ramdisk component image node offset */ + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME); + noffset = fit_image_get_node(fit, fit_uname); + } else { + /* + * no image node unit name, try to get config + * node first. If config unit node name is NULL + * fit_conf_get_node() will try to find default config node + */ + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME); + if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) { + cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob()); + } else { + cfg_noffset = fit_conf_get_node(fit, + fit_uname_config); + } + if (cfg_noffset < 0) { + puts("Could not find configuration node\n"); + bootstage_error(bootstage_id + + BOOTSTAGE_SUB_NO_UNIT_NAME); + return -ENOENT; + } + fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL); + printf(" Using '%s' configuration\n", fit_uname_config); + if (image_type == IH_TYPE_KERNEL) { + /* Remember (and possibly verify) this config */ + images->fit_uname_cfg = fit_uname_config; + if (IMAGE_ENABLE_VERIFY && images->verify) { + puts(" Verifying Hash Integrity ... "); + if (!fit_config_verify(fit, cfg_noffset)) { + puts("Bad Data Hash\n"); + bootstage_error(bootstage_id + + BOOTSTAGE_SUB_HASH); + return -EACCES; + } + puts("OK\n"); + } + bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); + } + + noffset = fit_conf_get_prop_node(fit, cfg_noffset, + prop_name); + fit_uname = fit_get_name(fit, noffset, NULL); + } + if (noffset < 0) { + puts("Could not find subimage node\n"); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE); + return -ENOENT; + } + + printf(" Trying '%s' %s subimage\n", fit_uname, prop_name); + + ret = fit_image_select(fit, noffset, images->verify); + if (ret) { + bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); + return ret; + } + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); + if (!fit_image_check_target_arch(fit, noffset)) { + puts("Unsupported Architecture\n"); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); + return -ENOEXEC; + } + + if (image_type == IH_TYPE_FLATDT && + !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) { + puts("FDT image is compressed"); + return -EPROTONOSUPPORT; + } + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); + type_ok = fit_image_check_type(fit, noffset, image_type) || + (image_type == IH_TYPE_KERNEL && + fit_image_check_type(fit, noffset, + IH_TYPE_KERNEL_NOLOAD)); + os_ok = image_type == IH_TYPE_FLATDT || + fit_image_check_os(fit, noffset, IH_OS_LINUX); + if (!type_ok || !os_ok) { + printf("No Linux %s %s Image\n", genimg_get_arch_name(arch), + genimg_get_type_name(image_type)); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); + return -EIO; + } + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); + + /* get image data address and length */ + if (fit_image_get_data(fit, noffset, &buf, &size)) { + printf("Could not find %s subimage data!\n", prop_name); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); + return -ENOMEDIUM; + } + len = (ulong)size; + + /* verify that image data is a proper FDT blob */ + if (image_type == IH_TYPE_FLATDT && fdt_check_header((char *)buf)) { + puts("Subimage data is not a FDT"); + return -ENOEXEC; + } + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK); + + /* + * Work-around for eldk-4.2 which gives this warning if we try to + * case in the unmap_sysmem() call: + * warning: initialization discards qualifiers from pointer target type + */ + { + void *vbuf = (void *)buf; + + data = map_to_sysmem(vbuf); + } + + if (load_op == FIT_LOAD_IGNORED) { + /* Don't load */ + } else if (fit_image_get_load(fit, noffset, &load)) { + if (load_op == FIT_LOAD_REQUIRED) { + printf("Can't get %s subimage load address!\n", + prop_name); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD); + return -EBADF; + } + } else { + ulong image_start, image_end; + ulong load_end; + void *dst; + + /* + * move image data to the load address, + * make sure we don't overwrite initial image + */ + image_start = addr; + image_end = addr + fit_get_size(fit); + + load_end = load + len; + if (image_type != IH_TYPE_KERNEL && + load < image_end && load_end > image_start) { + printf("Error: %s overwritten\n", prop_name); + return -EXDEV; + } + + printf(" Loading %s from 0x%08lx to 0x%08lx\n", + prop_name, data, load); + + dst = map_sysmem(load, len); + memmove(dst, buf, len); + data = load; + } + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD); + + *datap = data; + *lenp = len; + if (fit_unamep) + *fit_unamep = (char *)fit_uname; + + return noffset; } diff --git a/common/image.c b/common/image.c index e91c89e..f863502 100644 --- a/common/image.c +++ b/common/image.c @@ -51,6 +51,7 @@ #include <u-boot/md5.h> #include <sha1.h> +#include <asm/errno.h> #include <asm/io.h> #ifdef CONFIG_CMD_BDI @@ -810,14 +811,10 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, char *end; #endif #if defined(CONFIG_FIT) - void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_ramdisk = NULL; ulong default_addr; int rd_noffset; - int cfg_noffset; - const void *data; - size_t size; #endif *rd_start = 0; @@ -865,32 +862,16 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, #if defined(CONFIG_FIT) } else { /* use FIT configuration provided in first bootm - * command argument + * command argument. If the property is not defined, + * quit silently. */ rd_addr = map_to_sysmem(images->fit_hdr_os); - fit_uname_config = images->fit_uname_cfg; - debug("* ramdisk: using config '%s' from image " - "at 0x%08lx\n", - fit_uname_config, rd_addr); - - /* - * Check whether configuration has ramdisk defined, - * if not, don't try to use it, quit silently. - */ - fit_hdr = images->fit_hdr_os; - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - if (cfg_noffset < 0) { - debug("* ramdisk: no such config\n"); - return 1; - } - - rd_noffset = fit_conf_get_ramdisk_node(fit_hdr, - cfg_noffset); - if (rd_noffset < 0) { - debug("* ramdisk: no ramdisk in config\n"); + rd_noffset = fit_get_node_from_config(images, + FIT_RAMDISK_PROP, rd_addr); + if (rd_noffset == -ENOLINK) return 0; - } + else if (rd_noffset < 0) + return 1; } #endif @@ -921,87 +902,16 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - fit_hdr = buf; - printf("## Loading init Ramdisk from FIT " - "Image at %08lx ...\n", rd_addr); - - bootstage_mark(BOOTSTAGE_ID_FIT_RD_FORMAT); - if (!fit_check_format(fit_hdr)) { - puts("Bad FIT ramdisk image format!\n"); - bootstage_error( - BOOTSTAGE_ID_FIT_RD_FORMAT); + rd_noffset = fit_image_load(images, FIT_RAMDISK_PROP, + rd_addr, &fit_uname_ramdisk, + fit_uname_config, arch, + IH_TYPE_RAMDISK, + BOOTSTAGE_ID_FIT_RD_START, + FIT_LOAD_REQUIRED, &rd_data, &rd_len); + if (rd_noffset < 0) return 1; - } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_FORMAT_OK); - - if (!fit_uname_ramdisk) { - /* - * no ramdisk image node unit name, try to get config - * node first. If config unit node name is NULL - * fit_conf_get_node() will try to find default config node - */ - bootstage_mark( - BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME); - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - if (cfg_noffset < 0) { - puts("Could not find configuration " - "node\n"); - bootstage_error( - BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME); - return 1; - } - fit_uname_config = fdt_get_name(fit_hdr, - cfg_noffset, NULL); - printf(" Using '%s' configuration\n", - fit_uname_config); - - rd_noffset = fit_conf_get_ramdisk_node(fit_hdr, - cfg_noffset); - fit_uname_ramdisk = fit_get_name(fit_hdr, - rd_noffset, NULL); - } else { - /* get ramdisk component image node offset */ - bootstage_mark( - BOOTSTAGE_ID_FIT_RD_UNIT_NAME); - rd_noffset = fit_image_get_node(fit_hdr, - fit_uname_ramdisk); - } - if (rd_noffset < 0) { - puts("Could not find subimage node\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_SUBNODE); - return 1; - } - - printf(" Trying '%s' ramdisk subimage\n", - fit_uname_ramdisk); - - bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK); - if (!fit_check_ramdisk(fit_hdr, rd_noffset, arch, - images->verify)) - return 1; - - /* get ramdisk image data address and length */ - if (fit_image_get_data(fit_hdr, rd_noffset, &data, - &size)) { - puts("Could not find ramdisk subimage data!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_GET_DATA); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_GET_DATA_OK); - - rd_data = (ulong)data; - rd_len = size; - - if (fit_image_get_load(fit_hdr, rd_noffset, &rd_load)) { - puts("Can't get ramdisk subimage load " - "address!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_LOAD); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_LOAD); - images->fit_hdr_rd = fit_hdr; + images->fit_hdr_rd = map_sysmem(rd_addr, 0); images->fit_uname_rd = fit_uname_ramdisk; images->fit_noffset_rd = rd_noffset; break; diff --git a/common/main.c b/common/main.c index 953ef29..56da214 100644 --- a/common/main.c +++ b/common/main.c @@ -28,26 +28,15 @@ /* #define DEBUG */ #include <common.h> -#include <watchdog.h> #include <command.h> #include <fdtdec.h> -#include <malloc.h> -#include <version.h> -#ifdef CONFIG_MODEM_SUPPORT -#include <malloc.h> /* for free() prototype */ -#endif - -#ifdef CONFIG_SYS_HUSH_PARSER #include <hush.h> -#endif - -#ifdef CONFIG_OF_CONTROL -#include <fdtdec.h> -#endif - +#include <malloc.h> +#include <menu.h> #include <post.h> +#include <version.h> +#include <watchdog.h> #include <linux/ctype.h> -#include <menu.h> DECLARE_GLOBAL_DATA_PTR; @@ -57,13 +46,18 @@ DECLARE_GLOBAL_DATA_PTR; void inline __show_boot_progress (int val) {} void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress"))); -#if defined(CONFIG_UPDATE_TFTP) -int update_tftp (ulong addr); -#endif /* CONFIG_UPDATE_TFTP */ - #define MAX_DELAY_STOP_STR 32 -#undef DEBUG_PARSER +#define DEBUG_PARSER 0 /* set to 1 to debug */ + +#define debug_parser(fmt, args...) \ + debug_cond(DEBUG_PARSER, fmt, ##args) + +#ifndef DEBUG_BOOTKEYS +#define DEBUG_BOOTKEYS 0 +#endif +#define debug_bootkeys(fmt, args...) \ + debug_cond(DEBUG_BOOTKEYS, fmt, ##args) char console_buffer[CONFIG_SYS_CBSIZE + 1]; /* console I/O buffer */ @@ -93,10 +87,7 @@ extern void mdm_init(void); /* defined in board.c */ */ #if defined(CONFIG_BOOTDELAY) # if defined(CONFIG_AUTOBOOT_KEYED) -#ifndef CONFIG_MENU -static inline -#endif -int abortboot(int bootdelay) +static int abortboot_keyed(int bootdelay) { int abort = 0; uint64_t etime = endtick(bootdelay); @@ -152,11 +143,9 @@ int abortboot(int bootdelay) presskey_max = presskey_max > delaykey[i].len ? presskey_max : delaykey[i].len; -# if DEBUG_BOOTKEYS - printf("%s key:<%s>\n", - delaykey[i].retry ? "delay" : "stop", - delaykey[i].str ? delaykey[i].str : "NULL"); -# endif + debug_bootkeys("%s key:<%s>\n", + delaykey[i].retry ? "delay" : "stop", + delaykey[i].str ? delaykey[i].str : "NULL"); } /* In order to keep up with incoming data, check timeout only @@ -181,10 +170,9 @@ int abortboot(int bootdelay) memcmp (presskey + presskey_len - delaykey[i].len, delaykey[i].str, delaykey[i].len) == 0) { -# if DEBUG_BOOTKEYS - printf("got %skey\n", - delaykey[i].retry ? "delay" : "stop"); -# endif + debug_bootkeys("got %skey\n", + delaykey[i].retry ? "delay" : + "stop"); # ifdef CONFIG_BOOT_RETRY_TIME /* don't retry auto boot */ @@ -196,10 +184,8 @@ int abortboot(int bootdelay) } } while (!abort && get_ticks() <= etime); -# if DEBUG_BOOTKEYS if (!abort) - puts("key timeout\n"); -# endif + debug_bootkeys("key timeout\n"); #ifdef CONFIG_SILENT_CONSOLE if (abort) @@ -215,10 +201,7 @@ int abortboot(int bootdelay) static int menukey = 0; #endif -#ifndef CONFIG_MENU -static inline -#endif -int abortboot(int bootdelay) +static int abortboot_normal(int bootdelay) { int abort = 0; unsigned long ts; @@ -275,6 +258,15 @@ int abortboot(int bootdelay) return abort; } # endif /* CONFIG_AUTOBOOT_KEYED */ + +static int abortboot(int bootdelay) +{ +#ifdef CONFIG_AUTOBOOT_KEYED + return abortboot_keyed(bootdelay); +#else + return abortboot_normal(bootdelay); +#endif +} #endif /* CONFIG_BOOTDELAY */ /* @@ -342,93 +334,35 @@ static void process_fdt_options(const void *blob) } #endif /* CONFIG_OF_CONTROL */ - -/****************************************************************************/ - -void main_loop (void) +#ifdef CONFIG_BOOTDELAY +static void process_boot_delay(void) { -#ifndef CONFIG_SYS_HUSH_PARSER - static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, }; - int len; - int rc = 1; - int flag; -#endif -#if defined(CONFIG_BOOTDELAY) && defined(CONFIG_OF_CONTROL) +#ifdef CONFIG_OF_CONTROL char *env; #endif -#if defined(CONFIG_BOOTDELAY) char *s; int bootdelay; -#endif -#ifdef CONFIG_PREBOOT - char *p; -#endif #ifdef CONFIG_BOOTCOUNT_LIMIT unsigned long bootcount = 0; unsigned long bootlimit = 0; - char *bcs; - char bcs_set[16]; #endif /* CONFIG_BOOTCOUNT_LIMIT */ - bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); - #ifdef CONFIG_BOOTCOUNT_LIMIT bootcount = bootcount_load(); bootcount++; bootcount_store (bootcount); - sprintf (bcs_set, "%lu", bootcount); - setenv ("bootcount", bcs_set); - bcs = getenv ("bootlimit"); - bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0; + setenv_ulong("bootcount", bootcount); + bootlimit = getenv_ulong("bootlimit", 10, 0); #endif /* CONFIG_BOOTCOUNT_LIMIT */ -#ifdef CONFIG_MODEM_SUPPORT - debug ("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init); - if (do_mdm_init) { - char *str = strdup(getenv("mdm_cmd")); - setenv ("preboot", str); /* set or delete definition */ - if (str != NULL) - free (str); - mdm_init(); /* wait for modem connection */ - } -#endif /* CONFIG_MODEM_SUPPORT */ - -#ifdef CONFIG_VERSION_VARIABLE - { - setenv ("ver", version_string); /* set version variable */ - } -#endif /* CONFIG_VERSION_VARIABLE */ - -#ifdef CONFIG_SYS_HUSH_PARSER - u_boot_hush_start (); -#endif - -#if defined(CONFIG_HUSH_INIT_VAR) - hush_init_var (); -#endif - -#ifdef CONFIG_PREBOOT - if ((p = getenv ("preboot")) != NULL) { -# ifdef CONFIG_AUTOBOOT_KEYED - int prev = disable_ctrlc(1); /* disable Control C checking */ -# endif - - run_command_list(p, -1, 0); - -# ifdef CONFIG_AUTOBOOT_KEYED - disable_ctrlc(prev); /* restore Control C checking */ -# endif - } -#endif /* CONFIG_PREBOOT */ - -#if defined(CONFIG_UPDATE_TFTP) - update_tftp (0UL); -#endif /* CONFIG_UPDATE_TFTP */ - -#if defined(CONFIG_BOOTDELAY) s = getenv ("bootdelay"); bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; +#ifdef CONFIG_OF_CONTROL + bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay", + bootdelay); +#endif + debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay); #if defined(CONFIG_MENU_SHOW) @@ -474,26 +408,88 @@ void main_loop (void) debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); if (bootdelay != -1 && s && !abortboot(bootdelay)) { -# ifdef CONFIG_AUTOBOOT_KEYED +#ifdef CONFIG_AUTOBOOT_KEYED int prev = disable_ctrlc(1); /* disable Control C checking */ -# endif +#endif run_command_list(s, -1, 0); -# ifdef CONFIG_AUTOBOOT_KEYED +#ifdef CONFIG_AUTOBOOT_KEYED disable_ctrlc(prev); /* restore Control C checking */ -# endif +#endif } -# ifdef CONFIG_MENUKEY +#ifdef CONFIG_MENUKEY if (menukey == CONFIG_MENUKEY) { s = getenv("menucmd"); if (s) run_command_list(s, -1, 0); } #endif /* CONFIG_MENUKEY */ +} #endif /* CONFIG_BOOTDELAY */ +void main_loop(void) +{ +#ifndef CONFIG_SYS_HUSH_PARSER + static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, }; + int len; + int rc = 1; + int flag; +#endif +#ifdef CONFIG_PREBOOT + char *p; +#endif + + bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); + +#ifdef CONFIG_MODEM_SUPPORT + debug("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init); + if (do_mdm_init) { + char *str = strdup(getenv("mdm_cmd")); + setenv("preboot", str); /* set or delete definition */ + if (str != NULL) + free(str); + mdm_init(); /* wait for modem connection */ + } +#endif /* CONFIG_MODEM_SUPPORT */ + +#ifdef CONFIG_VERSION_VARIABLE + { + setenv("ver", version_string); /* set version variable */ + } +#endif /* CONFIG_VERSION_VARIABLE */ + +#ifdef CONFIG_SYS_HUSH_PARSER + u_boot_hush_start(); +#endif + +#if defined(CONFIG_HUSH_INIT_VAR) + hush_init_var(); +#endif + +#ifdef CONFIG_PREBOOT + p = getenv("preboot"); + if (p != NULL) { +# ifdef CONFIG_AUTOBOOT_KEYED + int prev = disable_ctrlc(1); /* disable Control C checking */ +# endif + + run_command_list(p, -1, 0); + +# ifdef CONFIG_AUTOBOOT_KEYED + disable_ctrlc(prev); /* restore Control C checking */ +# endif + } +#endif /* CONFIG_PREBOOT */ + +#if defined(CONFIG_UPDATE_TFTP) + update_tftp(0UL); +#endif /* CONFIG_UPDATE_TFTP */ + +#ifdef CONFIG_BOOTDELAY + process_boot_delay(); +#endif /* * Main Loop for Monitor Command Processing */ @@ -1080,20 +1076,20 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout) * Special character handling */ switch (c) { - case '\r': /* Enter */ + case '\r': /* Enter */ case '\n': *p = '\0'; puts ("\r\n"); - return (p - p_buf); + return p - p_buf; - case '\0': /* nul */ + case '\0': /* nul */ continue; - case 0x03: /* ^C - break */ + case 0x03: /* ^C - break */ p_buf[0] = '\0'; /* discard input */ - return (-1); + return -1; - case 0x15: /* ^U - erase line */ + case 0x15: /* ^U - erase line */ while (col > plen) { puts (erase_seq); --col; @@ -1102,15 +1098,15 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout) n = 0; continue; - case 0x17: /* ^W - erase word */ + case 0x17: /* ^W - erase word */ p=delete_char(p_buf, p, &col, &n, plen); while ((n > 0) && (*p != ' ')) { p=delete_char(p_buf, p, &col, &n, plen); } continue; - case 0x08: /* ^H - backspace */ - case 0x7F: /* DEL - backspace */ + case 0x08: /* ^H - backspace */ + case 0x7F: /* DEL - backspace */ p=delete_char(p_buf, p, &col, &n, plen); continue; @@ -1119,7 +1115,7 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout) * Must be a normal character then */ if (n < CONFIG_SYS_CBSIZE-2) { - if (c == '\t') { /* expand TABs */ + if (c == '\t') { /* expand TABs */ #ifdef CONFIG_AUTO_COMPLETE /* if auto completion triggered just continue */ *p = '\0'; @@ -1134,7 +1130,7 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout) char buf[2]; /* - * Echo input using puts() to force am + * Echo input using puts() to force an * LCD flush if we are using an LCD */ ++col; @@ -1192,9 +1188,7 @@ int parse_line (char *line, char *argv[]) { int nargs = 0; -#ifdef DEBUG_PARSER - printf ("parse_line: \"%s\"\n", line); -#endif + debug_parser("parse_line: \"%s\"\n", line); while (nargs < CONFIG_SYS_MAXARGS) { /* skip any white space */ @@ -1203,10 +1197,8 @@ int parse_line (char *line, char *argv[]) if (*line == '\0') { /* end of line, no more args */ argv[nargs] = NULL; -#ifdef DEBUG_PARSER - printf ("parse_line: nargs=%d\n", nargs); -#endif - return (nargs); + debug_parser("parse_line: nargs=%d\n", nargs); + return nargs; } argv[nargs++] = line; /* begin of argument string */ @@ -1217,10 +1209,8 @@ int parse_line (char *line, char *argv[]) if (*line == '\0') { /* end of line, no more args */ argv[nargs] = NULL; -#ifdef DEBUG_PARSER - printf ("parse_line: nargs=%d\n", nargs); -#endif - return (nargs); + debug_parser("parse_line: nargs=%d\n", nargs); + return nargs; } *line++ = '\0'; /* terminate current arg */ @@ -1228,9 +1218,7 @@ int parse_line (char *line, char *argv[]) printf ("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS); -#ifdef DEBUG_PARSER - printf ("parse_line: nargs=%d\n", nargs); -#endif + debug_parser("parse_line: nargs=%d\n", nargs); return (nargs); } @@ -1248,12 +1236,10 @@ static void process_macros (const char *input, char *output) /* 1 = waiting for '(' or '{' */ /* 2 = waiting for ')' or '}' */ /* 3 = waiting for ''' */ -#ifdef DEBUG_PARSER char *output_start = output; - printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen (input), - input); -#endif + debug_parser("[PROCESS_MACROS] INPUT len %zd: \"%s\"\n", strlen(input), + input); prev = '\0'; /* previous character */ @@ -1341,10 +1327,8 @@ static void process_macros (const char *input, char *output) else *(output - 1) = 0; -#ifdef DEBUG_PARSER - printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n", - strlen (output_start), output_start); -#endif + debug_parser("[PROCESS_MACROS] OUTPUT len %zd: \"%s\"\n", + strlen(output_start), output_start); } /**************************************************************************** @@ -1375,12 +1359,12 @@ static int builtin_run_command(const char *cmd, int flag) int repeatable = 1; int rc = 0; -#ifdef DEBUG_PARSER - printf ("[RUN_COMMAND] cmd[%p]=\"", cmd); - puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */ - puts ("\"\n"); -#endif - + debug_parser("[RUN_COMMAND] cmd[%p]=\"", cmd); + if (DEBUG_PARSER) { + /* use puts - string may be loooong */ + puts(cmd ? cmd : "NULL"); + puts("\"\n"); + } clear_ctrlc(); /* forget any previous Control C */ if (!cmd || !*cmd) { @@ -1398,9 +1382,7 @@ static int builtin_run_command(const char *cmd, int flag) * repeatable commands */ -#ifdef DEBUG_PARSER - printf ("[PROCESS_SEPARATORS] %s\n", cmd); -#endif + debug_parser("[PROCESS_SEPARATORS] %s\n", cmd); while (*str) { /* @@ -1429,9 +1411,7 @@ static int builtin_run_command(const char *cmd, int flag) } else str = sep; /* no more commands for next pass */ -#ifdef DEBUG_PARSER - printf ("token: \"%s\"\n", token); -#endif + debug_parser("token: \"%s\"\n", token); /* find macros in this token and replace them */ process_macros (token, finaltoken); diff --git a/disk/part_efi.c b/disk/part_efi.c index 5986589..fb5e9f0 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -372,7 +372,7 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, u32 offset = (u32)le32_to_cpu(gpt_h->first_usable_lba); ulong start; int i, k; - size_t name_len; + size_t efiname_len, dosname_len; #ifdef CONFIG_PARTITION_UUIDS char *str_uuid; #endif @@ -420,9 +420,14 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, sizeof(gpt_entry_attributes)); /* partition name */ - name_len = sizeof(gpt_e[i].partition_name) + efiname_len = sizeof(gpt_e[i].partition_name) / sizeof(efi_char16_t); - for (k = 0; k < name_len; k++) + dosname_len = sizeof(partitions[i].name); + + memset(gpt_e[i].partition_name, 0, + sizeof(gpt_e[i].partition_name)); + + for (k = 0; k < min(dosname_len, efiname_len); k++) gpt_e[i].partition_name[k] = (efi_char16_t)(partitions[i].name[k]); diff --git a/drivers/input/key_matrix.c b/drivers/input/key_matrix.c index 946a186..c900e45 100644 --- a/drivers/input/key_matrix.c +++ b/drivers/input/key_matrix.c @@ -154,54 +154,42 @@ static uchar *create_keymap(struct key_matrix *config, u32 *data, int len, return map; } -int key_matrix_decode_fdt(struct key_matrix *config, const void *blob, - int node) +int key_matrix_decode_fdt(struct key_matrix *config, const void *blob, int node) { const struct fdt_property *prop; - const char prefix[] = "linux,"; - int plen = sizeof(prefix) - 1; - int offset; - - /* Check each property name for ones that we understand */ - for (offset = fdt_first_property_offset(blob, node); - offset > 0; - offset = fdt_next_property_offset(blob, offset)) { - const char *name; - int len; - - prop = fdt_get_property_by_offset(blob, offset, NULL); - name = fdt_string(blob, fdt32_to_cpu(prop->nameoff)); - len = strlen(name); - - /* Name needs to match "1,<type>keymap" */ - debug("%s: property '%s'\n", __func__, name); - if (strncmp(name, prefix, plen) || - len < plen + 6 || - strcmp(name + len - 6, "keymap")) - continue; + int proplen; + uchar *plain_keycode; - len -= plen + 6; - if (len == 0) { - config->plain_keycode = create_keymap(config, - (u32 *)prop->data, fdt32_to_cpu(prop->len), - KEY_FN, &config->fn_pos); - } else if (0 == strncmp(name + plen, "fn-", len)) { - config->fn_keycode = create_keymap(config, - (u32 *)prop->data, fdt32_to_cpu(prop->len), - -1, NULL); - } else { - debug("%s: unrecognised property '%s'\n", __func__, - name); - } + prop = fdt_get_property(blob, node, "linux,keymap", &proplen); + /* Basic keymap is required */ + if (!prop) { + debug("%s: cannot find keycode-plain map\n", __func__); + return -1; } - debug("%s: Decoded key maps %p, %p from fdt\n", __func__, - config->plain_keycode, config->fn_keycode); - if (!config->plain_keycode) { - debug("%s: cannot find keycode-plain map\n", __func__); + plain_keycode = create_keymap(config, (u32 *)prop->data, + proplen, KEY_FN, &config->fn_pos); + config->plain_keycode = plain_keycode; + /* Conversion error -> fail */ + if (!config->plain_keycode) + return -1; + + prop = fdt_get_property(blob, node, "linux,fn-keymap", &proplen); + /* fn keymap is optional */ + if (!prop) + goto done; + + config->fn_keycode = create_keymap(config, (u32 *)prop->data, + proplen, -1, NULL); + /* Conversion error -> fail */ + if (!config->fn_keycode) { + free(plain_keycode); return -1; } +done: + debug("%s: Decoded key maps %p, %p from fdt\n", __func__, + config->plain_keycode, config->fn_keycode); return 0; } diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index e8c159c..913dd9c 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -25,9 +25,10 @@ LIB := $(obj)libtpm.o $(shell mkdir -p $(obj)slb9635_i2c) -COBJS-$(CONFIG_GENERIC_LPC_TPM) = generic_lpc_tpm.o -COBJS-$(CONFIG_INFINEON_TPM_I2C) += tis_i2c.o slb9635_i2c/tpm.o -COBJS-$(CONFIG_INFINEON_TPM_I2C) += slb9635_i2c/tpm_tis_i2c.o +# TODO: Merge tpm_tis_lpc.c with tpm.c +COBJS-$(CONFIG_TPM_TIS_I2C) += tpm.o +COBJS-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o +COBJS-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/tpm/slb9635_i2c/compatibility.h b/drivers/tpm/slb9635_i2c/compatibility.h deleted file mode 100644 index 62dc9fa..0000000 --- a/drivers/tpm/slb9635_i2c/compatibility.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011 Infineon Technologies - * - * Authors: - * Peter Huewe <huewe.external@infineon.com> - * - * Version: 2.1.1 - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef _COMPATIBILITY_H_ -#define _COMPATIBILITY_H_ - -/* all includes from U-Boot */ -#include <linux/types.h> -#include <linux/unaligned/be_byteshift.h> -#include <asm-generic/errno.h> -#include <compiler.h> -#include <common.h> - -/* extended error numbers from linux (see errno.h) */ -#define ECANCELED 125 /* Operation Canceled */ - -#define msleep(t) udelay((t)*1000) - -/* Timer frequency. Corresponds to msec timer resolution*/ -#define HZ 1000 - -#define dev_dbg(dev, format, arg...) debug(format, ##arg) -#define dev_err(dev, format, arg...) printf(format, ##arg) -#define dev_info(dev, format, arg...) debug(format, ##arg) -#define dbg_printf debug - -#endif diff --git a/drivers/tpm/tis_i2c.c b/drivers/tpm/tis_i2c.c index e818fba..22554e1 100644 --- a/drivers/tpm/tis_i2c.c +++ b/drivers/tpm/tis_i2c.c @@ -68,6 +68,10 @@ static int tpm_decode_config(struct tpm *dev) node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); if (node < 0) { + node = fdtdec_next_compatible(blob, 0, + COMPAT_INFINEON_SLB9645_TPM); + } + if (node < 0) { debug("%s: Node not found\n", __func__); return -1; } diff --git a/drivers/tpm/slb9635_i2c/tpm.c b/drivers/tpm/tpm.c index 496c48e..b657334 100644 --- a/drivers/tpm/slb9635_i2c/tpm.c +++ b/drivers/tpm/tpm.c @@ -32,11 +32,30 @@ * MA 02111-1307 USA */ -#include <malloc.h> -#include "tpm.h" +#include <config.h> +#include <common.h> +#include <compiler.h> +#include <fdtdec.h> +#include <i2c.h> +#include <tpm.h> +#include <asm-generic/errno.h> +#include <linux/types.h> +#include <linux/unaligned/be_byteshift.h> -/* global structure for tpm chip data */ -struct tpm_chip g_chip; +#include "tpm_private.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* TPM configuration */ +struct tpm { + int i2c_bus; + int slave_addr; + char inited; + int old_bus; +} tpm; + +/* Global structure for tpm chip data */ +static struct tpm_chip g_chip; enum tpm_duration { TPM_SHORT = 0, @@ -45,9 +64,18 @@ enum tpm_duration { TPM_UNDEFINED, }; -#define TPM_MAX_ORDINAL 243 -#define TPM_MAX_PROTECTED_ORDINAL 12 -#define TPM_PROTECTED_ORDINAL_MASK 0xFF +/* Extended error numbers from linux (see errno.h) */ +#define ECANCELED 125 /* Operation Canceled */ + +/* Timer frequency. Corresponds to msec timer resolution*/ +#define HZ 1000 + +#define TPM_MAX_ORDINAL 243 +#define TPM_MAX_PROTECTED_ORDINAL 12 +#define TPM_PROTECTED_ORDINAL_MASK 0xFF + +#define TPM_CMD_COUNT_BYTE 2 +#define TPM_CMD_ORDINAL_BYTE 6 /* * Array with one entry per ordinal defining the maximum amount @@ -318,34 +346,31 @@ static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { TPM_MEDIUM, }; -/* - * Returns max number of milliseconds to wait - */ -unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) +/* Returns max number of milliseconds to wait */ +static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, + u32 ordinal) { int duration_idx = TPM_UNDEFINED; int duration = 0; - if (ordinal < TPM_MAX_ORDINAL) + if (ordinal < TPM_MAX_ORDINAL) { duration_idx = tpm_ordinal_duration[ordinal]; - else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < - TPM_MAX_PROTECTED_ORDINAL) - duration_idx = - tpm_protected_ordinal_duration[ordinal & - TPM_PROTECTED_ORDINAL_MASK]; + } else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < + TPM_MAX_PROTECTED_ORDINAL) { + duration_idx = tpm_protected_ordinal_duration[ + ordinal & TPM_PROTECTED_ORDINAL_MASK]; + } if (duration_idx != TPM_UNDEFINED) duration = chip->vendor.duration[duration_idx]; + if (duration <= 0) - return 2 * 60 * HZ; /*two minutes timeout*/ + return 2 * 60 * HZ; /* Two minutes timeout */ else return duration; } -#define TPM_CMD_COUNT_BYTE 2 -#define TPM_CMD_ORDINAL_BYTE 6 - -ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) +static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) { ssize_t rc; u32 count, ordinal; @@ -358,18 +383,17 @@ ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE); if (count == 0) { - dev_err(chip->dev, "no data\n"); + error("no data\n"); return -ENODATA; } if (count > bufsiz) { - dev_err(chip->dev, - "invalid count value %x %zx\n", count, bufsiz); + error("invalid count value %x %zx\n", count, bufsiz); return -E2BIG; } rc = chip->vendor.send(chip, (u8 *)buf, count); if (rc < 0) { - dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc); + error("tpm_transmit: tpm_send: error %zd\n", rc); goto out; } @@ -379,47 +403,126 @@ ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) start = get_timer(0); stop = tpm_calc_ordinal_duration(chip, ordinal); do { - dbg_printf("waiting for status...\n"); + debug("waiting for status...\n"); u8 status = chip->vendor.status(chip); if ((status & chip->vendor.req_complete_mask) == chip->vendor.req_complete_val) { - dbg_printf("...got it;\n"); + debug("...got it;\n"); goto out_recv; } if ((status == chip->vendor.req_canceled)) { - dev_err(chip->dev, "Operation Canceled\n"); + error("Operation Canceled\n"); rc = -ECANCELED; goto out; } - msleep(TPM_TIMEOUT); + udelay(TPM_TIMEOUT * 1000); } while (get_timer(start) < stop); chip->vendor.cancel(chip); - dev_err(chip->dev, "Operation Timed out\n"); + error("Operation Timed out\n"); rc = -ETIME; goto out; out_recv: - - dbg_printf("out_recv: reading response...\n"); + debug("out_recv: reading response...\n"); rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE); if (rc < 0) - dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc); + error("tpm_transmit: tpm_recv: error %zd\n", rc); + out: return rc; } -#define TPM_ERROR_SIZE 10 +static int tpm_open(uint32_t dev_addr) +{ + int rc; + if (g_chip.is_open) + return -EBUSY; + rc = tpm_vendor_init(dev_addr); + if (rc < 0) + g_chip.is_open = 0; + return rc; +} -enum tpm_capabilities { - TPM_CAP_PROP = cpu_to_be32(5), -}; +static void tpm_close(void) +{ + if (g_chip.is_open) { + tpm_vendor_cleanup(&g_chip); + g_chip.is_open = 0; + } +} -enum tpm_sub_capabilities { - TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115), - TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120), -}; +static int tpm_select(void) +{ + int ret; + + tpm.old_bus = i2c_get_bus_num(); + if (tpm.old_bus != tpm.i2c_bus) { + ret = i2c_set_bus_num(tpm.i2c_bus); + if (ret) { + debug("%s: Fail to set i2c bus %d\n", __func__, + tpm.i2c_bus); + return -1; + } + } + return 0; +} + +static int tpm_deselect(void) +{ + int ret; + + if (tpm.old_bus != i2c_get_bus_num()) { + ret = i2c_set_bus_num(tpm.old_bus); + if (ret) { + debug("%s: Fail to restore i2c bus %d\n", + __func__, tpm.old_bus); + return -1; + } + } + tpm.old_bus = -1; + return 0; +} + +/** + * Decode TPM configuration. + * + * @param dev Returns a configuration of TPM device + * @return 0 if ok, -1 on error + */ +static int tpm_decode_config(struct tpm *dev) +{ +#ifdef CONFIG_OF_CONTROL + const void *blob = gd->fdt_blob; + int node, parent; + int i2c_bus; + + node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); + if (node < 0) { + node = fdtdec_next_compatible(blob, 0, + COMPAT_INFINEON_SLB9645_TPM); + } + if (node < 0) { + debug("%s: Node not found\n", __func__); + return -1; + } + parent = fdt_parent_offset(blob, node); + if (parent < 0) { + debug("%s: Cannot find node parent\n", __func__); + return -1; + } + i2c_bus = i2c_get_bus_num_fdt(parent); + if (i2c_bus < 0) + return -1; + dev->i2c_bus = i2c_bus; + dev->slave_addr = fdtdec_get_addr(blob, node, "reg"); +#else + dev->i2c_bus = CONFIG_TPM_TIS_I2C_BUS_NUMBER; + dev->slave_addr = CONFIG_TPM_TIS_I2C_SLAVE_ADDRESS; +#endif + return 0; +} struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry) { @@ -433,21 +536,94 @@ struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry) return chip; } -int tpm_open(uint32_t dev_addr) +int tis_init(void) +{ + if (tpm.inited) + return 0; + + if (tpm_decode_config(&tpm)) + return -1; + + if (tpm_select()) + return -1; + + /* + * Probe TPM twice; the first probing might fail because TPM is asleep, + * and the probing can wake up TPM. + */ + if (i2c_probe(tpm.slave_addr) && i2c_probe(tpm.slave_addr)) { + debug("%s: fail to probe i2c addr 0x%x\n", __func__, + tpm.slave_addr); + return -1; + } + + tpm_deselect(); + + tpm.inited = 1; + + return 0; +} + +int tis_open(void) { int rc; - if (g_chip.is_open) - return -EBUSY; - rc = tpm_vendor_init(dev_addr); - if (rc < 0) - g_chip.is_open = 0; + + if (!tpm.inited) + return -1; + + if (tpm_select()) + return -1; + + rc = tpm_open(tpm.slave_addr); + + tpm_deselect(); + return rc; } -void tpm_close(void) +int tis_close(void) { - if (g_chip.is_open) { - tpm_vendor_cleanup(&g_chip); - g_chip.is_open = 0; + if (!tpm.inited) + return -1; + + if (tpm_select()) + return -1; + + tpm_close(); + + tpm_deselect(); + + return 0; +} + +int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, + uint8_t *recvbuf, size_t *rbuf_len) +{ + int len; + uint8_t buf[4096]; + + if (!tpm.inited) + return -1; + + if (sizeof(buf) < sbuf_size) + return -1; + + memcpy(buf, sendbuf, sbuf_size); + + if (tpm_select()) + return -1; + + len = tpm_transmit(buf, sbuf_size); + + tpm_deselect(); + + if (len < 10) { + *rbuf_len = 0; + return -1; } + + memcpy(recvbuf, buf, len); + *rbuf_len = len; + + return 0; } diff --git a/drivers/tpm/slb9635_i2c/tpm.h b/drivers/tpm/tpm_private.h index 9ddee86..888a074 100644 --- a/drivers/tpm/slb9635_i2c/tpm.h +++ b/drivers/tpm/tpm_private.h @@ -33,12 +33,11 @@ * MA 02111-1307 USA */ -#ifndef _TPM_H_ -#define _TPM_H_ +#ifndef _TPM_PRIVATE_H_ +#define _TPM_PRIVATE_H_ #include <linux/compiler.h> - -#include "compatibility.h" +#include <linux/types.h> enum tpm_timeout { TPM_TIMEOUT = 5, /* msecs */ @@ -47,13 +46,9 @@ enum tpm_timeout { /* Size of external transmit buffer (used in tpm_transmit)*/ #define TPM_BUFSIZE 4096 -/* Index of fields in TPM command buffer */ -#define TPM_CMD_SIZE_BYTE 2 -#define TPM_CMD_ORDINAL_BYTE 6 - /* Index of Count field in TPM response buffer */ -#define TPM_RSP_SIZE_BYTE 2 -#define TPM_RSP_RC_BYTE 6 +#define TPM_RSP_SIZE_BYTE 2 +#define TPM_RSP_RC_BYTE 6 struct tpm_chip; @@ -65,10 +60,10 @@ struct tpm_vendor_specific { int (*recv) (struct tpm_chip *, u8 *, size_t); int (*send) (struct tpm_chip *, u8 *, size_t); void (*cancel) (struct tpm_chip *); - u8(*status) (struct tpm_chip *); + u8(*status) (struct tpm_chip *); int locality; - unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ - unsigned long duration[3]; /* msec */ + unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ + unsigned long duration[3]; /* msec */ }; struct tpm_chip { @@ -132,30 +127,11 @@ struct tpm_cmd_t { union tpm_cmd_params params; } __packed; +struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *); -/* ---------- Interface for TPM vendor ------------ */ - -extern struct tpm_chip *tpm_register_hardware( - const struct tpm_vendor_specific *); +int tpm_vendor_init(uint32_t dev_addr); -extern int tpm_vendor_init(uint32_t dev_addr); +void tpm_vendor_cleanup(struct tpm_chip *chip); -extern void tpm_vendor_cleanup(struct tpm_chip *chip); - -/* ---------- Interface for TDDL ------------------- */ - -/* - * if dev_addr != 0 - redefines TPM device address - * Returns < 0 on error, 0 on success. - */ -extern int tpm_open(uint32_t dev_addr); - -extern void tpm_close(void); - -/* - * Transmit bufsiz bytes out of buf to TPM and get results back in buf, too. - * Returns < 0 on error, 0 on success. - */ -extern ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz); #endif diff --git a/drivers/tpm/slb9635_i2c/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 82a41bf..2dd8501 100644 --- a/drivers/tpm/slb9635_i2c/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -37,46 +37,102 @@ */ #include <common.h> +#include <fdtdec.h> +#include <compiler.h> #include <i2c.h> +#include <tpm.h> +#include <asm-generic/errno.h> #include <linux/types.h> +#include <linux/unaligned/be_byteshift.h> -#include "compatibility.h" -#include "tpm.h" +#include "tpm_private.h" + +DECLARE_GLOBAL_DATA_PTR; -/* max. buffer size supported by our tpm */ -#ifdef TPM_BUFSIZE -#undef TPM_BUFSIZE -#endif -#define TPM_BUFSIZE 1260 /* Address of the TPM on the I2C bus */ -#define TPM_I2C_ADDR 0x20 -/* max. number of iterations after i2c NAK */ -#define MAX_COUNT 3 +#define TPM_I2C_ADDR 0x20 + +/* Max buffer size supported by our tpm */ +#define TPM_DEV_BUFSIZE 1260 -#define SLEEP_DURATION 60 /*in usec*/ +/* Max number of iterations after i2c NAK */ +#define MAX_COUNT 3 -/* max. number of iterations after i2c NAK for 'long' commands - * we need this especially for sending TPM_READY, since the cleanup after the +/* + * Max number of iterations after i2c NAK for 'long' commands + * + * We need this especially for sending TPM_READY, since the cleanup after the * transtion to the ready state may take some time, but it is unpredictable * how long it will take. */ -#define MAX_COUNT_LONG 50 +#define MAX_COUNT_LONG 50 + +#define SLEEP_DURATION 60 /* in usec */ +#define SLEEP_DURATION_LONG 210 /* in usec */ -#define SLEEP_DURATION_LONG 210 /* in usec */ +#define TPM_HEADER_SIZE 10 + +/* + * Expected value for DIDVID register + * + * The only device the system knows about at this moment is Infineon slb9635. + */ +#define TPM_TIS_I2C_DID_VID 0x000b15d1L + +enum tis_access { + TPM_ACCESS_VALID = 0x80, + TPM_ACCESS_ACTIVE_LOCALITY = 0x20, + TPM_ACCESS_REQUEST_PENDING = 0x04, + TPM_ACCESS_REQUEST_USE = 0x02, +}; + +enum tis_status { + TPM_STS_VALID = 0x80, + TPM_STS_COMMAND_READY = 0x40, + TPM_STS_GO = 0x20, + TPM_STS_DATA_AVAIL = 0x10, + TPM_STS_DATA_EXPECT = 0x08, +}; + +enum tis_defaults { + TIS_SHORT_TIMEOUT = 750, /* ms */ + TIS_LONG_TIMEOUT = 2000, /* ms */ +}; /* expected value for DIDVID register */ -#define TPM_TIS_I2C_DID_VID 0x000b15d1L +#define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L +#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L + +enum i2c_chip_type { + SLB9635, + SLB9645, + UNKNOWN, +}; + +static const char * const chip_name[] = { + [SLB9635] = "slb9635tt", + [SLB9645] = "slb9645tt", + [UNKNOWN] = "unknown/fallback to slb9635", +}; + +#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) +#define TPM_STS(l) (0x0001 | ((l) << 4)) +#define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) +#define TPM_DID_VID(l) (0x0006 | ((l) << 4)) /* Structure to store I2C TPM specific stuff */ -struct tpm_inf_dev { +struct tpm_dev { uint addr; - u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ + u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)]; /* Max buffer size + addr */ + enum i2c_chip_type chip_type; }; -static struct tpm_inf_dev tpm_dev = { +static struct tpm_dev tpm_dev = { .addr = TPM_I2C_ADDR }; +static struct tpm_dev tpm_dev; + /* * iic_tpm_read() - read from TPM register * @addr: register address to read from @@ -91,34 +147,52 @@ static struct tpm_inf_dev tpm_dev = { * * Return -EIO on error, 0 on success. */ -int iic_tpm_read(u8 addr, u8 *buffer, size_t len) +static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) { int rc; int count; - uint myaddr = addr; - /* we have to use uint here, uchar hangs the board */ - - for (count = 0; count < MAX_COUNT; count++) { - rc = i2c_write(tpm_dev.addr, 0, 0, (uchar *)&myaddr, 1); - if (rc == 0) - break; /*success, break to skip sleep*/ - - udelay(SLEEP_DURATION); - } - - if (rc) - return -rc; - - /* After the TPM has successfully received the register address it needs - * some time, thus we're sleeping here again, before retrieving the data - */ - for (count = 0; count < MAX_COUNT; count++) { - udelay(SLEEP_DURATION); - rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len); - if (rc == 0) - break; /*success, break to skip sleep*/ + uint32_t addrbuf = addr; + + if ((tpm_dev.chip_type == SLB9635) || (tpm_dev.chip_type == UNKNOWN)) { + /* slb9635 protocol should work in both cases */ + for (count = 0; count < MAX_COUNT; count++) { + rc = i2c_write(tpm_dev.addr, 0, 0, + (uchar *)&addrbuf, 1); + if (rc == 0) + break; /* Success, break to skip sleep */ + udelay(SLEEP_DURATION); + } + if (rc) + return -rc; + + /* After the TPM has successfully received the register address + * it needs some time, thus we're sleeping here again, before + * retrieving the data + */ + for (count = 0; count < MAX_COUNT; count++) { + udelay(SLEEP_DURATION); + rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len); + if (rc == 0) + break; /* success, break to skip sleep */ + } + } else { + /* + * Use a combined read for newer chips. + * Unfortunately the smbus functions are not suitable due to + * the 32 byte limit of the smbus. + * Retries should usually not be needed, but are kept just to + * be safe on the safe side. + */ + for (count = 0; count < MAX_COUNT; count++) { + rc = i2c_read(tpm_dev.addr, addr, 1, buffer, len); + if (rc == 0) + break; /* break here to skip sleep */ + udelay(SLEEP_DURATION); + } } + /* Take care of 'guard time' */ + udelay(SLEEP_DURATION); if (rc) return -rc; @@ -126,24 +200,24 @@ int iic_tpm_read(u8 addr, u8 *buffer, size_t len) } static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, - unsigned int sleep_time, - u8 max_count) + unsigned int sleep_time, u8 max_count) { int rc = 0; int count; - /* prepare send buffer */ + /* Prepare send buffer */ tpm_dev.buf[0] = addr; memcpy(&(tpm_dev.buf[1]), buffer, len); for (count = 0; count < max_count; count++) { rc = i2c_write(tpm_dev.addr, 0, 0, tpm_dev.buf, len + 1); if (rc == 0) - break; /*success, break to skip sleep*/ - + break; /* Success, break to skip sleep */ udelay(sleep_time); } + /* take care of 'guard time' */ + udelay(SLEEP_DURATION); if (rc) return -rc; @@ -175,42 +249,16 @@ static int iic_tpm_write(u8 addr, u8 *buffer, size_t len) /* * This function is needed especially for the cleanup situation after * sending TPM_READY - * */ + */ static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len) { return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG, MAX_COUNT_LONG); } -#define TPM_HEADER_SIZE 10 - -enum tis_access { - TPM_ACCESS_VALID = 0x80, - TPM_ACCESS_ACTIVE_LOCALITY = 0x20, - TPM_ACCESS_REQUEST_PENDING = 0x04, - TPM_ACCESS_REQUEST_USE = 0x02, -}; - -enum tis_status { - TPM_STS_VALID = 0x80, - TPM_STS_COMMAND_READY = 0x40, - TPM_STS_GO = 0x20, - TPM_STS_DATA_AVAIL = 0x10, - TPM_STS_DATA_EXPECT = 0x08, -}; - -enum tis_defaults { - TIS_SHORT_TIMEOUT = 750, /* ms */ - TIS_LONG_TIMEOUT = 2000, /* 2 sec */ -}; - -#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) -#define TPM_STS(l) (0x0001 | ((l) << 4)) -#define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) -#define TPM_DID_VID(l) (0x0006 | ((l) << 4)) - static int check_locality(struct tpm_chip *chip, int loc) { + const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID; u8 buf; int rc; @@ -218,8 +266,7 @@ static int check_locality(struct tpm_chip *chip, int loc) if (rc < 0) return rc; - if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == - (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { + if ((buf & mask) == mask) { chip->vendor.locality = loc; return loc; } @@ -229,12 +276,13 @@ static int check_locality(struct tpm_chip *chip, int loc) static void release_locality(struct tpm_chip *chip, int loc, int force) { + const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID; u8 buf; + if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0) return; - if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == - (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { + if (force || (buf & mask) == mask) { buf = TPM_ACCESS_ACTIVE_LOCALITY; iic_tpm_write(TPM_ACCESS(loc), &buf, 1); } @@ -246,17 +294,17 @@ static int request_locality(struct tpm_chip *chip, int loc) u8 buf = TPM_ACCESS_REQUEST_USE; if (check_locality(chip, loc) >= 0) - return loc; /* we already have the locality */ + return loc; /* We already have the locality */ iic_tpm_write(TPM_ACCESS(loc), &buf, 1); - /* wait for burstcount */ + /* Wait for burstcount */ start = get_timer(0); stop = chip->vendor.timeout_a; do { if (check_locality(chip, loc) >= 0) return loc; - msleep(TPM_TIMEOUT); + udelay(TPM_TIMEOUT * 1000); } while (get_timer(start) < stop); return -1; @@ -264,8 +312,9 @@ static int request_locality(struct tpm_chip *chip, int loc) static u8 tpm_tis_i2c_status(struct tpm_chip *chip) { - /* NOTE: since i2c read may fail, return 0 in this case --> time-out */ + /* NOTE: Since i2c read may fail, return 0 in this case --> time-out */ u8 buf; + if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) return 0; else @@ -274,8 +323,9 @@ static u8 tpm_tis_i2c_status(struct tpm_chip *chip) static void tpm_tis_i2c_ready(struct tpm_chip *chip) { - /* this causes the current command to be aborted */ + /* This causes the current command to be aborted */ u8 buf = TPM_STS_COMMAND_READY; + iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); } @@ -283,34 +333,34 @@ static ssize_t get_burstcount(struct tpm_chip *chip) { unsigned long start, stop; ssize_t burstcnt; - u8 buf[3]; + u8 addr, buf[3]; - /* wait for burstcount */ - /* which timeout value, spec has 2 answers (c & d) */ + /* Wait for burstcount */ + /* XXX: Which timeout value? Spec has 2 answers (c & d) */ start = get_timer(0); stop = chip->vendor.timeout_d; do { /* Note: STS is little endian */ - if (iic_tpm_read(TPM_STS(chip->vendor.locality) + 1, buf, 3) - < 0) + addr = TPM_STS(chip->vendor.locality) + 1; + if (iic_tpm_read(addr, buf, 3) < 0) burstcnt = 0; else burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; if (burstcnt) return burstcnt; - msleep(TPM_TIMEOUT); + udelay(TPM_TIMEOUT * 1000); } while (get_timer(start) < stop); return -EBUSY; } static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, - int *status) + int *status) { unsigned long start, stop; - /* check current status */ + /* Check current status */ *status = tpm_tis_i2c_status(chip); if ((*status & mask) == mask) return 0; @@ -318,11 +368,10 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, start = get_timer(0); stop = timeout; do { - msleep(TPM_TIMEOUT); + udelay(TPM_TIMEOUT * 1000); *status = tpm_tis_i2c_status(chip); if ((*status & mask) == mask) return 0; - } while (get_timer(start) < stop); return -ETIME; @@ -337,17 +386,16 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) while (size < count) { burstcnt = get_burstcount(chip); - /* burstcount < 0 = tpm is busy */ + /* burstcount < 0 -> tpm is busy */ if (burstcnt < 0) return burstcnt; - /* limit received data to max. left */ + /* Limit received data to max left */ if (burstcnt > (count - size)) burstcnt = count - size; rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality), - &(buf[size]), - burstcnt); + &(buf[size]), burstcnt); if (rc == 0) size += burstcnt; } @@ -365,10 +413,10 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) goto out; } - /* read first 10 bytes, including tag, paramsize, and result */ + /* Read first 10 bytes, including tag, paramsize, and result */ size = recv_data(chip, buf, TPM_HEADER_SIZE); if (size < TPM_HEADER_SIZE) { - dev_err(chip->dev, "Unable to read header\n"); + error("Unable to read header\n"); goto out; } @@ -379,23 +427,24 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) } size += recv_data(chip, &buf[TPM_HEADER_SIZE], - expected - TPM_HEADER_SIZE); + expected - TPM_HEADER_SIZE); if (size < expected) { - dev_err(chip->dev, "Unable to read remainder of result\n"); + error("Unable to read remainder of result\n"); size = -ETIME; goto out; } wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); - if (status & TPM_STS_DATA_AVAIL) { /* retry? */ - dev_err(chip->dev, "Error left over data\n"); + if (status & TPM_STS_DATA_AVAIL) { /* Retry? */ + error("Error left over data\n"); size = -EIO; goto out; } out: tpm_tis_i2c_ready(chip); - /* The TPM needs some time to clean up here, + /* + * The TPM needs some time to clean up here, * so we sleep rather than keeping the bus busy */ udelay(2000); @@ -409,10 +458,11 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) int rc, status; ssize_t burstcnt; size_t count = 0; + int retry = 0; u8 sts = TPM_STS_GO; - if (len > TPM_BUFSIZE) - return -E2BIG; /* command is too long for our tpm, sorry */ + if (len > TPM_DEV_BUFSIZE) + return -E2BIG; /* Command is too long for our tpm, sorry */ if (request_locality(chip, 0) < 0) return -EBUSY; @@ -420,44 +470,45 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) status = tpm_tis_i2c_status(chip); if ((status & TPM_STS_COMMAND_READY) == 0) { tpm_tis_i2c_ready(chip); - if (wait_for_stat - (chip, TPM_STS_COMMAND_READY, - chip->vendor.timeout_b, &status) < 0) { + if (wait_for_stat(chip, TPM_STS_COMMAND_READY, + chip->vendor.timeout_b, &status) < 0) { rc = -ETIME; goto out_err; } } - while (count < len - 1) { - burstcnt = get_burstcount(chip); + burstcnt = get_burstcount(chip); - /* burstcount < 0 = tpm is busy */ - if (burstcnt < 0) - return burstcnt; + /* burstcount < 0 -> tpm is busy */ + if (burstcnt < 0) + return burstcnt; - if (burstcnt > (len-1-count)) - burstcnt = len-1-count; + while (count < len - 1) { + if (burstcnt > len - 1 - count) + burstcnt = len - 1 - count; -#ifdef CONFIG_TPM_I2C_BURST_LIMITATION - if (burstcnt > CONFIG_TPM_I2C_BURST_LIMITATION) - burstcnt = CONFIG_TPM_I2C_BURST_LIMITATION; -#endif /* CONFIG_TPM_I2C_BURST_LIMITATION */ +#ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION + if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION) + burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION; +#endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */ rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), - &(buf[count]), burstcnt); + &(buf[count]), burstcnt); if (rc == 0) count += burstcnt; - - wait_for_stat(chip, TPM_STS_VALID, - chip->vendor.timeout_c, &status); - - if ((status & TPM_STS_DATA_EXPECT) == 0) { - rc = -EIO; - goto out_err; + else { + retry++; + wait_for_stat(chip, TPM_STS_VALID, + chip->vendor.timeout_c, &status); + + if ((status & TPM_STS_DATA_EXPECT) == 0) { + rc = -EIO; + goto out_err; + } } } - /* write last byte */ + /* Write last byte */ iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1); wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); if ((status & TPM_STS_DATA_EXPECT) != 0) { @@ -465,13 +516,15 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) goto out_err; } - /* go and do it */ + /* Go and do it */ iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); return len; + out_err: tpm_tis_i2c_ready(chip); - /* The TPM needs some time to clean up here, + /* + * The TPM needs some time to clean up here, * so we sleep rather than keeping the bus busy */ udelay(2000); @@ -490,12 +543,26 @@ static struct tpm_vendor_specific tpm_tis_i2c = { .req_canceled = TPM_STS_COMMAND_READY, }; -/* initialisation of i2c tpm */ +static enum i2c_chip_type tpm_vendor_chip_type(void) +{ +#ifdef CONFIG_OF_CONTROL + const void *blob = gd->fdt_blob; + + if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9645_TPM) >= 0) + return SLB9645; + + if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM) >= 0) + return SLB9635; +#endif + return UNKNOWN; +} +/* Initialisation of i2c tpm */ int tpm_vendor_init(uint32_t dev_addr) { u32 vendor; + u32 expected_did_vid; uint old_addr; int rc = 0; struct tpm_chip *chip; @@ -504,6 +571,8 @@ int tpm_vendor_init(uint32_t dev_addr) if (dev_addr != 0) tpm_dev.addr = dev_addr; + tpm_dev.chip_type = tpm_vendor_chip_type(); + chip = tpm_register_hardware(&tpm_tis_i2c); if (chip < 0) { rc = -ENODEV; @@ -519,26 +588,33 @@ int tpm_vendor_init(uint32_t dev_addr) chip->vendor.timeout_c = TIS_SHORT_TIMEOUT; chip->vendor.timeout_d = TIS_SHORT_TIMEOUT; - if (request_locality(chip, 0) != 0) { + if (request_locality(chip, 0) < 0) { rc = -ENODEV; goto out_err; } - /* read four bytes from DID_VID register */ + /* Read four bytes from DID_VID register */ if (iic_tpm_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { rc = -EIO; goto out_release; } - /* create DID_VID register value, after swapping to little-endian */ - vendor = be32_to_cpu(vendor); + if (tpm_dev.chip_type == SLB9635) { + vendor = be32_to_cpu(vendor); + expected_did_vid = TPM_TIS_I2C_DID_VID_9635; + } else { + /* device id and byte order has changed for newer i2c tpms */ + expected_did_vid = TPM_TIS_I2C_DID_VID_9645; + } - if (vendor != TPM_TIS_I2C_DID_VID) { + if (tpm_dev.chip_type != UNKNOWN && vendor != expected_did_vid) { + error("Vendor id did not match! ID was %08x\n", vendor); rc = -ENODEV; goto out_release; } - dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16); + debug("1.2 TPM (chip type %s device-id 0x%X)\n", + chip_name[tpm_dev.chip_type], vendor >> 16); /* * A timeout query to TPM can be placed here. diff --git a/drivers/tpm/generic_lpc_tpm.c b/drivers/tpm/tpm_tis_lpc.c index 04ad418..04ad418 100644 --- a/drivers/tpm/generic_lpc_tpm.c +++ b/drivers/tpm/tpm_tis_lpc.c diff --git a/include/bootstage.h b/include/bootstage.h index 6dc0422..ef07a87 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -37,6 +37,24 @@ enum bootstage_flags { BOOTSTAGEF_ALLOC = 1 << 1, /* Allocate an id */ }; +/* bootstate sub-IDs used for kernel and ramdisk ranges */ +enum { + BOOTSTAGE_SUB_FORMAT, + BOOTSTAGE_SUB_FORMAT_OK, + BOOTSTAGE_SUB_NO_UNIT_NAME, + BOOTSTAGE_SUB_UNIT_NAME, + BOOTSTAGE_SUB_SUBNODE, + + BOOTSTAGE_SUB_CHECK, + BOOTSTAGE_SUB_HASH = 5, + BOOTSTAGE_SUB_CHECK_ARCH = 5, + BOOTSTAGE_SUB_CHECK_ALL, + BOOTSTAGE_SUB_GET_DATA, + BOOTSTAGE_SUB_CHECK_ALL_OK = 7, + BOOTSTAGE_SUB_GET_DATA_OK, + BOOTSTAGE_SUB_LOAD, +}; + /* * A list of boot stages that we know about. Each of these indicates the * state that we are at, and the action that we are about to perform. For @@ -137,43 +155,24 @@ enum bootstage_id { BOOTSTAGE_ID_NET_DONE_ERR, BOOTSTAGE_ID_NET_DONE, + BOOTSTAGE_ID_FIT_FDT_START = 90, /* * Boot stages related to loading a FIT image. Some of these are a * bit wonky. */ - BOOTSTAGE_ID_FIT_FORMAT = 100, - BOOTSTAGE_ID_FIT_NO_UNIT_NAME, - BOOTSTAGE_ID_FIT_UNIT_NAME, - BOOTSTAGE_ID_FIT_CONFIG, - BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE, - BOOTSTAGE_ID_FIT_CHECK_HASH = 104, - - BOOTSTAGE_ID_FIT_CHECK_ARCH, - BOOTSTAGE_ID_FIT_CHECK_KERNEL, - BOOTSTAGE_ID_FIT_CHECKED, - - BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR = 107, - BOOTSTAGE_ID_FIT_KERNEL_INFO, + BOOTSTAGE_ID_FIT_KERNEL_START = 100, + + BOOTSTAGE_ID_FIT_CONFIG = 110, BOOTSTAGE_ID_FIT_TYPE, + BOOTSTAGE_ID_FIT_KERNEL_INFO, BOOTSTAGE_ID_FIT_COMPRESSION, BOOTSTAGE_ID_FIT_OS, BOOTSTAGE_ID_FIT_LOADADDR, BOOTSTAGE_ID_OVERWRITTEN, - BOOTSTAGE_ID_FIT_RD_FORMAT = 120, - BOOTSTAGE_ID_FIT_RD_FORMAT_OK, - BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME, - BOOTSTAGE_ID_FIT_RD_UNIT_NAME, - BOOTSTAGE_ID_FIT_RD_SUBNODE, - - BOOTSTAGE_ID_FIT_RD_CHECK, - BOOTSTAGE_ID_FIT_RD_HASH = 125, - BOOTSTAGE_ID_FIT_RD_CHECK_ALL, - BOOTSTAGE_ID_FIT_RD_GET_DATA, - BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK = 127, - BOOTSTAGE_ID_FIT_RD_GET_DATA_OK, - BOOTSTAGE_ID_FIT_RD_LOAD, + /* Next 10 IDs used by BOOTSTAGE_SUB_... */ + BOOTSTAGE_ID_FIT_RD_START = 120, /* Ramdisk stages */ BOOTSTAGE_ID_IDE_FIT_READ = 140, BOOTSTAGE_ID_IDE_FIT_READ_OK, diff --git a/include/common.h b/include/common.h index e682bd8..126891d 100644 --- a/include/common.h +++ b/include/common.h @@ -310,9 +310,6 @@ int readline_into_buffer(const char *const prompt, char *buffer, int parse_line (char *, char *[]); void init_cmd_timeout(void); void reset_cmd_timeout(void); -#ifdef CONFIG_MENU -int abortboot(int bootdelay); -#endif extern char console_buffer[]; /* arch/$(ARCH)/lib/board.c */ diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h index f019134..cd2c078 100644 --- a/include/configs/am335x_evm.h +++ b/include/configs/am335x_evm.h @@ -305,8 +305,13 @@ /* Defines for SPL */ #define CONFIG_SPL #define CONFIG_SPL_FRAMEWORK +/* + * Place the image at the start of the ROM defined image space. + * We limit our size to the ROM-defined downloaded image area, and use the + * rest of the space for stack. + */ #define CONFIG_SPL_TEXT_BASE 0x402F0400 -#define CONFIG_SPL_MAX_SIZE (101 * 1024) +#define CONFIG_SPL_MAX_SIZE (0x4030C000 - CONFIG_SPL_TEXT_BASE) #define CONFIG_SPL_STACK CONFIG_SYS_INIT_SP_ADDR #define CONFIG_SPL_BSS_START_ADDR 0x80000000 diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h index be04a75..2fefdc8 100644 --- a/include/configs/coreboot.h +++ b/include/configs/coreboot.h @@ -90,7 +90,8 @@ #endif /* Generic TPM interfaced through LPC bus */ -#define CONFIG_GENERIC_LPC_TPM +#define CONFIG_TPM +#define CONFIG_TPM_TIS_LPC #define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000 /*----------------------------------------------------------------------- diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h index 8a82892..41d6cf9 100644 --- a/include/configs/exynos5250-dt.h +++ b/include/configs/exynos5250-dt.h @@ -142,9 +142,9 @@ /* TPM */ #define CONFIG_TPM #define CONFIG_CMD_TPM -#define CONFIG_INFINEON_TPM_I2C -#define CONFIG_INFINEON_TPM_I2C_BUS 3 -#define CONFIG_INFINEON_TPM_I2C_ADDR 0x20 +#define CONFIG_TPM_TIS_I2C +#define CONFIG_TPM_TIS_I2C_BUS_NUMBER 3 +#define CONFIG_TPM_TIS_I2C_SLAVE_ADDR 0x20 /* MMC SPL */ #define CONFIG_SPL diff --git a/include/configs/igep0033.h b/include/configs/igep0033.h index 1912d7d..12f28f8 100644 --- a/include/configs/igep0033.h +++ b/include/configs/igep0033.h @@ -214,8 +214,13 @@ /* Defines for SPL */ #define CONFIG_SPL #define CONFIG_SPL_FRAMEWORK +/* + * Place the image at the start of the ROM defined image space. + * We limit our size to the ROM-defined downloaded image area, and use the + * rest of the space for stack. + */ #define CONFIG_SPL_TEXT_BASE 0x402F0400 -#define CONFIG_SPL_MAX_SIZE (101 * 1024) +#define CONFIG_SPL_MAX_SIZE (0x4030C000 - CONFIG_SPL_TEXT_BASE) #define CONFIG_SPL_STACK CONFIG_SYS_INIT_SP_ADDR #define CONFIG_SPL_BSS_START_ADDR 0x80000000 diff --git a/include/configs/pcm051.h b/include/configs/pcm051.h index 478f805..2ecd105 100644 --- a/include/configs/pcm051.h +++ b/include/configs/pcm051.h @@ -204,8 +204,13 @@ /* Defines for SPL */ #define CONFIG_SPL #define CONFIG_SPL_FRAMEWORK +/* + * Place the image at the start of the ROM defined image space. + * We limit our size to the ROM-defined downloaded image area, and use the + * rest of the space for stack. + */ #define CONFIG_SPL_TEXT_BASE 0x402F0400 -#define CONFIG_SPL_MAX_SIZE (101 * 1024) +#define CONFIG_SPL_MAX_SIZE (0x4030C000 - CONFIG_SPL_TEXT_BASE) #define CONFIG_SPL_STACK CONFIG_SYS_INIT_SP_ADDR #define CONFIG_SPL_BSS_START_ADDR 0x80000000 diff --git a/include/configs/pm9263.h b/include/configs/pm9263.h index b60a9ad..6f6ddfa 100644 --- a/include/configs/pm9263.h +++ b/include/configs/pm9263.h @@ -355,7 +355,7 @@ #define CONFIG_BOOTCOMMAND "run flashboot" #define CONFIG_ROOTPATH "/ronetix/rootfs" -#define CONFIG_AUTOBOOT_PROMPT "autoboot in %d seconds\n" +#define CONFIG_AUTOBOOT_PROMPT "autoboot in %d seconds\n", bootdelay #define CONFIG_CON_ROT "fbcon=rotate:3 " #define CONFIG_BOOTARGS "root=/dev/mtdblock4 rootfstype=jffs2 "\ diff --git a/include/fdtdec.h b/include/fdtdec.h index 4e8032b..1ece612 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -93,6 +93,7 @@ enum fdt_compat_id { COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */ COMPAT_MAXIM_98095_CODEC, /* MAX98095 Codec */ COMPAT_INFINEON_SLB9635_TPM, /* Infineon SLB9635 TPM */ + COMPAT_INFINEON_SLB9645_TPM, /* Infineon SLB9645 TPM */ COMPAT_COUNT, }; diff --git a/include/image.h b/include/image.h index b8cc523..8ccc00b 100644 --- a/include/image.h +++ b/include/image.h @@ -402,6 +402,13 @@ void genimg_print_size(uint32_t size); #endif void genimg_print_time(time_t timestamp); +/* What to do with a image load address ('load = <> 'in the FIT) */ +enum fit_load_op { + FIT_LOAD_IGNORED, /* Ignore load address */ + FIT_LOAD_OPTIONAL, /* Can be provided, but optional */ + FIT_LOAD_REQUIRED, /* Must be provided */ +}; + #ifndef USE_HOSTCC /* Image format types, returned by _get_format() routine */ #define IMAGE_FORMAT_INVALID 0x00 @@ -415,8 +422,71 @@ ulong genimg_get_image(ulong img_addr); int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, uint8_t arch, ulong *rd_start, ulong *rd_end); -int boot_get_fdt(int flag, int argc, char * const argv[], - bootm_headers_t *images, char **of_flat_tree, ulong *of_size); +/** + * fit_image_load() - load an image from a FIT + * + * This deals with all aspects of loading an image from a FIT, including + * selecting the right image based on configuration, verifying it, printing + * out progress messages, checking the type/arch/os and optionally copying it + * to the right load address. + * + * @param images Boot images structure + * @param prop_name Property name to look up (FIT_..._PROP) + * @param addr Address of FIT in memory + * @param fit_unamep On entry this is the requested image name + * (e.g. "kernel@1") or NULL to use the default. On exit + * points to the selected image name + * @param fit_uname_config Requested configuration name, or NULL for the + * default + * @param arch Expected architecture (IH_ARCH_...) + * @param image_type Required image type (IH_TYPE_...). If this is + * IH_TYPE_KERNEL then we allow IH_TYPE_KERNEL_NOLOAD + * also. + * @param bootstage_id ID of starting bootstage to use for progress updates. + * This will be added to the BOOTSTAGE_SUB values when + * calling bootstage_mark() + * @param load_op Decribes what to do with the load address + * @param datap Returns address of loaded image + * @param lenp Returns length of loaded image + */ +int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, + const char **fit_unamep, const char *fit_uname_config, + int arch, int image_type, int bootstage_id, + enum fit_load_op load_op, ulong *datap, ulong *lenp); + +/** + * fit_get_node_from_config() - Look up an image a FIT by type + * + * This looks in the selected conf@ node (images->fit_uname_cfg) for a + * particular image type (e.g. "kernel") and then finds the image that is + * referred to. + * + * For example, for something like: + * + * images { + * kernel@1 { + * ... + * }; + * }; + * configurations { + * conf@1 { + * kernel = "kernel@1"; + * }; + * }; + * + * the function will return the node offset of the kernel@1 node, assuming + * that conf@1 is the chosen configuration. + * + * @param images Boot images structure + * @param prop_name Property name to look up (FIT_..._PROP) + * @param addr Address of FIT in memory + */ +int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, + ulong addr); + +int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, + bootm_headers_t *images, + char **of_flat_tree, ulong *of_size); void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob); int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size); @@ -697,6 +767,7 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp); int fit_add_verification_data(void *fit); int fit_image_verify(const void *fit, int noffset); +int fit_config_verify(const void *fit, int conf_noffset); int fit_all_image_verify(const void *fit); int fit_image_check_os(const void *fit, int noffset, uint8_t os); int fit_image_check_arch(const void *fit, int noffset, uint8_t arch); @@ -706,9 +777,6 @@ int fit_check_format(const void *fit); int fit_conf_find_compat(const void *fit, const void *fdt); int fit_conf_get_node(const void *fit, const char *conf_uname); -int fit_conf_get_kernel_node(const void *fit, int noffset); -int fit_conf_get_ramdisk_node(const void *fit, int noffset); -int fit_conf_get_fdt_node(const void *fit, int noffset); /** * fit_conf_get_prop_node() - Get node refered to by a configuration @@ -732,12 +800,35 @@ int fit_check_ramdisk(const void *fit, int os_noffset, int calculate_hash(const void *data, int data_len, const char *algo, uint8_t *value, int *value_len); -#ifndef USE_HOSTCC +/* + * At present we only support verification on the device + */ +#if defined(CONFIG_FIT_SIGNATURE) +# ifdef USE_HOSTCC +# define IMAGE_ENABLE_VERIFY 0 +#else +# define IMAGE_ENABLE_VERIFY 1 +# endif +#else +# define IMAGE_ENABLE_VERIFY 0 +#endif + +#ifdef USE_HOSTCC +# define gd_fdt_blob() NULL +#else +# define gd_fdt_blob() (gd->fdt_blob) +#endif + +#ifdef CONFIG_FIT_BEST_MATCH +#define IMAGE_ENABLE_BEST_MATCH 1 +#else +#define IMAGE_ENABLE_BEST_MATCH 0 +#endif + static inline int fit_image_check_target_arch(const void *fdt, int node) { return fit_image_check_arch(fdt, node, IH_ARCH_DEFAULT); } -#endif /* USE_HOSTCC */ #ifdef CONFIG_FIT_VERBOSE #define fit_unsupported(msg) printf("! %s:%d " \ diff --git a/include/net.h b/include/net.h index 970d4d1..23fb947 100644 --- a/include/net.h +++ b/include/net.h @@ -695,6 +695,9 @@ extern void copy_filename(char *dst, const char *src, int size); /* get a random source port */ extern unsigned int random_port(void); +/* Update U-Boot over TFTP */ +extern int update_tftp(ulong addr); + /**********************************************************************/ #endif /* __NET_H__ */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index ac1fe0b..005ad3d 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -66,6 +66,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(GENERIC_SPI_FLASH, "spi-flash"), COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"), COMPAT(INFINEON_SLB9635_TPM, "infineon,slb9635-tpm"), + COMPAT(INFINEON_SLB9645_TPM, "infineon,slb9645-tpm"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) diff --git a/test/image/test-fit.py b/test/image/test-fit.py new file mode 100755 index 0000000..c4e8211 --- /dev/null +++ b/test/image/test-fit.py @@ -0,0 +1,422 @@ +#!/usr/bin/python +# +# Copyright (c) 2013, Google Inc. +# +# Sanity check of the FIT handling in U-Boot +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# To run this: +# +# make O=sandbox sandbox_config +# make O=sandbox +# ./test/image/test-fit.py -u sandbox/u-boot + +import doctest +from optparse import OptionParser +import os +import shutil +import struct +import sys +import tempfile + +# The 'command' library in patman is convenient for running commands +base_path = os.path.dirname(sys.argv[0]) +patman = os.path.join(base_path, '../../tools/patman') +sys.path.append(patman) + +import command + +# Define a base ITS which we can adjust using % and a dictionary +base_its = ''' +/dts-v1/; + +/ { + description = "Chrome OS kernel image with one or more FDT blobs"; + #address-cells = <1>; + + images { + kernel@1 { + data = /incbin/("%(kernel)s"); + type = "kernel"; + arch = "sandbox"; + os = "linux"; + compression = "none"; + load = <0x40000>; + entry = <0x8>; + }; + fdt@1 { + description = "snow"; + data = /incbin/("u-boot.dtb"); + type = "flat_dt"; + arch = "sandbox"; + %(fdt_load)s + compression = "none"; + signature@1 { + algo = "sha1,rsa2048"; + key-name-hint = "dev"; + }; + }; + ramdisk@1 { + description = "snow"; + data = /incbin/("%(ramdisk)s"); + type = "ramdisk"; + arch = "sandbox"; + os = "linux"; + %(ramdisk_load)s + compression = "none"; + }; + }; + configurations { + default = "conf@1"; + conf@1 { + kernel = "kernel@1"; + fdt = "fdt@1"; + %(ramdisk_config)s + }; + }; +}; +''' + +# Define a base FDT - currently we don't use anything in this +base_fdt = ''' +/dts-v1/; + +/ { + model = "Sandbox Verified Boot Test"; + compatible = "sandbox"; + +}; +''' + +# This is the U-Boot script that is run for each test. First load the fit, +# then do the 'bootm' command, then save out memory from the places where +# we expect 'bootm' to write things. Then quit. +base_script = ''' +sb load host 0 %(fit_addr)x %(fit)s +fdt addr %(fit_addr)x +bootm start %(fit_addr)x +bootm loados +sb save host 0 %(kernel_out)s %(kernel_addr)x %(kernel_size)x +sb save host 0 %(fdt_out)s %(fdt_addr)x %(fdt_size)x +sb save host 0 %(ramdisk_out)s %(ramdisk_addr)x %(ramdisk_size)x +reset +''' + +def make_fname(leaf): + """Make a temporary filename + + Args: + leaf: Leaf name of file to create (within temporary directory) + Return: + Temporary filename + """ + global base_dir + + return os.path.join(base_dir, leaf) + +def filesize(fname): + """Get the size of a file + + Args: + fname: Filename to check + Return: + Size of file in bytes + """ + return os.stat(fname).st_size + +def read_file(fname): + """Read the contents of a file + + Args: + fname: Filename to read + Returns: + Contents of file as a string + """ + with open(fname, 'r') as fd: + return fd.read() + +def make_dtb(): + """Make a sample .dts file and compile it to a .dtb + + Returns: + Filename of .dtb file created + """ + src = make_fname('u-boot.dts') + dtb = make_fname('u-boot.dtb') + with open(src, 'w') as fd: + print >>fd, base_fdt + command.Output('dtc', src, '-O', 'dtb', '-o', dtb) + return dtb + +def make_its(params): + """Make a sample .its file with parameters embedded + + Args: + params: Dictionary containing parameters to embed in the %() strings + Returns: + Filename of .its file created + """ + its = make_fname('test.its') + with open(its, 'w') as fd: + print >>fd, base_its % params + return its + +def make_fit(mkimage, params): + """Make a sample .fit file ready for loading + + This creates a .its script with the selected parameters and uses mkimage to + turn this into a .fit image. + + Args: + mkimage: Filename of 'mkimage' utility + params: Dictionary containing parameters to embed in the %() strings + Return: + Filename of .fit file created + """ + fit = make_fname('test.fit') + its = make_its(params) + command.Output(mkimage, '-f', its, fit) + with open(make_fname('u-boot.dts'), 'w') as fd: + print >>fd, base_fdt + return fit + +def make_kernel(): + """Make a sample kernel with test data + + Returns: + Filename of kernel created + """ + fname = make_fname('test-kernel.bin') + data = '' + for i in range(100): + data += 'this kernel %d is unlikely to boot\n' % i + with open(fname, 'w') as fd: + print >>fd, data + return fname + +def make_ramdisk(): + """Make a sample ramdisk with test data + + Returns: + Filename of ramdisk created + """ + fname = make_fname('test-ramdisk.bin') + data = '' + for i in range(100): + data += 'ramdisk %d was seldom used in the middle ages\n' % i + with open(fname, 'w') as fd: + print >>fd, data + return fname + +def find_matching(text, match): + """Find a match in a line of text, and return the unmatched line portion + + This is used to extract a part of a line from some text. The match string + is used to locate the line - we use the first line that contains that + match text. + + Once we find a match, we discard the match string itself from the line, + and return what remains. + + TODO: If this function becomes more generally useful, we could change it + to use regex and return groups. + + Args: + text: Text to check (each line separated by \n) + match: String to search for + Return: + String containing unmatched portion of line + Exceptions: + ValueError: If match is not found + + >>> find_matching('first line:10\\nsecond_line:20', 'first line:') + '10' + >>> find_matching('first line:10\\nsecond_line:20', 'second linex') + Traceback (most recent call last): + ... + ValueError: Test aborted + >>> find_matching('first line:10\\nsecond_line:20', 'second_line:') + '20' + """ + for line in text.splitlines(): + pos = line.find(match) + if pos != -1: + return line[:pos] + line[pos + len(match):] + + print "Expected '%s' but not found in output:" + print text + raise ValueError('Test aborted') + +def set_test(name): + """Set the name of the current test and print a message + + Args: + name: Name of test + """ + global test_name + + test_name = name + print name + +def fail(msg): + """Raise an error with a helpful failure message + + Args: + msg: Message to display + """ + raise ValueError("Test '%s' failed: %s" % (test_name, msg)) + +def run_fit_test(mkimage, u_boot): + """Basic sanity check of FIT loading in U-Boot + + TODO: Almost everything: + - hash algorithms - invalid hash/contents should be detected + - signature algorithms - invalid sig/contents should be detected + - compression + - checking that errors are detected like: + - image overwriting + - missing images + - invalid configurations + - incorrect os/arch/type fields + - empty data + - images too large/small + - invalid FDT (e.g. putting a random binary in instead) + - default configuration selection + - bootm command line parameters should have desired effect + - run code coverage to make sure we are testing all the code + """ + global test_name + + # Set up invariant files + control_dtb = make_dtb() + kernel = make_kernel() + ramdisk = make_ramdisk() + kernel_out = make_fname('kernel-out.bin') + fdt_out = make_fname('fdt-out.dtb') + ramdisk_out = make_fname('ramdisk-out.bin') + + # Set up basic parameters with default values + params = { + 'fit_addr' : 0x1000, + + 'kernel' : kernel, + 'kernel_out' : kernel_out, + 'kernel_addr' : 0x40000, + 'kernel_size' : filesize(kernel), + + 'fdt_out' : fdt_out, + 'fdt_addr' : 0x80000, + 'fdt_size' : filesize(control_dtb), + 'fdt_load' : '', + + 'ramdisk' : ramdisk, + 'ramdisk_out' : ramdisk_out, + 'ramdisk_addr' : 0xc0000, + 'ramdisk_size' : filesize(ramdisk), + 'ramdisk_load' : '', + 'ramdisk_config' : '', + } + + # Make a basic FIT and a script to load it + fit = make_fit(mkimage, params) + params['fit'] = fit + cmd = base_script % params + + # First check that we can load a kernel + # We could perhaps reduce duplication with some loss of readability + set_test('Kernel load') + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(kernel) != read_file(kernel_out): + fail('Kernel not loaded') + if read_file(control_dtb) == read_file(fdt_out): + fail('FDT loaded but should be ignored') + if read_file(ramdisk) == read_file(ramdisk_out): + fail('Ramdisk loaded but should not be') + + # Find out the offset in the FIT where U-Boot has found the FDT + line = find_matching(stdout, 'Booting using the fdt blob at ') + fit_offset = int(line, 16) - params['fit_addr'] + fdt_magic = struct.pack('>L', 0xd00dfeed) + data = read_file(fit) + + # Now find where it actually is in the FIT (skip the first word) + real_fit_offset = data.find(fdt_magic, 4) + if fit_offset != real_fit_offset: + fail('U-Boot loaded FDT from offset %#x, FDT is actually at %#x' % + (fit_offset, real_fit_offset)) + + # Now a kernel and an FDT + set_test('Kernel + FDT load') + params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr'] + fit = make_fit(mkimage, params) + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(kernel) != read_file(kernel_out): + fail('Kernel not loaded') + if read_file(control_dtb) != read_file(fdt_out): + fail('FDT not loaded') + if read_file(ramdisk) == read_file(ramdisk_out): + fail('Ramdisk loaded but should not be') + + # Try a ramdisk + set_test('Kernel + FDT + Ramdisk load') + params['ramdisk_config'] = 'ramdisk = "ramdisk@1";' + params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr'] + fit = make_fit(mkimage, params) + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(ramdisk) != read_file(ramdisk_out): + fail('Ramdisk not loaded') + +def run_tests(): + """Parse options, run the FIT tests and print the result""" + global base_path, base_dir + + # Work in a temporary directory + base_dir = tempfile.mkdtemp() + parser = OptionParser() + parser.add_option('-u', '--u-boot', + default=os.path.join(base_path, 'u-boot'), + help='Select U-Boot sandbox binary') + parser.add_option('-k', '--keep', action='store_true', + help="Don't delete temporary directory even when tests pass") + parser.add_option('-t', '--selftest', action='store_true', + help='Run internal self tests') + (options, args) = parser.parse_args() + + # Find the path to U-Boot, and assume mkimage is in its tools/mkimage dir + base_path = os.path.dirname(options.u_boot) + mkimage = os.path.join(base_path, 'tools/mkimage') + + # There are a few doctests - handle these here + if options.selftest: + doctest.testmod() + return + + title = 'FIT Tests' + print title, '\n', '=' * len(title) + + run_fit_test(mkimage, options.u_boot) + + print '\nTests passed' + print 'Caveat: this is only a sanity check - test coverage is poor' + + # Remove the tempoerary directory unless we are asked to keep it + if options.keep: + print "Output files are in '%s'" % base_dir + else: + shutil.rmtree(base_dir) + +run_tests() diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl index 9f23901..896e2bc 100755 --- a/tools/checkpatch.pl +++ b/tools/checkpatch.pl @@ -273,6 +273,7 @@ our $logFunctions = qr{(?x: WARN(?:_RATELIMIT|_ONCE|)| panic| debug| + printf| MODULE_[A-Z_]+ )}; diff --git a/tools/mkimage.h b/tools/mkimage.h index e07a615..03c6c8f 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -44,12 +44,24 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +static inline void *map_sysmem(ulong paddr, unsigned long len) +{ + return (void *)(uintptr_t)paddr; +} + +static inline ulong map_to_sysmem(void *ptr) +{ + return (ulong)(uintptr_t)ptr; +} + #define MKIMAGE_TMPFILE_SUFFIX ".tmp" #define MKIMAGE_MAX_TMPFILE_LEN 256 #define MKIMAGE_DEFAULT_DTC_OPTIONS "-I dts -O dtb -p 500" #define MKIMAGE_MAX_DTC_CMDLINE_LEN 512 #define MKIMAGE_DTC "dtc" /* assume dtc is in $PATH */ +#define IH_ARCH_DEFAULT IH_ARCH_INVALID + /* * This structure defines all such variables those are initialized by * mkimage main core and need to be referred by image type specific |