diff options
| author | Tom Rini <[email protected]> | 2025-11-06 17:41:28 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-11-06 17:41:28 -0600 |
| commit | 9e2bce78fd5ea59161b91b0885cfccb6fdf3b96f (patch) | |
| tree | ac4e35082848fbfe133547d1e165c94a76161c27 | |
| parent | f05576620c54f7465a2dd0ff5c3d8d56744ef31c (diff) | |
| parent | 489ec1ee14a87afa6c8a1a996878c5ac58b6827c (diff) | |
Merge patch series "Allow falcon boot from R5 SPL on TI's AM62 devices"
Anshul Dalal <[email protected]> says:
This patch set adds support for falcon boot on AM62a, 62p and 62x by bypassing
A53 SPL and U-boot.
Existing Boot flow:
R5 SPL -> ATF -> A53 SPL -> U-Boot -> Linux Kernel
Updated flow:
R5 SPL -> ATF -> Linux Kernel
U-Boot's falcon mode expects the jump from SPL to kernel to happen on the same
core which is not directly applicable for our heterogeneous platforms since
ATF, OPTEE and other non SPL binaries from tispl.bin should be loaded before the
kernel by the R5 SPL.
So we have to use a different flow to bypass A53 SPL and U-Boot, we first load
the newly added tispl_falcon.bin instead of tispl.bin which lacks u-boot-spl.bin
(A53's SPL) and the corresponding fdt. This sets up dm, tifs, optee and
atf. Once loaded, we load the kernel and the dtb (with fixups) at ATF's
PRELOADED_BL33_BASE and K3_HW_CONFIG_BASE.
NOTE:
Since we're now using the SPL to load the kernel and kernel expects a 2MiB
aligned load address, the existing PRELOADED_BL33_BASE has to be changed for ATF
to 0x82000000 with K3_HW_CONFIG_BASE set to 0x88000000 for the DTB.
Link: https://lore.kernel.org/r/[email protected]
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/dts/k3-am625-sk-binman.dtsi | 64 | ||||
| -rw-r--r-- | arch/arm/dts/k3-am62a-sk-binman.dtsi | 51 | ||||
| -rw-r--r-- | arch/arm/dts/k3-am62p-sk-binman.dtsi | 51 | ||||
| -rw-r--r-- | arch/arm/dts/k3-binman.dtsi | 54 | ||||
| -rw-r--r-- | arch/arm/mach-k3/am62ax/am62a7_init.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-k3/am62px/am62p5_init.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-k3/am62x/am625_init.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-k3/common.c | 8 | ||||
| -rw-r--r-- | arch/arm/mach-k3/common.h | 5 | ||||
| -rw-r--r-- | arch/arm/mach-k3/r5/common.c | 146 | ||||
| -rw-r--r-- | configs/k3_r5_falcon.config | 39 | ||||
| -rw-r--r-- | doc/board/ti/am62ax_sk.rst | 31 | ||||
| -rw-r--r-- | doc/board/ti/am62px_sk.rst | 31 | ||||
| -rw-r--r-- | doc/board/ti/am62x_sk.rst | 319 | ||||
| -rw-r--r-- | doc/board/ti/img/fitImage_falcon.svg | 180 | ||||
| -rw-r--r-- | doc/board/ti/img/tifsstub_dm_tifalcon.bin.svg | 285 |
17 files changed, 1277 insertions, 1 deletions
@@ -2471,7 +2471,7 @@ CLEAN_FILES += include/autoconf.mk* include/bmp_logo.h include/bmp_logo_data.h \ idbloader-spi.img lib/efi_loader/helloworld_efi.S *.itb \ Test* capsule*.*.efi-capsule capsule*.map mkimage.imx-boot.spl \ mkimage.imx-boot.u-boot mkimage-out.imx-boot.spl mkimage-out.imx-boot.u-boot \ - imx9image* m33-oei-ddrfw* + imx9image* m33-oei-ddrfw* tifalcon.bin # Directories & files removed with 'make mrproper' MRPROPER_DIRS += include/config include/generated spl tpl vpl \ diff --git a/arch/arm/dts/k3-am625-sk-binman.dtsi b/arch/arm/dts/k3-am625-sk-binman.dtsi index f743c4353b4..42edb35fa7b 100644 --- a/arch/arm/dts/k3-am625-sk-binman.dtsi +++ b/arch/arm/dts/k3-am625-sk-binman.dtsi @@ -206,6 +206,70 @@ }; }; + ti-falcon { + insert-template = <&ti_falcon_template>; + + fit { + images { + tifsstub-hs { + description = "TIFSSTUB"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-hs"; + load = <0x9dc00000>; + entry = <0x9dc00000>; + blob-ext { + filename = "tifsstub.bin_hs"; + }; + }; + tifsstub-fs { + description = "TIFSSTUB"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-fs"; + load = <0x9dc00000>; + entry = <0x9dc00000>; + blob-ext { + filename = "tifsstub.bin_fs"; + }; + }; + tifsstub-gp { + description = "TIFSSTUB"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-gp"; + load = <0x9dc00000>; + entry = <0x9dc00000>; + blob-ext { + filename = "tifsstub.bin_gp"; + }; + }; + dm { + ti-secure { + content = <&dm_falcon>; + keyfile = "custMpk.pem"; + }; + dm_falcon: ti-dm { + filename = "ti-dm/am62xx/ipc_echo_testb_mcu1_0_release_strip.xer5f"; + }; + }; + }; + + configurations { + default = "conf-0"; + conf-0 { + description = "k3-am625-sk-falcon"; + firmware = "atf"; + loadables = "tee", "tifsstub-hs", "tifsstub-fs", + "tifsstub-gp", "dm"; + }; + }; + }; + }; + ti-spl { insert-template = <&ti_spl_template>; diff --git a/arch/arm/dts/k3-am62a-sk-binman.dtsi b/arch/arm/dts/k3-am62a-sk-binman.dtsi index e3a2d155d51..cb9a56b8c37 100644 --- a/arch/arm/dts/k3-am62a-sk-binman.dtsi +++ b/arch/arm/dts/k3-am62a-sk-binman.dtsi @@ -144,6 +144,57 @@ }; + ti-falcon { + insert-template = <&ti_falcon_template>; + + fit { + images { + tifsstub-hs { + description = "TIFSSTUB"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-hs"; + load = <0x9ca00000>; + entry = <0x9ca00000>; + blob-ext { + filename = "tifsstub.bin_hs"; + }; + }; + tifsstub-fs { + description = "TIFSSTUB"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-fs"; + load = <0x9ca00000>; + entry = <0x9ca00000>; + blob-ext { + filename = "tifsstub.bin_fs"; + }; + }; + dm { + ti-secure { + content = <&dm_falcon>; + keyfile = "custMpk.pem"; + }; + dm_falcon: ti-dm { + filename = "ti-dm/am62axx/ipc_echo_testb_mcu1_0_release_strip.xer5f"; + }; + }; + }; + + configurations { + default = "conf-0"; + conf-0 { + description = "k3-am62a7-sk-falcon"; + firmware = "atf"; + loadables = "tee", "dm", "tifsstub-hs", "tifsstub-fs"; + }; + }; + }; + }; + ti-spl { insert-template = <&ti_spl_template>; diff --git a/arch/arm/dts/k3-am62p-sk-binman.dtsi b/arch/arm/dts/k3-am62p-sk-binman.dtsi index feb59edcd83..e1443d6226b 100644 --- a/arch/arm/dts/k3-am62p-sk-binman.dtsi +++ b/arch/arm/dts/k3-am62p-sk-binman.dtsi @@ -161,6 +161,57 @@ }; + ti-falcon { + insert-template = <&ti_falcon_template>; + + fit { + images { + tifsstub-hs { + description = "TIFSSTUB"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-hs"; + load = <0x9ca00000>; + entry = <0x9ca00000>; + blob-ext { + filename = "tifsstub.bin_hs"; + }; + }; + tifsstub-fs { + description = "TIFSSTUB"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-fs"; + load = <0x9ca00000>; + entry = <0x9ca00000>; + blob-ext { + filename = "tifsstub.bin_fs"; + }; + }; + dm { + ti-secure { + content = <&dm_falcon>; + keyfile = "custMpk.pem"; + }; + dm_falcon: ti-dm { + filename = "ti-dm/am62pxx/ipc_echo_testb_mcu1_0_release_strip.xer5f"; + }; + }; + }; + + configurations { + default = "conf-0"; + conf-0 { + description = "k3-am62p5-sk-falcon"; + firmware = "atf"; + loadables = "tee", "dm", "tifsstub-hs", "tifsstub-fs"; + }; + }; + }; + }; + ti-spl { insert-template = <&ti_spl_template>; diff --git a/arch/arm/dts/k3-binman.dtsi b/arch/arm/dts/k3-binman.dtsi index 5163161b94d..761b1730464 100644 --- a/arch/arm/dts/k3-binman.dtsi +++ b/arch/arm/dts/k3-binman.dtsi @@ -489,6 +489,60 @@ end_address = <0x0 0x9fffffff>; }; + ti_falcon_template: template-9 { + filename = "tifalcon.bin"; + pad-byte = <0xff>; + + fit { + description = "Configuration for falcon boot"; + #address-cells = <1>; + + images { + atf { + description = "ARM Trusted Firmware"; + type = "firmware"; + arch = "arm64"; + compression = "none"; + os = "arm-trusted-firmware"; + load = <CONFIG_K3_ATF_LOAD_ADDR>; + entry = <CONFIG_K3_ATF_LOAD_ADDR>; + ti-secure { + content = <&atf_falcon>; + keyfile = "custMpk.pem"; + }; + atf_falcon: atf-bl31 { + }; + }; + tee { + description = "OP-TEE"; + type = "tee"; + arch = "arm64"; + compression = "none"; + os = "tee"; + load = <CONFIG_K3_OPTEE_LOAD_ADDR>; + entry = <CONFIG_K3_OPTEE_LOAD_ADDR>; + ti-secure { + content = <&tee_falcon>; + keyfile = "custMpk.pem"; + }; + tee_falcon: tee-os { + optional; + }; + }; + dm { + description = "DM binary"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "DM"; + load = <0x89000000>; + entry = <0x89000000>; + }; + + }; + }; + }; + }; #endif diff --git a/arch/arm/mach-k3/am62ax/am62a7_init.c b/arch/arm/mach-k3/am62ax/am62a7_init.c index 48d578e7d6f..7de23461163 100644 --- a/arch/arm/mach-k3/am62ax/am62a7_init.c +++ b/arch/arm/mach-k3/am62ax/am62a7_init.c @@ -240,5 +240,9 @@ u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device) u32 spl_boot_device(void) { +#if IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE) && !IS_ENABLED(CONFIG_ARM64) + return k3_r5_falcon_bootmode(); +#else return get_boot_device(); +#endif } diff --git a/arch/arm/mach-k3/am62px/am62p5_init.c b/arch/arm/mach-k3/am62px/am62p5_init.c index aebd5200b0d..4c215d5cebe 100644 --- a/arch/arm/mach-k3/am62px/am62p5_init.c +++ b/arch/arm/mach-k3/am62px/am62p5_init.c @@ -375,6 +375,10 @@ u32 spl_boot_device(void) u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT); u32 bootmedia; +#if IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE) && !IS_ENABLED(CONFIG_ARM64) + return k3_r5_falcon_bootmode(); +#endif + if (bootindex == K3_PRIMARY_BOOTMODE) bootmedia = __get_primary_bootmedia(devstat); else diff --git a/arch/arm/mach-k3/am62x/am625_init.c b/arch/arm/mach-k3/am62x/am625_init.c index 14f93ac998f..02b7414e21c 100644 --- a/arch/arm/mach-k3/am62x/am625_init.c +++ b/arch/arm/mach-k3/am62x/am625_init.c @@ -327,5 +327,9 @@ u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device) u32 spl_boot_device(void) { +#if IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE) && !IS_ENABLED(CONFIG_ARM64) + return k3_r5_falcon_bootmode(); +#else return get_boot_device(); +#endif } diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index 3f51b9614d9..760aaad0341 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -361,6 +361,14 @@ void spl_perform_arch_fixups(struct spl_image_info *spl_image) void spl_board_prepare_for_boot(void) { +#if IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE) && !IS_ENABLED(CONFIG_ARM64) + int ret; + + ret = k3_r5_falcon_prep(); + if (ret) + panic("%s: Failed to boot in falcon mode: %d\n", __func__, ret); +#endif /* falcon mode on R5 SPL */ + #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) dcache_disable(); #endif diff --git a/arch/arm/mach-k3/common.h b/arch/arm/mach-k3/common.h index 52d3faaab5c..cd3e19374dc 100644 --- a/arch/arm/mach-k3/common.h +++ b/arch/arm/mach-k3/common.h @@ -52,6 +52,11 @@ void do_board_detect(void); void ti_secure_image_check_binary(void **p_image, size_t *p_size); int shutdown_mcu_r5_core1(void); +#if IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE) && !IS_ENABLED(CONFIG_ARM64) +int k3_r5_falcon_bootmode(void); +int k3_r5_falcon_prep(void); +#endif + #if (IS_ENABLED(CONFIG_K3_QOS)) void setup_qos(void); #else diff --git a/arch/arm/mach-k3/r5/common.c b/arch/arm/mach-k3/r5/common.c index 6269b33f66b..03638366046 100644 --- a/arch/arm/mach-k3/r5/common.c +++ b/arch/arm/mach-k3/r5/common.c @@ -376,3 +376,149 @@ void board_fit_image_post_process(const void *fit, int node, void **p_image, } } #endif + +#ifdef CONFIG_SPL_OS_BOOT_SECURE + +static bool tifalcon_loaded = false; + +int spl_start_uboot(void) +{ + /* If tifalcon.bin is not loaded, proceed to regular boot */ + if (!tifalcon_loaded) + return 1; + + /* Boot to linux on R5 SPL with tifalcon.bin loaded */ + return 0; +} + +int k3_r5_falcon_bootmode(void) +{ + char *mmcdev = env_get("mmcdev"); + + if (!mmcdev) + return BOOT_DEVICE_NOBOOT; + + if (strncmp(mmcdev, "0", sizeof("0")) == 0) + return BOOT_DEVICE_MMC1; + else if (strncmp(mmcdev, "1", sizeof("1")) == 0) + return BOOT_DEVICE_MMC2; + else + return BOOT_DEVICE_NOBOOT; +} + +static int k3_falcon_fdt_add_bootargs(void *fdt) +{ + struct disk_partition info; + struct blk_desc *dev_desc; + char bootmedia[32]; + char bootpart[32]; + char str[256]; + int ret; + + strlcpy(bootmedia, env_get("boot"), sizeof(bootmedia)); + strlcpy(bootpart, env_get("bootpart"), sizeof(bootpart)); + ret = blk_get_device_part_str(bootmedia, bootpart, &dev_desc, &info, 0); + if (ret < 0) { + printf("%s: Failed to get part details for %s %s [%d]\n", + __func__, bootmedia, bootpart, ret); + return ret; + } + + if (!CONFIG_IS_ENABLED(PARTITION_UUIDS)) { + printf("ERROR: Failed to find rootfs PARTUUID\n"); + printf("%s: CONFIG_SPL_PARTITION_UUIDS not enabled\n", + __func__); + return -EOPNOTSUPP; + } + + snprintf(str, sizeof(str), "console=%s root=PARTUUID=%s rootwait", + env_get("console"), disk_partition_uuid(&info)); + + ret = fdt_find_and_setprop(fdt, "/chosen", "bootargs", str, + strlen(str) + 1, 1); + if (ret) { + printf("%s: Could not set bootargs: %s\n", __func__, + fdt_strerror(ret)); + return ret; + } + + debug("%s: Set bootargs to: %s\n", __func__, str); + return 0; +} + +static int k3_falcon_fdt_fixup(void *fdt) +{ + int ret; + + if (!fdt) + return -EINVAL; + + fdt_set_totalsize(fdt, fdt_totalsize(fdt) + CONFIG_SYS_FDT_PAD); + + if (fdt_path_offset(fdt, "/chosen/bootargs") < 0) { + ret = k3_falcon_fdt_add_bootargs(fdt); + + if (ret) + return ret; + } + + if (IS_ENABLED(CONFIG_OF_BOARD_SETUP)) { + ret = ft_board_setup(fdt, gd->bd); + if (ret) { + printf("%s: Failed in board setup: %s\n", __func__, + fdt_strerror(ret)); + return ret; + } + } + + if (IS_ENABLED(CONFIG_OF_SYSTEM_SETUP)) { + ret = ft_system_setup(fdt, gd->bd); + if (ret) { + printf("%s: Failed in system setup: %s\n", __func__, + fdt_strerror(ret)); + return ret; + } + } + + return 0; +} + +int k3_r5_falcon_prep(void) +{ + struct spl_image_loader *loader, *drv; + struct spl_image_info kernel_image; + struct spl_boot_device bootdev; + int ret = -ENXIO, n_ents; + void *fdt; + + tifalcon_loaded = true; + memset(&kernel_image, '\0', sizeof(kernel_image)); + drv = ll_entry_start(struct spl_image_loader, spl_image_loader); + n_ents = ll_entry_count(struct spl_image_loader, spl_image_loader); + bootdev.boot_device = k3_r5_falcon_bootmode(); + + for (loader = drv; loader != drv + n_ents; loader++) { + if (loader && bootdev.boot_device != loader->boot_device) + continue; + + printf("Load falcon from %s\n", spl_loader_name(loader)); + ret = loader->load_image(&kernel_image, &bootdev); + if (ret) + continue; + + fdt = spl_image_fdt_addr(&kernel_image); + ret = k3_falcon_fdt_fixup(fdt); + if (ret) { + printf("Failed to fixup fdt in falcon mode: %d\n", ret); + return ret; + } + + return 0; + } + + printf("%s: ERROR: No supported loader for boot dev '%d'\n", __func__, + bootdev.boot_device); + + return ret; +} +#endif diff --git a/configs/k3_r5_falcon.config b/configs/k3_r5_falcon.config new file mode 100644 index 00000000000..b6762b35f74 --- /dev/null +++ b/configs/k3_r5_falcon.config @@ -0,0 +1,39 @@ +# Enable falcon mode +CONFIG_SPL_OS_BOOT=y +CONFIG_SPL_OS_BOOT_SECURE=y + +# We use envs for setting bootargs +CONFIG_SPL_ENV_SUPPORT=y + +# Allows for the SPL to detect UUID for kernel's rootfs +CONFIG_SPL_PARTITION_UUIDS=y + +# Perform FDT fixups from SPL +CONFIG_OF_SYSTEM_SETUP=y + +# We use the rootfs (i.e partition 2) for booting which is ext4 not FAT +CONFIG_SYS_MMCSD_FS_BOOT=y +CONFIG_SYS_MMCSD_FS_BOOT_PARTITION=2 +CONFIG_SPL_FS_EXT4=y + +# Loading tifalcon instead of tispl which has FDT and A53 SPL saves time +CONFIG_SPL_FS_LOAD_PAYLOAD_NAME="boot/tifalcon.bin" +CONFIG_SPL_FS_LOAD_KERNEL_NAME="boot/fitImage" +CONFIG_SPL_LOAD_FIT=y + +# Used as the 2MiB aligned load address for kernel +CONFIG_SYS_LOAD_ADDR=0x82000000 +CONFIG_SPL_STACK_R_ADDR=0x88000000 +CONFIG_SPL_LOAD_FIT_ADDRESS=0x82000000 +CONFIG_SPL_PAYLOAD_ARGS_ADDR=0x88000000 +CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2700000 + +# Disable all unsupported boot media to save space +# CONFIG_SPL_SYS_MMCSD_RAW_MODE is not set +# CONFIG_SPL_SPI_FLASH_SUPPORT is not set +# CONFIG_SPL_YMODEM_SUPPORT is not set +# CONFIG_SUPPORT_EMMC_BOOT is not set +# CONFIG_SPL_NAND_SUPPORT is not set +# CONFIG_SPL_NOR_SUPPORT is not set +# CONFIG_SPL_RAM_DEVICE is not set +# CONFIG_SPL_FS_FAT is not set diff --git a/doc/board/ti/am62ax_sk.rst b/doc/board/ti/am62ax_sk.rst index 4dd998bcce9..8eeb90a271b 100644 --- a/doc/board/ti/am62ax_sk.rst +++ b/doc/board/ti/am62ax_sk.rst @@ -187,6 +187,37 @@ https://www.ti.com/lit/pdf/spruj16 under the `Boot Mode Pins` section. For SW2 and SW1, the switch state in the "ON" position = 1. +Falcon Mode +----------- + +Falcon Mode on AM62ax platforms bypasses the A53 SPL and U-Boot with the overall +boot flow as below: + +.. include:: am62x_sk.rst + :start-after: .. am62x_evm_falcon_start_boot_flow + :end-before: .. am62x_evm_falcon_end_boot_flow + +Build Process +^^^^^^^^^^^^^ + +.. include:: am62x_sk.rst + :start-after: .. am62x_evm_falcon_start_build_process + :end-before: .. am62x_evm_falcon_end_build_process + +Usage +^^^^^ + +.. include:: am62x_sk.rst + :start-after: .. am62x_evm_falcon_start_usage + :end-before: .. am62x_evm_falcon_end_usage + +R5 SPL Memory Map +^^^^^^^^^^^^^^^^^ + +.. include:: am62x_sk.rst + :start-after: .. am62x_evm_falcon_start_r5_memory_map + :end-before: .. am62x_evm_falcon_end_r5_memory_map + Debugging U-Boot ---------------- diff --git a/doc/board/ti/am62px_sk.rst b/doc/board/ti/am62px_sk.rst index a07d6a4da45..da70cd58095 100644 --- a/doc/board/ti/am62px_sk.rst +++ b/doc/board/ti/am62px_sk.rst @@ -290,6 +290,37 @@ https://www.ti.com/lit/pdf/spruj83 under the `Boot Mode Pins` section. For SW2 and SW1, the switch state in the "ON" position = 1. +Falcon Mode +----------- + +Falcon Mode on AM62px platforms bypasses the A53 SPL and U-Boot with the overall +boot flow as below: + +.. include:: am62x_sk.rst + :start-after: .. am62x_evm_falcon_start_boot_flow + :end-before: .. am62x_evm_falcon_end_boot_flow + +Build Process +^^^^^^^^^^^^^ + +.. include:: am62x_sk.rst + :start-after: .. am62x_evm_falcon_start_build_process + :end-before: .. am62x_evm_falcon_end_build_process + +Usage +^^^^^ + +.. include:: am62x_sk.rst + :start-after: .. am62x_evm_falcon_start_usage + :end-before: .. am62x_evm_falcon_end_usage + +R5 SPL Memory Map +^^^^^^^^^^^^^^^^^ + +.. include:: am62x_sk.rst + :start-after: .. am62x_evm_falcon_start_r5_memory_map + :end-before: .. am62x_evm_falcon_end_r5_memory_map + Debugging U-Boot ---------------- diff --git a/doc/board/ti/am62x_sk.rst b/doc/board/ti/am62x_sk.rst index dab2970a85c..1a0e5e07c4b 100644 --- a/doc/board/ti/am62x_sk.rst +++ b/doc/board/ti/am62x_sk.rst @@ -526,6 +526,325 @@ Next, based on NET_VCI_STRING string mentioned in respective defconfig file `tib fetches `tispl.bin` and then `tispl.bin` fetches `u-boot.img` from TFTP server which completes Ethernet boot on the device. +Falcon Mode +----------- + +Falcon Mode on AM62x platforms bypasses the A53 SPL and U-Boot with the overall +boot flow as below: + +.. am62x_evm_falcon_start_boot_flow + +**Normal boot flow:** + +.. code-block:: + + | tiboot3.bin | tispl.bin | u-boot.img | Image | + |-------------+----------------------------+------------+---------| + R5 Core | SPL | | | | + ---------| \ | | | | + A53 Core | ------> TFA -> OP-TEE -> A53 SPL --> U-Boot --> Kernel | + +**With falcon mode:** + +.. code-block:: + + | tiboot3.bin | tifalcon.bin | fitImage | + |-------------+------------------+----------| + R5 Core | SPL | | | + ---------| \ | | | + A53 Core | ------> TFA -> OP-TEE --> Kernel | + +.. am62x_evm_falcon_end_boot_flow + +Build Process +^^^^^^^^^^^^^ + +.. am62x_evm_falcon_start_build_process + +Enabling falcon mode requires re-building TFA, U-Boot and the kernel +``fitImage`` as follows: + +0. Setup environment variables: +""""""""""""""""""""""""""""""" + +Refer to the build procedure above for setting up the environment variables. + +1. Trusted Firmware-A: +"""""""""""""""""""""" + +The R5 SPL in falcon mode loads the kernel at ``0x82000000`` and the +corresponding DTB at ``0x88000000``. Therefore TFA needs to be rebuild with +changes to the respective addresses. + +.. prompt:: bash $ + + # Change load addresses for the kernel and DTB + export TFA_EXTRA_ARGS="PRELOADED_BL33_BASE=0x82000000 K3_HW_CONFIG_BASE=0x88000000" + +.. include:: k3.rst + :start-after: .. k3_rst_include_start_build_steps_tfa + :end-before: .. k3_rst_include_end_build_steps_tfa + +2. U-Boot: +"""""""""" + +* **2.1 R5:** + +.. prompt:: bash $ + + # use the common falcon config fragment for all K3 platforms + export $UBOOT_FALCON_CFG_FRAGMENTR="k3_r5_falcon.config" + export UBOOT_CFG_CORTEXR="${UBOOT_CFG_CORTEXR} ${UBOOT_FALCON_CFG_FRAGMENTR}" + +.. include:: k3.rst + :start-after: .. k3_rst_include_start_build_steps_spl_r5 + :end-before: .. k3_rst_include_end_build_steps_spl_r5 + +* **2.2 A53:** + +After rebuilding TFA, the binary needs to be repackaged inside the tispl +binaries: + +.. include:: k3.rst + :start-after: .. k3_rst_include_start_build_steps_uboot + :end-before: .. k3_rst_include_end_build_steps_uboot + +3. fitImage: +"""""""""""" + +.. warning:: + + The ``fitImage`` available by default under ``boot/fitImage`` in rootfs of + the standard SDK release is not compatible with falcon mode. + +For authenticated boot in falcon mode, the compute heavy authentication +required for the ``fitImage`` is offloaded from the slower R5 core to TIFS. This +requires ``fitImage`` to package the necessary binaries (kernel and dtb) with a +pre-signed x509 certificate. + +**fitImage for falcon mode:** + +.. image:: img/fitImage_falcon.svg + :alt: fitImage for falcon boot image format + +* **Sources** + + * **Core Secdev K3** + + | **source:** https://git.ti.com/cgit/security-development-tools/core-secdev-k3 + | **branch:** master + +**Follow the steps below to create a falcon compatible fitImage:** + +**3.1 Environment setup** + +.. prompt:: bash $ + + export DTB=path/to/dtb + export IMAGE=path/to/kernel-image + +**3.2 fitImage creation** + + An Image tree source (*its*) file describes the structure and contents of the + final image produced by the ``mkimage`` tool. + + To create the ``fitImage`` for falcon mode, create a file ``fitImage.its`` + with the following contents inside the ``core-secdev-k3`` source directory,: + +.. code-block:: dts + + /dts-v1/; + + / { + description = "Kernel fitImage"; + #address-cells = <1>; + + images { + kernel-sec { + description = "Linux kernel"; + data = /incbin/("Image.sec"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x82000000>; + entry = <0x82000000>; + }; + + fdt-sec { + description = "Flattened Device Tree blob"; + data = /incbin/("falcon.dtb.sec"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x88000000>; + entry = <0x88000000>; + }; + }; + + configurations { + default = "conf-falcon"; + conf-falcon { + description = "Pre-signed Linux kernel, FDT blob"; + kernel = "kernel-sec"; + fdt = "fdt-sec"; + }; + }; + }; + +Sign the kernel and dtb using ``secure-binary-image.sh`` and create the +``fitImage`` using mkimage: + +.. prompt:: bash $ + + # inside core-secdev-k3 source + cp $IMAGE Image + cp $DTB falcon.dtb + ./scripts/secure-binary-image.sh Image Image.sec + ./scripts/secure-binary-image.sh falcon.dtb falcon.dtb.sec + mkimage -f fitImage.its fitImage + +.. am62x_evm_falcon_end_build_process + +Usage +^^^^^ + +.. am62x_evm_falcon_start_usage + +Falcon Mode makes use of a cut down variant of the tispl binary called +``tifalcon.bin`` with lacks the Cortex-A SPL and it's DTBs. This file should +be present alongside the existing ``tispl.bin`` after building U-Boot for the +Cortex-A core. + +- **tifalcon.bin** + +.. image:: img/tifsstub_dm_tifalcon.bin.svg + :alt: tifalcon.bin image format + +The R5 SPL requires both ``tifalcon.bin`` and the ``fitImage`` (created +in previous steps) to be present in the second partition of the MMC device +specified by the ``mmcdev`` environment variable. By default, ``mmcdev`` is +set to 1, which implies that the SD card is the boot media. Additionally, the +``bootpart`` environment variable, which defaults to 1:2, specifies that the +second partition of the SD card should be used as the root file system for the +kernel. + +To use eMMC instead of SD as the boot media, rebuild the R5 SPL with the +following diff: + +.. code-block:: diff + + diff --git a/board/ti/<soc>/<soc>.env b/board/ti/<soc>/<soc>.env + index 82b9f0741bb..73d59ac425c 100644 + --- a/board/ti/<soc>/<soc>.env + +++ b/board/ti/<soc>/<soc>.env + @@ -17,8 +17,8 @@ run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr} + + boot_targets=mmc1 mmc0 usb pxe dhcp + boot=mmc + -mmcdev=1 + -bootpart=1:2 + +mmcdev=0 + +bootpart=0:1 + bootdir=/boot + rd_spec=- + +**List of files required on SD/eMMC for Falcon Mode:** + +.. list-table:: + :widths: 8 8 8 25 + :header-rows: 1 + + * - File + - Copy path on SD/eMMC + - Partition + - Description + + * - ``tifalcon.bin`` + - ``/boot/tifalcon.bin`` + - rootfs (ext4) + - tispl binary without SPL for the A core and DTB + + * - ``fitImage`` + - ``/boot/fitImage`` + - rootfs (ext4) + - kernel and dtb fitImage with pre-signed binaries + +.. note:: + + Falcon mode requires the boot binaries to be present in the root file system + of either eMMC or SD, even when using raw eMMC boot mode to load + ``tiboot3.bin``. + +.. am62x_evm_falcon_end_usage + +R5 SPL Memory Map +^^^^^^^^^^^^^^^^^ + +.. am62x_evm_falcon_start_r5_memory_map + +Standard Boot: +"""""""""""""" + +.. code-block:: + + 0x80000000 +===============================+ Start of DDR + 512KiB | TFA reserved memory space | CONFIG_K3_ATF_LOAD_ADDR + | | + 0x80080000 +-------------------------------+ PRELOADED_BL33_BASE in TFA + 29.5MiB | A53 SPL + DTB + | CONFIG_SPL_LOAD_FIT_ADDRESS + | Download region for FIT in DFU| + 0x81e00000 +-------------------------------+ + | R5 U-Boot SPL Stack + Heap | + 2MiB | (size defined by | + | SPL_STACK_R_MALLOC_SIMPLE_LEN)| + 0x82000000 +-------------------------------+ CONFIG_SPL_STACK_R_ADDR + 112MiB | Unused | + 0x89000000 +-------------------------------+ + 331MiB | Device Manager (DM) Load Addr | + 0x9db00000 +-------------------------------+ + 12MiB | DM Reserved | + 0x9e700000 +-------------------------------+ + 1MiB | Unused | + 0x9e800000 +-------------------------------+ BL32_BASE in TFA + 24MiB | OPTEE | + 0xa0000000 +===============================+ End of DDR (512MiB) + +Falcon Mode: +"""""""""""" + +.. code-block:: + + 0x80000000 +===============================+ Start of DDR + 512KiB | TFA reserved memory space | CONFIG_K3_ATF_LOAD_ADDR + 0x80080000 +-------------------------------+ + 31.5MiB | Unused | + 0x82000000 +-------------------------------+ PRELOADED_BL33_BASE in TFA + | | CONFIG_SYS_LOAD_ADDR + 57MiB | Kernel + initramfs Image | CONFIG_SPL_LOAD_FIT_ADDRESS + | | + 0x85900000 +-------------------------------+ + | | + | R5 U-Boot SPL Stack + Heap | + 39MiB | (size defined by | + | SPL_STACK_R_MALLOC_SIMPLE_LEN)| + | | + 0x88000000 +-------------------------------+ CONFIG_SPL_STACK_R_ADDR + | | K3_HW_CONFIG_BASE in TFA + 16MiB | Kernel DTB | CONFIG_SPL_PAYLOAD_ARGS_ADDR + | | + 0x89000000 +-------------------------------+ + 331MiB | Device Manager (DM) Load Addr | + 0x9db00000 +-------------------------------+ + 12MiB | DM Reserved | + 0x9e700000 +-------------------------------+ + 1MiB | Unused | + 0x9e800000 +-------------------------------+ BL32_BASE in TFA + 24MiB | OPTEE | + 0xa0000000 +===============================+ End of DDR (512MiB) + +.. am62x_evm_falcon_end_r5_memory_map + Debugging U-Boot ---------------- diff --git a/doc/board/ti/img/fitImage_falcon.svg b/doc/board/ti/img/fitImage_falcon.svg new file mode 100644 index 00000000000..b5f0229397f --- /dev/null +++ b/doc/board/ti/img/fitImage_falcon.svg @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause --> + +<!-- Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/ --> + +<svg + version="1.1" + width="231" + height="220" + viewBox="-0.5 -0.5 231 220" + id="svg72" + sodipodi:docname="fitImage_falcon.svg" + inkscape:version="1.4.1 (93de688d07, 2025-03-30)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview74" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="2.9" + inkscape:cx="83.62069" + inkscape:cy="131.72414" + inkscape:window-width="1918" + inkscape:window-height="1078" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="0" + inkscape:current-layer="g62" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1" /> + <defs + id="defs2"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 104.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="231 : 104.5 : 1" + inkscape:persp3d-origin="115.5 : 46 : 1" + id="perspective1" /> + </defs> + <g + id="g62"> + <rect + x="-0.06279549" + y="-0.062792346" + width="230.12561" + height="219.12558" + rx="34.518837" + ry="27.33382" + fill="#d5e8d4" + stroke="#82b366" + pointer-events="all" + id="rect4" + style="display:inline;fill:#dbe4f4;fill-opacity:1;stroke:#8166b3;stroke-width:0.888796;stroke-dasharray:none;stroke-opacity:1" /> + <text + x="115.15599" + y="156.49472" + fill="#000000" + font-family="Helvetica" + font-size="12px" + text-anchor="middle" + id="text8-8-7-6-6" + style="display:inline" + inkscape:label="x509 cert">x509 Certificate</text> + <text + x="115.15598" + y="85.615631" + fill="#000000" + font-family="Helvetica" + font-size="12px" + text-anchor="middle" + id="text8-8-7-6-6-1" + style="display:inline" + inkscape:label="x509 cert">x509 Certificate</text> + <text + x="114.532" + y="42.263863" + fill="#000000" + font-family="Helvetica" + font-size="12px" + text-anchor="middle" + id="text8-8-7-6-6-5" + style="display:inline" + inkscape:label="x509 cert">Fit Header</text> + <text + x="114.78398" + y="106.884" + fill="#000000" + font-family="Helvetica" + font-size="12px" + text-anchor="middle" + id="text8-8-7-6-6-5-5" + style="display:inline" + inkscape:label="x509 cert">Kernel Image</text> + <rect + style="display:none;fill:#000000;fill-opacity:0;stroke:#000000;stroke-width:1.00157;stroke-dasharray:none;stroke-opacity:1" + id="rect1" + width="171.46796" + height="210.89911" + x="36.799908" + y="21.652758" + transform="translate(-7.533886,15.237117)" /> + <text + xml:space="preserve" + style="font-size:21.3333px;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:#db8c8c;fill-opacity:1;stroke:#000000;stroke-width:1.13386" + x="90.327087" + y="177.15775" + id="text1"><tspan + sodipodi:role="line" + id="tspan1" + x="90.327087" + y="177.15775" /></text> + <text + xml:space="preserve" + style="font-size:21.3333px;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:#db8c8c;fill-opacity:1;stroke:#000000;stroke-width:1.13386" + x="106.45526" + y="214.93161" + id="text2"><tspan + sodipodi:role="line" + id="tspan2" + x="106.45526" + y="214.93161" /></text> + <g + id="g62-6" + transform="translate(-5.6022949,-9.676433)"> + <text + x="120.33229" + y="188.7475" + fill="#000000" + font-family="Helvetica" + font-size="12px" + text-anchor="middle" + id="text8-8-7-6-6-5-2" + style="display:inline" + inkscape:label="x509 cert">DTB</text> + </g> + <rect + style="fill:#db8c8c;fill-opacity:0;stroke:#000000;stroke-width:1.13386" + id="rect2" + width="82.644012" + height="17.6518" + x="73.677986" + y="94.992081" /> + <rect + style="fill:#db8c8c;fill-opacity:0;stroke:#000000;stroke-width:1.13386;stroke-dasharray:none" + id="rect2-7" + width="32.336376" + height="18.068098" + x="98.83181" + y="165.66302" /> + <rect + style="fill:#db8c8c;fill-opacity:0;stroke:#000000;stroke-width:1.77036;stroke-dasharray:none" + id="rect3" + width="152.43475" + height="70.500725" + x="38.782627" + y="127.54861" /> + <rect + style="fill:#db8c8c;fill-opacity:0;stroke:#000000;stroke-width:1.77036;stroke-dasharray:none" + id="rect3-9" + width="152.43475" + height="70.500732" + x="38.782623" + y="56.777336" /> + <rect + style="fill:#db8c8c;fill-opacity:0;stroke:#000000;stroke-width:1.78506;stroke-dasharray:none" + id="rect5" + width="152.41736" + height="36.60006" + x="38.791306" + y="20.211617" /> + </g> +</svg> diff --git a/doc/board/ti/img/tifsstub_dm_tifalcon.bin.svg b/doc/board/ti/img/tifsstub_dm_tifalcon.bin.svg new file mode 100644 index 00000000000..2508923d480 --- /dev/null +++ b/doc/board/ti/img/tifsstub_dm_tifalcon.bin.svg @@ -0,0 +1,285 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause --> + +<!-- Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/ --> + +<svg + version="1.1" + width="231" + height="280" + viewBox="-0.5 -0.5 231 280" + id="svg72" + sodipodi:docname="tifsstub_dm_tifalcon.bin.svg" + inkscape:version="1.4.1 (93de688d07, 2025-03-30)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:xhtml="http://www.w3.org/1999/xhtml"> + <sodipodi:namedview + id="namedview74" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + showgrid="false" + inkscape:zoom="2.3561254" + inkscape:cx="175.5" + inkscape:cy="151.30774" + inkscape:window-width="1920" + inkscape:window-height="1080" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="0" + inkscape:current-layer="g62" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1" /> + <defs + id="defs2"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 104.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="231 : 104.5 : 1" + inkscape:persp3d-origin="115.5 : 46 : 1" + id="perspective1" /> + </defs> + <g + id="g62"> + <rect + x="-0.0064085587" + y="-0.0064054145" + width="230.01283" + height="278.39682" + rx="34.501923" + ry="34.727341" + fill="#d5e8d4" + stroke="#82b366" + pointer-events="all" + id="rect4" + style="stroke-width:1.00331" /> + <rect + x="40" + y="30" + width="160" + height="60" + fill="none" + stroke="#000000" + pointer-events="all" + id="rect6" /> + <g + transform="translate(-0.5,-0.5)" + id="g12"> + <switch + id="switch10"> + <foreignObject + style="overflow: visible; text-align: left;" + pointer-events="none" + width="100%" + height="100%" + requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <xhtml:div + style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 60px; margin-left: 41px;"> + <xhtml:div + style="box-sizing: border-box; font-size: 0px; text-align: center;" + data-drawio-colors="color: rgb(0, 0, 0); "> + <xhtml:div + style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FIT Header</xhtml:div> + </xhtml:div> + </xhtml:div> + </foreignObject> + <text + x="120" + y="64" + fill="#000000" + font-family="Helvetica" + font-size="12px" + text-anchor="middle" + id="text8">FIT Header</text> + </switch> + </g> + <rect + x="40" + y="160" + width="160" + height="50" + fill="none" + stroke="#000000" + pointer-events="all" + id="rect14" /> + <g + transform="translate(-0.5,-0.5)" + id="g20"> + <switch + id="switch18"> + <foreignObject + style="overflow: visible; text-align: left;" + pointer-events="none" + width="100%" + height="100%" + requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <xhtml:div + style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 185px; margin-left: 41px;"> + <xhtml:div + style="box-sizing: border-box; font-size: 0px; text-align: center;" + data-drawio-colors="color: rgb(0, 0, 0); "> + <xhtml:div + style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">TIFS Stub<xhtml:br /> + +(GP, HS-FS, HS-SE)</xhtml:div> + </xhtml:div> + </xhtml:div> + </foreignObject> + <text + x="120" + y="189" + fill="#000000" + font-family="Helvetica" + font-size="12px" + text-anchor="middle" + id="text16">TIFS Stub...</text> + </switch> + </g> + <rect + x="40" + y="90" + width="160" + height="30" + fill="none" + stroke="#000000" + pointer-events="all" + id="rect22" /> + <g + transform="translate(-0.5,-0.5)" + id="g28"> + <switch + id="switch26"> + <foreignObject + style="overflow: visible; text-align: left;" + pointer-events="none" + width="100%" + height="100%" + requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <xhtml:div + style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 105px; margin-left: 41px;"> + <xhtml:div + style="box-sizing: border-box; font-size: 0px; text-align: center;" + data-drawio-colors="color: rgb(0, 0, 0); "> + <xhtml:div + style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">TF-A</xhtml:div> + </xhtml:div> + </xhtml:div> + </foreignObject> + <text + x="120" + y="109" + fill="#000000" + font-family="Helvetica" + font-size="12px" + text-anchor="middle" + id="text24">TF-A</text> + </switch> + </g> + <rect + x="40" + y="120" + width="160" + height="40" + fill="none" + stroke="#000000" + pointer-events="all" + id="rect30" /> + <g + transform="translate(-0.5,-0.5)" + id="g36"> + <switch + id="switch34"> + <foreignObject + style="overflow: visible; text-align: left;" + pointer-events="none" + width="100%" + height="100%" + requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <xhtml:div + style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 140px; margin-left: 41px;"> + <xhtml:div + style="box-sizing: border-box; font-size: 0px; text-align: center;" + data-drawio-colors="color: rgb(0, 0, 0); "> + <xhtml:div + style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">OP-TEE</xhtml:div> + </xhtml:div> + </xhtml:div> + </foreignObject> + <text + x="120" + y="144" + fill="#000000" + font-family="Helvetica" + font-size="12px" + text-anchor="middle" + id="text32">OP-TEE</text> + </switch> + </g> + <rect + x="40" + y="210" + width="160" + height="40" + fill="none" + stroke="#000000" + pointer-events="all" + id="rect38" /> + <g + transform="translate(-0.5,-0.5)" + id="g44"> + <switch + id="switch42"> + <foreignObject + style="overflow: visible; text-align: left;" + pointer-events="none" + width="100%" + height="100%" + requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <xhtml:div + style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 230px; margin-left: 41px;"> + <xhtml:div + style="box-sizing: border-box; font-size: 0px; text-align: center;" + data-drawio-colors="color: rgb(0, 0, 0); "> + <xhtml:div + style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">R5 DM FW</xhtml:div> + </xhtml:div> + </xhtml:div> + </foreignObject> + <text + x="120" + y="234" + fill="#000000" + font-family="Helvetica" + font-size="12px" + text-anchor="middle" + id="text40">R5 DM FW</text> + </switch> + </g> + </g> + <switch + id="switch70"> + <g + requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" + id="g64" /> + <a + transform="translate(0,-5)" + xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" + target="_blank" + id="a68"> + <text + text-anchor="middle" + font-size="10px" + x="50%" + y="100%" + id="text66">Text is not SVG - cannot display</text> + </a> + </switch> +</svg> |
