| // 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++; |
| } |
| } |