summaryrefslogtreecommitdiffstats
path: root/drivers/hab/hab.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hab/hab.c')
-rw-r--r--drivers/hab/hab.c226
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);