]> www.infradead.org Git - linux.git/commitdiff
power: reset: reboot-mode: better compatibility with DT (replace ' ,/')
authorAndré Draszik <andre.draszik@linaro.org>
Fri, 7 Mar 2025 07:50:18 +0000 (07:50 +0000)
committerSebastian Reichel <sebastian.reichel@collabora.com>
Sun, 27 Apr 2025 22:05:31 +0000 (00:05 +0200)
This driver's purpose is to parse boot modes described in DT, via key
(node name) / value pairs, and to match them to a reboot mode requested
by the kernel. Unfortunately, DT node names can not contain certain
characters, like space ' ' or comma ',' or slash '/', while the
requested reboot mode may.

This is a problem because it makes it impossible to match reboot modes
containing any of those characters.

For example, this makes it impossible to communicate DM verity errors
to the boot loader - DM verity errors trigger a reboot with mode
"dm-verity device corrupted" in drivers/md/dm-verity-target.c and
devices typically have to take action in that case [1]. Changing this
string itself is not feasible, see e.g. discussion in [2], but would
also just cover this one case.

Another example is Android, which may use comma in the reboot mode
string, e.g. as "shutdown,thermal" in [3].

The kernel also shouldn't prescribe what characters are allowed inside
the boot mode string for a user to set. It hasn't done this so far, and
introducing such a restriction would be an interface break and
arbitrarily enforce a random new policy.

Therefore, update this driver to do another round of string matching,
after replacing the common characters mentioned above with dash '-', if
a match hasn't been found without doing said replacement.
This now allows us to have DT entries of e.g.:

    mode-dm-verity-device-corrupted = <...>

and so on.

Link: https://cs.android.com/android/kernel/superproject/+/android14-gs-pixel-6.1:private/google-modules/power/reset/exynos-gs101-reboot.c;l=144
Link: https://lore.kernel.org/all/CAAFS_9FuSb7PZwQ2itUh_H7ZdhvAEiiX7fhxJ4kmmv9JCaHmkA@mail.gmail.com/
Link: https://cs.android.com/android/platform/superproject/main/+/main:system/core/init/reboot_utils.cpp;drc=79ad1e2e9bf1628c141c8cd2fbb4f3df61a6ba75;l=122
Signed-off-by: André Draszik <andre.draszik@linaro.org>
Link: https://lore.kernel.org/r/20250307-reboot-mode-chars-v1-1-d83ff95da524@linaro.org
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
drivers/power/reset/reboot-mode.c

index b4076b10b89376a71ff6f6c3ba807b20e673de86..fba53f638da04655e756b5f8b7d2d666d1379535 100644 (file)
@@ -23,20 +23,29 @@ static unsigned int get_reboot_mode_magic(struct reboot_mode_driver *reboot,
                                          const char *cmd)
 {
        const char *normal = "normal";
-       int magic = 0;
        struct mode_info *info;
+       char cmd_[110];
 
        if (!cmd)
                cmd = normal;
 
-       list_for_each_entry(info, &reboot->head, list) {
-               if (!strcmp(info->mode, cmd)) {
-                       magic = info->magic;
-                       break;
-               }
-       }
+       list_for_each_entry(info, &reboot->head, list)
+               if (!strcmp(info->mode, cmd))
+                       return info->magic;
+
+       /* try to match again, replacing characters impossible in DT */
+       if (strscpy(cmd_, cmd, sizeof(cmd_)) == -E2BIG)
+               return 0;
 
-       return magic;
+       strreplace(cmd_, ' ', '-');
+       strreplace(cmd_, ',', '-');
+       strreplace(cmd_, '/', '-');
+
+       list_for_each_entry(info, &reboot->head, list)
+               if (!strcmp(info->mode, cmd_))
+                       return info->magic;
+
+       return 0;
 }
 
 static int reboot_mode_notify(struct notifier_block *this,