]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
debug-generator: add a kernel cmdline option to pause the boot process 35410/head
authorAntonio Alvarez Feijoo <antonio.feijoo@suse.com>
Fri, 20 Dec 2024 07:51:23 +0000 (08:51 +0100)
committerAntonio Alvarez Feijoo <antonio.feijoo@suse.com>
Fri, 20 Dec 2024 07:51:23 +0000 (08:51 +0100)
Introduce the `systemd.break=` kernel command line option to allow stopping the
boot process at a certain point and spawn a debug shell. After exiting this
shell, the system will resume booting.

It accepts the following values:
- `pre-udev`: before starting to process kernel uevents (initrd and host).
- `pre-basic`: before leaving early boot and regular services start (initrd and
host).
- `pre-mount`: before the root filesystem is mounted (initrd).
- `pre-switch-root`: before switching root (initrd).

man/kernel-command-line.xml
man/systemd-debug-generator.xml
src/debug-generator/debug-generator.c
test/units/TEST-81-GENERATORS.debug-generator.sh
units/breakpoint-pre-basic.service.in [new file with mode: 0644]
units/breakpoint-pre-mount.service.in [new file with mode: 0644]
units/breakpoint-pre-switch-root.service.in [new file with mode: 0644]
units/breakpoint-pre-udev.service.in [new file with mode: 0644]
units/meson.build

index baa712220409c4dfc1cbb8dc2877411070ec7569..94bc8740094c9edcfbc6f4258584b29a45347f62 100644 (file)
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>systemd.break=</varname></term>
+        <term><varname>rd.systemd.break=</varname></term>
+        <listitem>
+          <para>Parameters understood by
+          <citerefentry><refentrytitle>systemd-debug-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+          to pause the boot process at a certain point and spawn a debug shell.</para>
+
+          <xi:include href="version-info.xml" xpointer="v258"/>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>systemd.run=</varname></term>
         <term><varname>systemd.run_success_action=</varname></term>
index 90fc9c6d67f25d47cae213c7092bad221528e7f5..529d834b83b988d1b87d2f5dd1a306ca626dc8ee 100644 (file)
 
         <xi:include href="version-info.xml" xpointer="v215"/></listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><varname>systemd.break=</varname></term>
+        <term><varname>rd.systemd.break=</varname></term>
+
+        <listitem><para>Takes one of <option>pre-udev</option>, <option>pre-basic</option>,
+        <option>pre-mount</option>, or <option>pre-switch-root</option> (the default for the
+        <literal>rd.</literal> option). It also accepts multiple values separated by comma
+        (<literal>,</literal>). These options allow to pause the boot process at a certain point and spawn a
+        debug shell. After exiting this shell, the system will resume booting. The option prefixed with
+        <literal>rd.</literal> is honored only in the initrd, while the one without prefix is only honored in
+        the main system.</para>
+
+        <table>
+          <title>Available breakpoints</title>
+
+          <tgroup cols='4'>
+            <colspec colname='breakpoint' />
+            <colspec colname='description' />
+            <colspec colname='initrd' />
+            <colspec colname='main' />
+            <thead>
+              <row>
+                <entry>Breakpoints</entry>
+                <entry>Description</entry>
+                <entry>Can be used in the initrd</entry>
+                <entry>Can be used in the main system</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry><option>pre-udev</option></entry>
+                <entry>Before starting to process kernel uevents, i.e., before <filename>systemd-udevd.service</filename> starts.</entry>
+                <entry>✓</entry>
+                <entry>✓</entry>
+              </row>
+              <row>
+                <entry><option>pre-basic</option></entry>
+                <entry>Before leaving early boot and regular services start, i.e., before <filename>basic.target</filename> is reached.</entry>
+                <entry>✓</entry>
+                <entry>✓</entry>
+              </row>
+              <row>
+                <entry><option>pre-mount</option></entry>
+                <entry>Before the root filesystem is mounted, i.e., before <filename>sysroot.mount</filename> starts.</entry>
+                <entry>✓</entry>
+                <entry>✗</entry>
+              </row>
+              <row>
+                <entry><option>pre-switch-root</option></entry>
+                <entry>Before switching from the initrd to the real root.</entry>
+                <entry>✓</entry>
+                <entry>✗</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </table>
+
+        <xi:include href="version-info.xml" xpointer="v258"/></listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
       <member><citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
       <member><citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
       <member><citerefentry><refentrytitle>systemd.system-credentials</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
+      <member><citerefentry><refentrytitle>bootup</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
     </simplelist></para>
   </refsect1>
 
index 664d57d452fc45120a02289f0fd855e149d1e205..edc8e5f5f49bb0a45f3bc4ceecf68e62d1b6f66d 100644 (file)
@@ -3,9 +3,11 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
+#include "bitfield.h"
 #include "creds-util.h"
 #include "dropin.h"
 #include "errno-util.h"
+#include "extract-word.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "generator.h"
@@ -27,6 +29,7 @@ static char **arg_wants = NULL;
 static bool arg_debug_shell = false;
 static char *arg_debug_tty = NULL;
 static char *arg_default_debug_tty = NULL;
+static uint32_t arg_breakpoints = 0;
 
 STATIC_DESTRUCTOR_REGISTER(arg_default_unit, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_mask, strv_freep);
@@ -34,6 +37,91 @@ STATIC_DESTRUCTOR_REGISTER(arg_wants, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_debug_tty, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_default_debug_tty, freep);
 
+typedef enum BreakpointType {
+        BREAKPOINT_PRE_UDEV,
+        BREAKPOINT_PRE_BASIC,
+        BREAKPOINT_PRE_SYSROOT_MOUNT,
+        BREAKPOINT_PRE_SWITCH_ROOT,
+        _BREAKPOINT_TYPE_MAX,
+        _BREAKPOINT_TYPE_INVALID = -EINVAL,
+} BreakpointType;
+
+typedef enum BreakpointValidity {
+        BREAKPOINT_DEFAULT   = 1 << 0,
+        BREAKPOINT_IN_INITRD = 1 << 1,
+        BREAKPOINT_ON_HOST   = 1 << 2,
+} BreakpointValidity;
+
+typedef struct BreakpointInfo {
+        BreakpointType type;
+        const char *name;
+        const char *unit;
+        BreakpointValidity validity;
+} BreakpointInfo;
+
+static const struct BreakpointInfo breakpoint_info_table[_BREAKPOINT_TYPE_MAX] = {
+        { BREAKPOINT_PRE_UDEV,          "pre-udev",        "breakpoint-pre-udev.service",        BREAKPOINT_IN_INITRD | BREAKPOINT_ON_HOST },
+        { BREAKPOINT_PRE_BASIC,         "pre-basic",       "breakpoint-pre-basic.service",       BREAKPOINT_IN_INITRD | BREAKPOINT_ON_HOST },
+        { BREAKPOINT_PRE_SYSROOT_MOUNT, "pre-mount",       "breakpoint-pre-mount.service",       BREAKPOINT_IN_INITRD                      },
+        { BREAKPOINT_PRE_SWITCH_ROOT,   "pre-switch-root", "breakpoint-pre-switch-root.service", BREAKPOINT_IN_INITRD | BREAKPOINT_DEFAULT },
+};
+
+static BreakpointType parse_breakpoint_from_string_one(const char *s) {
+        assert(s);
+
+        FOREACH_ARRAY(i, breakpoint_info_table, ELEMENTSOF(breakpoint_info_table))
+                if (streq(i->name, s))
+                        return i->type;
+
+        return _BREAKPOINT_TYPE_INVALID;
+}
+
+static int parse_breakpoint_from_string(const char *s, uint32_t *ret_breakpoints) {
+        uint32_t breakpoints = 0;
+        int r;
+
+        assert(ret_breakpoints);
+
+        /* Empty value? set default breakpoint */
+        if (isempty(s)) {
+                if (in_initrd()) {
+                        FOREACH_ARRAY(i, breakpoint_info_table, ELEMENTSOF(breakpoint_info_table))
+                                if (i->validity & BREAKPOINT_DEFAULT) {
+                                        breakpoints |= 1 << i->type;
+                                        break;
+                                }
+                } else
+                        log_warning("No default breakpoint defined on the host, ignoring breakpoint request from kernel command line.");
+        } else
+                for (;;) {
+                        _cleanup_free_ char *t = NULL;
+                        BreakpointType tt;
+
+                        r = extract_first_word(&s, &t, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                break;
+
+                        tt = parse_breakpoint_from_string_one(t);
+                        if (tt < 0) {
+                                log_warning("Invalid breakpoint value '%s', ignoring.", t);
+                                continue;
+                        }
+
+                        if (in_initrd() && !FLAGS_SET(breakpoint_info_table[tt].validity, BREAKPOINT_IN_INITRD))
+                                log_warning("Breakpoint '%s' not valid in the initrd, ignoring.", t);
+                        else if (!in_initrd() && !FLAGS_SET(breakpoint_info_table[tt].validity, BREAKPOINT_ON_HOST))
+                                log_warning("Breakpoint '%s' not valid on the host, ignoring.", t);
+                        else
+                                breakpoints |= 1 << tt;
+                }
+
+        *ret_breakpoints = breakpoints;
+
+        return 0;
+}
+
 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
         int r;
 
@@ -88,6 +176,15 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
 
                 return free_and_strdup_warn(&arg_default_unit, value);
 
+        } else if (streq(key, "systemd.break")) {
+                uint32_t breakpoints = 0;
+
+                r = parse_breakpoint_from_string(value, &breakpoints);
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to parse breakpoint value '%s': %m", value);
+
+                arg_breakpoints |= breakpoints;
+
         } else if (!value) {
                 const char *target;
 
@@ -269,6 +366,10 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
                 RET_GATHER(r, install_debug_shell_dropin());
         }
 
+        BIT_FOREACH(i, arg_breakpoints)
+                if (strv_extend(&arg_wants, breakpoint_info_table[i].unit) < 0)
+                        return log_oom();
+
         if (get_credentials_dir(&credentials_dir) >= 0)
                 RET_GATHER(r, process_unit_credentials(credentials_dir));
 
index ef1e205aacfeee6fda2048b391374d81a20e177a..08ce2d66af4bce80436aa1c821c997665c14ddc8 100755 (executable)
@@ -69,6 +69,51 @@ SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
 link_endswith "$OUT_DIR/early/default.target.wants/debug-shell.service" /lib/systemd/system/debug-shell.service
 grep -F "/dev/tty666" "$OUT_DIR/early/debug-shell.service.d/50-tty.conf"
 
+# systemd.break (default)
+: "debug-shell: regular + systemd.break"
+CMDLINE="$CMDLINE systemd.break"
+SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service"
+test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-mount.service"
+test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-switch-root.service"
+
+# systemd.break=pre-switch-root
+: "debug-shell: regular + systemd.break=pre-switch-root"
+CMDLINE="$CMDLINE systemd.break=pre-switch-root"
+SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service"
+test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-mount.service"
+test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-switch-root.service"
+
+# systemd.break=pre-mount
+: "debug-shell: regular + systemd.break=pre-mount"
+CMDLINE="$CMDLINE systemd.break=pre-mount"
+SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service"
+test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-mount.service"
+test ! -h "$OUT_DIR/early/default.target.wants/breakpoint-pre-switch-root.service"
+
+# systemd.break=pre-basic
+: "debug-shell: regular + systemd.break=pre-basic"
+CMDLINE="$CMDLINE systemd.break=pre-basic"
+SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+link_endswith "$OUT_DIR/early/default.target.wants/breakpoint-pre-basic.service" /lib/systemd/system/breakpoint-pre-basic.service
+
+# systemd.break=pre-udev
+: "debug-shell: regular + systemd.break=pre-udev"
+CMDLINE="$CMDLINE systemd.break=pre-udev"
+SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+link_endswith "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service" /lib/systemd/system/breakpoint-pre-udev.service
+
+# systemd.break=pre-udev,pre-basic,pre-mount,pre-switch-root
+: "debug-shell: regular + systemd.break=pre-udev,pre-basic,pre-mount,pre-switch-root"
+rm -f "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service"
+rm -f "$OUT_DIR/early/default.target.wants/breakpoint-pre-basic.service"
+CMDLINE="$CMDLINE systemd.break=pre-udev,pre-basic,pre-mount,pre-switch-root"
+SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+link_endswith "$OUT_DIR/early/default.target.wants/breakpoint-pre-udev.service" /lib/systemd/system/breakpoint-pre-udev.service
+link_endswith "$OUT_DIR/early/default.target.wants/breakpoint-pre-basic.service" /lib/systemd/system/breakpoint-pre-basic.service
+
 # Now override the default target via systemd.unit=
 : "debug-shell: regular + systemd.unit="
 CMDLINE="$CMDLINE systemd.unit=my-fancy.target"
@@ -103,6 +148,50 @@ CMDLINE="$CMDLINE rd.systemd.debug_shell"
 SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
 link_endswith "$OUT_DIR/early/initrd.target.wants/debug-shell.service" /lib/systemd/system/debug-shell.service
 
+# rd.systemd.break (default)
+: "debug-shell: initrd + rd.systemd.break"
+CMDLINE="$CMDLINE rd.systemd.break"
+SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-switch-root.service" /lib/systemd/system/breakpoint-pre-switch-root.service
+
+# rd.systemd.break=pre-udev
+: "debug-shell: initrd + rd.systemd.break=pre-udev"
+CMDLINE="$CMDLINE rd.systemd.break=pre-udev"
+SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-udev.service" /lib/systemd/system/breakpoint-pre-udev.service
+
+# rd.systemd.break=pre-basic
+: "debug-shell: initrd + rd.systemd.break=pre-basic"
+CMDLINE="$CMDLINE rd.systemd.break=pre-basic"
+SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-basic.service" /lib/systemd/system/breakpoint-pre-basic.service
+
+# rd.systemd.break=pre-mount
+: "debug-shell: initrd + rd.systemd.break=pre-mount"
+CMDLINE="$CMDLINE rd.systemd.break=pre-mount"
+SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-mount.service" /lib/systemd/system/breakpoint-pre-mount.service
+
+# rd.systemd.break=pre-switch-root
+: "debug-shell: initrd + rd.systemd.break=pre-switch-root"
+rm -f "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-switch-root.service"
+CMDLINE="$CMDLINE rd.systemd.break=pre-switch-root"
+SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-switch-root.service" /lib/systemd/system/breakpoint-pre-switch-root.service
+
+# rd.systemd.break=pre-udev,pre-basic,pre-mount,pre-switch-root
+: "debug-shell: initrd + rd.systemd.break=pre-udev,pre-mount,pre-switch-root"
+rm -f "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-udev.service"
+rm -f "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-basic.service"
+rm -f "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-mount.service"
+rm -f "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-switch-root.service"
+CMDLINE="$CMDLINE rd.systemd.break=pre-udev,pre-basic,pre-mount,pre-switch-root"
+SYSTEMD_IN_INITRD=1 SYSTEMD_PROC_CMDLINE="$CMDLINE" run_and_list "$GENERATOR_BIN" "$OUT_DIR"
+link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-udev.service" /lib/systemd/system/breakpoint-pre-udev.service
+link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-basic.service" /lib/systemd/system/breakpoint-pre-basic.service
+link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-mount.service" /lib/systemd/system/breakpoint-pre-mount.service
+link_endswith "$OUT_DIR/early/initrd.target.wants/breakpoint-pre-switch-root.service" /lib/systemd/system/breakpoint-pre-switch-root.service
+
 # Override the default target
 : "debug-shell: initrd + rd.systemd.unit"
 CMDLINE="$CMDLINE rd.systemd.unit=my-fancy-initrd.target"
diff --git a/units/breakpoint-pre-basic.service.in b/units/breakpoint-pre-basic.service.in
new file mode 100644 (file)
index 0000000..69a4061
--- /dev/null
@@ -0,0 +1,35 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Breakpoint Before Basic System
+Documentation=man:systemd-debug-generator(8)
+DefaultDependencies=no
+Conflicts=shutdown.target emergency.target
+After=sysinit.target sockets.target paths.target slices.target tmp.mount systemd-vconsole-setup.service
+Before=basic.target
+
+[Service]
+Environment=SHELL_PROMPT_PREFIX="pre-basic "
+Type=oneshot
+ExecStartPre=-plymouth --wait quit
+# Execute shell with "-" prefix to not consider the unit failed if it exits with
+# a non-zero value
+ExecStart=-{{SUSHELL}}
+StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
+KillMode=process
+IgnoreSIGPIPE=no
+# bash ignores SIGTERM
+KillSignal=SIGHUP
+
+# Unset locale for the console getty since the console has problems
+# displaying some internationalized messages.
+UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
diff --git a/units/breakpoint-pre-mount.service.in b/units/breakpoint-pre-mount.service.in
new file mode 100644 (file)
index 0000000..b50c780
--- /dev/null
@@ -0,0 +1,36 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Breakpoint Before Mounting the Root Filesystem on /sysroot
+Documentation=man:systemd-debug-generator(8)
+AssertPathExists=/etc/initrd-release
+DefaultDependencies=no
+Conflicts=shutdown.target emergency.target
+After=basic.target systemd-vconsole-setup.service
+Before=initrd-root-fs.target sysroot.mount systemd-fsck-root.service
+
+[Service]
+Environment=SHELL_PROMPT_PREFIX="pre-mount "
+Type=oneshot
+ExecStartPre=-plymouth --wait quit
+# Execute shell with "-" prefix to not consider the unit failed if it exits with
+# a non-zero value
+ExecStart=-{{SUSHELL}}
+StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
+KillMode=process
+IgnoreSIGPIPE=no
+# bash ignores SIGTERM
+KillSignal=SIGHUP
+
+# Unset locale for the console getty since the console has problems
+# displaying some internationalized messages.
+UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
diff --git a/units/breakpoint-pre-switch-root.service.in b/units/breakpoint-pre-switch-root.service.in
new file mode 100644 (file)
index 0000000..76eaa80
--- /dev/null
@@ -0,0 +1,37 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Breakpoint Before Switching Root
+Documentation=man:systemd-debug-generator(8)
+AssertPathExists=/etc/initrd-release
+DefaultDependencies=no
+Conflicts=shutdown.target emergency.target
+Wants=remote-fs.target
+After=initrd.target initrd-parse-etc.service sysroot.mount remote-fs.target systemd-vconsole-setup.service
+Before=initrd-cleanup.service
+
+[Service]
+Environment=SHELL_PROMPT_PREFIX="pre-switch-root "
+Type=oneshot
+ExecStartPre=-plymouth --wait quit
+# Execute shell with "-" prefix to not consider the unit failed if it exits with
+# a non-zero value
+ExecStart=-{{SUSHELL}}
+StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
+KillMode=process
+IgnoreSIGPIPE=no
+# bash ignores SIGTERM
+KillSignal=SIGHUP
+
+# Unset locale for the console getty since the console has problems
+# displaying some internationalized messages.
+UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
diff --git a/units/breakpoint-pre-udev.service.in b/units/breakpoint-pre-udev.service.in
new file mode 100644 (file)
index 0000000..baf0e03
--- /dev/null
@@ -0,0 +1,36 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Breakpoint Before Starting to Process Kernel uevents
+Documentation=man:systemd-debug-generator(8)
+DefaultDependencies=no
+Conflicts=shutdown.target emergency.target
+Wants=systemd-journald.socket
+After=systemd-journald.socket systemd-vconsole-setup.service
+Before=systemd-udevd.service systemd-udev-trigger.service
+
+[Service]
+Environment=SHELL_PROMPT_PREFIX="pre-udev "
+Type=oneshot
+ExecStartPre=-plymouth --wait quit
+# Execute shell with "-" prefix to not consider the unit failed if it exits with
+# a non-zero value
+ExecStart=-{{SUSHELL}}
+StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
+KillMode=process
+IgnoreSIGPIPE=no
+# bash ignores SIGTERM
+KillSignal=SIGHUP
+
+# Unset locale for the console getty since the console has problems
+# displaying some internationalized messages.
+UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
index 792c4250c0ebf72c32aeacabe048bf079177e0c5..00978a18b00b40445159a6846ffd0933384b70db 100644 (file)
@@ -7,6 +7,10 @@ units = [
         { 'file' : 'blockdev@.target' },
         { 'file' : 'bluetooth.target' },
         { 'file' : 'boot-complete.target' },
+        { 'file' : 'breakpoint-pre-basic.service.in' },
+        { 'file' : 'breakpoint-pre-mount.service.in' },
+        { 'file' : 'breakpoint-pre-switch-root.service.in' },
+        { 'file' : 'breakpoint-pre-udev.service.in' },
         { 'file' : 'capsule@.service.in' },
         { 'file' : 'capsule.slice' },
         { 'file' : 'console-getty.service.in' },