diff options
Diffstat (limited to 'drivers/hab/hab.c')
-rw-r--r-- | drivers/hab/hab.c | 226 |
1 files changed, 186 insertions, 40 deletions
diff --git a/drivers/hab/hab.c b/drivers/hab/hab.c index a346e01567..ed091058d8 100644 --- a/drivers/hab/hab.c +++ b/drivers/hab/hab.c @@ -1,27 +1,21 @@ -/* - * 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; version 2. - * - * 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. - */ +// SPDX-License-Identifier: GPL-2.0-only #define pr_fmt(fmt) "HAB: " fmt #include <common.h> #include <fcntl.h> #include <environment.h> #include <libfile.h> -#include <mach/generic.h> +#include <mach/imx/generic.h> #include <hab.h> -#include <regmap.h> +#include <linux/regmap.h> #include <fs.h> -#include <mach/iim.h> -#include <mach/imx25-fusemap.h> -#include <mach/ocotp.h> -#include <mach/imx6-fusemap.h> +#include <mach/imx/iim.h> +#include <mach/imx/imx25-fusemap.h> +#include <mach/imx/ocotp.h> +#include <mach/imx/imx6-fusemap.h> +#include <mach/imx/ele.h> + +#include "hab.h" bool imx_hab_srk_hash_valid(const void *buf) { @@ -103,7 +97,7 @@ static int imx_hab_permanent_write_enable_iim(int enable) return imx_iim_permanent_write(enable); } -static int imx_hab_lockdown_device_iim(void) +static int imx_hab_lockdown_device_iim(unsigned flags) { return imx_iim_write_field(IMX25_IIM_HAB_TYPE, 3); } @@ -159,7 +153,7 @@ static int imx_hab_permanent_write_enable_ocotp(int enable) return imx_ocotp_permanent_write(enable); } -static int imx_hab_lockdown_device_ocotp(void) +static int imx6_hab_lockdown_device_ocotp(unsigned flags) { int ret; @@ -170,7 +164,22 @@ static int imx_hab_lockdown_device_ocotp(void) return imx_ocotp_write_field(OCOTP_SEC_CONFIG_1, 1); } -static int imx_hab_device_locked_down_ocotp(void) +static int imx8m_hab_lockdown_device_ocotp(unsigned flags) +{ + int ret; + + ret = imx_ocotp_write_field(MX8M_OCOTP_SEC_CONFIG_1, 1); + if (ret < 0) + return ret; + + /* Only i.MX8MQ requires fusing of DIR_BT_DIS */ + if (!cpu_is_mx8mq()) + return ret; + + return imx_ocotp_write_field(MX8MQ_OCOTP_DIR_BT_DIS, 1); +} + +static int imx6_hab_device_locked_down_ocotp(void) { int ret; unsigned int v; @@ -182,13 +191,25 @@ static int imx_hab_device_locked_down_ocotp(void) return v; } +static int imx8m_hab_device_locked_down_ocotp(void) +{ + int ret; + unsigned int v; + + ret = imx_ocotp_read_field(MX8M_OCOTP_SEC_CONFIG_1, &v); + if (ret < 0) + return ret; + + return v; +} + struct imx_hab_ops { - int (*init)(void); int (*write_srk_hash)(const u8 *srk, unsigned flags); int (*read_srk_hash)(u8 *srk); int (*permanent_write_enable)(int enable); - int (*lockdown_device)(void); + int (*lockdown_device)(unsigned flags); int (*device_locked_down)(void); + int (*print_status)(void); }; static struct imx_hab_ops imx_hab_ops_iim = { @@ -197,39 +218,143 @@ static struct imx_hab_ops imx_hab_ops_iim = { .lockdown_device = imx_hab_lockdown_device_iim, .device_locked_down = imx_hab_device_locked_down_iim, .permanent_write_enable = imx_hab_permanent_write_enable_iim, + .print_status = imx25_hab_print_status, }; -static struct imx_hab_ops imx_hab_ops_ocotp = { +static struct imx_hab_ops imx6_hab_ops_ocotp = { .write_srk_hash = imx_hab_write_srk_hash_ocotp, .read_srk_hash = imx_hab_read_srk_hash_ocotp, - .lockdown_device = imx_hab_lockdown_device_ocotp, - .device_locked_down = imx_hab_device_locked_down_ocotp, + .lockdown_device = imx6_hab_lockdown_device_ocotp, + .device_locked_down = imx6_hab_device_locked_down_ocotp, .permanent_write_enable = imx_hab_permanent_write_enable_ocotp, + .print_status = imx6_hab_print_status, }; -static struct imx_hab_ops *imx_get_hab_ops(void) +static struct imx_hab_ops imx8m_hab_ops_ocotp = { + .write_srk_hash = imx_hab_write_srk_hash_ocotp, + .read_srk_hash = imx_hab_read_srk_hash_ocotp, + .lockdown_device = imx8m_hab_lockdown_device_ocotp, + .device_locked_down = imx8m_hab_device_locked_down_ocotp, + .permanent_write_enable = imx_hab_permanent_write_enable_ocotp, + .print_status = imx8m_hab_print_status, +}; + +static int imx_ahab_write_srk_hash(const u8 *__newsrk, unsigned flags) +{ + u32 *newsrk = (u32 *)__newsrk; + u32 resp; + int ret, i; + + if (!(flags & IMX_SRK_HASH_WRITE_PERMANENT)) { + pr_err("Cannot write fuses temporarily\n"); + return -EPERM; + } + + for (i = 0; i < 32 / sizeof(u32); i++) { + ret = ele_write_fuse(0x80 + i, newsrk[i], false, &resp); + if (ret) + pr_err("Writing fuse index 0x%02x failed with %d, response 0x%08x\n", + i, ret, resp); + } + + return 0; +} + +static int imx_ahab_read_srk_hash(u8 *__srk) +{ + u32 *srk = (u32 *)__srk; + u32 resp; + int ret, i; + + for (i = 0; i < SRK_HASH_SIZE / sizeof(uint32_t); i++) { + ret = ele_read_common_fuse(0x80 + i, &srk[i], &resp); + if (ret < 0) + return ret; + } + + return 0; +} + +static int imx_ahab_permanent_write_enable(int enable) +{ + return 0; +} + +static int imx_ahab_lockdown_device(unsigned flags) { - static struct imx_hab_ops *ops, *tmp; + unsigned int lc; int ret; + if (!(flags & IMX_SRK_HASH_WRITE_PERMANENT)) { + pr_err("Cannot write fuses temporarily\n"); + return -EPERM; + } + + lc = imx93_ahab_read_lifecycle(); + if (lc == ELE_LIFECYCLE_OEM_CLOSED) { + pr_info("already OEM closed\n"); + return 0; + } + + if (lc != ELE_LIFECYCLE_OEM_OPEN) { + pr_err("Current lifecycle is NOT OEM open, can't move to OEM closed\n"); + return -EPERM; + } + + ret = ele_forward_lifecycle(ELE_LIFECYCLE_OEM_CLOSED, NULL); + if (ret) { + printf("failed to forward lifecycle to OEM closed\n"); + return ret; + } + + printf("Change to OEM closed successfully\n"); + + return 0; +} + +static int imx_ahab_device_locked_down(void) +{ + return imx93_ahab_read_lifecycle() != ELE_LIFECYCLE_OEM_OPEN; +} + +static int imx_ahab_print_status(void) +{ + int ret; + + ret = ele_print_events(); + if (ret) + pr_err("Cannot read ELE events: %pe\n", ERR_PTR(ret)); + + return ret; +} + +static struct imx_hab_ops imx93_ahab_ops = { + .write_srk_hash = imx_ahab_write_srk_hash, + .read_srk_hash = imx_ahab_read_srk_hash, + .lockdown_device = imx_ahab_lockdown_device, + .device_locked_down = imx_ahab_device_locked_down, + .permanent_write_enable = imx_ahab_permanent_write_enable, + .print_status = imx_ahab_print_status, +}; + +static struct imx_hab_ops *imx_get_hab_ops(void) +{ + static struct imx_hab_ops *ops; + if (ops) return ops; - if (IS_ENABLED(CONFIG_HABV3) && (cpu_is_mx25() || cpu_is_mx35())) - tmp = &imx_hab_ops_iim; - else if (IS_ENABLED(CONFIG_HABV4) && (cpu_is_mx6() || cpu_is_mx8mq())) - tmp = &imx_hab_ops_ocotp; + if (IS_ENABLED(CONFIG_HABV3) && cpu_is_mx25()) + ops = &imx_hab_ops_iim; + else if (IS_ENABLED(CONFIG_HABV4) && cpu_is_mx6()) + ops = &imx6_hab_ops_ocotp; + else if (IS_ENABLED(CONFIG_HABV4) && cpu_is_mx8m()) + ops = &imx8m_hab_ops_ocotp; + else if (IS_ENABLED(CONFIG_AHAB) && cpu_is_mx93()) + ops = &imx93_ahab_ops; else return NULL; - if (tmp->init) { - ret = tmp->init(); - if (ret) - return NULL; - } - - ops = tmp; - return ops; } @@ -327,7 +452,7 @@ int imx_hab_write_srk_hash_hex(const char *srkhash, unsigned flags) int imx_hab_lockdown_device(unsigned flags) { struct imx_hab_ops *ops = imx_get_hab_ops(); - u8 srk[SRK_HASH_SIZE]; + u8 srk[SRK_HASH_SIZE] = {}; int ret; ret = imx_hab_read_srk_hash(srk); @@ -348,7 +473,7 @@ int imx_hab_lockdown_device(unsigned flags) return ret; } - ret = ops->lockdown_device(); + ret = ops->lockdown_device(flags); if (flags & IMX_SRK_HASH_WRITE_PERMANENT) ops->permanent_write_enable(0); @@ -360,5 +485,26 @@ int imx_hab_device_locked_down(void) { struct imx_hab_ops *ops = imx_get_hab_ops(); + if (!ops) + return -ENOSYS; + return ops->device_locked_down(); } + +int imx_hab_print_status(void) +{ + struct imx_hab_ops *ops = imx_get_hab_ops(); + + if (!ops) + return -ENOSYS; + + return ops->print_status(); +} + +static int init_imx_hab_print_status(void) +{ + imx_hab_print_status(); + + return 0; +} +postmmu_initcall(init_imx_hab_print_status); |