From patchwork Thu May 14 09:19:47 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kasturi shekar X-Patchwork-Id: 5078 Return-Path: Received: from shymkent.ilbers.de ([unix socket]) by shymkent (Cyrus 2.5.10-Debian-2.5.10-3+deb9u2) with LMTPA; Thu, 14 May 2026 11:20:02 +0200 X-Sieve: CMU Sieve 2.4 Received: from mail-ej1-f61.google.com (mail-ej1-f61.google.com [209.85.218.61]) by shymkent.ilbers.de (8.15.2/8.15.2/Debian-8+deb9u1) with ESMTPS id 64E9Joir025831 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Thu, 14 May 2026 11:19:50 +0200 Received: by mail-ej1-f61.google.com with SMTP id a640c23a62f3a-b8f848ebcbbsf646059466b.0 for ; Thu, 14 May 2026 02:19:50 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1778750385; cv=pass; d=google.com; s=arc-20240605; b=ClAjarZxFpIr/MYe4Jvm9+3DCpea/WsQ1FLn7IN+48WtDTTuSyqyBECdx+TShOCsgs J3uRifSaFNmnfTzCO2NI1XcVK8UGYjvhJSKcQ4K6RTrN2gdnTSC7O0jd1HA4A5L6USXC J44+lbW4ZUlgmufhpbCpahwtKcjaVz5CSVVtfVmbVIgIrx68z1ADG1MJuq63FmdhEIxW 764ht5lR203fhOgf5/0pWF6fjQXcq8Asbqb7BrDoLLEoG51r2uK0U6yttLxLXe7vHutm qjrYXW1tjLI85cx7I0PqvQWN/hLhhyjScp226ym7NlrD70tjphqMLHS179LuiEqCbpgv RuPQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to:feedback-id:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=5bJlvptEJjBMU7GWu0AvOR1DeT00B+2oFF5ihVwIcLw=; fh=NE9djDauaaea6+pLAXiAAaYjatC8tJu1wxENLnm+uks=; b=I6pOGtDU4fp0R5HPP3VjghBlmFqJKdCd8chAG33dccI/sqCFe9iPuDAiXjyIa+SXbN x5gE0OF/BrwBCkzQrTNcke+Q1lFRuPrT5QzKCRE9BkBSGj1TXkFjp/N+cwGyPTUp+zBc jTCYg+4cSpZ7rpswPGx2ZB0TMebYwGZcY4gZHY88x7RyTs743omZ0Y3juuLinuhLArxH XvUChO7ulqrr+u/WsGsBUzonK+cZaTHzK7Ew9fOjr6impuUgsuQFa69SNm9wONipLtBT kSXj1SOLdsQ8gxy6TyBkUrkmkRgBTMOziomx/bzAnKSJRHSRK+/V6dgGW7LhUQEvFB0j EN7A==; darn=isar-build.org ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@siemens.com header.s=fm1 header.b=IJh3OGhU; spf=pass (google.com: domain of fm-1328757-20260514091942e6a899fd2100020708-f9d_ir@rts-flowmailer.siemens.com designates 185.136.64.226 as permitted sender) smtp.mailfrom=fm-1328757-20260514091942e6a899fd2100020708-f9D_Ir@rts-flowmailer.siemens.com; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=siemens.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20251104; t=1778750385; x=1779355185; darn=isar-build.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:feedback-id :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=5bJlvptEJjBMU7GWu0AvOR1DeT00B+2oFF5ihVwIcLw=; b=YPlpIIF3d49vfFVP7DCc4gdwQyRqDUjHgF6CMyFFku5F+2wFCNM721WF9LaoCPB9rn Z2oh6/29IE1104WWbe6BJjfdIQJ1x/as2gQSIpfrBldKMttXS+TALM/14DwV/BeuRn2D vJsbwJScBorrwf+9HkZavwPhOBm9JSaWV39F41P65+Y8m6LukbMBKQA0YWOdrPFTnuF9 yI/H/94q83B4VKm2Gt/0/I4eoJZeN1BQps980p0kK2vTeYTNP0q9bGbohHf+yzx0+o6w UFQq9ne0RHtdEZD5f8sZomDgI1Xe5ix3D2FbECs+7z7EK9ng9YHCk/W0/DgEocgoPhst c6GQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778750385; x=1779355185; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :x-spam-checked-in-group:list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:feedback-id :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:x-beenthere:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=5bJlvptEJjBMU7GWu0AvOR1DeT00B+2oFF5ihVwIcLw=; b=TJwkoLDVgL4MQiD3+NRMivK60x4JE23Qct3JH+fpu0S4oR4tcfWGMx0+mQ9sFkztbe G6xsAxKL2DM0jP6ESk7lkuFWK1J0P9ZEzgOQvkKSosOM5K+vQbPwHr7Lr1KOFplIsjQ0 pCvJQ6Bh2HBvscroSJzX/3mut3dP9rwJ6WwVvMApSL7WT8Sk5pRtnMaqSuceEBoYUV8g O9KuIsbhh1HL7iMcAkaOR7kjlw+ZrUHv4BPHENIJ7PykeUdO2/3du22m2UsLTpIB+Wt9 viWJRigmbhSI5GvS6a3ZwhS98VEXLh5fbKzbHJjOrBHP2A1xIJcMhQj6ENjFraRcNmuQ WLAw== X-Forwarded-Encrypted: i=2; AFNElJ94t4O0NszOXDis63SGhsXPeZ7cWFgwqLDJZhEKH7HUsJUqxoq1UjiFlj6x4PloSY0TsqDDofI=@isar-build.org X-Gm-Message-State: AOJu0Yzl89LsgCBMWaqYOcFRHN/cn10p/saAvHvRp2jr/vjpuKJHwqpq FVzINMC/DQzA4DbOjQufjJZe2oDBDadmP5rYk8NXxdsfHokfw1+LH5/n X-Received: by 2002:a17:907:7ba6:b0:bd5:a7c:f358 with SMTP id a640c23a62f3a-bd50a7cf697mr31645266b.47.1778750384940; Thu, 14 May 2026 02:19:44 -0700 (PDT) X-BeenThere: isar-users@googlegroups.com; h="AUV6zMNoG65OZijlW8yhprTbuEEQbZ5ZHIobF+yFDQE8HCqQLA==" Received: by 2002:a05:6402:1394:b0:67b:7c3f:d238 with SMTP id 4fb4d7f45d1cf-6832de5aa04ls517801a12.0.-pod-prod-05-eu; Thu, 14 May 2026 02:19:43 -0700 (PDT) X-Received: by 2002:a05:6402:3224:b0:683:6705:6e09 with SMTP id 4fb4d7f45d1cf-68367057056mr221920a12.13.1778750382865; Thu, 14 May 2026 02:19:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1778750382; cv=none; d=google.com; s=arc-20240605; b=hBt45uchm/F7iwJlOv4p+EFybKTRceBe6c7fnKV6AIcLEOFwrc0MKnTqhxyTiZx/Mi 2vH+2krkaGBtwDcTw1FkD8Onnl7ji0qksSpM/MGwaui6/e/TysUR1lLQ0ezGDgWY7pS+ VgBJqkBjIcS36QnpQIIJkulQtHMPKQxBTl9+cMCu4zONdXDaIze9Sy+i8zNyB1KqveRV OfhcnN1acnzCASJHx/GKgMzcvqU9D2tit7MxqjfmG1716z3ymC0I83blHSJxfd7u6to2 T6tJag7RuKe2OWXvCXUUSL2OmVxLHaffz565CsII81EkHaYsj9YWmLnToaPovez6lRXP tZLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=feedback-id:content-transfer-encoding:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=RMeKT9ncX4fxpuvtmuGNWPRsjC05lnaky/fZe1UtSdk=; fh=pR4tJPO4NbHlIB/rP4bIo54Z1zh5hd/ksAGQ0tcKkYM=; b=kTHPCy9by+pJXSJ0A6VEOc4fFtT4bBXQ7R1EWPvw0ZyRn35q0sROGKlCKZqf15fl74 zRY+nJTeagOP84mPoWnTFwBgVguVR1QBNVnDIBalWzni3v1ljQWrWoDQXHXZBgFNq9r8 jfQJ/k5nzuHnu8QsebU3uF6H/VGW4DYdnOwrBoRJtQaXD/iCM5CQSEq/3R6Gq9rjDl/W WovD36USf1Ha8zrS+GeQKBnJy2ToodVnRSa3Qiyc+gxOls5NKaDEamAlObQl2BoZ3PAa MBw5HOZHFaZgEwjQrhwPmXHz021WWDWVPGb+JVI8pgg9FDdeccunShtlk4TJnoYzOVh3 AAsA==; dara=google.com ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@siemens.com header.s=fm1 header.b=IJh3OGhU; spf=pass (google.com: domain of fm-1328757-20260514091942e6a899fd2100020708-f9d_ir@rts-flowmailer.siemens.com designates 185.136.64.226 as permitted sender) smtp.mailfrom=fm-1328757-20260514091942e6a899fd2100020708-f9D_Ir@rts-flowmailer.siemens.com; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=siemens.com Received: from mta-64-226.siemens.flowmailer.net (mta-64-226.siemens.flowmailer.net. [185.136.64.226]) by gmr-mx.google.com with ESMTPS id 4fb4d7f45d1cf-68311058e41si41827a12.4.2026.05.14.02.19.42 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 14 May 2026 02:19:42 -0700 (PDT) Received-SPF: pass (google.com: domain of fm-1328757-20260514091942e6a899fd2100020708-f9d_ir@rts-flowmailer.siemens.com designates 185.136.64.226 as permitted sender) client-ip=185.136.64.226; Received: by mta-64-226.siemens.flowmailer.net with ESMTPSA id 20260514091942e6a899fd2100020708 for ; Thu, 14 May 2026 11:19:42 +0200 X-Patchwork-Original-From: "'Kasturi shekar' via isar-users" From: Kasturi shekar To: isar-users@googlegroups.com Cc: Kasturi Shekar Subject: [PATCH v2 3/4] installer: add installer flow module and entrypoint Date: Thu, 14 May 2026 14:49:47 +0530 Message-ID: <20260514091951.1572682-4-kasturi.shekar@siemens.com> In-Reply-To: <20260514091951.1572682-1-kasturi.shekar@siemens.com> References: <20260427063957.603123-4-kasturi.shekar@siemens.com> <20260514091951.1572682-1-kasturi.shekar@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1328757:519-21489:flowmailer X-Original-Sender: kasturi.shekar@siemens.com X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@siemens.com header.s=fm1 header.b=IJh3OGhU; spf=pass (google.com: domain of fm-1328757-20260514091942e6a899fd2100020708-f9d_ir@rts-flowmailer.siemens.com designates 185.136.64.226 as permitted sender) smtp.mailfrom=fm-1328757-20260514091942e6a899fd2100020708-f9D_Ir@rts-flowmailer.siemens.com; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=siemens.com X-Original-From: Kasturi shekar Reply-To: Kasturi shekar Precedence: list Mailing-list: list isar-users@googlegroups.com; contact isar-users+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: isar-users@googlegroups.com X-Google-Group-Id: 914930254986 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , X-Spam-Status: No, score=-4.9 required=5.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, RCVD_IN_DNSWL_BLOCKED,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, RCVD_IN_RP_CERTIFIED,RCVD_IN_RP_RNBL,RCVD_IN_RP_SAFE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on shymkent.ilbers.de X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= From: Kasturi Shekar high-level orchestration and keep deploy-image-wic.sh as a thin launcher. This keeps the externally used script name stable while making the flow easier to review and maintain by separating: - backend APIs - UI frontend - mode/orchestration flow Signed-off-by: Kasturi Shekar --- .../files/usr/bin/deploy-image-wic.sh | 475 +++++++----------- 1 file changed, 192 insertions(+), 283 deletions(-) mode change 100755 => 100644 meta-isar/recipes-installer/deploy-image/files/usr/bin/deploy-image-wic.sh diff --git a/meta-isar/recipes-installer/deploy-image/files/usr/bin/deploy-image-wic.sh b/meta-isar/recipes-installer/deploy-image/files/usr/bin/deploy-image-wic.sh old mode 100755 new mode 100644 index 9a4102b2..a692b679 --- a/meta-isar/recipes-installer/deploy-image/files/usr/bin/deploy-image-wic.sh +++ b/meta-isar/recipes-installer/deploy-image/files/usr/bin/deploy-image-wic.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # This software is a part of Isar. -# Copyright (C) Siemens AG, 2024 +# Copyright (C) Siemens AG, 2026 # # SPDX-License-Identifier: MIT @@ -9,293 +9,202 @@ installdata=${INSTALL_DATA:-/install} SCRIPT_DIR=$( dirname -- "$( readlink -f -- "$0"; )"; ) . "${SCRIPT_DIR}/../lib/deploy-image-wic/handle-config.sh" +. "${SCRIPT_DIR}/sys_api.sh" +. "${SCRIPT_DIR}/installer_ui.sh" -if [ "$installer_unattended" = true ] && [ "$installer_unattended_abort_enable" = true ]; then - abort_file=/run/attended_mode_trigger - for ((i=$installer_unattended_abort_timeout; i>0; i--)); do - echo -ne "\rUnattended installation will start in $i seconds. Press any key to switch to attended mode..." +#-------------------------------------------------------------------------- +# This module contains high-level installer flow logic +# while keeping low-level backend APIs in sys_api.sh +# and user-facing dialogs in installer_ui.sh. +#-------------------------------------------------------------------------- - # Switch to attended mode if the abort file exists or any key pressed during countdown - # Create abort file to notify all other console instances to abort - if [ -f "$abort_file" ] || read -n 1 -t 1; then - installer_unattended=false - touch "$abort_file" - break - fi - done -fi - -if ! $installer_unattended; then - installer_image_uri=$(find "$installdata" -type f -iname "*.wic*" -a -not -iname "*.wic.bmap" -exec basename {} \;) - if [ -z "$installer_image_uri" ] || [ ! -f "$installdata/$installer_image_uri" ]; then - pushd "$installdata" - for f in $(find . -type f ! -iname "*.wic.bmap"); do - array+=("$f" "$f") - done - popd - if [ ${#array[@]} -gt 0 ]; then - if ! installer_image_uri=$(dialog --no-tags \ - --menu "Select image to be installed" 10 60 3 \ - "${array[@]}" --output-fd 1); then - exit 0 - fi - fi - fi - - if [ ! -f "$installdata/$installer_image_uri" ]; then - dialog --msgbox "Could not find an image to install. Installation aborted." 6 60 - exit 1 - fi - - # inspired by poky/meta/recipes-core/initrdscripts/files/install-efi.sh - target_device_list="" - current_root_dev_type=$(findmnt / -o fstype -n) - exclude_list=() - - if [ "$current_root_dev_type" = "nfs" ]; then - current_root_dev="nfs" - exclude_list+=("nfs") - else - # For normal or immutable systems, get the backing device of '/' - root_source=$(findmnt / -o source -n) - root_source_resolved=$(readlink -f "$root_source" 2>/dev/null || echo "$root_source") - current_root_dev=${root_source_resolved#/dev/} - - # Always exclude the exact device mounted as / - exclude_list+=("$current_root_dev") - - if [[ "$current_root_dev" =~ ^(mmcblk|nvme) ]]; then - base_no_part="${current_root_dev%p[0-9]*}" - else - base_no_part="${current_root_dev%%[0-9]*}" - fi - if [ -n "$base_no_part" ]; then - exclude_list+=("$base_no_part") - fi - - # If root is coming through a dm-* device (e.g., dm-verity), - # the actual physical devices appear under /sys/block//slaves/. - # We must exclude those slaves as well, otherwise the installer - # might show the live USB stick as a valid target. - if [ -d "/sys/block/$current_root_dev/slaves" ]; then - for slave in /sys/block/"$current_root_dev"/slaves/*; do - [ -e "$slave" ] || continue - slave_dev=$(basename "$slave") - exclude_list+=("$slave_dev") - slave_base=${slave_dev%%[0-9]*} - [ -n "$slave_base" ] && exclude_list+=("$slave_base") - done - fi - fi - - echo "Searching for target device..." - - devices=$(find /sys/block/ -type b,c,f,l -not -iname "mmcblk*" -printf "%f\n") || true - mmc_devices=$(find /sys/block/ -type b,c,f,l -iname "mmcblk[0-9]" -printf "%f\n") || true - devices="$devices $mmc_devices" - - for device in $devices; do - is_raid_member=0 - - if [ -d "/sys/block/$device/holders" ] && [ ! -d "/sys/block/$device/md" ]; then - for holder_path in /sys/block/$device/holders/*; do - holder_name=$(basename "$holder_path") - case "$holder_name" in - md[0-9]*) - is_raid_member=1 - break - ;; - esac - done - fi - - if [ "$is_raid_member" -eq 1 ]; then - continue # Skip RAID member disks - fi - - if [[ "$device" == md* ]]; then - if [ -f "/sys/block/$device/md/array_state" ]; then - state=$(cat /sys/block/$device/md/array_state) - if [ "$state" != "active" ] && [ "$state" != "clean" ]; then - continue - fi - else - continue - fi - fi - - case $device in - dm-*) - # skip device-mapper device - ;; - loop*) - # skip loop device - ;; - mtd*) - ;; - sr*) - # skip CDROM device - ;; - ram*) - # skip ram device - ;; - zram*) - # skip zram device - ;; - *) - #skip any excluded devices (root and its slaves) - skip_device=0 - for ex in "${exclude_list[@]}"; do - if [[ "$device" == "$ex"* ]]; then - skip_device=1 - break - fi - done - - if [ "$skip_device" -eq 0 ]; then - target_device_list="$target_device_list $device" - fi - ;; - esac - done - - if [ -z "${target_device_list}" ]; then - dialog --msgbox "You need another device (besides the live device /dev/${current_root_dev}) to install the image. Installation aborted." 7 60 - exit 1 - fi - - if [ "$(echo "$target_device_list" | wc -w)" -gt 1 ]; then - array=() - for target in $(echo "$target_device_list" | xargs -n1 | sort); do - target_size=$(lsblk --nodeps --noheadings -o SIZE /dev/"$target" | tr -d " ") - if cmp /dev/zero /dev/"$target" -n 1M; then - state="empty" - else - state="contains data" - fi - array+=("/dev/$target" "/dev/$target ($target_size, $state)") - done - if ! installer_target_dev=$(dialog --no-tags \ - --menu "Select device to install image to" 10 60 3 \ - "${array[@]}" --output-fd 1); then - exit 0 - fi - else - installer_target_dev="/dev/$(echo "$target_device_list" | tr -d " ")" - fi - TARGET_DEVICE_SIZE=$(lsblk --nodeps --noheadings -o SIZE "$installer_target_dev" | tr -d " ") - if ! dialog --yes-label Ok --no-label Cancel \ - --yesno "Start installing\n'$installer_image_uri'\nto $installer_target_dev (capacity: $TARGET_DEVICE_SIZE)" 7 60; then - exit 0 - fi - - # set absolute paths to be compatible with unattended mode - installer_image_uri="$installdata/$installer_image_uri" -fi - -if ! cmp /dev/zero "$installer_target_dev" -n 1M; then - if ! $installer_unattended; then - if ! dialog --defaultno \ - --yesno "WARNING: Target device is not empty! Continue anyway?" 5 60; then - exit 0 - fi - else - if [ "$installer_target_overwrite" != "OVERWRITE" ]; then - echo "Target device is not empty! -> Abort" - echo "If you want to override existing data set \"installer.target.overwrite=OVERWRITE\" on your kernel cmdline or edit your \"auto.install\" file accordingly." - - exit 1 - fi - fi -fi - -bmap_options="" - -# bmap file is expected to be next to the installer image -DISK_BMAP="${installer_image_uri%.wic*}.wic.bmap" - -if [ ! -f "$DISK_BMAP" ]; then - bmap_options="--nobmap" -fi - -if ! $installer_unattended; then - clear -fi - -# Function to compare version numbers -version_ge() { - if [ "$(printf '%s\n' "$1"X "$2" | sort -V | head -n 1)" != "$1"X ]; then - return 0 - else - return 1 - fi +#-------------------------------------------------------------------------- +# flow_run_attended +# +# Handles all attended-mode interactions and assigns: +# installer_image_uri +# installer_target_dev +# +# Returns: +# 0 on success +# 1 on hard error +# 2 on user cancel +#-------------------------------------------------------------------------- +flow_run_attended() { + local default_image + local selected_image + local selected_target + local target_device_size + + default_image=$(sys_first_default_image_name "$installdata") + if [ -n "$default_image" ] && [ -f "$installdata/$default_image" ]; then + installer_image_uri="$default_image" + fi + + if [ -z "$installer_image_uri" ] || [ ! -f "$installdata/$installer_image_uri" ]; then + selected_image=$(ui_select_image_menu "$installdata") + case $? in + 0) + installer_image_uri="$selected_image" + ;; + 1) + ui_show_error "Could not find an image to install. Installation aborted." + return 1 + ;; + 2) + return 2 + ;; + *) + return 1 + ;; + esac + fi + + if [ ! -f "$installdata/$installer_image_uri" ]; then + ui_show_error "Could not find an image to install. Installation aborted." + return 1 + fi + + echo "Searching for target device..." + sys_discover_target_devices + if [ "${#SYS_TARGET_DEVICES[@]}" -eq 0 ]; then + ui_show_error "You need another device (besides the live device /dev/${SYS_CURRENT_ROOT_DEV}) to install the image. Installation aborted." + return 1 + fi + + if [ "${#SYS_TARGET_DEVICES[@]}" -gt 1 ]; then + selected_target=$(ui_select_target_device_menu "${SYS_TARGET_DEVICES[@]}") + case $? in + 0) + installer_target_dev="$selected_target" + ;; + 1) + ui_show_error "No installable target devices available. Installation aborted." + return 1 + ;; + 2) + return 2 + ;; + *) + return 1 + ;; + esac + else + installer_target_dev="${SYS_TARGET_DEVICES[0]}" + fi + + target_device_size=$(sys_device_size "$installer_target_dev") + if ! ui_confirm_install "$installer_image_uri" "$installer_target_dev" "$target_device_size"; then + return 2 + fi + + installer_image_uri="$installdata/$installer_image_uri" + return 0 } -lockfile="/run/installer.lock" -progress_pipe="/run/installer.fifo" - -exec 9>"$lockfile" -if flock -n 9; then - # Get bmap-tools version - bmap_version=$(bmaptool --version | awk '{ print $NF }') - - if version_ge "$bmap_version" "3.6"; then - if ! mkfifo "$progress_pipe"; then - echo "Error: Failed to create named pipe $progress_pipe" - exit 1 - fi - - # Add psplash pipe to bmap_options - bmap_options="$bmap_options --psplash-pipe=$progress_pipe" - quiet_flag="-q" - - # Initialize the dialog gauge and update it dynamically - ( - while true; do - if read -r line < "$progress_pipe"; then - percentage=$(echo "$line" | awk '{ print $2 }') - echo "$percentage" - fi - done - ) | dialog --gauge "Flashing image, please wait..." 10 70 0 & - - gauge_pid=$! - fi - - if ! bmaptool $quiet_flag copy $bmap_options "$installer_image_uri" "$installer_target_dev"; then - kill "$gauge_pid" - exit 1 - fi - - # Attempt to terminate the gauge process if still running. - # Errors are ignored since the process may already have exited. - kill "$gauge_pid" 2>/dev/null -else - echo "Installation already running in another console." +#-------------------------------------------------------------------------- +# flow_validate_target_overwrite_policy +# +# Enforces overwrite policy for non-empty targets in both attended and +# unattended modes. +# +# Returns: +# 0 when policy permits installation +# 1 when policy rejects installation +# 2 when user cancels in attended mode +#-------------------------------------------------------------------------- +flow_validate_target_overwrite_policy() { + if sys_device_is_empty "$installer_target_dev"; then + return 0 + fi + + if ! $installer_unattended; then + if ! ui_confirm_overwrite; then + return 2 + fi + else + if [ "$installer_target_overwrite" != "OVERWRITE" ]; then + echo "Target device is not empty! -> Abort" + echo "If you want to override existing data set \"installer.target.overwrite=OVERWRITE\" on your kernel cmdline or edit your \"auto.install\" file accordingly." + return 1 + fi + fi + + return 0 +} - # Wait for running console to create the progress pipe - sleep 5 +#-------------------------------------------------------------------------- +# flow_maybe_switch_to_attended +# +# If unattended abort-by-key is enabled, this function offers a timeout +# window to switch to attended mode. +#-------------------------------------------------------------------------- +flow_maybe_switch_to_attended() { + local abort_file + + if [ "$installer_unattended" = true ] && [ "$installer_unattended_abort_enable" = true ]; then + abort_file=/run/attended_mode_trigger + if ui_countdown_allow_attended_switch "$installer_unattended_abort_timeout" "$abort_file"; then + installer_unattended=false + fi + fi +} - # Check if progress pipe exists and has content - if [ -e "$progress_pipe" ]; then - echo "Installation progress..." - tail -f "$progress_pipe" | while read line; do - printf "\r%s%%" "$line" - done - else - # Periodically check if bmaptool is still running every 5 seconds - echo "Waiting for installation to finish..." - while pgrep -x "bmaptool" > /dev/null; do - sleep 5 - done - fi -fi +#-------------------------------------------------------------------------- +# flow_run +# +# Main installer flow combining attended/unattended execution paths. +#-------------------------------------------------------------------------- +flow_run() { + flow_maybe_switch_to_attended + + if ! $installer_unattended; then + flow_run_attended + case $? in + 0) + ;; + 2) + return 0 + ;; + *) + return 1 + ;; + esac + fi + + flow_validate_target_overwrite_policy + case $? in + 0) + ;; + 2) + return 0 + ;; + *) + return 1 + ;; + esac + + if ! $installer_unattended; then + clear + fi + + if ! sys_install_image_with_lock "$installer_image_uri" "$installer_target_dev"; then + if ! $installer_unattended; then + ui_show_error "Installation failed." + fi + return 1 + fi + + if ! $installer_unattended; then + ui_show_info "Installation was successful. System will be rebooted. Please remove the USB stick." + else + echo "Installation was successful." + fi + + return 0 +} -if ! $installer_unattended; then - dialog --title "Reboot" \ - --msgbox "Installation was successful. System will be rebooted. Please remove the USB stick." 6 60 -else - echo "Installation was successful." -fi +# Entrypoint: run the installer flow and propagate status. +flow_run +exit $? -exit 0