[PATCH 00/12] IOT2050-related enhancements

Flushing our upstream queue for the IOT2050 device, this mostly brings board-specific changes such as:
- updated build process and firmware layout for PG1 vs. PG2 devices - more watchdog preparations - preparations for verified boot on IOT2050 Advanced devices
There are also some generic extensions in this series which are dependencies for the above:
- env: Complete generic support for writable list - env: Couple networking-related variable flags to CONFIG_NET (repost) - tools: Add script for converting public key into device tree include
Jan
CC: Joe Hershberger joe.hershberger@ni.com CC: Marek Vasut marex@denx.de CC: Su Baocheng baocheng.su@siemens.com
Jan Kiszka (10): env: Complete generic support for writable list env: Couple networking-related variable flags to CONFIG_NET tools: Add script for converting public key into device tree include iot2050: Update firmware layout iot2050: Add watchdog start to bootcmd iot2050: Add CONFIG_ENV_FLAGS_LIST_STATIC arm: dts: iot2050: Allow verifying U-Boot proper by SPL iot2050: Add script for signing artifacts arm: dts: iot2050: Optionally embed OTP programming data into image doc: iot2050: Add a note about the watchdog firmware
Su Baocheng (2): board: siemens: iot2050: Split the build for PG1 and PG2 arm: dts: iot2050: Use the auto generator nodes for fdt
arch/arm/dts/k3-am65-iot2050-boot-image.dtsi | 134 ++++++------------ board/siemens/iot2050/Kconfig | 35 ++++- board/siemens/iot2050/board.c | 15 +- ...ot2050_defconfig => iot2050_pg1_defconfig} | 7 +- ...ot2050_defconfig => iot2050_pg2_defconfig} | 10 +- doc/board/siemens/iot2050.rst | 79 ++++++++++- env/Kconfig | 2 + env/env.c | 17 ++- env/flags.c | 10 +- include/configs/iot2050.h | 17 +++ include/env_flags.h | 4 +- tools/binman/missing-blob-help | 14 +- tools/iot2050-sign-fw.sh | 51 +++++++ tools/key2dtsi.py | 64 +++++++++ 14 files changed, 328 insertions(+), 131 deletions(-) copy configs/{iot2050_defconfig => iot2050_pg1_defconfig} (93%) rename configs/{iot2050_defconfig => iot2050_pg2_defconfig} (91%) create mode 100755 tools/iot2050-sign-fw.sh create mode 100755 tools/key2dtsi.py

From: Jan Kiszka jan.kiszka@siemens.com
This completes what 890feecaab72 started by selecting ENV_APPEND and ENV_IS_NOWHERE and by moving this driver to top if the list. This ensures that load operations pick up both the default env and the permitted parts of the next-prio location. When writing though, we must not use NOWHERE and rather need to forward directly to the first external location.
With this change, boards only need to define the list of writable variables but no longer have to provide a custom env_get_location implementation.
CC: Joe Hershberger joe.hershberger@ni.com CC: Marek Vasut marex@denx.de Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- env/Kconfig | 2 ++ env/env.c | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/env/Kconfig b/env/Kconfig index 2f625b22575..00db63a136c 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -696,6 +696,8 @@ config ENV_APPEND
config ENV_WRITEABLE_LIST bool "Permit write access only to listed variables" + select ENV_IS_NOWHERE + select ENV_APPEND help If defined, only environment variables which explicitly set the 'w' writeable flag can be written and modified at runtime. No variables diff --git a/env/env.c b/env/env.c index 69848fb0608..3b24f7941c0 100644 --- a/env/env.c +++ b/env/env.c @@ -54,6 +54,13 @@ static struct env_driver *_env_driver_lookup(enum env_location loc) }
static enum env_location env_locations[] = { +#if defined(CONFIG_ENV_IS_NOWHERE) && defined(CONFIG_ENV_WRITEABLE_LIST) + /* + * In writeable-list mode, the built-in env must have highest prio + * while loading. This is achieved by moving ENVL_NOWHERE to the front. + */ + ENVL_NOWHERE, +#endif #ifdef CONFIG_ENV_IS_IN_EEPROM ENVL_EEPROM, #endif @@ -87,7 +94,7 @@ static enum env_location env_locations[] = { #ifdef CONFIG_ENV_IS_IN_UBI ENVL_UBI, #endif -#ifdef CONFIG_ENV_IS_NOWHERE +#if defined(CONFIG_ENV_IS_NOWHERE) && !defined(CONFIG_ENV_WRITEABLE_LIST) ENVL_NOWHERE, #endif }; @@ -133,6 +140,14 @@ __weak enum env_location arch_env_get_location(enum env_operation op, int prio) if (prio >= ARRAY_SIZE(env_locations)) return ENVL_UNKNOWN;
+#ifdef CONFIG_ENV_WRITEABLE_LIST + /* + * In writeable-list mode, ENVL_NOWHERE gains highest prio. This blocks + * writing, though. So return the location of the next prio instead. + */ + if ((op == ENVOP_SAVE || op == ENVOP_ERASE) && prio == 0) + prio++; +#endif return env_locations[prio]; }

On 5/28/22 15:02, Jan Kiszka wrote:
From: Jan Kiszka jan.kiszka@siemens.com
This completes what 890feecaab72 started by selecting ENV_APPEND and ENV_IS_NOWHERE and by moving this driver to top if the list. This
s@if the list@of the list@
ensures that load operations pick up both the default env and the permitted parts of the next-prio location. When writing though, we must not use NOWHERE and rather need to forward directly to the first external location.
Isn't the env load order a board-specific setting ?
With this change, boards only need to define the list of writable variables but no longer have to provide a custom env_get_location implementation.
This also brings in a lot of ifdeffery and extra complexity. If you implement this as a board-specific env_get_location() override, you can avoid that. Try:
enum env_location env_get_location(enum env_operation op, int prio) { if (op == ENVOP_SAVE) { if (prio == 0) return ENVL_SPI_FLASH; } else { if (prio == 0) return ENVL_NOWHERE; if (prio == 1) return ENVL_SPI_FLASH; }
return ENVL_UNKNOWN; }

On 29.05.22 03:46, Marek Vasut wrote:
On 5/28/22 15:02, Jan Kiszka wrote:
From: Jan Kiszka jan.kiszka@siemens.com
This completes what 890feecaab72 started by selecting ENV_APPEND and ENV_IS_NOWHERE and by moving this driver to top if the list. This
s@if the list@of the list@
ensures that load operations pick up both the default env and the permitted parts of the next-prio location. When writing though, we must not use NOWHERE and rather need to forward directly to the first external location.
Isn't the env load order a board-specific setting ?
There can always be special cases, but I don't see why it should be _always_ board-specific.
With this change, boards only need to define the list of writable variables but no longer have to provide a custom env_get_location implementation.
This also brings in a lot of ifdeffery and extra complexity. If you implement this as a board-specific env_get_location() override, you can avoid that. Try:
enum env_location env_get_location(enum env_operation op, int prio) { if (op == ENVOP_SAVE) { if (prio == 0) return ENVL_SPI_FLASH; } else { if (prio == 0) return ENVL_NOWHERE; if (prio == 1) return ENVL_SPI_FLASH; }
return ENVL_UNKNOWN; }
This is exactly what I would like to avoid, having to carry such a generic function (minus that hard-coded the choice of storage - this can be controlled via .config) in every board.
Jan

On 5/29/22 17:37, Jan Kiszka wrote:
On 29.05.22 03:46, Marek Vasut wrote:
On 5/28/22 15:02, Jan Kiszka wrote:
From: Jan Kiszka jan.kiszka@siemens.com
This completes what 890feecaab72 started by selecting ENV_APPEND and ENV_IS_NOWHERE and by moving this driver to top if the list. This
s@if the list@of the list@
ensures that load operations pick up both the default env and the permitted parts of the next-prio location. When writing though, we must not use NOWHERE and rather need to forward directly to the first external location.
Isn't the env load order a board-specific setting ?
There can always be special cases, but I don't see why it should be _always_ board-specific.
Because this is a special case, right ?
With this change, boards only need to define the list of writable variables but no longer have to provide a custom env_get_location implementation.
This also brings in a lot of ifdeffery and extra complexity. If you implement this as a board-specific env_get_location() override, you can avoid that. Try:
enum env_location env_get_location(enum env_operation op, int prio) { if (op == ENVOP_SAVE) { if (prio == 0) return ENVL_SPI_FLASH; } else { if (prio == 0) return ENVL_NOWHERE; if (prio == 1) return ENVL_SPI_FLASH; }
return ENVL_UNKNOWN; }
This is exactly what I would like to avoid, having to carry such a generic function (minus that hard-coded the choice of storage - this can be controlled via .config) in every board.
Just for a quick statistics -- how many boards would make use of this generic function ?
If you want to make this into a generic patch, can you somehow reduce the ever-growing ifdeffery, so that the patch won't add to it so much ? I suspect the code above can help with that, maybe it can be used to remove at least the env_locations[] reordering ifdeffery ?

On 06.06.22 08:42, Marek Vasut wrote:
On 5/29/22 17:37, Jan Kiszka wrote:
On 29.05.22 03:46, Marek Vasut wrote:
On 5/28/22 15:02, Jan Kiszka wrote:
From: Jan Kiszka jan.kiszka@siemens.com
This completes what 890feecaab72 started by selecting ENV_APPEND and ENV_IS_NOWHERE and by moving this driver to top if the list. This
s@if the list@of the list@
ensures that load operations pick up both the default env and the permitted parts of the next-prio location. When writing though, we must not use NOWHERE and rather need to forward directly to the first external location.
Isn't the env load order a board-specific setting ?
There can always be special cases, but I don't see why it should be _always_ board-specific.
Because this is a special case, right ?
It's no longer special when you request the feature by turning on the related config options.
With this change, boards only need to define the list of writable variables but no longer have to provide a custom env_get_location implementation.
This also brings in a lot of ifdeffery and extra complexity. If you implement this as a board-specific env_get_location() override, you can avoid that. Try:
enum env_location env_get_location(enum env_operation op, int prio) { if (op == ENVOP_SAVE) { if (prio == 0) return ENVL_SPI_FLASH; } else { if (prio == 0) return ENVL_NOWHERE; if (prio == 1) return ENVL_SPI_FLASH; }
return ENVL_UNKNOWN; }
This is exactly what I would like to avoid, having to carry such a generic function (minus that hard-coded the choice of storage - this can be controlled via .config) in every board.
Just for a quick statistics -- how many boards would make use of this generic function ?
I don't have stats for how many boards are turning on ENV_WRITEABLE_LIST except for our boards. Here, I have about 3-5 boards (depending on how you count variants) that would all be fine with this switch and could then drop their custom handler (or never introduce one - IOT2050).
If you want to make this into a generic patch, can you somehow reduce the ever-growing ifdeffery, so that the patch won't add to it so much ? I suspect the code above can help with that, maybe it can be used to remove at least the env_locations[] reordering ifdeffery ?
Your code is not generic enough as it ignores the config-selected storage device. It would only happen to cover all our boards, but we are not the world. That's why I had to add some ifdeffery.
I could try write an alternative arch_env_get_location that does the required logic with a single ifdef. The prize might be some code duplication, though.
Jan

On 6/8/22 16:39, Jan Kiszka wrote:
[...]
If you want to make this into a generic patch, can you somehow reduce the ever-growing ifdeffery, so that the patch won't add to it so much ? I suspect the code above can help with that, maybe it can be used to remove at least the env_locations[] reordering ifdeffery ?
Your code is not generic enough as it ignores the config-selected storage device. It would only happen to cover all our boards, but we are not the world. That's why I had to add some ifdeffery.
That storage device part is trivial to fix, right.
I could try write an alternative arch_env_get_location that does the required logic with a single ifdef. The prize might be some code duplication, though.
Can you use CONFIG_IS_ENABLED()/IS_ENABLED() in arch_env_get_location() to avoid the #if ... and outright return ENVL_NOWHERE or whatever to avoid adding ifdefs to env_locations[] array ?
That should likely be possible.
[...]

From: Jan Kiszka jan.kiszka@siemens.com
Boards may set networking variables programmatically, thus may have CONFIG_NET on but CONFIG_CMD_NET off. The IOT2050 is an example.
CC: Joe Hershberger joe.hershberger@ni.com Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- env/flags.c | 10 +++++----- include/env_flags.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/env/flags.c b/env/flags.c index e3e833c4333..e2866361dfe 100644 --- a/env/flags.c +++ b/env/flags.c @@ -22,7 +22,7 @@ #include <env_internal.h> #endif
-#ifdef CONFIG_CMD_NET +#ifdef CONFIG_NET #define ENV_FLAGS_NET_VARTYPE_REPS "im" #else #define ENV_FLAGS_NET_VARTYPE_REPS "" @@ -57,7 +57,7 @@ static const char * const env_flags_vartype_names[] = { "decimal", "hexadecimal", "boolean", -#ifdef CONFIG_CMD_NET +#ifdef CONFIG_NET "IP address", "MAC address", #endif @@ -211,7 +211,7 @@ static void skip_num(int hex, const char *value, const char **end, *end = value; }
-#ifdef CONFIG_CMD_NET +#ifdef CONFIG_NET int eth_validate_ethaddr_str(const char *addr) { const char *end; @@ -244,7 +244,7 @@ static int _env_flags_validate_type(const char *value, enum env_flags_vartype type) { const char *end; -#ifdef CONFIG_CMD_NET +#ifdef CONFIG_NET const char *cur; int i; #endif @@ -273,7 +273,7 @@ static int _env_flags_validate_type(const char *value, if (value[1] != '\0') return -1; break; -#ifdef CONFIG_CMD_NET +#ifdef CONFIG_NET case env_flags_vartype_ipaddr: cur = value; for (i = 0; i < 4; i++) { diff --git a/include/env_flags.h b/include/env_flags.h index 313cb8c49a6..b49ec8e80f1 100644 --- a/include/env_flags.h +++ b/include/env_flags.h @@ -12,7 +12,7 @@ enum env_flags_vartype { env_flags_vartype_decimal, env_flags_vartype_hex, env_flags_vartype_bool, -#ifdef CONFIG_CMD_NET +#ifdef CONFIG_NET env_flags_vartype_ipaddr, env_flags_vartype_macaddr, #endif @@ -111,7 +111,7 @@ enum env_flags_varaccess env_flags_parse_varaccess(const char *flags); */ enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags);
-#ifdef CONFIG_CMD_NET +#ifdef CONFIG_NET /* * Check if a string has the format of an Ethernet MAC address */

From: Jan Kiszka jan.kiszka@siemens.com
Allows to create a public key device tree dtsi for inclusion into U-Boot SPL and proper during first build already. This can be achieved via CONFIG_DEVICE_TREE_INCLUDES.
Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- tools/key2dtsi.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100755 tools/key2dtsi.py
diff --git a/tools/key2dtsi.py b/tools/key2dtsi.py new file mode 100755 index 00000000000..1dbb2cc94bf --- /dev/null +++ b/tools/key2dtsi.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-only +# +# Public key to dtsi converter. +# +# Copyright (c) Siemens AG, 2022 +# + +from argparse import ArgumentParser, FileType +from os.path import basename, splitext +from Cryptodome.PublicKey import RSA +from Cryptodome.Util.number import inverse + +def int_to_bytestr(n, length=None): + if not length: + length = (n.bit_length() + 7) // 8 + byte_array = n.to_bytes(length, 'big') + return ' '.join(['{:02x}'.format(byte) for byte in byte_array]) + +ap = ArgumentParser(description='Public key to dtsi converter') + +ap.add_argument('--hash', '-H', default='sha256', + help='hash to be used with key (default: sha256)') +ap.add_argument('--required-conf', '-c', action='store_true', + help='mark key required for configuration') +ap.add_argument('--required-image', '-i', action='store_true', + help='mark key required for image') +ap.add_argument('--spl', '-s', action='store_true', + help='mark key for usage in SPL') +ap.add_argument('key_file', metavar='KEY_FILE', type=FileType('r'), + help='key file (formats: X.509, PKCS#1, OpenSSH)') +ap.add_argument('dtsi_file', metavar='DTSI_FILE', type=FileType('w'), + help='dtsi output file') + +args = ap.parse_args() + +key_name, _ = splitext(basename(args.key_file.name)) + +key_data = args.key_file.read() +key = RSA.importKey(key_data) + +r_squared = (2**key.size_in_bits())**2 % key.n +n0_inverse = 2**32 - inverse(key.n, 2**32) + +out = args.dtsi_file +out.write('/ {\n') +out.write('\tsignature {\n') +out.write('\t\tkey-{} {{\n'.format(key_name)) +out.write('\t\t\tkey-name-hint = "{}";\n'.format(key_name)) +out.write('\t\t\talgo = "{},rsa{}";\n'.format(args.hash, key.size_in_bits())) +out.write('\t\t\trsa,num-bits = <{}>;\n'.format(key.size_in_bits())) +out.write('\t\t\trsa,modulus = [{}];\n'.format(int_to_bytestr(key.n))) +out.write('\t\t\trsa,exponent = [{}];\n'.format(int_to_bytestr(key.e, 8))) +out.write('\t\t\trsa,r-squared = [{}];\n'.format(int_to_bytestr(r_squared))) +out.write('\t\t\trsa,n0-inverse = <0x{:x}>;\n'.format(n0_inverse)) +if args.required_conf: + out.write('\t\t\trequired = "conf";\n') +elif args.required_image: + out.write('\t\t\trequired = "image";\n') +if args.spl: + out.write('\t\t\tu-boot,dm-spl;\n') +out.write('\t\t};\n') +out.write('\t};\n') +out.write('};\n')

From: Su Baocheng baocheng.su@siemens.com
Due to different signature keys, the PG1 and the PG2 boards can no longer use the same FSBL (tiboot3). This makes it impossible anyway to maintaine a single flash.bin for both variants, so we can also split the build.
A new target is added to indicates the build is for PG1 vs. PG2 boards. Hence now the variants have separated defconfig files.
The runtime board_is_sr1() check does make no sense anymore, so remove it and replace with build time check.
Documentation is updated accordingly. New binary artifacts are already available via meta-iot2050.
Signed-off-by: Su Baocheng baocheng.su@siemens.com [Jan: refactor config option into targets, tweak some wordings] Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- arch/arm/dts/k3-am65-iot2050-boot-image.dtsi | 80 ++++++------------- board/siemens/iot2050/Kconfig | 28 ++++++- board/siemens/iot2050/board.c | 12 +-- ...ot2050_defconfig => iot2050_pg1_defconfig} | 2 +- ...ot2050_defconfig => iot2050_pg2_defconfig} | 5 +- doc/board/siemens/iot2050.rst | 15 +++- 6 files changed, 66 insertions(+), 76 deletions(-) copy configs/{iot2050_defconfig => iot2050_pg1_defconfig} (99%) rename configs/{iot2050_defconfig => iot2050_pg2_defconfig} (96%)
diff --git a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi index 27058370ccc..3135ad04715 100644 --- a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi +++ b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) Siemens AG, 2020-2021 + * Copyright (c) Siemens AG, 2020-2022 * * Authors: * Jan Kiszka jan.kiszka@siemens.com @@ -17,7 +17,11 @@
blob-ext@0x000000 { offset = <0x000000>; - filename = "tiboot3.bin"; +#ifdef CONFIG_TARGET_IOT2050_A53_PG1 + filename = "seboot_pg1.bin"; +#else + filename = "seboot_pg2.bin"; +#endif missing-msg = "iot2050-seboot"; };
@@ -43,42 +47,30 @@ };
fdt-iot2050-basic { - description = "k3-am6528-iot2050-basic.dtb"; + description = "k3-am6528-iot2050-basic*.dtb"; type = "flat_dt"; arch = "arm64"; compression = "none"; blob { +#ifdef CONFIG_TARGET_IOT2050_A53_PG1 filename = "arch/arm/dts/k3-am6528-iot2050-basic.dtb"; - }; - }; - - fdt-iot2050-basic-pg2 { - description = "k3-am6528-iot2050-basic-pg2.dtb"; - type = "flat_dt"; - arch = "arm64"; - compression = "none"; - blob { +#else filename = "arch/arm/dts/k3-am6528-iot2050-basic-pg2.dtb"; +#endif }; };
fdt-iot2050-advanced { - description = "k3-am6548-iot2050-advanced.dtb"; + description = "k3-am6548-iot2050-advanced*.dtb"; type = "flat_dt"; arch = "arm64"; compression = "none"; blob { +#ifdef CONFIG_TARGET_IOT2050_A53_PG1 filename = "arch/arm/dts/k3-am6548-iot2050-advanced.dtb"; - }; - }; - - fdt-iot2050-advanced-pg2 { - description = "k3-am6548-iot2050-advanced-pg2.dtb"; - type = "flat_dt"; - arch = "arm64"; - compression = "none"; - blob { +#else filename = "arch/arm/dts/k3-am6548-iot2050-advanced-pg2.dtb"; +#endif }; };
@@ -108,30 +100,12 @@ #endif };
- conf-iot2050-basic-pg2 { - description = "iot2050-basic-pg2"; - firmware = "u-boot"; - fdt = "fdt-iot2050-basic-pg2"; -#ifdef CONFIG_WDT_K3_RTI_FW_FILE - loadables = "k3-rti-wdt-firmware"; -#endif - }; - conf-iot2050-advanced { description = "iot2050-advanced"; firmware = "u-boot"; fdt = "fdt-iot2050-advanced"; #ifdef CONFIG_WDT_K3_RTI_FW_FILE loadables = "k3-rti-wdt-firmware"; -#endif - }; - - conf-iot2050-advanced-pg2 { - description = "iot2050-advanced-pg2"; - firmware = "u-boot"; - fdt = "fdt-iot2050-advanced-pg2"; -#ifdef CONFIG_WDT_K3_RTI_FW_FILE - loadables = "k3-rti-wdt-firmware"; #endif }; }; @@ -150,28 +124,24 @@ fill-byte = [00]; };
- /* PG1 sysfw, basic variant */ + /* sysfw, basic variant */ blob-ext@0x6c0000 { offset = <0x6c0000>; - filename = "sysfw.itb"; +#ifdef CONFIG_TARGET_IOT2050_A53_PG1 + filename = "sysfw_sr1.itb"; +#else + filename = "sysfw_sr2.itb"; +#endif missing-msg = "iot2050-sysfw"; }; - /* PG1 sysfw, advanced variant */ + /* sysfw, advanced variant */ blob-ext@0x740000 { offset = <0x740000>; - filename = "sysfw.itb_HS"; - missing-msg = "iot2050-sysfw"; - }; - /* PG2 sysfw, basic variant */ - blob-ext@0x7c0000 { - offset = <0x7c0000>; - filename = "sysfw_sr2.itb"; - missing-msg = "iot2050-sysfw"; - }; - /* PG2 sysfw, advanced variant */ - blob-ext@0x840000 { - offset = <0x840000>; +#ifdef CONFIG_TARGET_IOT2050_A53_PG1 + filename = "sysfw_sr1.itb_HS"; +#else filename = "sysfw_sr2.itb_HS"; +#endif missing-msg = "iot2050-sysfw"; }; }; diff --git a/board/siemens/iot2050/Kconfig b/board/siemens/iot2050/Kconfig index 8f634c172c1..e264bec2d44 100644 --- a/board/siemens/iot2050/Kconfig +++ b/board/siemens/iot2050/Kconfig @@ -1,20 +1,40 @@ # SPDX-License-Identifier: GPL-2.0+ # -# Copyright (c) Siemens AG, 2018-2021 +# Copyright (c) Siemens AG, 2018-2022 # # Authors: # Le Jin le.jin@siemens.com # Jan Kiszka jan.kiszka@siemens.com
-config TARGET_IOT2050_A53 - bool "IOT2050 running on A53" +choice + prompt "Siemens SIMATIC IOT2050 boards" + optional + +config TARGET_IOT2050_A53_PG1 + bool "IOT2050 PG1 running on A53" + select IOT2050_A53_COMMON + help + This builds U-Boot for the Product Generation 1 (PG1) of the IOT2050 + devices. + +config TARGET_IOT2050_A53_PG2 + bool "IOT2050 PG2 running on A53" + select IOT2050_A53_COMMON + help + This builds U-Boot for the Product Generation 2 (PG2) of the IOT2050 + devices. + +endchoice + +config IOT2050_A53_COMMON + bool select ARM64 select SOC_K3_AM6 select BOARD_LATE_INIT select SYS_DISABLE_DCACHE_OPS select BINMAN
-if TARGET_IOT2050_A53 +if IOT2050_A53_COMMON
config SYS_BOARD default "iot2050" diff --git a/board/siemens/iot2050/board.c b/board/siemens/iot2050/board.c index b965ae9fa49..050ddb5899b 100644 --- a/board/siemens/iot2050/board.c +++ b/board/siemens/iot2050/board.c @@ -55,14 +55,6 @@ static bool board_is_advanced(void) strstr((char *)info->name, "IOT2050-ADVANCED") != NULL; }
-static bool board_is_sr1(void) -{ - struct iot2050_info *info = IOT2050_INFO_DATA; - - return info->magic == IOT2050_INFO_MAGIC && - !strstr((char *)info->name, "-PG2"); -} - static void remove_mmc1_target(void) { char *boot_targets = strdup(env_get("boot_targets")); @@ -109,12 +101,12 @@ void set_board_info_env(void) }
if (board_is_advanced()) { - if (board_is_sr1()) + if (IS_ENABLED(CONFIG_TARGET_IOT2050_A53_PG1)) fdtfile = "ti/k3-am6548-iot2050-advanced.dtb"; else fdtfile = "ti/k3-am6548-iot2050-advanced-pg2.dtb"; } else { - if (board_is_sr1()) + if (IS_ENABLED(CONFIG_TARGET_IOT2050_A53_PG1)) fdtfile = "ti/k3-am6528-iot2050-basic.dtb"; else fdtfile = "ti/k3-am6528-iot2050-basic-pg2.dtb"; diff --git a/configs/iot2050_defconfig b/configs/iot2050_pg1_defconfig similarity index 99% copy from configs/iot2050_defconfig copy to configs/iot2050_pg1_defconfig index 175ec70915d..0e6f1257a94 100644 --- a/configs/iot2050_defconfig +++ b/configs/iot2050_pg1_defconfig @@ -8,7 +8,7 @@ CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_NR_DRAM_BANKS=2 CONFIG_SOC_K3_AM6=y -CONFIG_TARGET_IOT2050_A53=y +CONFIG_TARGET_IOT2050_A53_PG1=y CONFIG_ENV_SIZE=0x20000 CONFIG_ENV_OFFSET=0x680000 CONFIG_ENV_SECT_SIZE=0x20000 diff --git a/configs/iot2050_defconfig b/configs/iot2050_pg2_defconfig similarity index 96% rename from configs/iot2050_defconfig rename to configs/iot2050_pg2_defconfig index 175ec70915d..1bee7c46175 100644 --- a/configs/iot2050_defconfig +++ b/configs/iot2050_pg2_defconfig @@ -8,13 +8,13 @@ CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_NR_DRAM_BANKS=2 CONFIG_SOC_K3_AM6=y -CONFIG_TARGET_IOT2050_A53=y +CONFIG_TARGET_IOT2050_A53_PG2=y CONFIG_ENV_SIZE=0x20000 CONFIG_ENV_OFFSET=0x680000 CONFIG_ENV_SECT_SIZE=0x20000 CONFIG_DM_GPIO=y CONFIG_SPL_DM_SPI=y -CONFIG_DEFAULT_DEVICE_TREE="k3-am6528-iot2050-basic" +CONFIG_DEFAULT_DEVICE_TREE="k3-am6528-iot2050-basic-pg2" CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_SPL_SERIAL=y CONFIG_SPL_STACK_R_ADDR=0x82000000 @@ -34,6 +34,7 @@ CONFIG_CONSOLE_MUX=y CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y +CONFIG_SPL_SEPARATE_BSS=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400 CONFIG_SPL_DM_MAILBOX=y diff --git a/doc/board/siemens/iot2050.rst b/doc/board/siemens/iot2050.rst index 7e97f817ce4..fd3431fa3f8 100644 --- a/doc/board/siemens/iot2050.rst +++ b/doc/board/siemens/iot2050.rst @@ -24,9 +24,10 @@ Binary dependencies can be found in https://github.com/siemens/meta-iot2050/tree/master/recipes-bsp/u-boot/files.... The following binaries from that source need to be present in the build folder:
- - tiboot3.bin - - sysfw.itb - - sysfw.itb_HS + - seboot_pg1.bin + - sysfw_sr1.itb + - sysfw_sr1.itb_HS + - seboot_pg2.bin - sysfw_sr2.itb - sysfw_sr2.itb_HS
@@ -57,7 +58,13 @@ U-Boot:
$ export ATF=/path/to/bl31.bin $ export TEE=/path/to/tee-pager_v2.bin - $ make iot2050_defconfig + + # configure for PG1 + $ make iot2050_pg1_defconfig + + # or configure for PG2 + $ make iot2050_pg2_defconfig + $ make
Flashing

From: Su Baocheng baocheng.su@siemens.com
Refactor according to the entry `fit: Entry containing a FIT` of document tools/binman/README.entries.
As the generator uses the device tree name for the config description, board_fit_config_name_match requires a small adjustment as well.
Signed-off-by: Su Baocheng baocheng.su@siemens.com [Jan: re-add now required CONFIG_OF_LIST, update config matching] Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- arch/arm/dts/k3-am65-iot2050-boot-image.dtsi | 44 ++++---------------- board/siemens/iot2050/board.c | 3 ++ configs/iot2050_pg1_defconfig | 1 + configs/iot2050_pg2_defconfig | 1 + 4 files changed, 12 insertions(+), 37 deletions(-)
diff --git a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi index 3135ad04715..46669576864 100644 --- a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi +++ b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi @@ -32,6 +32,7 @@
fit@0x280000 { description = "U-Boot for IOT2050"; + fit,fdt-list = "of-list"; offset = <0x280000>; images { u-boot { @@ -46,32 +47,11 @@ }; };
- fdt-iot2050-basic { - description = "k3-am6528-iot2050-basic*.dtb"; + @fdt-SEQ { + description = "fdt-NAME"; type = "flat_dt"; arch = "arm64"; compression = "none"; - blob { -#ifdef CONFIG_TARGET_IOT2050_A53_PG1 - filename = "arch/arm/dts/k3-am6528-iot2050-basic.dtb"; -#else - filename = "arch/arm/dts/k3-am6528-iot2050-basic-pg2.dtb"; -#endif - }; - }; - - fdt-iot2050-advanced { - description = "k3-am6548-iot2050-advanced*.dtb"; - type = "flat_dt"; - arch = "arm64"; - compression = "none"; - blob { -#ifdef CONFIG_TARGET_IOT2050_A53_PG1 - filename = "arch/arm/dts/k3-am6548-iot2050-advanced.dtb"; -#else - filename = "arch/arm/dts/k3-am6548-iot2050-advanced-pg2.dtb"; -#endif - }; };
#ifdef CONFIG_WDT_K3_RTI_FW_FILE @@ -89,21 +69,11 @@ };
configurations { - default = "conf-iot2050-basic"; - - conf-iot2050-basic { - description = "iot2050-basic"; - firmware = "u-boot"; - fdt = "fdt-iot2050-basic"; -#ifdef CONFIG_WDT_K3_RTI_FW_FILE - loadables = "k3-rti-wdt-firmware"; -#endif - }; - - conf-iot2050-advanced { - description = "iot2050-advanced"; + default = "@config-DEFAULT-SEQ"; + @config-SEQ { + description = "NAME"; firmware = "u-boot"; - fdt = "fdt-iot2050-advanced"; + fdt = "fdt-SEQ"; #ifdef CONFIG_WDT_K3_RTI_FW_FILE loadables = "k3-rti-wdt-firmware"; #endif diff --git a/board/siemens/iot2050/board.c b/board/siemens/iot2050/board.c index 050ddb5899b..2be5d1eefc3 100644 --- a/board/siemens/iot2050/board.c +++ b/board/siemens/iot2050/board.c @@ -154,6 +154,9 @@ int board_fit_config_name_match(const char *name) struct iot2050_info *info = IOT2050_INFO_DATA; char upper_name[32];
+ /* skip the prefix "k3-am65x8-" */ + name += 10; + if (info->magic != IOT2050_INFO_MAGIC || strlen(name) >= sizeof(upper_name)) return -1; diff --git a/configs/iot2050_pg1_defconfig b/configs/iot2050_pg1_defconfig index 0e6f1257a94..2373bab5306 100644 --- a/configs/iot2050_pg1_defconfig +++ b/configs/iot2050_pg1_defconfig @@ -59,6 +59,7 @@ CONFIG_CMD_TIME=y # CONFIG_ISO_PARTITION is not set CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_LIST="k3-am6528-iot2050-basic k3-am6548-iot2050-advanced" CONFIG_SPL_MULTI_DTB_FIT=y CONFIG_SPL_OF_LIST="k3-am65-iot2050-spl" CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y diff --git a/configs/iot2050_pg2_defconfig b/configs/iot2050_pg2_defconfig index 1bee7c46175..c8c21f71e25 100644 --- a/configs/iot2050_pg2_defconfig +++ b/configs/iot2050_pg2_defconfig @@ -60,6 +60,7 @@ CONFIG_CMD_TIME=y # CONFIG_ISO_PARTITION is not set CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_LIST="k3-am6528-iot2050-basic-pg2 k3-am6548-iot2050-advanced-pg2" CONFIG_SPL_MULTI_DTB_FIT=y CONFIG_SPL_OF_LIST="k3-am65-iot2050-spl" CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y

From: Jan Kiszka jan.kiszka@siemens.com
The latest version of the binary-only firmware parts come in a combined form of FSBL and sysfw containers. This implies some layout changes to the generated firmware image but also makes handling of artifacts much simpler (4 files less). The env locations will not change, just the space reserved for U-Boot will shrink from 4 to 3 MB - still plenty of space left in practice.
Adjust configuration and documentation accordingly.
Along this change, add a new reservation for update commands of the user-controlled OTP part. A specific userspace tool will fill it, and the FSBL will evaluate it during boot. This reservation will use 64K of the former sysfw section.
Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- arch/arm/dts/k3-am65-iot2050-boot-image.dtsi | 30 ++++++-------------- configs/iot2050_pg1_defconfig | 2 +- configs/iot2050_pg2_defconfig | 2 +- doc/board/siemens/iot2050.rst | 4 --- tools/binman/missing-blob-help | 8 +----- 5 files changed, 11 insertions(+), 35 deletions(-)
diff --git a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi index 46669576864..3ee0842e993 100644 --- a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi +++ b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi @@ -25,15 +25,15 @@ missing-msg = "iot2050-seboot"; };
- blob@0x080000 { - offset = <0x080000>; + blob@0x180000 { + offset = <0x180000>; filename = "tispl.bin"; };
- fit@0x280000 { + fit@0x380000 { description = "U-Boot for IOT2050"; fit,fdt-list = "of-list"; - offset = <0x280000>; + offset = <0x380000>; images { u-boot { description = "U-Boot"; @@ -94,25 +94,11 @@ fill-byte = [00]; };
- /* sysfw, basic variant */ - blob-ext@0x6c0000 { + /* OTP update command block */ + fill@0x6c0000 { offset = <0x6c0000>; -#ifdef CONFIG_TARGET_IOT2050_A53_PG1 - filename = "sysfw_sr1.itb"; -#else - filename = "sysfw_sr2.itb"; -#endif - missing-msg = "iot2050-sysfw"; - }; - /* sysfw, advanced variant */ - blob-ext@0x740000 { - offset = <0x740000>; -#ifdef CONFIG_TARGET_IOT2050_A53_PG1 - filename = "sysfw_sr1.itb_HS"; -#else - filename = "sysfw_sr2.itb_HS"; -#endif - missing-msg = "iot2050-sysfw"; + size = <0x010000>; + fill-byte = [ff]; }; }; }; diff --git a/configs/iot2050_pg1_defconfig b/configs/iot2050_pg1_defconfig index 2373bab5306..1dbfa135426 100644 --- a/configs/iot2050_pg1_defconfig +++ b/configs/iot2050_pg1_defconfig @@ -43,7 +43,7 @@ CONFIG_SPL_POWER_DOMAIN=y # CONFIG_SPL_SPI_FLASH_TINY is not set CONFIG_SPL_SPI_FLASH_SFDP_SUPPORT=y CONFIG_SPL_SPI_LOAD=y -CONFIG_SYS_SPI_U_BOOT_OFFS=0x280000 +CONFIG_SYS_SPI_U_BOOT_OFFS=0x380000 CONFIG_SYS_PROMPT="IOT2050> " CONFIG_CMD_ASKENV=y CONFIG_CMD_DFU=y diff --git a/configs/iot2050_pg2_defconfig b/configs/iot2050_pg2_defconfig index c8c21f71e25..83866af4c68 100644 --- a/configs/iot2050_pg2_defconfig +++ b/configs/iot2050_pg2_defconfig @@ -44,7 +44,7 @@ CONFIG_SPL_POWER_DOMAIN=y # CONFIG_SPL_SPI_FLASH_TINY is not set CONFIG_SPL_SPI_FLASH_SFDP_SUPPORT=y CONFIG_SPL_SPI_LOAD=y -CONFIG_SYS_SPI_U_BOOT_OFFS=0x280000 +CONFIG_SYS_SPI_U_BOOT_OFFS=0x380000 CONFIG_SYS_PROMPT="IOT2050> " CONFIG_CMD_ASKENV=y CONFIG_CMD_DFU=y diff --git a/doc/board/siemens/iot2050.rst b/doc/board/siemens/iot2050.rst index fd3431fa3f8..26972e20ae9 100644 --- a/doc/board/siemens/iot2050.rst +++ b/doc/board/siemens/iot2050.rst @@ -25,11 +25,7 @@ https://github.com/siemens/meta-iot2050/tree/master/recipes-bsp/u-boot/files... The following binaries from that source need to be present in the build folder:
- seboot_pg1.bin - - sysfw_sr1.itb - - sysfw_sr1.itb_HS - seboot_pg2.bin - - sysfw_sr2.itb - - sysfw_sr2.itb_HS
Building -------- diff --git a/tools/binman/missing-blob-help b/tools/binman/missing-blob-help index c61ca02a35e..5bb8961ce03 100644 --- a/tools/binman/missing-blob-help +++ b/tools/binman/missing-blob-help @@ -21,13 +21,7 @@ Please read the section on SCP firmware in board/sunxi/README.sunxi64 iot2050-seboot: See the documentation for IOT2050 board. Your image is missing SEBoot which is mandatory for board startup. Prebuilt SEBoot located at -meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/tiboot3.bin. - -iot2050-sysfw: -See the documentation for IOT2050 board. Your image is missing system -firmware which is mandatory for board startup. Prebuilt system firmware -located at meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/ -with sysfw prefix. +meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/seboot_pg*.bin.
k3-rti-wdt-firmware: If CONFIG_WDT_K3_RTI_LOAD_FW is enabled, a firmware image is needed for

From: Jan Kiszka jan.kiszka@siemens.com
Allows run-time control over watchdog auto-start and the timeout via setting the environment variable watchdog_timeout_ms. A value of zero means "do not start". Use CONFIG_WATCHDOG_TIMEOUT_MSECS as initial value and this to zero by default. Users can then enable the watchdog once the use and OS which picks it up during boot.
Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- configs/iot2050_pg1_defconfig | 2 ++ configs/iot2050_pg2_defconfig | 2 ++ include/configs/iot2050.h | 9 +++++++++ 3 files changed, 13 insertions(+)
diff --git a/configs/iot2050_pg1_defconfig b/configs/iot2050_pg1_defconfig index 1dbfa135426..356d53d57bc 100644 --- a/configs/iot2050_pg1_defconfig +++ b/configs/iot2050_pg1_defconfig @@ -29,6 +29,7 @@ CONFIG_OF_BOARD_SETUP=y CONFIG_BOOTSTAGE=y CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_SPL_SHOW_BOOT_PROGRESS=y +CONFIG_BOOTCOMMAND="run start_watchdog; run distro_bootcmd" CONFIG_CONSOLE_MUX=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_BOARD_INIT=y @@ -133,6 +134,7 @@ CONFIG_USB_DWC3_GENERIC=y CONFIG_USB_KEYBOARD=y # CONFIG_WATCHDOG is not set # CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WATCHDOG_TIMEOUT_MSECS=0 CONFIG_WDT=y CONFIG_WDT_K3_RTI=y CONFIG_WDT_K3_RTI_LOAD_FW=y diff --git a/configs/iot2050_pg2_defconfig b/configs/iot2050_pg2_defconfig index 83866af4c68..d5ed53c40d5 100644 --- a/configs/iot2050_pg2_defconfig +++ b/configs/iot2050_pg2_defconfig @@ -29,6 +29,7 @@ CONFIG_OF_BOARD_SETUP=y CONFIG_BOOTSTAGE=y CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_SPL_SHOW_BOOT_PROGRESS=y +CONFIG_BOOTCOMMAND="run start_watchdog; run distro_bootcmd" CONFIG_CONSOLE_MUX=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_BOARD_INIT=y @@ -134,6 +135,7 @@ CONFIG_USB_DWC3_GENERIC=y CONFIG_USB_KEYBOARD=y # CONFIG_WATCHDOG is not set # CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WATCHDOG_TIMEOUT_MSECS=0 CONFIG_WDT=y CONFIG_WDT_K3_RTI=y CONFIG_WDT_K3_RTI_LOAD_FW=y diff --git a/include/configs/iot2050.h b/include/configs/iot2050.h index 91ed76bb40b..26875afdeaf 100644 --- a/include/configs/iot2050.h +++ b/include/configs/iot2050.h @@ -21,6 +21,14 @@
#define CONFIG_SYS_BOOTM_LEN SZ_64M
+#define WATCHDOG_ENV \ + "watchdog_timeout_ms=" __stringify(CONFIG_WATCHDOG_TIMEOUT_MSECS) "\0" \ + "start_watchdog=if test ${watchdog_timeout_ms} -gt 0; then " \ + "wdt dev watchdog@40610000; " \ + "wdt start ${watchdog_timeout_ms}; " \ + "echo Watchdog started, timeout ${watchdog_timeout_ms} ms; " \ + "fi\0" + /* U-Boot general configuration */ #define EXTRA_ENV_IOT2050_BOARD_SETTINGS \ "usb_pgood_delay=900\0" @@ -53,6 +61,7 @@ #define CONFIG_EXTRA_ENV_SETTINGS \ DEFAULT_LINUX_BOOT_ENV \ BOOTENV \ + WATCHDOG_ENV \ EXTRA_ENV_IOT2050_BOARD_SETTINGS
#include <configs/ti_armv7_common.h>

From: Jan Kiszka jan.kiszka@siemens.com
Will be needed when CONFIG_ENV_WRITEABLE_LIST is enabled. The listed variables shall remain writable, for informational purposes - they have to be considered untrusted because the persistent U-Boot env is not protected.
Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- include/configs/iot2050.h | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/include/configs/iot2050.h b/include/configs/iot2050.h index 26875afdeaf..097fca5e3b3 100644 --- a/include/configs/iot2050.h +++ b/include/configs/iot2050.h @@ -66,4 +66,12 @@
#include <configs/ti_armv7_common.h>
+#ifdef CONFIG_ENV_WRITEABLE_LIST +/* relevant for secure boot with CONFIG_ENV_WRITEABLE_LIST=y */ +#define CONFIG_ENV_FLAGS_LIST_STATIC \ + "board_uuid:sw,board_name:sw,board_serial:sw,board_a5e:sw," \ + "mlfb:sw,fw_version:sw,seboot_version:sw," \ + "eth1addr:mw,eth2addr:mw,watchdog_timeout_ms:dw,boot_targets:sw" +#endif + #endif /* __CONFIG_IOT2050_H */

From: Jan Kiszka jan.kiszka@siemens.com
Add hashes and configuration signature stubs to prepare verified boot of main U-Boot by SPL.
Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- arch/arm/dts/k3-am65-iot2050-boot-image.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi index 3ee0842e993..9082a79a034 100644 --- a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi +++ b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi @@ -14,6 +14,7 @@ filename = "flash.bin"; pad-byte = <0xff>; size = <0x8c0000>; + allow-repack;
blob-ext@0x000000 { offset = <0x000000>; @@ -45,6 +46,9 @@ entry = <0x80800000>; u-boot-nodtb { }; + hash { + algo = "sha256"; + }; };
@fdt-SEQ { @@ -52,6 +56,9 @@ type = "flat_dt"; arch = "arm64"; compression = "none"; + hash { + algo = "sha256"; + }; };
#ifdef CONFIG_WDT_K3_RTI_FW_FILE @@ -64,6 +71,9 @@ filename = CONFIG_WDT_K3_RTI_FW_FILE; missing-msg = "k3-rti-wdt-firmware"; }; + hash { + algo = "sha256"; + }; }; #endif }; @@ -77,10 +87,16 @@ #ifdef CONFIG_WDT_K3_RTI_FW_FILE loadables = "k3-rti-wdt-firmware"; #endif + signature { + sign-images = "firmware", "fdt", "loadables"; + }; }; }; };
+ fdtmap { + }; + /* primary env */ fill@0x680000 { offset = <0x680000>;

From: Jan Kiszka jan.kiszka@siemens.com
There are many ways to get a signed firmware for the IOT2050 devices, namely for the parts under user-control. This script documents one way of doing it, given a signing key. Augment the board documentation with the required procedure around it.
Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- doc/board/siemens/iot2050.rst | 52 +++++++++++++++++++++++++++++++++++ tools/iot2050-sign-fw.sh | 51 ++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100755 tools/iot2050-sign-fw.sh
diff --git a/doc/board/siemens/iot2050.rst b/doc/board/siemens/iot2050.rst index 26972e20ae9..4e0925c72c9 100644 --- a/doc/board/siemens/iot2050.rst +++ b/doc/board/siemens/iot2050.rst @@ -79,3 +79,55 @@ Via external programmer Dediprog SF100 or SF600: .. code-block:: text
$ dpcmd --vcc 2 -v -u flash.bin + +Signing (optional) +------------------ + +To enable verified boot for the firmware artifacts after the Siemens-managed +first-stage loader (seboot_pg*.bin), the following steps need to be taken +before and after the build: + +Generate dtsi holding the public key +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + tools/key2dtsi.py -c -s key.pem public-key.dtsi + +This will be used to embed the public key into U-Boot SPL and main so that each +step can validate signatures of the succeeding one. + +Adjust U-Boot configuration +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Enabled at least the following options in U-Boot: + +.. code-block:: text + + CONFIG_SPL_FIT_SIGNATURE=y + CONFIG_DEVICE_TREE_INCLUDES="/path/to/public-key.dtsi" + CONFIG_RSA=y + +Note that there are more configuration changes needed in order to lock-down +the command line and the boot process of U-Boot for secure scenarios. These are +not in scope here. + +Build U-Boot +^^^^^^^^^^^^ + +See related section above. + +Sign flash.bin +^^^^^^^^^^^^^^ + +In the build folder still containing artifacts from step 3, invoke: + +.. code-block:: text + + tools/iot2050-sign-fw.sh /path/to/key.pem + +Flash signed flash.bin +^^^^^^^^^^^^^^^^^^^^^^ + +The signing has happen in-place in flash.bin, thus the flashing procedure +described above. diff --git a/tools/iot2050-sign-fw.sh b/tools/iot2050-sign-fw.sh new file mode 100755 index 00000000000..4d1d79498c2 --- /dev/null +++ b/tools/iot2050-sign-fw.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +if [ -z "$1" ]; then + echo "Usage: $0 KEY" + exit 1 +fi + +TEMP_X509=$(mktemp XXXXXXXX.temp) + +REVISION=${2:-0} +SHA_VAL=$(openssl dgst -sha512 -hex tispl.bin | sed -e "s/^.*= //g") +BIN_SIZE=$(stat -c %s tispl.bin) + +cat <<EOF >$TEMP_X509 +[ req ] +distinguished_name = req_distinguished_name +x509_extensions = v3_ca +prompt = no +dirstring_type = nobmp + +[ req_distinguished_name ] +CN = IOT2050 Firmware Signature + +[ v3_ca ] +basicConstraints = CA:true +1.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv +1.3.6.1.4.1.294.1.34 = ASN1:SEQUENCE:sysfw_image_integrity + +[ swrv ] +swrv = INTEGER:$REVISION + +[ sysfw_image_integrity ] +shaType = OID:2.16.840.1.101.3.4.2.3 +shaValue = FORMAT:HEX,OCT:$SHA_VAL +imageSize = INTEGER:$BIN_SIZE +EOF + +CERT_X509=$(mktemp XXXXXXXX.crt) + +openssl req -new -x509 -key $1 -nodes -outform DER -out $CERT_X509 -config $TEMP_X509 -sha512 +cat $CERT_X509 tispl.bin > tispl.bin_signed +# currently broken in upstream +#source/tools/binman/binman replace -i flash.bin -f tispl.bin_signed blob@0x180000 +dd if=tispl.bin_signed of=flash.bin bs=$((0x1000)) seek=$((0x180000/0x1000)) conv=notrunc + +rm $TEMP_X509 $CERT_X509 + +tools/mkimage -G $1 -r -o sha256,rsa4096 -F fit@0x380000.fit +# currently broken in upstream +#source/tools/binman/binman replace -i flash.bin -f fit@0x380000.fit fit@0x380000 +dd if=fit@0x380000.fit of=flash.bin bs=$((0x1000)) seek=$((0x380000/0x1000)) conv=notrunc

From: Jan Kiszka jan.kiszka@siemens.com
Use external blob otpcmd.bin to replace the 0xff filled OTP programming command block to create a firmware image that provisions the OTP on first boot. This otpcmd.bin is generated from the customer keys using steps described in the meta-iot2050 integration layer for the device.
Based on original patch by Baocheng Su.
Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- arch/arm/dts/k3-am65-iot2050-boot-image.dtsi | 8 ++++++++ board/siemens/iot2050/Kconfig | 7 +++++++ doc/board/siemens/iot2050.rst | 8 ++++++++ tools/binman/missing-blob-help | 8 ++++++++ 4 files changed, 31 insertions(+)
diff --git a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi index 9082a79a034..25a22a7b7b8 100644 --- a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi +++ b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi @@ -111,10 +111,18 @@ };
/* OTP update command block */ +#if CONFIG_IOT2050_EMBED_OTPCMD + blob-ext@0x6c0000 { + offset = <0x6c0000>; + size = <0x010000>; + filename = "otpcmd.bin"; + missing-msg = "iot2050-otpcmd"; +#else fill@0x6c0000 { offset = <0x6c0000>; size = <0x010000>; fill-byte = [ff]; +#endif }; }; }; diff --git a/board/siemens/iot2050/Kconfig b/board/siemens/iot2050/Kconfig index e264bec2d44..09b47257bbf 100644 --- a/board/siemens/iot2050/Kconfig +++ b/board/siemens/iot2050/Kconfig @@ -49,4 +49,11 @@ config IOT2050_BOOT_SWITCH bool "Disable eMMC boot via USER button (Advanced version only)" default y
+config IOT2050_EMBED_OTPCMD + bool "Embed OTP programming data" + help + Embed signed OTP programming data 'otpcmd.bin' into the firmware + image. This data will be evaluated and executed on first boot of the + device. + endif diff --git a/doc/board/siemens/iot2050.rst b/doc/board/siemens/iot2050.rst index 4e0925c72c9..cb49a0e36bf 100644 --- a/doc/board/siemens/iot2050.rst +++ b/doc/board/siemens/iot2050.rst @@ -27,6 +27,14 @@ The following binaries from that source need to be present in the build folder: - seboot_pg1.bin - seboot_pg2.bin
+For building an image containing the OTP key provisioning data, below binary +needs to be present in the build folder: + + - otpcmd.bin + +Regarding how to generating this otpcmd.bin, please refer to: +https://github.com/siemens/meta-iot2050/tree/master/recipes-bsp/secure-boot-... + Building --------
diff --git a/tools/binman/missing-blob-help b/tools/binman/missing-blob-help index 5bb8961ce03..7e88cd03954 100644 --- a/tools/binman/missing-blob-help +++ b/tools/binman/missing-blob-help @@ -23,6 +23,14 @@ See the documentation for IOT2050 board. Your image is missing SEBoot which is mandatory for board startup. Prebuilt SEBoot located at meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/seboot_pg*.bin.
+iot2050-otpcmd: +See the documentation for IOT2050 board. Your image is missing OTP command data +block which is used for provisioning the customer keys to the board. +Please refer to +meta-iot2050/tree/master/recipes-bsp/secure-boot-otp-provisioning/files/make-otpcmd.sh +for how to generate this binary. If you are not using secure boot or do not +intend to provision the keys, disable CONFIG_IOT2050_EMBED_OTPCMD. + k3-rti-wdt-firmware: If CONFIG_WDT_K3_RTI_LOAD_FW is enabled, a firmware image is needed for the R5F core(s) to trigger the system reset. One possible source is

From: Jan Kiszka jan.kiszka@siemens.com
This is enabled by default, thus should be described as well.
Signed-off-by: Jan Kiszka jan.kiszka@siemens.com --- doc/board/siemens/iot2050.rst | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/doc/board/siemens/iot2050.rst b/doc/board/siemens/iot2050.rst index cb49a0e36bf..efe94a448a9 100644 --- a/doc/board/siemens/iot2050.rst +++ b/doc/board/siemens/iot2050.rst @@ -27,6 +27,10 @@ The following binaries from that source need to be present in the build folder: - seboot_pg1.bin - seboot_pg2.bin
+When using the watchdog, a related firmware for the R5 core(s) is needed, e.g. +https://github.com/siemens/k3-rti-wdt. The name and location of the image is +configured via CONFIG_WDT_K3_RTI_FW_FILE. + For building an image containing the OTP key provisioning data, below binary needs to be present in the build folder:
participants (2)
-
Jan Kiszka
-
Marek Vasut