@@ -2,7 +2,9 @@ diff --git a/drivers/tee/CMakeLists.txt b/drivers/tee/CMakeLists.txt
22index aaf8924b096..15ca3a06782 100644
33--- a/drivers/tee/CMakeLists.txt
44+++ b/drivers/tee/CMakeLists.txt
5- @@ -3,4 +3,5 @@
5+ @@ -1,6 +1,7 @@
6+ # SPDX-License-Identifier: Apache-2.0
7+
68 add_subdirectory_ifdef(CONFIG_OPTEE optee)
79+ add_subdirectory_ifdef(CONFIG_WOLFBOOT_TEE wolfboot)
810
@@ -19,3 +21,358 @@ index dd5acce4e00..24447494d01 100644
1921+ source "drivers/tee/wolfboot/Kconfig"
2022
2123 endif # TEE
24+ diff --git a/drivers/tee/wolfboot/CMakeLists.txt b/drivers/tee/wolfboot/CMakeLists.txt
25+ new file mode 100644
26+ index 00000000000..812499ea603
27+ --- /dev/null
28+ +++ b/drivers/tee/wolfboot/CMakeLists.txt
29+ @@ -0,0 +1,9 @@
30+ + # SPDX-License-Identifier: GPL-3.0 OR LicenceRef-wolfssl.com-Commercial
31+ +
32+ + zephyr_library()
33+ + zephyr_library_sources_ifdef(CONFIG_WOLFBOOT_TEE wolfboot.c)
34+ +
35+ + if(CONFIG_WOLFBOOT_TEE)
36+ + set_target_properties(zephyr_property_target PROPERTIES SIGNING_SCRIPT
37+ + ${CMAKE_CURRENT_LIST_DIR}/wolfboot_sign.cmake)
38+ + endif()
39+ diff --git a/drivers/tee/wolfboot/Kconfig b/drivers/tee/wolfboot/Kconfig
40+ new file mode 100644
41+ index 00000000000..d32faaf8e9b
42+ --- /dev/null
43+ +++ b/drivers/tee/wolfboot/Kconfig
44+ @@ -0,0 +1,9 @@
45+ + # SPDX-License-Identifier: GPL-3.0 OR LicenceRef-wolfssl.com-Commercial
46+ +
47+ + config WOLFBOOT_TEE
48+ + bool "wolfBoot TEE driver"
49+ + depends on TEE
50+ + select PSA_CRYPTO_CLIENT
51+ + select WOLFBOOT
52+ + help
53+ + Enable the wolfBoot TEE driver and PSA CMSE glue.
54+ diff --git a/drivers/tee/wolfboot/wolfboot.c b/drivers/tee/wolfboot/wolfboot.c
55+ new file mode 100644
56+ index 00000000000..ae69692422c
57+ --- /dev/null
58+ +++ b/drivers/tee/wolfboot/wolfboot.c
59+ @@ -0,0 +1,41 @@
60+ + /* SPDX-License-Identifier: GPL-3.0 OR LicenceRef-wolfssl.com-Commercial */
61+ +
62+ + #include <errno.h>
63+ + #include <zephyr/device.h>
64+ + #include <zephyr/drivers/tee.h>
65+ +
66+ + #define DT_DRV_COMPAT wolfboot_tee
67+ +
68+ + #define TEE_IMPL_ID_WOLFBOOT 0x57424F4F /* "WBOO" */
69+ +
70+ + static int wolfboot_get_version(const struct device *dev, struct tee_version_info *info)
71+ + {
72+ + ARG_UNUSED(dev);
73+ +
74+ + if (!info) {
75+ + return -EINVAL;
76+ + }
77+ +
78+ + info->impl_id = TEE_IMPL_ID_WOLFBOOT;
79+ + info->impl_caps = 0;
80+ + info->gen_caps = TEE_GEN_CAP_GP;
81+ +
82+ + return 0;
83+ + }
84+ +
85+ + static const struct tee_driver_api wolfboot_tee_api = {
86+ + .get_version = wolfboot_get_version,
87+ + };
88+ +
89+ + static int wolfboot_tee_init(const struct device *dev)
90+ + {
91+ + ARG_UNUSED(dev);
92+ + return 0;
93+ + }
94+ +
95+ + #define WOLFBOOT_TEE_INIT(inst) \
96+ + DEVICE_DT_INST_DEFINE(inst, wolfboot_tee_init, NULL, NULL, NULL, \
97+ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
98+ + &wolfboot_tee_api);
99+ +
100+ + DT_INST_FOREACH_STATUS_OKAY(WOLFBOOT_TEE_INIT)
101+ diff --git a/drivers/tee/wolfboot/wolfboot_config.py b/drivers/tee/wolfboot/wolfboot_config.py
102+ new file mode 100644
103+ index 00000000000..b5110089d78
104+ --- /dev/null
105+ +++ b/drivers/tee/wolfboot/wolfboot_config.py
106+ @@ -0,0 +1,69 @@
107+ + #!/usr/bin/env python3
108+ + # SPDX-License-Identifier: GPL-3.0 OR LicenceRef-wolfssl.com-Commercial
109+ +
110+ + """Import select values from a wolfBoot .config file."""
111+ +
112+ + from __future__ import annotations
113+ +
114+ + import argparse
115+ + import re
116+ + from pathlib import Path
117+ +
118+ +
119+ + _CONFIG_RE = re.compile(r"^([A-Za-z0-9_]+)\??=\s*(.+)$")
120+ +
121+ +
122+ + def _parse_value(raw: str) -> int:
123+ + val = raw.strip()
124+ + if val.lower().startswith("0x"):
125+ + return int(val, 16)
126+ + return int(val, 10)
127+ +
128+ +
129+ + def parse_config(path: Path) -> dict[str, str]:
130+ + data: dict[str, str] = {}
131+ + for line in path.read_text(encoding="utf-8").splitlines():
132+ + line = line.strip()
133+ + if not line or line.startswith("#"):
134+ + continue
135+ + match = _CONFIG_RE.match(line)
136+ + if not match:
137+ + continue
138+ + key, value = match.group(1), match.group(2)
139+ + data[key] = value.strip()
140+ + return data
141+ +
142+ +
143+ + def emit_conf(path: Path, header_size: int) -> None:
144+ + content = f"CONFIG_ROM_START_OFFSET=0x{header_size:x}\n"
145+ + path.write_text(content, encoding="utf-8")
146+ +
147+ +
148+ + def main() -> int:
149+ + parser = argparse.ArgumentParser()
150+ + parser.add_argument("--config", required=True, type=Path)
151+ + parser.add_argument("--emit-conf", type=Path)
152+ + parser.add_argument("--print-header-size", action="store_true")
153+ + args = parser.parse_args()
154+ +
155+ + cfg_path: Path = args.config
156+ + if not cfg_path.exists():
157+ + raise SystemExit(f"wolfBoot config not found: {cfg_path}")
158+ +
159+ + cfg = parse_config(cfg_path)
160+ + if "IMAGE_HEADER_SIZE" not in cfg:
161+ + raise SystemExit("IMAGE_HEADER_SIZE not found in wolfBoot config")
162+ +
163+ + header_size = _parse_value(cfg["IMAGE_HEADER_SIZE"])
164+ +
165+ + if args.emit_conf:
166+ + emit_conf(args.emit_conf, header_size)
167+ +
168+ + if args.print_header_size:
169+ + print(header_size)
170+ +
171+ + return 0
172+ +
173+ +
174+ + if __name__ == "__main__":
175+ + raise SystemExit(main())
176+ diff --git a/drivers/tee/wolfboot/wolfboot_sign.cmake b/drivers/tee/wolfboot/wolfboot_sign.cmake
177+ new file mode 100644
178+ index 00000000000..c5f0017cbea
179+ --- /dev/null
180+ +++ b/drivers/tee/wolfboot/wolfboot_sign.cmake
181+ @@ -0,0 +1,164 @@
182+ + # SPDX-License-Identifier: GPL-3.0 OR LicenceRef-wolfssl.com-Commercial
183+ +
184+ + function(wolfboot_parse_version version_string out_var)
185+ + if(version_string STREQUAL "")
186+ + set(${out_var} 0 PARENT_SCOPE)
187+ + return()
188+ + endif()
189+ +
190+ + string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)" _match "${version_string}")
191+ + if(NOT _match STREQUAL "")
192+ + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+).*" "\\1;\\2;\\3" _parts "${version_string}")
193+ + list(GET _parts 0 _maj)
194+ + list(GET _parts 1 _min)
195+ + list(GET _parts 2 _pat)
196+ + math(EXPR _ver "${_maj} * 10000 + ${_min} * 100 + ${_pat}")
197+ + set(${out_var} ${_ver} PARENT_SCOPE)
198+ + return()
199+ + endif()
200+ +
201+ + set(${out_var} 0 PARENT_SCOPE)
202+ + endfunction()
203+ +
204+ + function(zephyr_wolfboot_tasks)
205+ + if(NOT DEFINED WOLFBOOT_MODULE_DIR AND DEFINED ZEPHYR_WOLFBOOT_MODULE_DIR)
206+ + set(WOLFBOOT_MODULE_DIR ${ZEPHYR_WOLFBOOT_MODULE_DIR})
207+ + endif()
208+ +
209+ + if(NOT CONFIG_BUILD_OUTPUT_BIN)
210+ + message(FATAL_ERROR "Can't sign images for wolfBoot: CONFIG_BUILD_OUTPUT_BIN is required.")
211+ + endif()
212+ +
213+ + set(keyfile "${CONFIG_WOLFBOOT_SIGNATURE_KEY_FILE}")
214+ + if("${keyfile}" STREQUAL "")
215+ + set(keyfile "${CONFIG_MCUBOOT_SIGNATURE_KEY_FILE}")
216+ + endif()
217+ +
218+ + if("${keyfile}" STREQUAL "")
219+ + message(WARNING "No signing key configured; wolfBoot signing skipped.")
220+ + return()
221+ + endif()
222+ +
223+ + if(NOT IS_ABSOLUTE "${keyfile}")
224+ + if(EXISTS "${APPLICATION_CONFIG_DIR}/${keyfile}")
225+ + set(keyfile "${APPLICATION_CONFIG_DIR}/${keyfile}")
226+ + elseif(DEFINED WEST_TOPDIR AND EXISTS "${WEST_TOPDIR}/${keyfile}")
227+ + set(keyfile "${WEST_TOPDIR}/${keyfile}")
228+ + elseif(DEFINED WOLFBOOT_MODULE_DIR AND EXISTS "${WOLFBOOT_MODULE_DIR}/${keyfile}")
229+ + set(keyfile "${WOLFBOOT_MODULE_DIR}/${keyfile}")
230+ + endif()
231+ + endif()
232+ +
233+ + if(NOT EXISTS "${keyfile}")
234+ + message(FATAL_ERROR "Can't sign images for wolfBoot: can't find key ${keyfile}")
235+ + endif()
236+ + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${keyfile})
237+ +
238+ + if("${CONFIG_WOLFBOOT_SIGN_TOOL}" STREQUAL "")
239+ + if(DEFINED WOLFBOOT_MODULE_DIR)
240+ + set(sign_tool "${WOLFBOOT_MODULE_DIR}/tools/keytools/sign")
241+ + else()
242+ + message(FATAL_ERROR "Can't sign images for wolfBoot: WOLFBOOT_MODULE_DIR not set.")
243+ + endif()
244+ + else()
245+ + set(sign_tool "${CONFIG_WOLFBOOT_SIGN_TOOL}")
246+ + endif()
247+ +
248+ + if(NOT IS_ABSOLUTE "${sign_tool}")
249+ + if(DEFINED WOLFBOOT_MODULE_DIR AND EXISTS "${WOLFBOOT_MODULE_DIR}/${sign_tool}")
250+ + set(sign_tool "${WOLFBOOT_MODULE_DIR}/${sign_tool}")
251+ + elseif(DEFINED WEST_TOPDIR AND EXISTS "${WEST_TOPDIR}/${sign_tool}")
252+ + set(sign_tool "${WEST_TOPDIR}/${sign_tool}")
253+ + endif()
254+ + endif()
255+ +
256+ + if(NOT EXISTS "${sign_tool}")
257+ + message(FATAL_ERROR "Can't sign images for wolfBoot: can't find sign tool ${sign_tool}")
258+ + endif()
259+ +
260+ + set(wolfboot_header_size "")
261+ + if(DEFINED WOLFBOOT_MODULE_DIR)
262+ + set(wolfboot_config "${WOLFBOOT_MODULE_DIR}/.config")
263+ + if(EXISTS "${wolfboot_config}")
264+ + set(wolfboot_cfg_tool
265+ + "${CMAKE_CURRENT_LIST_DIR}/wolfboot_config.py")
266+ + execute_process(
267+ + COMMAND ${PYTHON_EXECUTABLE} ${wolfboot_cfg_tool}
268+ + --config ${wolfboot_config}
269+ + --emit-conf ${ZEPHYR_BINARY_DIR}/wolfboot.conf
270+ + --print-header-size
271+ + OUTPUT_VARIABLE wolfboot_header_size
272+ + OUTPUT_STRIP_TRAILING_WHITESPACE
273+ + RESULT_VARIABLE wolfboot_cfg_result
274+ + )
275+ + if(NOT wolfboot_cfg_result EQUAL 0)
276+ + message(FATAL_ERROR "Failed to parse wolfBoot config at ${wolfboot_config}")
277+ + endif()
278+ + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
279+ + ${wolfboot_config})
280+ + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
281+ + ${wolfboot_cfg_tool})
282+ + else()
283+ + message(WARNING "wolfBoot config not found at ${wolfboot_config}; using Zephyr defaults.")
284+ + endif()
285+ + endif()
286+ +
287+ + set(ver_int "${CONFIG_WOLFBOOT_SIGN_VERSION}")
288+ + if("${ver_int}" STREQUAL "1" AND NOT "${CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION}" STREQUAL "")
289+ + wolfboot_parse_version("${CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION}" ver_int)
290+ + if(ver_int EQUAL 0)
291+ + set(ver_int "${CONFIG_WOLFBOOT_SIGN_VERSION}")
292+ + endif()
293+ + endif()
294+ +
295+ + set(output ${ZEPHYR_BINARY_DIR}/${KERNEL_NAME})
296+ + set(signed_bin ${output}.signed.bin)
297+ + set(signed_hex ${output}.signed.hex)
298+ + set(payload_bin ${output}.payload.bin)
299+ + set(sign_input ${output}.bin)
300+ + set(signed_base ${output})
301+ + set(sign_input ${output}.bin)
302+ +
303+ + set(sign_args "--${CONFIG_WOLFBOOT_SIGN_ALG}" "--${CONFIG_WOLFBOOT_SIGN_HASH}")
304+ +
305+ + set(sign_env_cmd ${CMAKE_COMMAND} -E env)
306+ + if(NOT "${wolfboot_header_size}" STREQUAL "")
307+ + list(APPEND sign_env_cmd IMAGE_HEADER_SIZE=${wolfboot_header_size})
308+ + endif()
309+ +
310+ + if(DEFINED CONFIG_ROM_START_OFFSET AND NOT "${CONFIG_ROM_START_OFFSET}" STREQUAL "0")
311+ + set(strip_tool "${CMAKE_CURRENT_LIST_DIR}/wolfboot_strip.py")
312+ + set(sign_input ${payload_bin})
313+ + set(signed_base ${output}.payload)
314+ + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
315+ + COMMAND ${PYTHON_EXECUTABLE} ${strip_tool}
316+ + --input ${output}.bin
317+ + --output ${payload_bin}
318+ + --strip ${CONFIG_ROM_START_OFFSET})
319+ + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
320+ + ${strip_tool})
321+ + endif()
322+ +
323+ + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
324+ + COMMAND ${sign_env_cmd} ${sign_tool} ${sign_args}
325+ + ${sign_input} ${keyfile} ${ver_int}
326+ + COMMAND ${CMAKE_COMMAND} -E copy
327+ + ${signed_base}_v${ver_int}_signed.bin ${signed_bin})
328+ +
329+ + if(CONFIG_BUILD_OUTPUT_BIN)
330+ + set(BYPRODUCT_KERNEL_SIGNED_BIN_NAME "${signed_bin}"
331+ + CACHE FILEPATH "Signed kernel bin file" FORCE)
332+ + set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts ${signed_bin})
333+ + endif()
334+ +
335+ + if(CONFIG_BUILD_OUTPUT_HEX)
336+ + set(BYPRODUCT_KERNEL_SIGNED_HEX_NAME "${signed_hex}"
337+ + CACHE FILEPATH "Signed kernel hex file" FORCE)
338+ + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
339+ + COMMAND ${CMAKE_OBJCOPY} -I binary -O ihex
340+ + ${signed_bin} ${signed_hex})
341+ + set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts ${signed_hex})
342+ + endif()
343+ + endfunction()
344+ +
345+ + zephyr_wolfboot_tasks()
346+ diff --git a/drivers/tee/wolfboot/wolfboot_strip.py b/drivers/tee/wolfboot/wolfboot_strip.py
347+ new file mode 100644
348+ index 00000000000..6411412767c
349+ --- /dev/null
350+ +++ b/drivers/tee/wolfboot/wolfboot_strip.py
351+ @@ -0,0 +1,27 @@
352+ + #!/usr/bin/env python3
353+ + # SPDX-License-Identifier: GPL-3.0 OR LicenceRef-wolfssl.com-Commercial
354+ +
355+ + """Strip a fixed number of bytes from the start of a binary image."""
356+ +
357+ + from __future__ import annotations
358+ +
359+ + import argparse
360+ + from pathlib import Path
361+ +
362+ +
363+ + def main() -> int:
364+ + parser = argparse.ArgumentParser()
365+ + parser.add_argument("--input", required=True, type=Path)
366+ + parser.add_argument("--output", required=True, type=Path)
367+ + parser.add_argument("--strip", required=True, type=lambda x: int(x, 0))
368+ + args = parser.parse_args()
369+ +
370+ + data = args.input.read_bytes()
371+ + if args.strip < 0 or args.strip > len(data):
372+ + raise SystemExit(f"strip size {args.strip} exceeds input size {len(data)}")
373+ + args.output.write_bytes(data[args.strip:])
374+ + return 0
375+ +
376+ +
377+ + if __name__ == "__main__":
378+ + raise SystemExit(main())
0 commit comments