From b6b59ce2dbe87a52be9155d03f18010382ab68a7 Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Wed, 20 Dec 2023 21:25:27 +0800
Subject: [PATCH 0171/1160] systemctl: configure boot loader options only when
 going through firmware

Fixes #30497

(cherry picked from commit bc9e592c4f01dd8a4f8fb5e2bbcdec5ee4bf129d)
---
 man/systemctl.xml                       | 25 +++++++++++----------
 src/systemctl/systemctl-start-special.c | 29 ++++++++++++-------------
 2 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/man/systemctl.xml b/man/systemctl.xml
index 1d791b44fd..25b6e46c60 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -2589,9 +2589,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
         <term><option>--firmware-setup</option></term>
 
         <listitem>
-          <para>When used with the <command>reboot</command> command, indicate to the system's firmware to
-          reboot into the firmware setup interface. Note that this functionality is not available on all
-          systems.</para>
+          <para>When used with the <command>reboot</command>, <command>poweroff</command>, or
+          <command>halt</command> command, indicate to the system's firmware to reboot into the firmware
+          setup interface for the next boot. Note that this functionality is not available on all systems.
+          </para>
 
         <xi:include href="version-info.xml" xpointer="v220"/>
         </listitem>
@@ -2601,10 +2602,11 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
         <term><option>--boot-loader-menu=<replaceable>timeout</replaceable></option></term>
 
         <listitem>
-          <para>When used with the <command>reboot</command> command, indicate to the system's boot loader to
-          show the boot loader menu on the following boot. Takes a time value as parameter — indicating the
-          menu timeout. Pass zero in order to disable the menu timeout. Note that not all boot loaders
-          support this functionality.</para>
+          <para>When used with the <command>reboot</command>, <command>poweroff</command>, or
+          <command>halt</command> command, indicate to the system's boot loader to show the boot loader menu
+          on the following boot. Takes a time value as parameter — indicating the menu timeout. Pass zero
+          in order to disable the menu timeout. Note that not all boot loaders support this functionality.
+          </para>
 
         <xi:include href="version-info.xml" xpointer="v242"/>
         </listitem>
@@ -2614,10 +2616,11 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
         <term><option>--boot-loader-entry=<replaceable>ID</replaceable></option></term>
 
         <listitem>
-          <para>When used with the <command>reboot</command> command, indicate to the system's boot loader to
-          boot into a specific boot loader entry on the following boot. Takes a boot loader entry identifier
-          as argument, or <literal>help</literal> in order to list available entries. Note that not all boot
-          loaders support this functionality.</para>
+          <para>When used with the <command>reboot</command>, <command>poweroff</command>, or
+          <command>halt</command> command, indicate to the system's boot loader to boot into a specific
+          boot loader entry on the following boot. Takes a boot loader entry identifier as argument,
+          or <literal>help</literal> in order to list available entries. Note that not all boot loaders
+          support this functionality.</para>
 
         <xi:include href="version-info.xml" xpointer="v242"/>
         </listitem>
diff --git a/src/systemctl/systemctl-start-special.c b/src/systemctl/systemctl-start-special.c
index d93bffb759..d23ce36bfc 100644
--- a/src/systemctl/systemctl-start-special.c
+++ b/src/systemctl/systemctl-start-special.c
@@ -121,8 +121,7 @@ static int set_exit_code(uint8_t code) {
 }
 
 int verb_start_special(int argc, char *argv[], void *userdata) {
-        bool termination_action; /* An action that terminates the manager, can be performed also by
-                                  * signal. */
+        bool termination_action; /* An action that terminates the system, can be performed also by signal. */
         enum action a;
         int r;
 
@@ -140,17 +139,21 @@ int verb_start_special(int argc, char *argv[], void *userdata) {
                         return r;
         }
 
-        r = prepare_firmware_setup();
-        if (r < 0)
-                return r;
+        termination_action = IN_SET(a, ACTION_HALT, ACTION_POWEROFF, ACTION_REBOOT);
 
-        r = prepare_boot_loader_menu();
-        if (r < 0)
-                return r;
+        if (termination_action) {
+                r = prepare_firmware_setup();
+                if (r < 0)
+                        return r;
 
-        r = prepare_boot_loader_entry();
-        if (r < 0)
-                return r;
+                r = prepare_boot_loader_menu();
+                if (r < 0)
+                        return r;
+
+                r = prepare_boot_loader_entry();
+                if (r < 0)
+                        return r;
+        }
 
         if (a == ACTION_REBOOT) {
                 if (arg_reboot_argument) {
@@ -181,10 +184,6 @@ int verb_start_special(int argc, char *argv[], void *userdata) {
                         return r;
         }
 
-        termination_action = IN_SET(a,
-                                    ACTION_HALT,
-                                    ACTION_POWEROFF,
-                                    ACTION_REBOOT);
         if (termination_action && arg_force >= 2)
                 return halt_now(a);
 
-- 
2.33.0