Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

power: reset: reboot-mode: better compatibility with DT (replace ' ,/')

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 [1]
Link: https://lore.kernel.org/all/CAAFS_9FuSb7PZwQ2itUh_H7ZdhvAEiiX7fhxJ4kmmv9JCaHmkA@mail.gmail.com/ [2]
Link: https://cs.android.com/android/platform/superproject/main/+/main:system/core/init/reboot_utils.cpp;drc=79ad1e2e9bf1628c141c8cd2fbb4f3df61a6ba75;l=122 [3]
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>

authored by

André Draszik and committed by
Sebastian Reichel
ca3d2ea5 62d48983

+17 -8
+17 -8
drivers/power/reset/reboot-mode.c
··· 23 23 const char *cmd) 24 24 { 25 25 const char *normal = "normal"; 26 - int magic = 0; 27 26 struct mode_info *info; 27 + char cmd_[110]; 28 28 29 29 if (!cmd) 30 30 cmd = normal; 31 31 32 - list_for_each_entry(info, &reboot->head, list) { 33 - if (!strcmp(info->mode, cmd)) { 34 - magic = info->magic; 35 - break; 36 - } 37 - } 32 + list_for_each_entry(info, &reboot->head, list) 33 + if (!strcmp(info->mode, cmd)) 34 + return info->magic; 38 35 39 - return magic; 36 + /* try to match again, replacing characters impossible in DT */ 37 + if (strscpy(cmd_, cmd, sizeof(cmd_)) == -E2BIG) 38 + return 0; 39 + 40 + strreplace(cmd_, ' ', '-'); 41 + strreplace(cmd_, ',', '-'); 42 + strreplace(cmd_, '/', '-'); 43 + 44 + list_for_each_entry(info, &reboot->head, list) 45 + if (!strcmp(info->mode, cmd_)) 46 + return info->magic; 47 + 48 + return 0; 40 49 } 41 50 42 51 static int reboot_mode_notify(struct notifier_block *this,