1 // SPDX-License-Identifier: GPL-2.0
2 #define boot_fmt(fmt)	"alt: " fmt
3 #include "boot.h"
4 
5 #define a_debug		boot_debug
6 
7 #include "../kernel/alternative.c"
8 
alt_debug_all(int type)9 static void alt_debug_all(int type)
10 {
11 	int i;
12 
13 	switch (type) {
14 	case ALT_TYPE_FACILITY:
15 		for (i = 0; i < ARRAY_SIZE(alt_debug.facilities); i++)
16 			alt_debug.facilities[i] = -1UL;
17 		break;
18 	case ALT_TYPE_FEATURE:
19 		for (i = 0; i < ARRAY_SIZE(alt_debug.mfeatures); i++)
20 			alt_debug.mfeatures[i] = -1UL;
21 		break;
22 	case ALT_TYPE_SPEC:
23 		alt_debug.spec = 1;
24 		break;
25 	}
26 }
27 
alt_debug_modify(int type,unsigned int nr,bool clear)28 static void alt_debug_modify(int type, unsigned int nr, bool clear)
29 {
30 	switch (type) {
31 	case ALT_TYPE_FACILITY:
32 		if (clear)
33 			__clear_facility(nr, alt_debug.facilities);
34 		else
35 			__set_facility(nr, alt_debug.facilities);
36 		break;
37 	case ALT_TYPE_FEATURE:
38 		if (clear)
39 			__clear_machine_feature(nr, alt_debug.mfeatures);
40 		else
41 			__set_machine_feature(nr, alt_debug.mfeatures);
42 		break;
43 	}
44 }
45 
alt_debug_parse(int type,char * str)46 static char *alt_debug_parse(int type, char *str)
47 {
48 	unsigned long val, endval;
49 	char *endp;
50 	bool clear;
51 	int i;
52 
53 	if (*str == ':') {
54 		str++;
55 	} else {
56 		alt_debug_all(type);
57 		return str;
58 	}
59 	clear = false;
60 	if (*str == '!') {
61 		alt_debug_all(type);
62 		clear = true;
63 		str++;
64 	}
65 	while (*str) {
66 		val = simple_strtoull(str, &endp, 0);
67 		if (str == endp)
68 			break;
69 		str = endp;
70 		if (*str == '-') {
71 			str++;
72 			endval = simple_strtoull(str, &endp, 0);
73 			if (str == endp)
74 				break;
75 			str = endp;
76 			while (val <= endval) {
77 				alt_debug_modify(type, val, clear);
78 				val++;
79 			}
80 		} else {
81 			alt_debug_modify(type, val, clear);
82 		}
83 		if (*str != ',')
84 			break;
85 		str++;
86 	}
87 	return str;
88 }
89 
90 /*
91  * Use debug-alternative command line parameter for debugging:
92  * "debug-alternative"
93  *  -> print debug message for every single alternative
94  *
95  * "debug-alternative=0;2"
96  * -> print debug message for all alternatives with type 0 and 2
97  *
98  * "debug-alternative=0:0-7"
99  * -> print debug message for all alternatives with type 0 and with
100  *    facility numbers within the range of 0-7
101  *    (if type 0 is ALT_TYPE_FACILITY)
102  *
103  * "debug-alternative=0:!8;1"
104  * -> print debug message for all alternatives with type 0, for all
105  *    facility number, except facility 8, and in addition print all
106  *    alternatives with type 1
107  */
alt_debug_setup(char * str)108 void alt_debug_setup(char *str)
109 {
110 	unsigned long type;
111 	char *endp;
112 	int i;
113 
114 	if (!str) {
115 		alt_debug_all(ALT_TYPE_FACILITY);
116 		alt_debug_all(ALT_TYPE_FEATURE);
117 		alt_debug_all(ALT_TYPE_SPEC);
118 		return;
119 	}
120 	while (*str) {
121 		type = simple_strtoull(str, &endp, 0);
122 		if (str == endp)
123 			break;
124 		str = endp;
125 		switch (type) {
126 		case ALT_TYPE_FACILITY:
127 		case ALT_TYPE_FEATURE:
128 			str = alt_debug_parse(type, str);
129 			break;
130 		case ALT_TYPE_SPEC:
131 			alt_debug_all(ALT_TYPE_SPEC);
132 			break;
133 		}
134 		if (*str != ';')
135 			break;
136 		str++;
137 	}
138 }
139