global: Migrate CONFIG_SYS_FSL* symbols to the CFG_SYS namespace
[platform/kernel/u-boot.git] / board / freescale / common / fsl_validate.c
index 8fd6dd6..3424d49 100644 (file)
@@ -1,23 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2015 Freescale Semiconductor, Inc.
- *
- * SPDX-License-Identifier:    GPL-2.0+
+ * Copyright 2021-2022 NXP
  */
 
 #include <common.h>
+#include <dm.h>
 #include <fsl_validate.h>
 #include <fsl_secboot_err.h>
 #include <fsl_sfp.h>
 #include <fsl_sec.h>
 #include <command.h>
+#include <log.h>
 #include <malloc.h>
-#include <dm/uclass.h>
 #include <u-boot/rsa-mod-exp.h>
 #include <hash.h>
 #include <fsl_secboot_err.h>
-#ifdef CONFIG_LS102XA
+#ifdef CONFIG_ARCH_LS1021A
 #include <asm/arch/immap_ls102xa.h>
 #endif
+#include <dm/lists.h>
 
 #define SHA256_BITS    256
 #define SHA256_BYTES   (256/8)
 #define CHECK_KEY_LEN(key_len) (((key_len) == 2 * KEY_SIZE_BYTES / 4) || \
                                 ((key_len) == 2 * KEY_SIZE_BYTES / 2) || \
                                 ((key_len) == 2 * KEY_SIZE_BYTES))
+#if defined(CONFIG_FSL_ISBC_KEY_EXT)
+/* Global data structure */
+static struct fsl_secboot_glb glb;
+#endif
 
 /* This array contains DER value for SHA-256 */
 static const u8 hash_identifier[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
@@ -35,7 +41,13 @@ static const u8 hash_identifier[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
                };
 
 static u8 hash_val[SHA256_BYTES];
+
+#ifdef CONFIG_ESBC_HDR_LS
+/* New Barker Code for LS ESBC Header */
+static const u8 barker_code[ESBC_BARKER_LEN] = { 0x12, 0x19, 0x20, 0x01 };
+#else
 static const u8 barker_code[ESBC_BARKER_LEN] = { 0x68, 0x39, 0x27, 0x81 };
+#endif
 
 void branch_to_self(void) __attribute__ ((noreturn));
 
@@ -54,7 +66,7 @@ self:
 #if defined(CONFIG_FSL_ISBC_KEY_EXT)
 static u32 check_ie(struct fsl_secboot_img_priv *img)
 {
-       if (img->hdr.ie_flag)
+       if (img->hdr.ie_flag & IE_FLAG_MASK)
                return 1;
 
        return 0;
@@ -67,9 +79,11 @@ static u32 check_ie(struct fsl_secboot_img_priv *img)
  * address
  */
 #if defined(CONFIG_MPC85xx)
+#include <flash.h>
+
 int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
 {
-       struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+       struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_MPC85xx_GUTS_ADDR);
        u32 csf_hdr_addr = in_be32(&gur->scratchrw[0]);
        u32 csf_flash_offset = csf_hdr_addr & ~(CONFIG_SYS_PBI_FLASH_BASE);
        u32 flash_addr, addr;
@@ -100,7 +114,7 @@ int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
  */
 int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
 {
-       struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+       struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR);
        u32 csf_hdr_addr = in_be32(&gur->scratchrw[0]);
 
        if (memcmp((u8 *)(uintptr_t)csf_hdr_addr,
@@ -113,7 +127,21 @@ int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
 }
 #endif
 
-static int get_ie_info_addr(u32 *ie_addr)
+#if defined(CONFIG_ESBC_HDR_LS)
+static int get_ie_info_addr(uintptr_t *ie_addr)
+{
+       struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR);
+       /* For LS-CH3, the address of IE Table is
+        * stated in Scratch13 and scratch14 of DCFG.
+        * Bootrom validates this table while validating uboot.
+        * DCFG is LE*/
+       *ie_addr = in_le32(&gur->scratchrw[SCRATCH_IE_HIGH_ADR - 1]);
+       *ie_addr = *ie_addr << 32;
+       *ie_addr |= in_le32(&gur->scratchrw[SCRATCH_IE_LOW_ADR - 1]);
+       return 0;
+}
+#else /* CONFIG_ESBC_HDR_LS */
+static int get_ie_info_addr(uintptr_t *ie_addr)
 {
        struct fsl_secboot_img_hdr *hdr;
        struct fsl_secboot_sg_table *sg_tbl;
@@ -141,26 +169,35 @@ static int get_ie_info_addr(u32 *ie_addr)
 
        /* IE Key Table is the first entry in the SG Table */
 #if defined(CONFIG_MPC85xx)
-       *ie_addr = (sg_tbl->src_addr & ~(CONFIG_SYS_PBI_FLASH_BASE)) +
-                  flash_base_addr;
+       *ie_addr = (uintptr_t)((sg_tbl->src_addr &
+                       ~(CONFIG_SYS_PBI_FLASH_BASE)) +
+                       flash_base_addr);
 #else
-       *ie_addr = sg_tbl->src_addr;
+       *ie_addr = (uintptr_t)sg_tbl->src_addr;
 #endif
 
-       debug("IE Table address is %x\n", *ie_addr);
+       debug("IE Table address is %lx\n", *ie_addr);
        return 0;
 }
-
+#endif /* CONFIG_ESBC_HDR_LS */
 #endif
 
 #ifdef CONFIG_KEY_REVOCATION
 /* This function checks srk_table_flag in header and set/reset srk_flag.*/
 static u32 check_srk(struct fsl_secboot_img_priv *img)
 {
+#ifdef CONFIG_ESBC_HDR_LS
+       /* In LS, No SRK Flag as SRK is always present if IE not present*/
+#if defined(CONFIG_FSL_ISBC_KEY_EXT)
+       return !check_ie(img);
+#endif
+       return 1;
+#else
        if (img->hdr.len_kr.srk_table_flag & SRK_FLAG)
                return 1;
 
        return 0;
+#endif
 }
 
 /* This function returns ospr's key_revoc values.*/
@@ -223,6 +260,7 @@ static u32 read_validate_srk_tbl(struct fsl_secboot_img_priv *img)
 }
 #endif
 
+#ifndef CONFIG_ESBC_HDR_LS
 static u32 read_validate_single_key(struct fsl_secboot_img_priv *img)
 {
        struct fsl_secboot_img_hdr *hdr = &img->hdr;
@@ -238,16 +276,32 @@ static u32 read_validate_single_key(struct fsl_secboot_img_priv *img)
 
        return 0;
 }
+#endif /* CONFIG_ESBC_HDR_LS */
 
 #if defined(CONFIG_FSL_ISBC_KEY_EXT)
+
+static void install_ie_tbl(uintptr_t ie_tbl_addr,
+               struct fsl_secboot_img_priv *img)
+{
+       /* Copy IE tbl to Global Data */
+       memcpy(&glb.ie_tbl, (u8 *)ie_tbl_addr, sizeof(struct ie_key_info));
+       img->ie_addr = (uintptr_t)&glb.ie_tbl;
+       glb.ie_addr = img->ie_addr;
+}
+
 static u32 read_validate_ie_tbl(struct fsl_secboot_img_priv *img)
 {
        struct fsl_secboot_img_hdr *hdr = &img->hdr;
        u32 ie_key_len, ie_revoc_flag, ie_num;
        struct ie_key_info *ie_info;
 
-       if (get_ie_info_addr(&img->ie_addr))
-               return ERROR_IE_TABLE_NOT_FOUND;
+       if (!img->ie_addr) {
+               if (get_ie_info_addr(&img->ie_addr))
+                       return ERROR_IE_TABLE_NOT_FOUND;
+               else
+                       install_ie_tbl(img->ie_addr, img);
+               }
+
        ie_info = (struct ie_key_info *)(uintptr_t)img->ie_addr;
        if (ie_info->num_keys == 0 || ie_info->num_keys > 32)
                return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_NUM_ENTRY;
@@ -288,30 +342,20 @@ static inline u32 get_key_len(struct fsl_secboot_img_priv *img)
  */
 static void fsl_secboot_header_verification_failure(void)
 {
-       struct ccsr_sec_mon_regs *sec_mon_regs = (void *)
-                                               (CONFIG_SYS_SEC_MON_ADDR);
        struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
-       u32 sts = sec_mon_in32(&sec_mon_regs->hp_stat);
 
        /* 29th bit of OSPR is ITS */
        u32 its = sfp_in32(&sfp_regs->ospr) >> 2;
 
-       /*
-        * Read the SEC_MON status register
-        * Read SSM_ST field
-        */
-       sts = sec_mon_in32(&sec_mon_regs->hp_stat);
-       if ((sts & HPSR_SSM_ST_MASK) == HPSR_SSM_ST_TRUST) {
-               if (its == 1)
-                       change_sec_mon_state(HPSR_SSM_ST_TRUST,
-                                            HPSR_SSM_ST_SOFT_FAIL);
-               else
-                       change_sec_mon_state(HPSR_SSM_ST_TRUST,
-                                            HPSR_SSM_ST_NON_SECURE);
-       }
+       if (its == 1)
+               set_sec_mon_state(HPSR_SSM_ST_SOFT_FAIL);
+       else
+               set_sec_mon_state(HPSR_SSM_ST_NON_SECURE);
 
        printf("Generating reset request\n");
        do_reset(NULL, 0, 0, NULL);
+       /* If reset doesn't coocur, halt execution */
+       do_esbc_halt(NULL, 0, 0, NULL);
 }
 
 /*
@@ -323,29 +367,20 @@ static void fsl_secboot_header_verification_failure(void)
  */
 static void fsl_secboot_image_verification_failure(void)
 {
-       struct ccsr_sec_mon_regs *sec_mon_regs = (void *)
-                                               (CONFIG_SYS_SEC_MON_ADDR);
        struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
-       u32 sts = sec_mon_in32(&sec_mon_regs->hp_stat);
 
        u32 its = (sfp_in32(&sfp_regs->ospr) & ITS_MASK) >> ITS_BIT;
 
-       /*
-        * Read the SEC_MON status register
-        * Read SSM_ST field
-        */
-       sts = sec_mon_in32(&sec_mon_regs->hp_stat);
-       if ((sts & HPSR_SSM_ST_MASK) == HPSR_SSM_ST_TRUST) {
-               if (its == 1) {
-                       change_sec_mon_state(HPSR_SSM_ST_TRUST,
-                                            HPSR_SSM_ST_SOFT_FAIL);
-
-                       printf("Generating reset request\n");
-                       do_reset(NULL, 0, 0, NULL);
-               } else {
-                       change_sec_mon_state(HPSR_SSM_ST_TRUST,
-                                            HPSR_SSM_ST_NON_SECURE);
-               }
+       if (its == 1) {
+               set_sec_mon_state(HPSR_SSM_ST_SOFT_FAIL);
+
+               printf("Generating reset request\n");
+               do_reset(NULL, 0, 0, NULL);
+               /* If reset doesn't coocur, halt execution */
+               do_esbc_halt(NULL, 0, 0, NULL);
+
+       } else {
+               set_sec_mon_state(HPSR_SSM_ST_NON_SECURE);
        }
 }
 
@@ -362,6 +397,7 @@ static void fsl_secboot_bootscript_parse_failure(void)
  */
 void fsl_secboot_handle_error(int error)
 {
+#ifndef CONFIG_SPL_BUILD
        const struct fsl_secboot_errcode *e;
 
        for (e = fsl_secboot_errcodes; e->errcode != ERROR_ESBC_CLIENT_MAX;
@@ -369,6 +405,9 @@ void fsl_secboot_handle_error(int error)
                if (e->errcode == error)
                        printf("ERROR :: %x :: %s\n", error, e->name);
        }
+#else
+       printf("ERROR :: %x\n", error);
+#endif
 
        /* If Boot Mode is secure, transition the SNVS state and issue
         * reset based on type of failure and ITS setting.
@@ -388,6 +427,7 @@ void fsl_secboot_handle_error(int error)
        case ERROR_ESBC_CLIENT_HEADER_SIG_KEY_MOD:
        case ERROR_ESBC_CLIENT_HEADER_SG_ESBC_EP:
        case ERROR_ESBC_CLIENT_HEADER_SG_ENTIRES_BAD:
+       case ERROR_KEY_TABLE_NOT_FOUND:
 #ifdef CONFIG_KEY_REVOCATION
        case ERROR_ESBC_CLIENT_HEADER_KEY_REVOKED:
        case ERROR_ESBC_CLIENT_HEADER_INVALID_SRK_NUM_ENTRY:
@@ -463,7 +503,6 @@ static int calc_img_key_hash(struct fsl_secboot_img_priv *img)
        ret = algo->hash_init(algo, &ctx);
        if (ret)
                return ret;
-
        /* Update hash for ESBC key */
 #ifdef CONFIG_KEY_REVOCATION
        if (check_srk(img)) {
@@ -478,12 +517,12 @@ static int calc_img_key_hash(struct fsl_secboot_img_priv *img)
                        img->img_key, img->key_len, 1);
        if (ret)
                return ret;
-
        /* Copy hash at destination buffer */
        ret = algo->hash_finish(algo, ctx, hash_val, algo->digest_size);
-       if (ret)
+       if (ret) {
+               free(ctx);
                return ret;
-
+       }
        for (i = 0; i < SHA256_BYTES; i++)
                img->img_key_hash[i] = hash_val[i];
 
@@ -536,23 +575,32 @@ static int calc_esbchdr_esbc_hash(struct fsl_secboot_img_priv *img)
        if (!key_hash && check_ie(img))
                key_hash = 1;
 #endif
-       if (!key_hash)
+#ifndef CONFIG_ESBC_HDR_LS
+/* No single key support in LS ESBC header */
+       if (!key_hash) {
                ret = algo->hash_update(algo, ctx,
                        img->img_key, img->hdr.key_len, 0);
+               key_hash = 1;
+       }
+#endif
        if (ret)
                return ret;
-
+       if (!key_hash) {
+               free(ctx);
+               return ERROR_KEY_TABLE_NOT_FOUND;
+       }
        /* Update hash for actual Image */
        ret = algo->hash_update(algo, ctx,
-               (u8 *)img->img_addr, img->img_size, 1);
+               (u8 *)(*(img->img_addr_ptr)), img->img_size, 1);
        if (ret)
                return ret;
 
        /* Copy hash at destination buffer */
        ret = algo->hash_finish(algo, ctx, hash_val, algo->digest_size);
-       if (ret)
+       if (ret) {
+               free(ctx);
                return ret;
-
+       }
        return 0;
 }
 
@@ -620,14 +668,11 @@ static void construct_img_encoded_hash_second(struct fsl_secboot_img_priv *img)
  */
 static int read_validate_esbc_client_header(struct fsl_secboot_img_priv *img)
 {
-       char buf[20];
        struct fsl_secboot_img_hdr *hdr = &img->hdr;
        void *esbc = (u8 *)(uintptr_t)img->ehdrloc;
        u8 *k, *s;
        u32 ret = 0;
 
-#ifdef CONFIG_KEY_REVOCATION
-#endif
        int  key_found = 0;
 
        /* check barker code */
@@ -637,17 +682,14 @@ static int read_validate_esbc_client_header(struct fsl_secboot_img_priv *img)
        /* If Image Address is not passed as argument to function,
         * then Address and Size must be read from the Header.
         */
-       if (img->img_addr == 0) {
+       if (*(img->img_addr_ptr) == 0) {
        #ifdef CONFIG_ESBC_ADDR_64BIT
-               img->img_addr = hdr->pimg64;
+               *(img->img_addr_ptr) = hdr->pimg64;
        #else
-               img->img_addr = hdr->pimg;
+               *(img->img_addr_ptr) = hdr->pimg;
        #endif
        }
 
-       sprintf(buf, "%lx", img->img_addr);
-       setenv("img_addr", buf);
-
        if (!hdr->img_size)
                return ERROR_ESBC_CLIENT_HEADER_IMG_SIZE;
 
@@ -671,13 +713,17 @@ static int read_validate_esbc_client_header(struct fsl_secboot_img_priv *img)
                key_found = 1;
        }
 #endif
-
+#ifndef CONFIG_ESBC_HDR_LS
+/* Single Key Feature not available in LS ESBC Header */
        if (key_found == 0) {
                ret = read_validate_single_key(img);
                if (ret != 0)
                        return ret;
                key_found = 1;
        }
+#endif
+       if (!key_found)
+               return ERROR_KEY_TABLE_NOT_FOUND;
 
        /* check signaure */
        if (get_key_len(img) == 2 * hdr->sign_len) {
@@ -691,10 +737,12 @@ static int read_validate_esbc_client_header(struct fsl_secboot_img_priv *img)
        }
 
        memcpy(&img->img_sign, esbc + hdr->psign, hdr->sign_len);
-
+/* No SG support in LS-CH3 */
+#ifndef CONFIG_ESBC_HDR_LS
        /* No SG support */
        if (hdr->sg_flag)
                return ERROR_ESBC_CLIENT_HEADER_SG;
+#endif
 
        /* modulus most significant bit should be set */
        k = (u8 *)&img->img_key;
@@ -723,7 +771,7 @@ static inline int str2longbe(const char *p, ulong *num)
        if (!p) {
                return 0;
        } else {
-               tmp = simple_strtoul(p, &endptr, 16);
+               tmp = hextoul(p, &endptr);
                if (sizeof(ulong) == 4)
                        *num = cpu_to_be32(tmp);
                else
@@ -760,6 +808,13 @@ static int calculate_cmp_img_sig(struct fsl_secboot_img_priv *img)
        prop.num_bits = key_len * 8;
        prop.exp_len = key_len;
 
+#if defined(CONFIG_SPL_BUILD)
+       ret = device_bind_driver(NULL, "fsl_rsa_mod_exp", "fsl_rsa_mod_exp", NULL);
+       if (ret) {
+               printf("Couldn't bind fsl_rsa_mod_exp driver (%d)\n", ret);
+               return -EINVAL;
+       }
+#endif
        ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev);
        if (ret) {
                printf("RSA: Can't find Modular Exp implementation\n");
@@ -784,9 +839,37 @@ static int calculate_cmp_img_sig(struct fsl_secboot_img_priv *img)
 
        return 0;
 }
+/* Function to initialize img priv and global data structure
+ */
+static int secboot_init(struct fsl_secboot_img_priv **img_ptr)
+{
+       *img_ptr = malloc(sizeof(struct fsl_secboot_img_priv));
+
+       struct fsl_secboot_img_priv *img = *img_ptr;
+
+       if (!img)
+               return -ENOMEM;
+       memset(img, 0, sizeof(struct fsl_secboot_img_priv));
+
+#if defined(CONFIG_FSL_ISBC_KEY_EXT)
+       if (glb.ie_addr)
+               img->ie_addr = glb.ie_addr;
+#endif
+       return 0;
+}
+
 
+/* haddr - Address of the header of image to be validated.
+ * arg_hash_str - Option hash string. If provided, this
+ * overrides the key hash in the SFP fuses.
+ * img_addr_ptr - Optional pointer to address of image to be validated.
+ * If non zero addr, this overrides the addr of image in header,
+ * otherwise updated to image addr in header.
+ * Acts as both input and output of function.
+ * This pointer shouldn't be NULL.
+ */
 int fsl_secboot_validate(uintptr_t haddr, char *arg_hash_str,
-                       uintptr_t img_addr)
+                       uintptr_t *img_addr_ptr)
 {
        struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
        ulong hash[SHA256_BYTES/sizeof(ulong)];
@@ -797,7 +880,7 @@ int fsl_secboot_validate(uintptr_t haddr, char *arg_hash_str,
        int ret, i, hash_cmd = 0;
        u32 srk_hash[8];
 
-       if (arg_hash_str != NULL) {
+       if (strlen(arg_hash_str) != 0) {
                const char *cp = arg_hash_str;
                int i = 0;
 
@@ -829,17 +912,14 @@ int fsl_secboot_validate(uintptr_t haddr, char *arg_hash_str,
                hash_cmd = 1;
        }
 
-       img = malloc(sizeof(struct fsl_secboot_img_priv));
-
-       if (!img)
-               return -1;
-
-       memset(img, 0, sizeof(struct fsl_secboot_img_priv));
+       ret = secboot_init(&img);
+       if (ret)
+               goto exit;
 
        /* Update the information in Private Struct */
        hdr = &img->hdr;
        img->ehdrloc = haddr;
-       img->img_addr = img_addr;
+       img->img_addr_ptr = img_addr_ptr;
        esbc = (u8 *)img->ehdrloc;
 
        memcpy(hdr, esbc, sizeof(struct fsl_secboot_img_hdr));
@@ -889,5 +969,7 @@ int fsl_secboot_validate(uintptr_t haddr, char *arg_hash_str,
        }
 
 exit:
+       /* Free Img as it was malloc'ed*/
+       free(img);
        return ret;
 }