| // 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, limit; | |
| char *endp; | |
| bool clear; | |
| int i; | |
| limit = type == ALT_TYPE_FACILITY ? MAX_FACILITY_BIT : MAX_MFEATURE_BIT; | |
| 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 && val < limit) { | |
| 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++; | |
| } | |
| } |