new file mode 100644
@@ -0,0 +1,37 @@
+# This software is a part of ISAR.
+# Copyright (C) Siemens AG, 2024-2025
+#
+# SPDX-License-Identifier: MIT
+
+python() {
+ additional_packages = d.getVar('TARGET_BOOTSTRAPPER_ADDITIONAL_PACKAGES').split()
+
+ names = []
+ workdirs = []
+ scripts = []
+ efforts = []
+ effort_total = 0
+
+ for package in additional_packages:
+ additional_package_task = f"TARGET_BOOTSTRAPPER_TASK_{package}"
+
+ names.append(package)
+ workdirs.append(d.getVarFlag(additional_package_task, "workdir") or ".")
+
+ script = d.getVarFlag(additional_package_task, "script")
+ if not script:
+ bb.warn("Script not set for {task_name} - consider setting {task_name}[script] = \"<your-script-for-{task_name}>\"".format(task_name=additional_package_task))
+
+ scripts.append(script or "/bin/true")
+
+ effort = d.getVarFlag(additional_package_task, "effort") or "1"
+ efforts.append(effort)
+
+ effort_total = effort_total + int(effort)
+
+ d.setVar('TMPL_TARGET_BOOTSTRAPPER_TASK_NAMES', ' '.join(names))
+ d.setVar('TMPL_TARGET_BOOTSTRAPPER_TASK_WORKDIRS', ' '.join(workdirs))
+ d.setVar('TMPL_TARGET_BOOTSTRAPPER_TASK_SCRIPTS', ' '.join(scripts))
+ d.setVar('TMPL_TARGET_BOOTSTRAPPER_TASK_EFFORTS', ' '.join(efforts))
+ d.setVar('TMPL_TARGET_BOOTSTRAPPER_TASK_TOTAL_EFFORT', str(effort_total))
+}
new file mode 100644
@@ -0,0 +1,3 @@
+[Service]
+ExecStart=
+ExecStart=/bin/sh -c "target-bootstrapper.sh || (echo 'Rebooting in 60 s'; sleep 60); reboot"
new file mode 100644
@@ -0,0 +1,38 @@
+# This software is a part of ISAR.
+# Copyright (C) Siemens AG, 2024-2025
+#
+# SPDX-License-Identifier: MIT
+
+DESCRIPTION = "systemd service to run target bootstrapper on ${TARGET_BOOTSTRAPPER_TTY_SERVICES}"
+
+TARGET_BOOTSTRAPPER_TTY_SERVICES ??= "\
+ getty@tty1 \
+ serial-getty@ttyS0 \
+ "
+
+python(){
+ if not d.getVar('TARGET_BOOTSTRAPPER_TTY_SERVICES'):
+ bb.error("No ttys for target bootstrapper configured - review TARGET_BOOTSTRAPPER_TTY_SERVICES setting")
+
+ if (bb.utils.to_boolean(d.getVar('INSTALLER_UNATTENDED')) and
+ len(d.getVar('TARGET_BOOTSTRAPPER_TTY_SERVICES').split()) != 1):
+ bb.warn("Multiple ttys are configured for target bootstrapper in unattended mode. - potential race condition detected!")
+}
+
+inherit dpkg-raw
+
+SRC_URI = "\
+ file://target-bootstrapper.override.conf \
+ "
+
+DEPENDS += " target-bootstrapper"
+DEBIAN_DEPENDS = "target-bootstrapper"
+
+do_install[cleandirs] = "${D}/usr/lib/systemd/system/"
+do_install() {
+ for svc_name in ${TARGET_BOOTSTRAPPER_TTY_SERVICES}
+ do
+ mkdir -p ${D}/usr/lib/systemd/system/${svc_name}.service.d/
+ install -m 0644 ${WORKDIR}/target-bootstrapper.override.conf ${D}/usr/lib/systemd/system/${svc_name}.service.d/10-target-bootstrapper.override.conf
+ done
+}
new file mode 100644
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+# This software is a part of ISAR.
+# Copyright (C) Siemens AG, 2024
+#
+# SPDX-License-Identifier: MIT
+
+task_names=($TMPL_TARGET_BOOTSTRAPPER_TASK_NAMES)
+task_workdirs=($TMPL_TARGET_BOOTSTRAPPER_TASK_WORKDIRS)
+task_scripts=($TMPL_TARGET_BOOTSTRAPPER_TASK_SCRIPTS)
+task_efforts=($TMPL_TARGET_BOOTSTRAPPER_TASK_EFFORTS)
+handled_effort=0
+total_effort=$TMPL_TARGET_BOOTSTRAPPER_TASK_TOTAL_EFFORT
+
+tasks_total=${#task_names[@]}
+tasks_indices=${!task_names[@]}
+
+echo "Found $tasks_total tasks to execute for target bootstrapping."
+echo ""
+
+for idx in ${tasks_indices}
+do
+ echo "Task $(( idx+1 ))/${tasks_total} - $((handled_effort*100/total_effort))%"
+ echo "Handling task ${task_names[$idx]}"
+
+ echo "Entering workdir ${task_workdirs[$idx]}..."
+ pushd ${task_workdirs[$idx]} > /dev/null
+
+ ## execute task in subshell
+ (./${task_scripts[$idx]})
+ execution_result=$?
+ if [ ${execution_result} -eq 0 ]; then
+ echo "${task_names[$idx]} executed sucessfully"
+ else
+ echo "${task_names[$idx]} failed with ${execution_result}" -> abort!
+ exit ${execution_result}
+ fi
+
+ echo "Leaving workdir ${task_workdirs[$idx]}..."
+ popd > /dev/null
+
+ handled_effort=$((handled_effort+task_efforts[idx]))
+done
+
+echo "All tasks completed!"
new file mode 100644
@@ -0,0 +1,41 @@
+# This software is a part of ISAR.
+# Copyright (C) Siemens AG, 2024-2025
+#
+# SPDX-License-Identifier: MIT
+
+inherit dpkg-raw
+inherit target-bootstrapper
+
+DESCRIPTION = "Device bootstrapping framework"
+
+TARGET_BOOTSTRAPPER_ADDITIONAL_PACKAGES ??= "deploy-image"
+TARGET_BOOTSTRAPPER_TASK_deploy-image[script] ??= "deploy-image-wic.sh"
+TARGET_BOOTSTRAPPER_TASK_deploy-image[workdir] ??= "/usr/bin"
+TARGET_BOOTSTRAPPER_TASK_deploy-image[effort] ??= "2"
+
+DEPENDS += " ${@isar_multiarch_packages('TARGET_BOOTSTRAPPER_ADDITIONAL_PACKAGES', d)}"
+DEBIAN_DEPENDS += " \
+ , bash \
+ , ${@ ', '.join(isar_multiarch_packages('TARGET_BOOTSTRAPPER_ADDITIONAL_PACKAGES', d).split())} \
+ "
+
+SRC_URI = " \
+ file://target-bootstrapper.sh.tmpl \
+ "
+
+TEMPLATE_FILES = " \
+ target-bootstrapper.sh.tmpl \
+ "
+
+TEMPLATE_VARS = " \
+ TMPL_TARGET_BOOTSTRAPPER_TASK_NAMES \
+ TMPL_TARGET_BOOTSTRAPPER_TASK_WORKDIRS \
+ TMPL_TARGET_BOOTSTRAPPER_TASK_SCRIPTS \
+ TMPL_TARGET_BOOTSTRAPPER_TASK_EFFORTS \
+ TMPL_TARGET_BOOTSTRAPPER_TASK_TOTAL_EFFORT \
+ "
+
+do_install[cleandirs] = "${D}/usr/bin/"
+do_install() {
+ install -m 0755 ${WORKDIR}/target-bootstrapper.sh ${D}/usr/bin/
+}