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.c215
1 files changed, 185 insertions, 30 deletions
diff --git a/drivers/hab/hab.c b/drivers/hab/hab.c
index 2746f27a1e..ed091058d8 100644
--- a/drivers/hab/hab.c
+++ b/drivers/hab/hab.c
@@ -5,14 +5,17 @@
#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)
{
@@ -94,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);
}
@@ -150,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;
@@ -161,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;
@@ -173,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 = {
@@ -188,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;
}
@@ -318,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);
@@ -339,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);
@@ -351,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);