<varlistentry>
<term><option>status</option></term>
- <listitem><para>The current status of the boot loader entry file or unified kernel image file is shown. This
- outputs one of <literal>good</literal>, <literal>bad</literal>, <literal>indeterminate</literal>,
- <literal>clean</literal>, depending on the state and previous invocations of the command. The string
- <literal>indeterminate</literal> is shown initially after boot, before it has been marked as "good" or
- "bad". The string <literal>good</literal> is shown after the boot was marked as "good" with the
- <option>good</option> command below, and "bad" conversely after the <option>bad</option> command was
- invoked. The string <literal>clean</literal> is returned when boot counting is currently not in effect.</para>
+ <listitem><para>The current status of the boot loader entry file or unified kernel image file is
+ shown. This outputs one of <literal>good</literal>, <literal>bad</literal>,
+ <literal>indeterminate</literal>, <literal>clean</literal>, <literal>dirty</literal>, depending on
+ the state and previous invocations of the command. The string <literal>indeterminate</literal> is
+ shown initially after boot, before it has been marked as "good" or "bad". The string
+ <literal>good</literal> is shown after the boot was marked as "good" with the <option>good</option>
+ command below, and "bad" conversely after the <option>bad</option> command was invoked. The string
+ <literal>clean</literal> is returned when boot counting is currently not in effect (which includes
+ the case where the current entry was already marked as persistently good). The string
+ <literal>dirty</literal> is returned when the system is booted up with a known-bad kernel (i.e. one
+ where the tries left counter has previously reached zero already).</para>
<para>This command is implied if no command argument is specified.</para>
<varlistentry>
<term><option>indeterminate</option></term>
- <listitem><para>This command undoes any marking of the current boot loader entry file or unified kernel image
- file as good or bad. This is implemented by renaming the boot loader entry file or unified kernel image file
- back to the path encoded in the <varname>LoaderBootCountPath</varname> EFI variable.</para>
+ <listitem><para>This command undoes any marking of the current boot loader entry file or unified
+ kernel image file as good or bad. This is implemented by renaming the boot loader entry file or
+ unified kernel image file back to the path encoded in the <varname>LoaderBootCountPath</varname> EFI
+ variable. Note that operation will fail if the current kernel is not booted with boot counting
+ enabled (i.e. if the EFI variable is not set). If the boot counter already reached zero tries left on
+ a previous boot this operation will fail too: once an entry is marked <option>bad</option> it can
+ only be reset to <option>good</option> again, but not to <option>indeterminate</option>.</para>
<xi:include href="version-info.xml" xpointer="v240"/></listitem>
</varlistentry>
}
if (faccessat(fd, skip_leading_slash(path), F_OK, 0) >= 0) {
- puts("indeterminate");
+ /* If the item we booted with still exists under its name, it means we have not
+ * change the current boot's marking so far. This may have two reasons: because we
+ * simply didn't do that yet but still plan to, or because the left tries counter is
+ * already at zero, hence we cannot further decrease it to mark it even
+ * "worse"... Here we check the current counter to detect the latter case and return
+ * "dirty", since the item is already marked bad from a previous boot, but otherwise
+ * report "indeterminate" since we just didn't make a decision yet. */
+ puts(left == 0 ? "dirty" : "indeterminate");
return 0;
}
if (errno != ENOENT)
static int verb_set(int argc, char *argv[], void *userdata) {
_cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL, *good = NULL, *bad = NULL;
const char *target, *source1, *source2;
- uint64_t done;
+ uint64_t left, done;
int r;
- r = acquire_boot_count_path(&path, &prefix, NULL, &done, &suffix);
+ r = acquire_boot_count_path(&path, &prefix, &left, &done, &suffix);
if (r == -EUNATCH) /* acquire_boot_count_path() won't log on its own for this specific error */
return log_error_errno(r, "Not booted with boot counting in effect.");
if (r < 0)
source2 = good; /* Maybe this boot was previously marked as 'good'? */
} else {
assert(streq(argv[0], "indeterminate"));
+
+ if (left == 0)
+ return log_error_errno(r, "Current boot entry was already marked bad in a previous boot, cannot reset to indeterminate.");
+
target = path;
source1 = good;
source2 = bad;