]> git.saurik.com Git - apple/xnu.git/blame - pexpert/gen/bootargs.c
xnu-3789.41.3.tar.gz
[apple/xnu.git] / pexpert / gen / bootargs.c
CommitLineData
1c79356b 1/*
39037602 2 * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
3e170ce0 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
3e170ce0 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
3e170ce0 17 *
2d21ac55
A
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
3e170ce0 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28#include <pexpert/pexpert.h>
6d2010ae 29#include <pexpert/device_tree.h>
1c79356b 30
3e170ce0
A
31typedef boolean_t (*argsep_func_t) (char c);
32
6d2010ae 33static boolean_t isargsep( char c);
3e170ce0 34static boolean_t israngesep( char c);
6d2010ae 35static int argstrcpy(char *from, char *to);
cf7d32b8 36static int argstrcpy2(char *from,char *to, unsigned maxlen);
3e170ce0
A
37static int argnumcpy(long long val, void *to, unsigned maxlen);
38static int getval(char *s, long long *val, argsep_func_t issep, boolean_t skip_equal_sign);
39boolean_t get_range_bounds(char * c, int64_t * lower, int64_t * upper);
6d2010ae
A
40
41extern int IODTGetDefault(const char *key, void *infoAddr, unsigned int infoSize);
42
316670eb 43
6d2010ae
A
44struct i24 {
45 int32_t i24 : 24;
46 int32_t _pad : 8;
47};
2d21ac55 48
1c79356b
A
49#define NUM 0
50#define STR 1
51
b0d623f7 52#if !defined(__LP64__) && !defined(__arm__)
3e170ce0 53boolean_t
1c79356b 54PE_parse_boot_arg(
91447636
A
55 const char *arg_string,
56 void *arg_ptr)
57{
2d21ac55
A
58 int max_len = -1;
59
2d21ac55
A
60
61 return PE_parse_boot_argn(arg_string, arg_ptr, max_len);
91447636 62}
b0d623f7 63#endif
91447636 64
39037602
A
65static boolean_t
66PE_parse_boot_argn_internal(
67 const char *arg_string,
68 void * arg_ptr,
69 int max_len,
70 boolean_t force_string)
1c79356b
A
71{
72 char *args;
73 char *cp, c;
316670eb 74 uintptr_t i;
39037602 75 long long val = 0;
1c79356b
A
76 boolean_t arg_boolean;
77 boolean_t arg_found;
78
79 args = PE_boot_args();
9bccf70c
A
80 if (*args == '\0') return FALSE;
81
6d2010ae 82
1c79356b
A
83 arg_found = FALSE;
84
b0d623f7 85 while(*args && isargsep(*args)) args++;
1c79356b
A
86
87 while (*args)
88 {
3e170ce0 89 if (*args == '-')
1c79356b
A
90 arg_boolean = TRUE;
91 else
92 arg_boolean = FALSE;
93
94 cp = args;
95 while (!isargsep (*cp) && *cp != '=')
96 cp++;
97 if (*cp != '=' && !arg_boolean)
98 goto gotit;
99
100 c = *cp;
101
102 i = cp-args;
103 if (strncmp(args, arg_string, i) ||
104 (i!=strlen(arg_string)))
105 goto gotit;
39037602 106
1c79356b 107 if (arg_boolean) {
39037602
A
108 if (!force_string){
109 argnumcpy(1, arg_ptr, max_len);
110 arg_found = TRUE;
111 }
1c79356b
A
112 break;
113 } else {
b0d623f7 114 while (*cp && isargsep (*cp))
1c79356b
A
115 cp++;
116 if (*cp == '=' && c != '=') {
117 args = cp+1;
118 goto gotit;
119 }
55e303ae 120 if ('_' == *arg_string) /* Force a string copy if the argument name begins with an underscore */
91447636 121 {
2d21ac55
A
122 int hacklen = 17 > max_len ? 17 : max_len;
123 argstrcpy2 (++cp, (char *)arg_ptr, hacklen - 1); /* Hack - terminate after 16 characters */
91447636
A
124 arg_found = TRUE;
125 break;
126 }
39037602 127 switch ((force_string && *cp == '=') ? STR : getval(cp, &val, isargsep, FALSE))
1c79356b
A
128 {
129 case NUM:
6d2010ae 130 argnumcpy(val, arg_ptr, max_len);
1c79356b
A
131 arg_found = TRUE;
132 break;
133 case STR:
91447636 134 if(max_len > 0) //max_len of 0 performs no copy at all
2d21ac55 135 argstrcpy2(++cp, (char *)arg_ptr, max_len - 1);
6d2010ae 136 else if(max_len == -1) // unreachable on embedded
91447636 137 argstrcpy(++cp, (char *)arg_ptr);
1c79356b
A
138 arg_found = TRUE;
139 break;
140 }
141 goto gotit;
142 }
143gotit:
144 /* Skip over current arg */
145 while(!isargsep(*args)) args++;
146
147 /* Skip leading white space (catch end of args) */
148 while(*args && isargsep(*args)) args++;
149 }
150
151 return(arg_found);
152}
153
39037602
A
154boolean_t
155PE_parse_boot_argn(
156 const char *arg_string,
157 void *arg_ptr,
158 int max_len)
159{
160 return PE_parse_boot_argn_internal(arg_string, arg_ptr, max_len, FALSE);
161}
162
163boolean_t
164PE_parse_boot_arg_str(
165 const char *arg_string,
166 char *arg_ptr,
167 int strlen)
168{
169 return PE_parse_boot_argn_internal(arg_string, arg_ptr, strlen, TRUE);
170}
171
6d2010ae 172static boolean_t
3e170ce0 173isargsep(char c)
1c79356b
A
174{
175 if (c == ' ' || c == '\0' || c == '\t')
3e170ce0 176 return (TRUE);
1c79356b 177 else
3e170ce0
A
178 return (FALSE);
179}
180
181static boolean_t
182israngesep(char c)
183{
184 if (isargsep(c) || c == '_' || c == ',')
185 return (TRUE);
186 else
187 return (FALSE);
1c79356b
A
188}
189
6d2010ae 190static int
1c79356b 191argstrcpy(
3e170ce0 192 char *from,
1c79356b
A
193 char *to)
194{
195 int i = 0;
196
197 while (!isargsep(*from)) {
198 i++;
199 *to++ = *from++;
200 }
201 *to = 0;
202 return(i);
203}
204
cf7d32b8 205static int
55e303ae 206argstrcpy2(
3e170ce0 207 char *from,
55e303ae
A
208 char *to,
209 unsigned maxlen)
210{
2d21ac55 211 unsigned int i = 0;
55e303ae
A
212
213 while (!isargsep(*from) && i < maxlen) {
214 i++;
215 *to++ = *from++;
216 }
217 *to = 0;
218 return(i);
219}
220
3e170ce0 221static int argnumcpy(long long val, void *to, unsigned maxlen)
6d2010ae
A
222{
223 switch (maxlen) {
224 case 0:
225 /* No write-back, caller just wants to know if arg was found */
226 break;
227 case 1:
228 *(int8_t *)to = val;
229 break;
230 case 2:
231 *(int16_t *)to = val;
232 break;
233 case 3:
234 /* Unlikely in practice */
235 ((struct i24 *)to)->i24 = val;
236 break;
237 case 4:
3e170ce0
A
238 *(int32_t *)to = val;
239 break;
240 case 8:
241 *(int64_t *)to = val;
242 break;
6d2010ae
A
243 default:
244 *(int32_t *)to = val;
245 maxlen = 4;
246 break;
247 }
248
249 return (int)maxlen;
250}
251
252static int
1c79356b 253getval(
3e170ce0
A
254 char *s,
255 long long *val,
256 argsep_func_t issep,
257 boolean_t skip_equal_sign )
1c79356b 258{
3e170ce0
A
259 unsigned long long radix, intval;
260 unsigned char c;
1c79356b 261 int sign = 1;
3e170ce0 262 boolean_t has_value = FALSE;
1c79356b
A
263
264 if (*s == '=') {
265 s++;
3e170ce0
A
266 has_value = TRUE;
267 }
268
269 if (has_value || skip_equal_sign) {
39037602
A
270 if (*s == '-') {
271 sign = -1;
272 s++;
273 }
1c79356b
A
274 intval = *s++-'0';
275 radix = 10;
0c530ab8 276 if (intval == 0) {
1c79356b
A
277 switch(*s) {
278
279 case 'x':
280 radix = 16;
281 s++;
282 break;
283
284 case 'b':
285 radix = 2;
286 s++;
287 break;
288
289 case '0': case '1': case '2': case '3':
290 case '4': case '5': case '6': case '7':
291 intval = *s-'0';
292 s++;
293 radix = 8;
294 break;
295
296 default:
3e170ce0 297 if (!issep(*s))
1c79356b
A
298 return (STR);
299 }
0c530ab8
A
300 } else if (intval >= radix) {
301 return (STR);
302 }
1c79356b 303 for(;;) {
0c530ab8 304 c = *s++;
3e170ce0 305 if (issep(c))
0c530ab8
A
306 break;
307 if ((radix <= 10) &&
308 ((c >= '0') && (c <= ('9' - (10 - radix))))) {
309 c -= '0';
310 } else if ((radix == 16) &&
311 ((c >= '0') && (c <= '9'))) {
1c79356b 312 c -= '0';
0c530ab8
A
313 } else if ((radix == 16) &&
314 ((c >= 'a') && (c <= 'f'))) {
1c79356b 315 c -= 'a' - 10;
0c530ab8
A
316 } else if ((radix == 16) &&
317 ((c >= 'A') && (c <= 'F'))) {
1c79356b 318 c -= 'A' - 10;
0c530ab8
A
319 } else if (c == 'k' || c == 'K') {
320 sign *= 1024;
1c79356b 321 break;
0c530ab8
A
322 } else if (c == 'm' || c == 'M') {
323 sign *= 1024 * 1024;
324 break;
325 } else if (c == 'g' || c == 'G') {
326 sign *= 1024 * 1024 * 1024;
327 break;
328 } else {
1c79356b 329 return (STR);
0c530ab8 330 }
1c79356b
A
331 if (c >= radix)
332 return (STR);
333 intval *= radix;
334 intval += c;
335 }
3e170ce0 336 if (!issep(c) && !issep(*s))
0c530ab8 337 return STR;
1c79356b
A
338 *val = intval * sign;
339 return (NUM);
340 }
341 *val = 1;
342 return (NUM);
343}
b7266188 344
3e170ce0 345boolean_t
b7266188
A
346PE_imgsrc_mount_supported()
347{
348 return TRUE;
349}
6d2010ae
A
350
351boolean_t
352PE_get_default(
353 const char *property_name,
354 void *property_ptr,
355 unsigned int max_property)
356{
357 DTEntry dte;
358 void **property_data;
359 unsigned int property_size;
360
361 /*
362 * Look for the property using the PE DT support.
363 */
364 if (kSuccess == DTLookupEntry(NULL, "/defaults", &dte)) {
365
366 /*
367 * We have a /defaults node, look for the named property.
368 */
369 if (kSuccess != DTGetProperty(dte, property_name, (void **)&property_data, &property_size))
370 return FALSE;
371
372 /*
373 * This would be a fine place to do smart argument size management for 32/64
374 * translation, but for now we'll insist that callers know how big their
375 * default values are.
376 */
377 if (property_size > max_property)
378 return FALSE;
379
380 /*
381 * Copy back the precisely-sized result.
382 */
383 memcpy(property_ptr, property_data, property_size);
384 return TRUE;
385 }
386
387 /*
388 * Look for the property using I/O Kit's DT support.
389 */
390 return IODTGetDefault(property_name, property_ptr, max_property) ? FALSE : TRUE;
391}
3e170ce0
A
392
393/* function: get_range_bounds
394 * Parse a range string like "1_3,5_20" and return 1,3 as lower and upper.
395 * Note: '_' is separator for bounds integer delimiter and
396 * ',' is considered as separator for range pair.
397 * returns TRUE when both range values are found
398 */
399boolean_t
400get_range_bounds(char *c, int64_t *lower, int64_t *upper)
401{
402 if (c == NULL || lower == NULL || upper == NULL) {
403 return FALSE;
404 }
405
406 if (NUM != getval(c, lower, israngesep, TRUE)) {
407 return FALSE;
408 }
409
410 while (*c != '\0') {
411 if (*c == '_') {
412 break;
413 }
414 c++;
415 }
416
417 if (*c == '_') {
418 c++;
419 if (NUM != getval(c, upper, israngesep, TRUE)) {
420 return FALSE;
421 }
422 } else {
423 return FALSE;
424 }
425 return TRUE;
426}