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