]> git.saurik.com Git - apple/xnu.git/blob - pexpert/gen/bootargs.c
c5efead48273faaf190fecdbd5ff09dff00f54d9
[apple/xnu.git] / pexpert / gen / bootargs.c
1 /*
2 * Copyright (c) 2000-2008 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
31 typedef boolean_t (*argsep_func_t) (char c);
32
33 static boolean_t isargsep( char c);
34 static boolean_t israngesep( char c);
35 static int argstrcpy(char *from, char *to);
36 static int argstrcpy2(char *from,char *to, unsigned maxlen);
37 static int argnumcpy(long long val, void *to, unsigned maxlen);
38 static int getval(char *s, long long *val, argsep_func_t issep, boolean_t skip_equal_sign);
39 boolean_t get_range_bounds(char * c, int64_t * lower, int64_t * upper);
40
41 extern int IODTGetDefault(const char *key, void *infoAddr, unsigned int infoSize);
42
43
44 struct 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__)
53 boolean_t
54 PE_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
65 boolean_t
66 PE_parse_boot_argn(
67 const char *arg_string,
68 void *arg_ptr,
69 int max_len)
70 {
71 char *args;
72 char *cp, c;
73 uintptr_t i;
74 long long val;
75 boolean_t arg_boolean;
76 boolean_t arg_found;
77
78 args = PE_boot_args();
79 if (*args == '\0') return FALSE;
80
81
82 arg_found = FALSE;
83
84 while(*args && isargsep(*args)) args++;
85
86 while (*args)
87 {
88 if (*args == '-')
89 arg_boolean = TRUE;
90 else
91 arg_boolean = FALSE;
92
93 cp = args;
94 while (!isargsep (*cp) && *cp != '=')
95 cp++;
96 if (*cp != '=' && !arg_boolean)
97 goto gotit;
98
99 c = *cp;
100
101 i = cp-args;
102 if (strncmp(args, arg_string, i) ||
103 (i!=strlen(arg_string)))
104 goto gotit;
105 if (arg_boolean) {
106 argnumcpy(1, arg_ptr, max_len);
107 arg_found = TRUE;
108 break;
109 } else {
110 while (*cp && isargsep (*cp))
111 cp++;
112 if (*cp == '=' && c != '=') {
113 args = cp+1;
114 goto gotit;
115 }
116 if ('_' == *arg_string) /* Force a string copy if the argument name begins with an underscore */
117 {
118 int hacklen = 17 > max_len ? 17 : max_len;
119 argstrcpy2 (++cp, (char *)arg_ptr, hacklen - 1); /* Hack - terminate after 16 characters */
120 arg_found = TRUE;
121 break;
122 }
123 switch (getval(cp, &val, isargsep, FALSE))
124 {
125 case NUM:
126 argnumcpy(val, arg_ptr, max_len);
127 arg_found = TRUE;
128 break;
129 case STR:
130 if(max_len > 0) //max_len of 0 performs no copy at all
131 argstrcpy2(++cp, (char *)arg_ptr, max_len - 1);
132 else if(max_len == -1) // unreachable on embedded
133 argstrcpy(++cp, (char *)arg_ptr);
134 arg_found = TRUE;
135 break;
136 }
137 goto gotit;
138 }
139 gotit:
140 /* Skip over current arg */
141 while(!isargsep(*args)) args++;
142
143 /* Skip leading white space (catch end of args) */
144 while(*args && isargsep(*args)) args++;
145 }
146
147 return(arg_found);
148 }
149
150 static boolean_t
151 isargsep(char c)
152 {
153 if (c == ' ' || c == '\0' || c == '\t')
154 return (TRUE);
155 else
156 return (FALSE);
157 }
158
159 static boolean_t
160 israngesep(char c)
161 {
162 if (isargsep(c) || c == '_' || c == ',')
163 return (TRUE);
164 else
165 return (FALSE);
166 }
167
168 static int
169 argstrcpy(
170 char *from,
171 char *to)
172 {
173 int i = 0;
174
175 while (!isargsep(*from)) {
176 i++;
177 *to++ = *from++;
178 }
179 *to = 0;
180 return(i);
181 }
182
183 static int
184 argstrcpy2(
185 char *from,
186 char *to,
187 unsigned maxlen)
188 {
189 unsigned int i = 0;
190
191 while (!isargsep(*from) && i < maxlen) {
192 i++;
193 *to++ = *from++;
194 }
195 *to = 0;
196 return(i);
197 }
198
199 static int argnumcpy(long long val, void *to, unsigned maxlen)
200 {
201 switch (maxlen) {
202 case 0:
203 /* No write-back, caller just wants to know if arg was found */
204 break;
205 case 1:
206 *(int8_t *)to = val;
207 break;
208 case 2:
209 *(int16_t *)to = val;
210 break;
211 case 3:
212 /* Unlikely in practice */
213 ((struct i24 *)to)->i24 = val;
214 break;
215 case 4:
216 *(int32_t *)to = val;
217 break;
218 case 8:
219 *(int64_t *)to = val;
220 break;
221 default:
222 *(int32_t *)to = val;
223 maxlen = 4;
224 break;
225 }
226
227 return (int)maxlen;
228 }
229
230 static int
231 getval(
232 char *s,
233 long long *val,
234 argsep_func_t issep,
235 boolean_t skip_equal_sign )
236 {
237 unsigned long long radix, intval;
238 unsigned char c;
239 int sign = 1;
240 boolean_t has_value = FALSE;
241
242 if (*s == '=') {
243 s++;
244 has_value = TRUE;
245 }
246
247 if (has_value || skip_equal_sign) {
248 if (*s == '-')
249 sign = -1, s++;
250 intval = *s++-'0';
251 radix = 10;
252 if (intval == 0) {
253 switch(*s) {
254
255 case 'x':
256 radix = 16;
257 s++;
258 break;
259
260 case 'b':
261 radix = 2;
262 s++;
263 break;
264
265 case '0': case '1': case '2': case '3':
266 case '4': case '5': case '6': case '7':
267 intval = *s-'0';
268 s++;
269 radix = 8;
270 break;
271
272 default:
273 if (!issep(*s))
274 return (STR);
275 }
276 } else if (intval >= radix) {
277 return (STR);
278 }
279 for(;;) {
280 c = *s++;
281 if (issep(c))
282 break;
283 if ((radix <= 10) &&
284 ((c >= '0') && (c <= ('9' - (10 - radix))))) {
285 c -= '0';
286 } else if ((radix == 16) &&
287 ((c >= '0') && (c <= '9'))) {
288 c -= '0';
289 } else if ((radix == 16) &&
290 ((c >= 'a') && (c <= 'f'))) {
291 c -= 'a' - 10;
292 } else if ((radix == 16) &&
293 ((c >= 'A') && (c <= 'F'))) {
294 c -= 'A' - 10;
295 } else if (c == 'k' || c == 'K') {
296 sign *= 1024;
297 break;
298 } else if (c == 'm' || c == 'M') {
299 sign *= 1024 * 1024;
300 break;
301 } else if (c == 'g' || c == 'G') {
302 sign *= 1024 * 1024 * 1024;
303 break;
304 } else {
305 return (STR);
306 }
307 if (c >= radix)
308 return (STR);
309 intval *= radix;
310 intval += c;
311 }
312 if (!issep(c) && !issep(*s))
313 return STR;
314 *val = intval * sign;
315 return (NUM);
316 }
317 *val = 1;
318 return (NUM);
319 }
320
321 boolean_t
322 PE_imgsrc_mount_supported()
323 {
324 return TRUE;
325 }
326
327 boolean_t
328 PE_get_default(
329 const char *property_name,
330 void *property_ptr,
331 unsigned int max_property)
332 {
333 DTEntry dte;
334 void **property_data;
335 unsigned int property_size;
336
337 /*
338 * Look for the property using the PE DT support.
339 */
340 if (kSuccess == DTLookupEntry(NULL, "/defaults", &dte)) {
341
342 /*
343 * We have a /defaults node, look for the named property.
344 */
345 if (kSuccess != DTGetProperty(dte, property_name, (void **)&property_data, &property_size))
346 return FALSE;
347
348 /*
349 * This would be a fine place to do smart argument size management for 32/64
350 * translation, but for now we'll insist that callers know how big their
351 * default values are.
352 */
353 if (property_size > max_property)
354 return FALSE;
355
356 /*
357 * Copy back the precisely-sized result.
358 */
359 memcpy(property_ptr, property_data, property_size);
360 return TRUE;
361 }
362
363 /*
364 * Look for the property using I/O Kit's DT support.
365 */
366 return IODTGetDefault(property_name, property_ptr, max_property) ? FALSE : TRUE;
367 }
368
369 /* function: get_range_bounds
370 * Parse a range string like "1_3,5_20" and return 1,3 as lower and upper.
371 * Note: '_' is separator for bounds integer delimiter and
372 * ',' is considered as separator for range pair.
373 * returns TRUE when both range values are found
374 */
375 boolean_t
376 get_range_bounds(char *c, int64_t *lower, int64_t *upper)
377 {
378 if (c == NULL || lower == NULL || upper == NULL) {
379 return FALSE;
380 }
381
382 if (NUM != getval(c, lower, israngesep, TRUE)) {
383 return FALSE;
384 }
385
386 while (*c != '\0') {
387 if (*c == '_') {
388 break;
389 }
390 c++;
391 }
392
393 if (*c == '_') {
394 c++;
395 if (NUM != getval(c, upper, israngesep, TRUE)) {
396 return FALSE;
397 }
398 } else {
399 return FALSE;
400 }
401 return TRUE;
402 }