xref: /xnu-8796.101.5/pexpert/gen/bootargs.c (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
1*aca3beaaSApple OSS Distributions /*
2*aca3beaaSApple OSS Distributions  * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
3*aca3beaaSApple OSS Distributions  *
4*aca3beaaSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*aca3beaaSApple OSS Distributions  *
6*aca3beaaSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*aca3beaaSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*aca3beaaSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*aca3beaaSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*aca3beaaSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*aca3beaaSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*aca3beaaSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*aca3beaaSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*aca3beaaSApple OSS Distributions  *
15*aca3beaaSApple OSS Distributions  * Please obtain a copy of the License at
16*aca3beaaSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*aca3beaaSApple OSS Distributions  *
18*aca3beaaSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*aca3beaaSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*aca3beaaSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*aca3beaaSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*aca3beaaSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*aca3beaaSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*aca3beaaSApple OSS Distributions  * limitations under the License.
25*aca3beaaSApple OSS Distributions  *
26*aca3beaaSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*aca3beaaSApple OSS Distributions  */
28*aca3beaaSApple OSS Distributions #include <pexpert/pexpert.h>
29*aca3beaaSApple OSS Distributions #include <pexpert/device_tree.h>
30*aca3beaaSApple OSS Distributions 
31*aca3beaaSApple OSS Distributions #if defined(CONFIG_XNUPOST)
32*aca3beaaSApple OSS Distributions #include <tests/xnupost.h>
33*aca3beaaSApple OSS Distributions #endif
34*aca3beaaSApple OSS Distributions 
35*aca3beaaSApple OSS Distributions typedef boolean_t (*argsep_func_t) (char c);
36*aca3beaaSApple OSS Distributions 
37*aca3beaaSApple OSS Distributions static boolean_t isargsep( char c);
38*aca3beaaSApple OSS Distributions static boolean_t israngesep( char c);
39*aca3beaaSApple OSS Distributions #if defined(__x86_64__)
40*aca3beaaSApple OSS Distributions static int argstrcpy(char *from, char *to);
41*aca3beaaSApple OSS Distributions #endif
42*aca3beaaSApple OSS Distributions static int argstrcpy2(char *from, char *to, unsigned maxlen);
43*aca3beaaSApple OSS Distributions static int argnumcpy(long long val, void *to, unsigned maxlen);
44*aca3beaaSApple OSS Distributions static int getval(char *s, long long *val, argsep_func_t issep, boolean_t skip_equal_sign);
45*aca3beaaSApple OSS Distributions boolean_t get_range_bounds(char * c, int64_t * lower, int64_t * upper);
46*aca3beaaSApple OSS Distributions 
47*aca3beaaSApple OSS Distributions extern int IODTGetDefault(const char *key, void *infoAddr, unsigned int infoSize);
48*aca3beaaSApple OSS Distributions #if defined(CONFIG_XNUPOST)
49*aca3beaaSApple OSS Distributions kern_return_t parse_boot_arg_test(void);
50*aca3beaaSApple OSS Distributions #endif
51*aca3beaaSApple OSS Distributions 
52*aca3beaaSApple OSS Distributions struct i24 {
53*aca3beaaSApple OSS Distributions 	int32_t i24 : 24;
54*aca3beaaSApple OSS Distributions 	int32_t _pad : 8;
55*aca3beaaSApple OSS Distributions };
56*aca3beaaSApple OSS Distributions 
57*aca3beaaSApple OSS Distributions #define NUM     0
58*aca3beaaSApple OSS Distributions #define STR     1
59*aca3beaaSApple OSS Distributions 
60*aca3beaaSApple OSS Distributions static boolean_t
PE_parse_boot_argn_internal(char * args,const char * arg_string,void * arg_ptr,int max_len,boolean_t force_string)61*aca3beaaSApple OSS Distributions PE_parse_boot_argn_internal(
62*aca3beaaSApple OSS Distributions 	char *args,
63*aca3beaaSApple OSS Distributions 	const char *arg_string,
64*aca3beaaSApple OSS Distributions 	void *      arg_ptr,
65*aca3beaaSApple OSS Distributions 	int         max_len,
66*aca3beaaSApple OSS Distributions 	boolean_t   force_string)
67*aca3beaaSApple OSS Distributions {
68*aca3beaaSApple OSS Distributions 	char *cp, c;
69*aca3beaaSApple OSS Distributions 	uintptr_t i;
70*aca3beaaSApple OSS Distributions 	long long val = 0;
71*aca3beaaSApple OSS Distributions 	boolean_t arg_boolean;
72*aca3beaaSApple OSS Distributions 	boolean_t arg_found;
73*aca3beaaSApple OSS Distributions 
74*aca3beaaSApple OSS Distributions 	if (*args == '\0') {
75*aca3beaaSApple OSS Distributions 		return FALSE;
76*aca3beaaSApple OSS Distributions 	}
77*aca3beaaSApple OSS Distributions 
78*aca3beaaSApple OSS Distributions #if !defined(__x86_64__)
79*aca3beaaSApple OSS Distributions 	if (max_len == -1) {
80*aca3beaaSApple OSS Distributions 		return FALSE;
81*aca3beaaSApple OSS Distributions 	}
82*aca3beaaSApple OSS Distributions #endif
83*aca3beaaSApple OSS Distributions 
84*aca3beaaSApple OSS Distributions 	arg_found = FALSE;
85*aca3beaaSApple OSS Distributions 
86*aca3beaaSApple OSS Distributions 	while (*args && isargsep(*args)) {
87*aca3beaaSApple OSS Distributions 		args++;
88*aca3beaaSApple OSS Distributions 	}
89*aca3beaaSApple OSS Distributions 
90*aca3beaaSApple OSS Distributions 	while (*args) {
91*aca3beaaSApple OSS Distributions 		if (*args == '-') {
92*aca3beaaSApple OSS Distributions 			arg_boolean = TRUE;
93*aca3beaaSApple OSS Distributions 		} else {
94*aca3beaaSApple OSS Distributions 			arg_boolean = FALSE;
95*aca3beaaSApple OSS Distributions 		}
96*aca3beaaSApple OSS Distributions 
97*aca3beaaSApple OSS Distributions 		cp = args;
98*aca3beaaSApple OSS Distributions 		while (!isargsep(*cp) && *cp != '=') {
99*aca3beaaSApple OSS Distributions 			cp++;
100*aca3beaaSApple OSS Distributions 		}
101*aca3beaaSApple OSS Distributions 
102*aca3beaaSApple OSS Distributions 		c = *cp;
103*aca3beaaSApple OSS Distributions 
104*aca3beaaSApple OSS Distributions 		i = cp - args;
105*aca3beaaSApple OSS Distributions 		if (strncmp(args, arg_string, i) ||
106*aca3beaaSApple OSS Distributions 		    (i != strlen(arg_string))) {
107*aca3beaaSApple OSS Distributions 			goto gotit;
108*aca3beaaSApple OSS Distributions 		}
109*aca3beaaSApple OSS Distributions 
110*aca3beaaSApple OSS Distributions 		if (arg_boolean) {
111*aca3beaaSApple OSS Distributions 			if (max_len > 0) {
112*aca3beaaSApple OSS Distributions 				if (force_string) {
113*aca3beaaSApple OSS Distributions 					argstrcpy2("1", arg_ptr, max_len);
114*aca3beaaSApple OSS Distributions 				} else {
115*aca3beaaSApple OSS Distributions 					argnumcpy(1, arg_ptr, max_len);/* max_len of 0 performs no copy at all*/
116*aca3beaaSApple OSS Distributions 				}
117*aca3beaaSApple OSS Distributions 				arg_found = TRUE;
118*aca3beaaSApple OSS Distributions 			} else if (max_len == 0) {
119*aca3beaaSApple OSS Distributions 				arg_found = TRUE;
120*aca3beaaSApple OSS Distributions 			}
121*aca3beaaSApple OSS Distributions 			break;
122*aca3beaaSApple OSS Distributions 		} else {
123*aca3beaaSApple OSS Distributions 			while (*cp && isargsep(*cp)) {
124*aca3beaaSApple OSS Distributions 				cp++;
125*aca3beaaSApple OSS Distributions 			}
126*aca3beaaSApple OSS Distributions 			if (*cp == '=' && c != '=') {
127*aca3beaaSApple OSS Distributions 				args = cp + 1;
128*aca3beaaSApple OSS Distributions 				goto gotit;
129*aca3beaaSApple OSS Distributions 			}
130*aca3beaaSApple OSS Distributions 			if ('_' == *arg_string) { /* Force a string copy if the argument name begins with an underscore */
131*aca3beaaSApple OSS Distributions 				if (max_len > 0) {
132*aca3beaaSApple OSS Distributions 					int hacklen = 17 > max_len ? 17 : max_len;
133*aca3beaaSApple OSS Distributions 					argstrcpy2(++cp, (char *)arg_ptr, hacklen - 1);  /* Hack - terminate after 16 characters */
134*aca3beaaSApple OSS Distributions 					arg_found = TRUE;
135*aca3beaaSApple OSS Distributions 				} else if (max_len == 0) {
136*aca3beaaSApple OSS Distributions 					arg_found = TRUE;
137*aca3beaaSApple OSS Distributions 				}
138*aca3beaaSApple OSS Distributions 				break;
139*aca3beaaSApple OSS Distributions 			}
140*aca3beaaSApple OSS Distributions 			switch (force_string ? STR : getval(cp, &val, isargsep, FALSE)) {
141*aca3beaaSApple OSS Distributions 			case NUM:
142*aca3beaaSApple OSS Distributions 				if (max_len > 0) {
143*aca3beaaSApple OSS Distributions 					argnumcpy(val, arg_ptr, max_len);
144*aca3beaaSApple OSS Distributions 					arg_found = TRUE;
145*aca3beaaSApple OSS Distributions 				} else if (max_len == 0) {
146*aca3beaaSApple OSS Distributions 					arg_found = TRUE;
147*aca3beaaSApple OSS Distributions 				}
148*aca3beaaSApple OSS Distributions 				break;
149*aca3beaaSApple OSS Distributions 			case STR:
150*aca3beaaSApple OSS Distributions 				if (*cp == '=') {
151*aca3beaaSApple OSS Distributions 					if (max_len > 0) {
152*aca3beaaSApple OSS Distributions 						argstrcpy2(++cp, (char *)arg_ptr, max_len - 1);        /*max_len of 0 performs no copy at all*/
153*aca3beaaSApple OSS Distributions 						arg_found = TRUE;
154*aca3beaaSApple OSS Distributions 					} else if (max_len == 0) {
155*aca3beaaSApple OSS Distributions 						arg_found = TRUE;
156*aca3beaaSApple OSS Distributions 					}
157*aca3beaaSApple OSS Distributions #if defined(__x86_64__)
158*aca3beaaSApple OSS Distributions 					else if (max_len == -1) {         /* unreachable on embedded */
159*aca3beaaSApple OSS Distributions 						argstrcpy(++cp, (char *)arg_ptr);
160*aca3beaaSApple OSS Distributions 						arg_found = TRUE;
161*aca3beaaSApple OSS Distributions 					}
162*aca3beaaSApple OSS Distributions #endif
163*aca3beaaSApple OSS Distributions 				} else {
164*aca3beaaSApple OSS Distributions 					if (max_len > 0) {
165*aca3beaaSApple OSS Distributions 						argstrcpy2("1", arg_ptr, max_len);
166*aca3beaaSApple OSS Distributions 						arg_found = TRUE;
167*aca3beaaSApple OSS Distributions 					} else if (max_len == 0) {
168*aca3beaaSApple OSS Distributions 						arg_found = TRUE;
169*aca3beaaSApple OSS Distributions 					}
170*aca3beaaSApple OSS Distributions 				}
171*aca3beaaSApple OSS Distributions 				break;
172*aca3beaaSApple OSS Distributions 			}
173*aca3beaaSApple OSS Distributions 			goto gotit;
174*aca3beaaSApple OSS Distributions 		}
175*aca3beaaSApple OSS Distributions gotit:
176*aca3beaaSApple OSS Distributions 		/* Skip over current arg */
177*aca3beaaSApple OSS Distributions 		while (!isargsep(*args)) {
178*aca3beaaSApple OSS Distributions 			args++;
179*aca3beaaSApple OSS Distributions 		}
180*aca3beaaSApple OSS Distributions 
181*aca3beaaSApple OSS Distributions 		/* Skip leading white space (catch end of args) */
182*aca3beaaSApple OSS Distributions 		while (*args && isargsep(*args)) {
183*aca3beaaSApple OSS Distributions 			args++;
184*aca3beaaSApple OSS Distributions 		}
185*aca3beaaSApple OSS Distributions 	}
186*aca3beaaSApple OSS Distributions 
187*aca3beaaSApple OSS Distributions 	return arg_found;
188*aca3beaaSApple OSS Distributions }
189*aca3beaaSApple OSS Distributions 
190*aca3beaaSApple OSS Distributions boolean_t
PE_parse_boot_argn(const char * arg_string,void * arg_ptr,int max_len)191*aca3beaaSApple OSS Distributions PE_parse_boot_argn(
192*aca3beaaSApple OSS Distributions 	const char      *arg_string,
193*aca3beaaSApple OSS Distributions 	void            *arg_ptr,
194*aca3beaaSApple OSS Distributions 	int                     max_len)
195*aca3beaaSApple OSS Distributions {
196*aca3beaaSApple OSS Distributions 	return PE_parse_boot_argn_internal(PE_boot_args(), arg_string, arg_ptr, max_len, FALSE);
197*aca3beaaSApple OSS Distributions }
198*aca3beaaSApple OSS Distributions 
199*aca3beaaSApple OSS Distributions boolean_t
PE_parse_boot_arg_str(const char * arg_string,char * arg_ptr,int strlen)200*aca3beaaSApple OSS Distributions PE_parse_boot_arg_str(
201*aca3beaaSApple OSS Distributions 	const char      *arg_string,
202*aca3beaaSApple OSS Distributions 	char            *arg_ptr,
203*aca3beaaSApple OSS Distributions 	int                     strlen)
204*aca3beaaSApple OSS Distributions {
205*aca3beaaSApple OSS Distributions 	return PE_parse_boot_argn_internal(PE_boot_args(), arg_string, arg_ptr, strlen, TRUE);
206*aca3beaaSApple OSS Distributions }
207*aca3beaaSApple OSS Distributions 
208*aca3beaaSApple OSS Distributions #if defined(CONFIG_XNUPOST)
209*aca3beaaSApple OSS Distributions kern_return_t
parse_boot_arg_test(void)210*aca3beaaSApple OSS Distributions parse_boot_arg_test(void)
211*aca3beaaSApple OSS Distributions {
212*aca3beaaSApple OSS Distributions 	// Tests are derived from libc/tests/darwin_bsd.c
213*aca3beaaSApple OSS Distributions 	static struct string_test_case {
214*aca3beaaSApple OSS Distributions 		char *args;
215*aca3beaaSApple OSS Distributions 		const char *argname;
216*aca3beaaSApple OSS Distributions 		char *argvalue;
217*aca3beaaSApple OSS Distributions 		boolean_t found;
218*aca3beaaSApple OSS Distributions 	} string_test_cases[] = {
219*aca3beaaSApple OSS Distributions 		{"-x -a b=3 y=42", "-a", "1", TRUE},
220*aca3beaaSApple OSS Distributions 		{"-x -a b=3 y=42", "b", "3", TRUE},
221*aca3beaaSApple OSS Distributions 		{"-x -a b=2 ba=3 y=42", "b", "2", TRUE},
222*aca3beaaSApple OSS Distributions 		{"-x -a ba=3 b=2 y=42", "b", "2", TRUE},
223*aca3beaaSApple OSS Distributions 		{"-x -a b=2 ba=3 y=42", "ba", "3", TRUE},
224*aca3beaaSApple OSS Distributions 		{"-x -a ba=3 b=2 y=42", "ba", "3", TRUE},
225*aca3beaaSApple OSS Distributions 		{"-x -ab -aa y=42", "-a", NULL, FALSE},
226*aca3beaaSApple OSS Distributions 		{"-x b=96 y=42", "bx", NULL, FALSE},
227*aca3beaaSApple OSS Distributions 		{"-x ab=96 y=42", "a", NULL, FALSE},
228*aca3beaaSApple OSS Distributions 		{"hello=world -foobar abc debug=0xBAADF00D", "notarealthing", NULL,
229*aca3beaaSApple OSS Distributions 		 FALSE},
230*aca3beaaSApple OSS Distributions 		{"hello=world -foobar abc debug=0xBAADF00D", "hello", "world", TRUE},
231*aca3beaaSApple OSS Distributions 		{"hello=world -foobar abc debug=0xBAADF00D", "debug", "0xBAADF00D",
232*aca3beaaSApple OSS Distributions 		 TRUE},
233*aca3beaaSApple OSS Distributions 		{"hello=world -foobar abc debug=0xBAADF00D", "-foobar", "1", TRUE},
234*aca3beaaSApple OSS Distributions 		{"hello=world -foobar abc debug=0xBAADF00D", "abc", "1", TRUE},
235*aca3beaaSApple OSS Distributions 	};
236*aca3beaaSApple OSS Distributions 
237*aca3beaaSApple OSS Distributions 	T_LOG("Testing boot-arg string parsing.\n");
238*aca3beaaSApple OSS Distributions 	for (int i = 0; i < (int)(sizeof(string_test_cases) /
239*aca3beaaSApple OSS Distributions 	    sizeof(string_test_cases[0])); i++) {
240*aca3beaaSApple OSS Distributions 		struct string_test_case *test_case = &string_test_cases[i];
241*aca3beaaSApple OSS Distributions 
242*aca3beaaSApple OSS Distributions 		char result[256] = "NOT_FOUND";
243*aca3beaaSApple OSS Distributions 		boolean_t found = PE_parse_boot_argn_internal(test_case->args,
244*aca3beaaSApple OSS Distributions 		    test_case->argname, result, sizeof(result), TRUE);
245*aca3beaaSApple OSS Distributions 
246*aca3beaaSApple OSS Distributions 		if (test_case->found) {
247*aca3beaaSApple OSS Distributions 			T_LOG("\"%s\": Looking for \"%s\", expecting \"%s\" found",
248*aca3beaaSApple OSS Distributions 			    test_case->args, test_case->argname, test_case->argvalue);
249*aca3beaaSApple OSS Distributions 			T_EXPECT(found, "Should find argument");
250*aca3beaaSApple OSS Distributions 			T_EXPECT_EQ_STR(result, test_case->argvalue,
251*aca3beaaSApple OSS Distributions 			    "Should find correct result");
252*aca3beaaSApple OSS Distributions 		} else {
253*aca3beaaSApple OSS Distributions 			T_LOG("\"%s\": Looking for \"%s\", expecting not found",
254*aca3beaaSApple OSS Distributions 			    test_case->args, test_case->argname, test_case->argvalue);
255*aca3beaaSApple OSS Distributions 			T_EXPECT(!found, "Should not find argument");
256*aca3beaaSApple OSS Distributions 		}
257*aca3beaaSApple OSS Distributions 	}
258*aca3beaaSApple OSS Distributions 
259*aca3beaaSApple OSS Distributions 	static struct integer_test_case {
260*aca3beaaSApple OSS Distributions 		char *args;
261*aca3beaaSApple OSS Distributions 		const char *argname;
262*aca3beaaSApple OSS Distributions 		int argvalue;
263*aca3beaaSApple OSS Distributions 		boolean_t found;
264*aca3beaaSApple OSS Distributions 	} integer_test_cases[] = {
265*aca3beaaSApple OSS Distributions 		{"-x -a b=3 y=42", "-a", 1, TRUE},
266*aca3beaaSApple OSS Distributions 		{"-x -a b=3 y=42", "b", 3, TRUE},
267*aca3beaaSApple OSS Distributions 		{"-x -a b=2 ba=3 y=42", "b", 2, TRUE},
268*aca3beaaSApple OSS Distributions 		{"-x -a ba=3 b=2 y=42", "b", 2, TRUE},
269*aca3beaaSApple OSS Distributions 		{"-x -a b=2 ba=3 y=42", "ba", 3, TRUE},
270*aca3beaaSApple OSS Distributions 		{"-x -a ba=3 b=2 y=42", "ba", 3, TRUE},
271*aca3beaaSApple OSS Distributions 		{"-x -ab -aa y=42", "-a", 0, FALSE},
272*aca3beaaSApple OSS Distributions 		{"-x b=96 y=42", "bx", 0, FALSE},
273*aca3beaaSApple OSS Distributions 		{"-x ab=96 y=42", "a", 0, FALSE},
274*aca3beaaSApple OSS Distributions 		{"hello=world -foobar abc debug=0xBAADF00D", "notarealthing", 0, FALSE},
275*aca3beaaSApple OSS Distributions 		{"hello=world -foobar abc debug=0xBAADF00D", "hello",
276*aca3beaaSApple OSS Distributions 		 0x00726F77 /* "wor" */, TRUE},
277*aca3beaaSApple OSS Distributions 		{"hello=world -foobar abc debug=0xBAADF00D", "debug", 0xBAADF00D, TRUE},
278*aca3beaaSApple OSS Distributions 		{"hello=world -foobar abc debug=0xBAADF00D", "-foobar", 1, TRUE},
279*aca3beaaSApple OSS Distributions 		{"hello=world -foobar abc debug=0xBAADF00D", "abc", 1, TRUE},
280*aca3beaaSApple OSS Distributions 	};
281*aca3beaaSApple OSS Distributions 
282*aca3beaaSApple OSS Distributions 	T_LOG("Testing boot-arg integer parsing.\n");
283*aca3beaaSApple OSS Distributions 	for (int i = 0; i < (int)(sizeof(integer_test_cases) /
284*aca3beaaSApple OSS Distributions 	    sizeof(integer_test_cases[0])); i++) {
285*aca3beaaSApple OSS Distributions 		struct integer_test_case *test_case = &integer_test_cases[i];
286*aca3beaaSApple OSS Distributions 
287*aca3beaaSApple OSS Distributions 		int result = 0xCAFEFACE;
288*aca3beaaSApple OSS Distributions 		boolean_t found = PE_parse_boot_argn_internal(test_case->args,
289*aca3beaaSApple OSS Distributions 		    test_case->argname, &result, sizeof(result), FALSE);
290*aca3beaaSApple OSS Distributions 
291*aca3beaaSApple OSS Distributions 		if (test_case->found) {
292*aca3beaaSApple OSS Distributions 			T_LOG("\"%s\": Looking for \"%s\", expecting %d found",
293*aca3beaaSApple OSS Distributions 			    test_case->args, test_case->argname, test_case->argvalue);
294*aca3beaaSApple OSS Distributions 			T_EXPECT(found, "Should find argument");
295*aca3beaaSApple OSS Distributions 			T_EXPECT_EQ_INT(result, test_case->argvalue,
296*aca3beaaSApple OSS Distributions 			    "Should find correct result");
297*aca3beaaSApple OSS Distributions 		} else {
298*aca3beaaSApple OSS Distributions 			T_LOG("\"%s\": Looking for \"%s\", expecting not found",
299*aca3beaaSApple OSS Distributions 			    test_case->args, test_case->argname, test_case->argvalue);
300*aca3beaaSApple OSS Distributions 			T_EXPECT(!found, "Should not find argument");
301*aca3beaaSApple OSS Distributions 		}
302*aca3beaaSApple OSS Distributions 	}
303*aca3beaaSApple OSS Distributions 
304*aca3beaaSApple OSS Distributions 	return KERN_SUCCESS;
305*aca3beaaSApple OSS Distributions }
306*aca3beaaSApple OSS Distributions #endif /* defined(CONFIG_XNUPOST) */
307*aca3beaaSApple OSS Distributions 
308*aca3beaaSApple OSS Distributions static boolean_t
isargsep(char c)309*aca3beaaSApple OSS Distributions isargsep(char c)
310*aca3beaaSApple OSS Distributions {
311*aca3beaaSApple OSS Distributions 	if (c == ' ' || c == '\0' || c == '\t') {
312*aca3beaaSApple OSS Distributions 		return TRUE;
313*aca3beaaSApple OSS Distributions 	} else {
314*aca3beaaSApple OSS Distributions 		return FALSE;
315*aca3beaaSApple OSS Distributions 	}
316*aca3beaaSApple OSS Distributions }
317*aca3beaaSApple OSS Distributions 
318*aca3beaaSApple OSS Distributions static boolean_t
israngesep(char c)319*aca3beaaSApple OSS Distributions israngesep(char c)
320*aca3beaaSApple OSS Distributions {
321*aca3beaaSApple OSS Distributions 	if (isargsep(c) || c == '_' || c == ',') {
322*aca3beaaSApple OSS Distributions 		return TRUE;
323*aca3beaaSApple OSS Distributions 	} else {
324*aca3beaaSApple OSS Distributions 		return FALSE;
325*aca3beaaSApple OSS Distributions 	}
326*aca3beaaSApple OSS Distributions }
327*aca3beaaSApple OSS Distributions 
328*aca3beaaSApple OSS Distributions #if defined(__x86_64__)
329*aca3beaaSApple OSS Distributions static int
argstrcpy(char * from,char * to)330*aca3beaaSApple OSS Distributions argstrcpy(
331*aca3beaaSApple OSS Distributions 	char *from,
332*aca3beaaSApple OSS Distributions 	char *to)
333*aca3beaaSApple OSS Distributions {
334*aca3beaaSApple OSS Distributions 	int i = 0;
335*aca3beaaSApple OSS Distributions 
336*aca3beaaSApple OSS Distributions 	while (!isargsep(*from)) {
337*aca3beaaSApple OSS Distributions 		i++;
338*aca3beaaSApple OSS Distributions 		*to++ = *from++;
339*aca3beaaSApple OSS Distributions 	}
340*aca3beaaSApple OSS Distributions 	*to = 0;
341*aca3beaaSApple OSS Distributions 	return i;
342*aca3beaaSApple OSS Distributions }
343*aca3beaaSApple OSS Distributions #endif
344*aca3beaaSApple OSS Distributions 
345*aca3beaaSApple OSS Distributions static int
argstrcpy2(char * from,char * to,unsigned maxlen)346*aca3beaaSApple OSS Distributions argstrcpy2(
347*aca3beaaSApple OSS Distributions 	char *from,
348*aca3beaaSApple OSS Distributions 	char *to,
349*aca3beaaSApple OSS Distributions 	unsigned maxlen)
350*aca3beaaSApple OSS Distributions {
351*aca3beaaSApple OSS Distributions 	unsigned int i = 0;
352*aca3beaaSApple OSS Distributions 
353*aca3beaaSApple OSS Distributions 	while (!isargsep(*from) && i < maxlen) {
354*aca3beaaSApple OSS Distributions 		i++;
355*aca3beaaSApple OSS Distributions 		*to++ = *from++;
356*aca3beaaSApple OSS Distributions 	}
357*aca3beaaSApple OSS Distributions 	*to = 0;
358*aca3beaaSApple OSS Distributions 	return i;
359*aca3beaaSApple OSS Distributions }
360*aca3beaaSApple OSS Distributions 
361*aca3beaaSApple OSS Distributions static int
argnumcpy(long long val,void * to,unsigned maxlen)362*aca3beaaSApple OSS Distributions argnumcpy(long long val, void *to, unsigned maxlen)
363*aca3beaaSApple OSS Distributions {
364*aca3beaaSApple OSS Distributions 	switch (maxlen) {
365*aca3beaaSApple OSS Distributions 	case 0:
366*aca3beaaSApple OSS Distributions 		/* No write-back, caller just wants to know if arg was found */
367*aca3beaaSApple OSS Distributions 		break;
368*aca3beaaSApple OSS Distributions 	case 1:
369*aca3beaaSApple OSS Distributions 		*(int8_t *)to = (int8_t)val;
370*aca3beaaSApple OSS Distributions 		break;
371*aca3beaaSApple OSS Distributions 	case 2:
372*aca3beaaSApple OSS Distributions 		*(int16_t *)to = (int16_t)val;
373*aca3beaaSApple OSS Distributions 		break;
374*aca3beaaSApple OSS Distributions 	case 3:
375*aca3beaaSApple OSS Distributions 		/* Unlikely in practice */
376*aca3beaaSApple OSS Distributions 		((struct i24 *)to)->i24 = (int32_t)val;
377*aca3beaaSApple OSS Distributions 		break;
378*aca3beaaSApple OSS Distributions 	case 4:
379*aca3beaaSApple OSS Distributions 		*(int32_t *)to = (int32_t)val;
380*aca3beaaSApple OSS Distributions 		break;
381*aca3beaaSApple OSS Distributions 	case 8:
382*aca3beaaSApple OSS Distributions 		*(int64_t *)to = (int64_t)val;
383*aca3beaaSApple OSS Distributions 		break;
384*aca3beaaSApple OSS Distributions 	default:
385*aca3beaaSApple OSS Distributions 		*(int32_t *)to = (int32_t)val;
386*aca3beaaSApple OSS Distributions 		maxlen = 4;
387*aca3beaaSApple OSS Distributions 		break;
388*aca3beaaSApple OSS Distributions 	}
389*aca3beaaSApple OSS Distributions 
390*aca3beaaSApple OSS Distributions 	return (int)maxlen;
391*aca3beaaSApple OSS Distributions }
392*aca3beaaSApple OSS Distributions 
393*aca3beaaSApple OSS Distributions static int
getval(char * s,long long * val,argsep_func_t issep,boolean_t skip_equal_sign)394*aca3beaaSApple OSS Distributions getval(
395*aca3beaaSApple OSS Distributions 	char *s,
396*aca3beaaSApple OSS Distributions 	long long *val,
397*aca3beaaSApple OSS Distributions 	argsep_func_t issep,
398*aca3beaaSApple OSS Distributions 	boolean_t skip_equal_sign )
399*aca3beaaSApple OSS Distributions {
400*aca3beaaSApple OSS Distributions 	unsigned long long radix, intval;
401*aca3beaaSApple OSS Distributions 	unsigned char c;
402*aca3beaaSApple OSS Distributions 	int sign = 1;
403*aca3beaaSApple OSS Distributions 	boolean_t has_value = FALSE;
404*aca3beaaSApple OSS Distributions 
405*aca3beaaSApple OSS Distributions 	if (*s == '=') {
406*aca3beaaSApple OSS Distributions 		s++;
407*aca3beaaSApple OSS Distributions 		has_value = TRUE;
408*aca3beaaSApple OSS Distributions 	}
409*aca3beaaSApple OSS Distributions 
410*aca3beaaSApple OSS Distributions 	if (has_value || skip_equal_sign) {
411*aca3beaaSApple OSS Distributions 		if (*s == '-') {
412*aca3beaaSApple OSS Distributions 			sign = -1;
413*aca3beaaSApple OSS Distributions 			s++;
414*aca3beaaSApple OSS Distributions 		}
415*aca3beaaSApple OSS Distributions 		intval = *s++ - '0';
416*aca3beaaSApple OSS Distributions 		radix = 10;
417*aca3beaaSApple OSS Distributions 		if (intval == 0) {
418*aca3beaaSApple OSS Distributions 			switch (*s) {
419*aca3beaaSApple OSS Distributions 			case 'x':
420*aca3beaaSApple OSS Distributions 				radix = 16;
421*aca3beaaSApple OSS Distributions 				s++;
422*aca3beaaSApple OSS Distributions 				break;
423*aca3beaaSApple OSS Distributions 
424*aca3beaaSApple OSS Distributions 			case 'b':
425*aca3beaaSApple OSS Distributions 				radix = 2;
426*aca3beaaSApple OSS Distributions 				s++;
427*aca3beaaSApple OSS Distributions 				break;
428*aca3beaaSApple OSS Distributions 
429*aca3beaaSApple OSS Distributions 			case '0': case '1': case '2': case '3':
430*aca3beaaSApple OSS Distributions 			case '4': case '5': case '6': case '7':
431*aca3beaaSApple OSS Distributions 				intval = *s - '0';
432*aca3beaaSApple OSS Distributions 				s++;
433*aca3beaaSApple OSS Distributions 				radix = 8;
434*aca3beaaSApple OSS Distributions 				break;
435*aca3beaaSApple OSS Distributions 
436*aca3beaaSApple OSS Distributions 			default:
437*aca3beaaSApple OSS Distributions 				if (!issep(*s)) {
438*aca3beaaSApple OSS Distributions 					return STR;
439*aca3beaaSApple OSS Distributions 				}
440*aca3beaaSApple OSS Distributions 			}
441*aca3beaaSApple OSS Distributions 		} else if (intval >= radix) {
442*aca3beaaSApple OSS Distributions 			return STR;
443*aca3beaaSApple OSS Distributions 		}
444*aca3beaaSApple OSS Distributions 		for (;;) {
445*aca3beaaSApple OSS Distributions 			c = *s++;
446*aca3beaaSApple OSS Distributions 			if (issep(c)) {
447*aca3beaaSApple OSS Distributions 				break;
448*aca3beaaSApple OSS Distributions 			}
449*aca3beaaSApple OSS Distributions 			if ((radix <= 10) &&
450*aca3beaaSApple OSS Distributions 			    ((c >= '0') && (c <= ('9' - (10 - radix))))) {
451*aca3beaaSApple OSS Distributions 				c -= '0';
452*aca3beaaSApple OSS Distributions 			} else if ((radix == 16) &&
453*aca3beaaSApple OSS Distributions 			    ((c >= '0') && (c <= '9'))) {
454*aca3beaaSApple OSS Distributions 				c -= '0';
455*aca3beaaSApple OSS Distributions 			} else if ((radix == 16) &&
456*aca3beaaSApple OSS Distributions 			    ((c >= 'a') && (c <= 'f'))) {
457*aca3beaaSApple OSS Distributions 				c -= 'a' - 10;
458*aca3beaaSApple OSS Distributions 			} else if ((radix == 16) &&
459*aca3beaaSApple OSS Distributions 			    ((c >= 'A') && (c <= 'F'))) {
460*aca3beaaSApple OSS Distributions 				c -= 'A' - 10;
461*aca3beaaSApple OSS Distributions 			} else if (c == 'k' || c == 'K') {
462*aca3beaaSApple OSS Distributions 				sign *= 1024;
463*aca3beaaSApple OSS Distributions 				break;
464*aca3beaaSApple OSS Distributions 			} else if (c == 'm' || c == 'M') {
465*aca3beaaSApple OSS Distributions 				sign *= 1024 * 1024;
466*aca3beaaSApple OSS Distributions 				break;
467*aca3beaaSApple OSS Distributions 			} else if (c == 'g' || c == 'G') {
468*aca3beaaSApple OSS Distributions 				sign *= 1024 * 1024 * 1024;
469*aca3beaaSApple OSS Distributions 				break;
470*aca3beaaSApple OSS Distributions 			} else {
471*aca3beaaSApple OSS Distributions 				return STR;
472*aca3beaaSApple OSS Distributions 			}
473*aca3beaaSApple OSS Distributions 			if (c >= radix) {
474*aca3beaaSApple OSS Distributions 				return STR;
475*aca3beaaSApple OSS Distributions 			}
476*aca3beaaSApple OSS Distributions 			intval *= radix;
477*aca3beaaSApple OSS Distributions 			intval += c;
478*aca3beaaSApple OSS Distributions 		}
479*aca3beaaSApple OSS Distributions 		if (!issep(c) && !issep(*s)) {
480*aca3beaaSApple OSS Distributions 			return STR;
481*aca3beaaSApple OSS Distributions 		}
482*aca3beaaSApple OSS Distributions 		*val = intval * sign;
483*aca3beaaSApple OSS Distributions 		return NUM;
484*aca3beaaSApple OSS Distributions 	}
485*aca3beaaSApple OSS Distributions 	*val = 1;
486*aca3beaaSApple OSS Distributions 	return NUM;
487*aca3beaaSApple OSS Distributions }
488*aca3beaaSApple OSS Distributions 
489*aca3beaaSApple OSS Distributions boolean_t
PE_imgsrc_mount_supported()490*aca3beaaSApple OSS Distributions PE_imgsrc_mount_supported()
491*aca3beaaSApple OSS Distributions {
492*aca3beaaSApple OSS Distributions 	return TRUE;
493*aca3beaaSApple OSS Distributions }
494*aca3beaaSApple OSS Distributions 
495*aca3beaaSApple OSS Distributions boolean_t
PE_get_default(const char * property_name,void * property_ptr,unsigned int max_property)496*aca3beaaSApple OSS Distributions PE_get_default(
497*aca3beaaSApple OSS Distributions 	const char      *property_name,
498*aca3beaaSApple OSS Distributions 	void            *property_ptr,
499*aca3beaaSApple OSS Distributions 	unsigned int max_property)
500*aca3beaaSApple OSS Distributions {
501*aca3beaaSApple OSS Distributions 	DTEntry         dte;
502*aca3beaaSApple OSS Distributions 	void const      *property_data;
503*aca3beaaSApple OSS Distributions 	unsigned int property_size;
504*aca3beaaSApple OSS Distributions 
505*aca3beaaSApple OSS Distributions 	/*
506*aca3beaaSApple OSS Distributions 	 * Look for the property using the PE DT support.
507*aca3beaaSApple OSS Distributions 	 */
508*aca3beaaSApple OSS Distributions 	if (kSuccess == SecureDTLookupEntry(NULL, "/defaults", &dte)) {
509*aca3beaaSApple OSS Distributions 		/*
510*aca3beaaSApple OSS Distributions 		 * We have a /defaults node, look for the named property.
511*aca3beaaSApple OSS Distributions 		 */
512*aca3beaaSApple OSS Distributions 		if (kSuccess != SecureDTGetProperty(dte, property_name, &property_data, &property_size)) {
513*aca3beaaSApple OSS Distributions 			return FALSE;
514*aca3beaaSApple OSS Distributions 		}
515*aca3beaaSApple OSS Distributions 
516*aca3beaaSApple OSS Distributions 		/*
517*aca3beaaSApple OSS Distributions 		 * This would be a fine place to do smart argument size management for 32/64
518*aca3beaaSApple OSS Distributions 		 * translation, but for now we'll insist that callers know how big their
519*aca3beaaSApple OSS Distributions 		 * default values are.
520*aca3beaaSApple OSS Distributions 		 */
521*aca3beaaSApple OSS Distributions 		if (property_size > max_property) {
522*aca3beaaSApple OSS Distributions 			return FALSE;
523*aca3beaaSApple OSS Distributions 		}
524*aca3beaaSApple OSS Distributions 
525*aca3beaaSApple OSS Distributions 		/*
526*aca3beaaSApple OSS Distributions 		 * Copy back the precisely-sized result.
527*aca3beaaSApple OSS Distributions 		 */
528*aca3beaaSApple OSS Distributions 		memcpy(property_ptr, property_data, property_size);
529*aca3beaaSApple OSS Distributions 		return TRUE;
530*aca3beaaSApple OSS Distributions 	}
531*aca3beaaSApple OSS Distributions 
532*aca3beaaSApple OSS Distributions 	/*
533*aca3beaaSApple OSS Distributions 	 * Look for the property using I/O Kit's DT support.
534*aca3beaaSApple OSS Distributions 	 */
535*aca3beaaSApple OSS Distributions 	return IODTGetDefault(property_name, property_ptr, max_property) ? FALSE : TRUE;
536*aca3beaaSApple OSS Distributions }
537*aca3beaaSApple OSS Distributions 
538*aca3beaaSApple OSS Distributions /* function: get_range_bounds
539*aca3beaaSApple OSS Distributions  * Parse a range string like "1_3,5_20" and return 1,3 as lower and upper.
540*aca3beaaSApple OSS Distributions  * Note: '_' is separator for bounds integer delimiter and
541*aca3beaaSApple OSS Distributions  *       ',' is considered as separator for range pair.
542*aca3beaaSApple OSS Distributions  * returns TRUE when both range values are found
543*aca3beaaSApple OSS Distributions  */
544*aca3beaaSApple OSS Distributions boolean_t
get_range_bounds(char * c,int64_t * lower,int64_t * upper)545*aca3beaaSApple OSS Distributions get_range_bounds(char *c, int64_t *lower, int64_t *upper)
546*aca3beaaSApple OSS Distributions {
547*aca3beaaSApple OSS Distributions 	if (c == NULL || lower == NULL || upper == NULL) {
548*aca3beaaSApple OSS Distributions 		return FALSE;
549*aca3beaaSApple OSS Distributions 	}
550*aca3beaaSApple OSS Distributions 
551*aca3beaaSApple OSS Distributions 	if (NUM != getval(c, lower, israngesep, TRUE)) {
552*aca3beaaSApple OSS Distributions 		return FALSE;
553*aca3beaaSApple OSS Distributions 	}
554*aca3beaaSApple OSS Distributions 
555*aca3beaaSApple OSS Distributions 	while (*c != '\0') {
556*aca3beaaSApple OSS Distributions 		if (*c == '_') {
557*aca3beaaSApple OSS Distributions 			break;
558*aca3beaaSApple OSS Distributions 		}
559*aca3beaaSApple OSS Distributions 		c++;
560*aca3beaaSApple OSS Distributions 	}
561*aca3beaaSApple OSS Distributions 
562*aca3beaaSApple OSS Distributions 	if (*c == '_') {
563*aca3beaaSApple OSS Distributions 		c++;
564*aca3beaaSApple OSS Distributions 		if (NUM != getval(c, upper, israngesep, TRUE)) {
565*aca3beaaSApple OSS Distributions 			return FALSE;
566*aca3beaaSApple OSS Distributions 		}
567*aca3beaaSApple OSS Distributions 	} else {
568*aca3beaaSApple OSS Distributions 		return FALSE;
569*aca3beaaSApple OSS Distributions 	}
570*aca3beaaSApple OSS Distributions 	return TRUE;
571*aca3beaaSApple OSS Distributions }
572