summaryrefslogtreecommitdiffstats
path: root/scripts/imx/imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/imx/imx.c')
-rw-r--r--scripts/imx/imx.c265
1 files changed, 217 insertions, 48 deletions
diff --git a/scripts/imx/imx.c b/scripts/imx/imx.c
index c820c9a0c8..5ccc116cfe 100644
--- a/scripts/imx/imx.c
+++ b/scripts/imx/imx.c
@@ -1,20 +1,5 @@
-/*
- * (C) Copyright 2016 Sascha Hauer, Pengutronix
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * 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; either version 2 of
- * the License, or (at your option) any later version.
- *
- * 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-or-later
+// SPDX-FileCopyrightText: 2016 Sascha Hauer, Pengutronix
#define _GNU_SOURCE
#include <stdio.h>
@@ -35,6 +20,23 @@
*/
#define ENCRYPT_OFFSET (HEADER_LEN + 0x10)
+static char *strcata(char *str, const char *add)
+{
+ size_t size = (str ? strlen(str) : 0) + strlen(add) + 1;
+ bool need_init = str ? false : true;
+
+ str = realloc(str, size);
+ if (!str)
+ return NULL;
+
+ if (need_init)
+ memset(str, 0, size);
+
+ strcat(str, add);
+
+ return str;
+}
+
static int parse_line(char *line, char *argv[])
{
int nargs = 0;
@@ -214,16 +216,22 @@ static int do_loadaddr(struct config_data *data, int argc, char *argv[])
return 0;
}
-static int do_dcd_offset(struct config_data *data, int argc, char *argv[])
+static int do_ivt_offset(struct config_data *data, int argc, char *argv[])
{
if (argc < 2)
return -EINVAL;
- data->image_dcd_offset = strtoul(argv[1], NULL, 0);
+ data->image_ivt_offset = strtoul(argv[1], NULL, 0);
return 0;
}
+static int do_dcdofs_error(struct config_data *data, int argc, char *argv[])
+{
+ fprintf(stderr, "ERROR: misnomer dcdofs has been renamed to ivtofs. imxcfg must be adapted.\n");
+ return -EINVAL;
+}
+
struct soc_type {
char *name;
int header_version;
@@ -243,6 +251,8 @@ static struct soc_type socs[] = {
{ .name = "imx6", .header_version = 2, .cpu_type = IMX_CPU_IMX6, .header_gap = 0, .first_opcode = 0xea0003fe /* b 0x1000 */},
{ .name = "imx7", .header_version = 2, .cpu_type = IMX_CPU_IMX7, .header_gap = 0, .first_opcode = 0xea0003fe /* b 0x1000 */},
{ .name = "imx8mm", .header_version = 2, .cpu_type = IMX_CPU_IMX8MM, .header_gap = SZ_32K, .first_opcode = 0x14000000 /* b 0x0000 (offset computed) */},
+ { .name = "imx8mn", .header_version = 2, .cpu_type = IMX_CPU_IMX8MN, .header_gap = SZ_32K, .first_opcode = 0x14000000 /* b 0x0000 (offset computed) */},
+ { .name = "imx8mp", .header_version = 2, .cpu_type = IMX_CPU_IMX8MP, .header_gap = SZ_32K, .first_opcode = 0x14000000 /* b 0x0000 (offset computed) */},
{ .name = "imx8mq", .header_version = 2, .cpu_type = IMX_CPU_IMX8MQ, .header_gap = SZ_32K, .first_opcode = 0x14000000 /* b 0x0000 (offset computed) */},
{ .name = "vf610", .header_version = 2, .cpu_type = IMX_CPU_VF610, .header_gap = 0, .first_opcode = 0xea0003fe /* b 0x1000 */},
};
@@ -271,7 +281,7 @@ static int do_soc(struct config_data *data, int argc, char *argv[])
}
}
- fprintf(stderr, "unkown SoC type \"%s\". Known SoCs are:\n", soc);
+ fprintf(stderr, "unknown SoC type \"%s\". Known SoCs are:\n", soc);
for (i = 0; i < ARRAY_SIZE(socs); i++)
fprintf(stderr, "%s ", socs[i].name);
fprintf(stderr, "\n");
@@ -289,16 +299,53 @@ static int do_max_load_size(struct config_data *data, int argc, char *argv[])
return 0;
}
+static int do_hab_qspi(struct config_data *data, int argc, char *argv[])
+{
+ /*
+ * Force 'hab_qspi' to specified before any 'hab' to ensure correct CSF
+ * generation.
+ */
+ if (data->csf) {
+ fprintf(stderr,
+ "'hab_qspi' must be specified before any 'hab' command\n");
+ return -EINVAL;
+ }
+
+ data->hab_qspi_support = true;
+
+ return 0;
+}
+
static int hab_add_str(struct config_data *data, const char *str)
{
- int len = strlen(str);
+ data->csf = strcata(data->csf, str);
+ if (!data->csf)
+ return -ENOMEM;
+
+ if (!data->hab_qspi_support)
+ return 0;
+
+ data->flexspi_csf = strcata(data->flexspi_csf, str);
+ if (!data->flexspi_csf)
+ return -ENOMEM;
- if (data->csf_space < len)
+ return 0;
+}
+
+static int hab_add_barebox_blocks(struct config_data *data,
+ const char *csf_str,
+ const char *flexspi_csf_str)
+{
+ data->csf = strcata(data->csf, csf_str);
+ if (!data->csf)
return -ENOMEM;
- strcat(data->csf, str);
+ if (!flexspi_csf_str)
+ return 0;
- data->csf_space -= len;
+ data->flexspi_csf = strcata(data->flexspi_csf, flexspi_csf_str);
+ if (!data->flexspi_csf)
+ return -ENOMEM;
return 0;
}
@@ -307,14 +354,6 @@ static int do_hab(struct config_data *data, int argc, char *argv[])
{
int i, ret;
- if (!data->csf) {
- data->csf_space = 0x10000;
-
- data->csf = calloc(data->csf_space + 1, 1);
- if (!data->csf)
- return -ENOMEM;
- }
-
for (i = 1; i < argc; i++) {
ret = hab_add_str(data, argv[i]);
if (ret)
@@ -332,12 +371,44 @@ static int do_hab(struct config_data *data, int argc, char *argv[])
return 0;
}
+static void
+imx8m_get_offset_size(struct config_data *data,
+ uint32_t *offset, uint32_t *signed_size,
+ uint32_t *flexspi_offset, uint32_t *flexspi_signed_size)
+{
+ unsigned int hdrlen = HEADER_LEN;
+
+ if (flexspi_image(data))
+ hdrlen += FLEXSPI_HEADER_LEN;
+
+ *signed_size = roundup(data->pbl_code_size + hdrlen, 0x1000);
+ *flexspi_signed_size = roundup(data->pbl_code_size + FLEXSPI_HEADER_LEN,
+ 0x1000);
+
+ *offset += data->header_gap;
+ *flexspi_offset += data->header_gap;
+ /*
+ * Starting with i.MX8MP/N the FlexSPI IVT offset is 0x0 but the primary
+ * image offset is at 0x1000.
+ */
+ if (data->cpu_type != IMX_CPU_IMX8MM)
+ *flexspi_offset += HEADER_LEN;
+
+ if (data->signed_hdmi_firmware_file) {
+ *offset += PLUGIN_HDMI_SIZE;
+ *flexspi_offset += PLUGIN_HDMI_SIZE;
+ }
+}
+
static int do_hab_blocks(struct config_data *data, int argc, char *argv[])
{
- char *str;
+ char *str, *flexspi_str = NULL;
int ret;
+ int i;
uint32_t signed_size = data->load_size;
- uint32_t offset = data->image_dcd_offset;
+ uint32_t flexspi_signed_size = signed_size;
+ uint32_t offset = data->image_ivt_offset;
+ uint32_t flexspi_offset = data->image_flexspi_ivt_offset;
if (!data->csf)
return -EINVAL;
@@ -352,17 +423,21 @@ static int do_hab_blocks(struct config_data *data, int argc, char *argv[])
/*
* Ensure we only sign the PBL for i.MX8MQ
*/
- if (data->pbl_code_size && cpu_is_mx8m(data)) {
- offset += data->header_gap;
- signed_size = roundup(data->pbl_code_size + HEADER_LEN, 0x1000);
- if (data->signed_hdmi_firmware_file)
- offset += PLUGIN_HDMI_SIZE;
- }
+ if (data->pbl_code_size && cpu_is_mx8m(data))
+ imx8m_get_offset_size(data, &offset, &signed_size,
+ &flexspi_offset, &flexspi_signed_size);
if (signed_size > 0) {
- ret = asprintf(&str, "Blocks = 0x%08x 0x%08x 0x%08x \"%s\"\n",
- data->image_load_addr + data->image_dcd_offset, offset,
- signed_size - data->image_dcd_offset, data->outfile);
+ ret = asprintf(&str, "Blocks = 0x%08x 0x%08x 0x%08x \"%s\"",
+ data->image_load_addr + data->image_ivt_offset, offset,
+ signed_size - data->image_ivt_offset, data->outfile);
+ if (data->flexspi_csf)
+ ret |= asprintf(&flexspi_str,
+ "Blocks = 0x%08x 0x%08x 0x%08x \"%s\"",
+ data->image_load_addr +
+ data->image_flexspi_ivt_offset,
+ flexspi_offset, flexspi_signed_size,
+ data->outfile);
} else {
fprintf(stderr, "Invalid signed size area 0x%08x\n",
signed_size);
@@ -372,11 +447,59 @@ static int do_hab_blocks(struct config_data *data, int argc, char *argv[])
if (ret < 0)
return -ENOMEM;
- ret = hab_add_str(data, str);
+ ret = hab_add_barebox_blocks(data, str, flexspi_str);
+ free(str);
+ free(flexspi_str);
if (ret)
return ret;
- return 0;
+ for (i = 1; i < argc; i++) {
+ uint32_t addr;
+ uint32_t off;
+ uint32_t size;
+ char *b;
+ char *e;
+
+ b = argv[i];
+ if (*b == '"') // remove leading qoute
+ b++;
+ if (!*b || *b == '"')
+ continue; // skip if empty
+
+ off = strtoul(b, &e, 0);
+ if (*e != '+') {
+ fprintf(stderr, "failed to find '+' in '%s'\n", b);
+ fprintf(stderr, "format off+size@addr expected, but given: %s\n", argv[i]);
+ return -EINVAL;
+ }
+
+ b = e + 1;
+ size = strtoul(b, &e, 0);
+ if (*e != '@') {
+ fprintf(stderr, "failed to find '@' in '%s'\n", b);
+ fprintf(stderr, "format off+size@addr expected, but given: %s\n", argv[i]);
+ return -EINVAL;
+ }
+
+ b = e + 1;
+ addr = strtoul(b, &e, 0);
+ if (*e && *e != '"') { // ignore trailing qoute
+ fprintf(stderr, "unexpected char at the end: '%c'\n", *e);
+ fprintf(stderr, "format off+size@addr expected, but given: %s\n", argv[i]);
+ return -EINVAL;
+ }
+
+ ret = asprintf(&str, ", 0x%08x 0x%08x 0x%08x \"%s\"", addr, off, size, data->outfile);
+ if (ret < 0)
+ return -ENOMEM;
+
+ ret = hab_add_str(data, str);
+ free(str);
+ if (ret)
+ return ret;
+ }
+
+ return hab_add_str(data, "\n");
}
static int do_hab_encrypt(struct config_data *data, int argc, char *argv[])
@@ -568,6 +691,38 @@ do_signed_hdmi_firmware(struct config_data *data, int argc, char *argv[])
return 0;
}
+static int do_flexspi_ivtofs(struct config_data *data, int argc, char *argv[])
+{
+ if (argc < 2)
+ return -EINVAL;
+
+ if (data->csf) {
+ fprintf(stderr, "#include <mach/imx/flexspi-imx8m*-cfg.h> must be placed in front "
+ "of #include <mach/imx/habv4-imx8-gencsf.h>\n");
+ return -EINVAL;
+ }
+
+ data->image_flexspi_ivt_offset = strtoul(argv[1], NULL, 0);
+
+ return 0;
+}
+
+static int do_flexspi_fcfbofs(struct config_data *data, int argc, char *argv[])
+{
+ if (argc < 2)
+ return -EINVAL;
+
+ if (data->csf) {
+ fprintf(stderr, "#include <mach/imx/flexspi-imx8m*-cfg.h> must be placed in front "
+ "of #include <mach/imx/habv4-imx8-gencsf.h>\n");
+ return -EINVAL;
+ }
+
+ data->image_flexspi_fcfb_offset = strtoul(argv[1], NULL, 0);
+
+ return 0;
+}
+
struct command cmds[] = {
{
.name = "wm",
@@ -588,8 +743,11 @@ struct command cmds[] = {
.name = "loadaddr",
.parse = do_loadaddr,
}, {
+ .name = "ivtofs",
+ .parse = do_ivt_offset,
+ }, {
.name = "dcdofs",
- .parse = do_dcd_offset,
+ .parse = do_dcdofs_error,
}, {
.name = "soc",
.parse = do_soc,
@@ -618,11 +776,20 @@ struct command cmds[] = {
.name = "hab_encrypt_blocks",
.parse = do_hab_encrypt_blocks,
}, {
+ .name = "hab_qspi",
+ .parse = do_hab_qspi,
+ }, {
.name = "super_root_key",
.parse = do_super_root_key,
}, {
.name = "signed_hdmi_firmware",
.parse = do_signed_hdmi_firmware,
+ }, {
+ .name = "flexspi_fcfbofs",
+ .parse = do_flexspi_fcfbofs,
+ }, {
+ .name = "flexspi_ivtofs",
+ .parse = do_flexspi_ivtofs,
},
};
@@ -631,6 +798,7 @@ static char *readcmd(struct config_data *data, FILE *f)
static char *buf;
char *str;
ssize_t ret;
+ int inquotes = 0;
if (!buf) {
buf = malloc(4096);
@@ -645,8 +813,9 @@ static char *readcmd(struct config_data *data, FILE *f)
ret = fread(str, 1, 1, f);
if (!ret)
return strlen(buf) ? buf : NULL;
-
- if (*str == '\n' || *str == ';') {
+ if (*str == '"') {
+ inquotes = !inquotes;
+ } else if ((*str == '\n' || *str == ';') && !inquotes) {
*str = 0;
return buf;
}