Home | History | Annotate | Download | only in common
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright 2015 Freescale Semiconductor, Inc.
      4  */
      5 
      6 #include <common.h>
      7 #include <dm.h>
      8 #include <fsl_validate.h>
      9 #include <fsl_secboot_err.h>
     10 #include <fsl_sfp.h>
     11 #include <dm/root.h>
     12 
     13 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_FRAMEWORK)
     14 #include <spl.h>
     15 #endif
     16 
     17 #ifdef CONFIG_ADDR_MAP
     18 #include <asm/mmu.h>
     19 #endif
     20 
     21 #ifdef CONFIG_FSL_CORENET
     22 #include <asm/fsl_pamu.h>
     23 #endif
     24 
     25 #ifdef CONFIG_ARCH_LS1021A
     26 #include <asm/arch/immap_ls102xa.h>
     27 #endif
     28 
     29 #if defined(CONFIG_MPC85xx)
     30 #define CONFIG_DCFG_ADDR	CONFIG_SYS_MPC85xx_GUTS_ADDR
     31 #else
     32 #define CONFIG_DCFG_ADDR	CONFIG_SYS_FSL_GUTS_ADDR
     33 #endif
     34 
     35 #ifdef CONFIG_SYS_FSL_CCSR_GUR_LE
     36 #define gur_in32(a)       in_le32(a)
     37 #else
     38 #define gur_in32(a)       in_be32(a)
     39 #endif
     40 
     41 /* Check the Boot Mode. If Secure, return 1 else return 0 */
     42 int fsl_check_boot_mode_secure(void)
     43 {
     44 	uint32_t val;
     45 	struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
     46 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_DCFG_ADDR);
     47 
     48 	val = sfp_in32(&sfp_regs->ospr) & ITS_MASK;
     49 	if (val == ITS_MASK)
     50 		return 1;
     51 
     52 #if defined(CONFIG_FSL_CORENET) || !defined(CONFIG_MPC85xx)
     53 	/* For PBL based platforms check the SB_EN bit in RCWSR */
     54 	val = gur_in32(&gur->rcwsr[RCW_SB_EN_REG_INDEX - 1]) & RCW_SB_EN_MASK;
     55 	if (val == RCW_SB_EN_MASK)
     56 		return 1;
     57 #endif
     58 
     59 #if defined(CONFIG_MPC85xx) && !defined(CONFIG_FSL_CORENET)
     60 	/* For Non-PBL Platforms, check the Device Status register 2*/
     61 	val = gur_in32(&gur->pordevsr2) & MPC85xx_PORDEVSR2_SBC_MASK;
     62 	if (val != MPC85xx_PORDEVSR2_SBC_MASK)
     63 		return 1;
     64 
     65 #endif
     66 	return 0;
     67 }
     68 
     69 #ifndef CONFIG_SPL_BUILD
     70 int fsl_setenv_chain_of_trust(void)
     71 {
     72 	/* Check Boot Mode
     73 	 * If Boot Mode is Non-Secure, no changes are required
     74 	 */
     75 	if (fsl_check_boot_mode_secure() == 0)
     76 		return 0;
     77 
     78 	/* If Boot mode is Secure, set the environment variables
     79 	 * bootdelay = 0 (To disable Boot Prompt)
     80 	 * bootcmd = CONFIG_CHAIN_BOOT_CMD (Validate and execute Boot script)
     81 	 */
     82 	env_set("bootdelay", "0");
     83 
     84 #ifdef CONFIG_ARM
     85 	env_set("secureboot", "y");
     86 #else
     87 	env_set("bootcmd", CONFIG_CHAIN_BOOT_CMD);
     88 #endif
     89 
     90 	return 0;
     91 }
     92 #endif
     93 
     94 #ifdef CONFIG_SPL_BUILD
     95 void spl_validate_uboot(uint32_t hdr_addr, uintptr_t img_addr)
     96 {
     97 	int res;
     98 
     99 	/*
    100 	 * Check Boot Mode
    101 	 * If Boot Mode is Non-Secure, skip validation
    102 	 */
    103 	if (fsl_check_boot_mode_secure() == 0)
    104 		return;
    105 
    106 	printf("SPL: Validating U-Boot image\n");
    107 
    108 #ifdef CONFIG_ADDR_MAP
    109 	init_addr_map();
    110 #endif
    111 
    112 #ifdef CONFIG_FSL_CORENET
    113 	if (pamu_init() < 0)
    114 		fsl_secboot_handle_error(ERROR_ESBC_PAMU_INIT);
    115 #endif
    116 
    117 #ifdef CONFIG_FSL_CAAM
    118 	if (sec_init() < 0)
    119 		fsl_secboot_handle_error(ERROR_ESBC_SEC_INIT);
    120 #endif
    121 
    122 /*
    123  * dm_init_and_scan() is called as part of common SPL framework, so no
    124  * need to call it again but in case of powerpc platforms which currently
    125  * do not use common SPL framework, so need to call this function here.
    126  */
    127 #if defined(CONFIG_SPL_DM) && (!defined(CONFIG_SPL_FRAMEWORK))
    128 	dm_init_and_scan(true);
    129 #endif
    130 	res = fsl_secboot_validate(hdr_addr, CONFIG_SPL_UBOOT_KEY_HASH,
    131 				   &img_addr);
    132 
    133 	if (res == 0)
    134 		printf("SPL: Validation of U-boot successful\n");
    135 }
    136 
    137 #ifdef CONFIG_SPL_FRAMEWORK
    138 /* Override weak funtion defined in SPL framework to enable validation
    139  * of main u-boot image before jumping to u-boot image.
    140  */
    141 void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
    142 {
    143 	typedef void __noreturn (*image_entry_noargs_t)(void);
    144 	uint32_t hdr_addr;
    145 
    146 	image_entry_noargs_t image_entry =
    147 		(image_entry_noargs_t)(unsigned long)spl_image->entry_point;
    148 
    149 	hdr_addr = (spl_image->entry_point + spl_image->size -
    150 			CONFIG_U_BOOT_HDR_SIZE);
    151 	spl_validate_uboot(hdr_addr, (uintptr_t)spl_image->entry_point);
    152 	/*
    153 	 * In case of failure in validation, spl_validate_uboot would
    154 	 * not return back in case of Production environment with ITS=1.
    155 	 * Thus U-Boot will not start.
    156 	 * In Development environment (ITS=0 and SB_EN=1), the function
    157 	 * may return back in case of non-fatal failures.
    158 	 */
    159 
    160 	debug("image entry point: 0x%lX\n", spl_image->entry_point);
    161 	image_entry();
    162 }
    163 #endif /* ifdef CONFIG_SPL_FRAMEWORK */
    164 #endif /* ifdef CONFIG_SPL_BUILD */
    165