// SPDX-License-Identifier: GPL-2.0 #define boot_fmt(fmt) "alt: " fmt #include "boot.h" #define a_debug boot_debug #include "../kernel/alternative.c" static void alt_debug_all(int type) { int i; switch (type) { case ALT_TYPE_FACILITY: for (i = 0; i < ARRAY_SIZE(alt_debug.facilities); i++) alt_debug.facilities[i] = -1UL; break; case ALT_TYPE_FEATURE: for (i = 0; i < ARRAY_SIZE(alt_debug.mfeatures); i++) alt_debug.mfeatures[i] = -1UL; break; case ALT_TYPE_SPEC: alt_debug.spec = 1; break; } } static void alt_debug_modify(int type, unsigned int nr, bool clear) { switch (type) { case ALT_TYPE_FACILITY: if (clear) __clear_facility(nr, alt_debug.facilities); else __set_facility(nr, alt_debug.facilities); break; case ALT_TYPE_FEATURE: if (clear) __clear_machine_feature(nr, alt_debug.mfeatures); else __set_machine_feature(nr, alt_debug.mfeatures); break; } } static char *alt_debug_parse(int type, char *str) { unsigned long val, endval; char *endp; bool clear; int i; if (*str == ':') { str++; } else { alt_debug_all(type); return str; } clear = false; if (*str == '!') { alt_debug_all(type); clear = true; str++; } while (*str) { val = simple_strtoull(str, &endp, 0); if (str == endp) break; str = endp; if (*str == '-') { str++; endval = simple_strtoull(str, &endp, 0); if (str == endp) break; str = endp; while (val <= endval) { alt_debug_modify(type, val, clear); val++; } } else { alt_debug_modify(type, val, clear); } if (*str != ',') break; str++; } return str; } /* * Use debug-alternative command line parameter for debugging: * "debug-alternative" * -> print debug message for every single alternative * * "debug-alternative=0;2" * -> print debug message for all alternatives with type 0 and 2 * * "debug-alternative=0:0-7" * -> print debug message for all alternatives with type 0 and with * facility numbers within the range of 0-7 * (if type 0 is ALT_TYPE_FACILITY) * * "debug-alternative=0:!8;1" * -> print debug message for all alternatives with type 0, for all * facility number, except facility 8, and in addition print all * alternatives with type 1 */ void alt_debug_setup(char *str) { unsigned long type; char *endp; int i; if (!str) { alt_debug_all(ALT_TYPE_FACILITY); alt_debug_all(ALT_TYPE_FEATURE); alt_debug_all(ALT_TYPE_SPEC); return; } while (*str) { type = simple_strtoull(str, &endp, 0); if (str == endp) break; str = endp; switch (type) { case ALT_TYPE_FACILITY: case ALT_TYPE_FEATURE: str = alt_debug_parse(type, str); break; case ALT_TYPE_SPEC: alt_debug_all(ALT_TYPE_SPEC); break; } if (*str != ';') break; str++; } }