]> git.saurik.com Git - apple/xnu.git/blame_incremental - pexpert/gen/bootargs.c
xnu-3789.41.3.tar.gz
[apple/xnu.git] / pexpert / gen / bootargs.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#include <pexpert/pexpert.h>
29#include <pexpert/device_tree.h>
30
31typedef boolean_t (*argsep_func_t) (char c);
32
33static boolean_t isargsep( char c);
34static boolean_t israngesep( char c);
35static int argstrcpy(char *from, char *to);
36static int argstrcpy2(char *from,char *to, unsigned maxlen);
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);
40
41extern int IODTGetDefault(const char *key, void *infoAddr, unsigned int infoSize);
42
43
44struct i24 {
45 int32_t i24 : 24;
46 int32_t _pad : 8;
47};
48
49#define NUM 0
50#define STR 1
51
52#if !defined(__LP64__) && !defined(__arm__)
53boolean_t
54PE_parse_boot_arg(
55 const char *arg_string,
56 void *arg_ptr)
57{
58 int max_len = -1;
59
60
61 return PE_parse_boot_argn(arg_string, arg_ptr, max_len);
62}
63#endif
64
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)
71{
72 char *args;
73 char *cp, c;
74 uintptr_t i;
75 long long val = 0;
76 boolean_t arg_boolean;
77 boolean_t arg_found;
78
79 args = PE_boot_args();
80 if (*args == '\0') return FALSE;
81
82
83 arg_found = FALSE;
84
85 while(*args && isargsep(*args)) args++;
86
87 while (*args)
88 {
89 if (*args == '-')
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;
106
107 if (arg_boolean) {
108 if (!force_string){
109 argnumcpy(1, arg_ptr, max_len);
110 arg_found = TRUE;
111 }
112 break;
113 } else {
114 while (*cp && isargsep (*cp))
115 cp++;
116 if (*cp == '=' && c != '=') {
117 args = cp+1;
118 goto gotit;
119 }
120 if ('_' == *arg_string) /* Force a string copy if the argument name begins with an underscore */
121 {
122 int hacklen = 17 > max_len ? 17 : max_len;
123 argstrcpy2 (++cp, (char *)arg_ptr, hacklen - 1); /* Hack - terminate after 16 characters */
124 arg_found = TRUE;
125 break;
126 }
127 switch ((force_string && *cp == '=') ? STR : getval(cp, &val, isargsep, FALSE))
128 {
129 case NUM:
130 argnumcpy(val, arg_ptr, max_len);
131 arg_found = TRUE;
132 break;
133 case STR:
134 if(max_len > 0) //max_len of 0 performs no copy at all
135 argstrcpy2(++cp, (char *)arg_ptr, max_len - 1);
136 else if(max_len == -1) // unreachable on embedded
137 argstrcpy(++cp, (char *)arg_ptr);
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
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
172static boolean_t
173isargsep(char c)
174{
175 if (c == ' ' || c == '\0' || c == '\t')
176 return (TRUE);
177 else
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);
188}
189
190static int
191argstrcpy(
192 char *from,
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
205static int
206argstrcpy2(
207 char *from,
208 char *to,
209 unsigned maxlen)
210{
211 unsigned int i = 0;
212
213 while (!isargsep(*from) && i < maxlen) {
214 i++;
215 *to++ = *from++;
216 }
217 *to = 0;
218 return(i);
219}
220
221static int argnumcpy(long long val, void *to, unsigned maxlen)
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:
238 *(int32_t *)to = val;
239 break;
240 case 8:
241 *(int64_t *)to = val;
242 break;
243 default:
244 *(int32_t *)to = val;
245 maxlen = 4;
246 break;
247 }
248
249 return (int)maxlen;
250}
251
252static int
253getval(
254 char *s,
255 long long *val,
256 argsep_func_t issep,
257 boolean_t skip_equal_sign )
258{
259 unsigned long long radix, intval;
260 unsigned char c;
261 int sign = 1;
262 boolean_t has_value = FALSE;
263
264 if (*s == '=') {
265 s++;
266 has_value = TRUE;
267 }
268
269 if (has_value || skip_equal_sign) {
270 if (*s == '-') {
271 sign = -1;
272 s++;
273 }
274 intval = *s++-'0';
275 radix = 10;
276 if (intval == 0) {
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:
297 if (!issep(*s))
298 return (STR);
299 }
300 } else if (intval >= radix) {
301 return (STR);
302 }
303 for(;;) {
304 c = *s++;
305 if (issep(c))
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'))) {
312 c -= '0';
313 } else if ((radix == 16) &&
314 ((c >= 'a') && (c <= 'f'))) {
315 c -= 'a' - 10;
316 } else if ((radix == 16) &&
317 ((c >= 'A') && (c <= 'F'))) {
318 c -= 'A' - 10;
319 } else if (c == 'k' || c == 'K') {
320 sign *= 1024;
321 break;
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 {
329 return (STR);
330 }
331 if (c >= radix)
332 return (STR);
333 intval *= radix;
334 intval += c;
335 }
336 if (!issep(c) && !issep(*s))
337 return STR;
338 *val = intval * sign;
339 return (NUM);
340 }
341 *val = 1;
342 return (NUM);
343}
344
345boolean_t
346PE_imgsrc_mount_supported()
347{
348 return TRUE;
349}
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}
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}