]> git.saurik.com Git - apple/xnu.git/blob - pexpert/gen/bootargs.c
6ca4fa102ab25a9afd0e105f5dba9ef944c56139
[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 struct i24 {
42 int32_t i24 : 24;
43 int32_t _pad : 8;
44 };
45
46 #define NUM 0
47 #define STR 1
48
49 #if !defined(__LP64__) && !defined(__arm__)
50 boolean_t
51 PE_parse_boot_arg(
52 const char *arg_string,
53 void *arg_ptr)
54 {
55 int max_len = -1;
56
57 #if CONFIG_EMBEDDED
58 /* Limit arg size to 4 byte when no size is given */
59 max_len = 4;
60 #endif
61
62 return PE_parse_boot_argn(arg_string, arg_ptr, max_len);
63 }
64 #endif
65
66 boolean_t
67 PE_parse_boot_argn(
68 const char *arg_string,
69 void *arg_ptr,
70 int max_len)
71 {
72 char *args;
73 char *cp, c;
74 unsigned int i;
75 int val;
76 boolean_t arg_boolean;
77 boolean_t arg_found;
78
79 args = PE_boot_args();
80 if (*args == '\0') return FALSE;
81
82 #if CONFIG_EMBEDDED
83 if (max_len == -1) return FALSE;
84 #endif
85
86 arg_found = FALSE;
87
88 while(*args && isargsep(*args)) args++;
89
90 while (*args)
91 {
92 if (*args == '-')
93 arg_boolean = TRUE;
94 else
95 arg_boolean = FALSE;
96
97 cp = args;
98 while (!isargsep (*cp) && *cp != '=')
99 cp++;
100 if (*cp != '=' && !arg_boolean)
101 goto gotit;
102
103 c = *cp;
104
105 i = cp-args;
106 if (strncmp(args, arg_string, i) ||
107 (i!=strlen(arg_string)))
108 goto gotit;
109 if (arg_boolean) {
110 argnumcpy(1, arg_ptr, max_len);
111 arg_found = TRUE;
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 (getval(cp, &val))
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 #if !CONFIG_EMBEDDED
137 else if(max_len == -1) // unreachable on embedded
138 argstrcpy(++cp, (char *)arg_ptr);
139 #endif
140 arg_found = TRUE;
141 break;
142 }
143 goto gotit;
144 }
145 gotit:
146 /* Skip over current arg */
147 while(!isargsep(*args)) args++;
148
149 /* Skip leading white space (catch end of args) */
150 while(*args && isargsep(*args)) args++;
151 }
152
153 return(arg_found);
154 }
155
156 static boolean_t
157 isargsep(
158 char c)
159 {
160 if (c == ' ' || c == '\0' || c == '\t')
161 return(TRUE);
162 else
163 return(FALSE);
164 }
165
166 #if !CONFIG_EMBEDDED
167 static int
168 argstrcpy(
169 char *from,
170 char *to)
171 {
172 int i = 0;
173
174 while (!isargsep(*from)) {
175 i++;
176 *to++ = *from++;
177 }
178 *to = 0;
179 return(i);
180 }
181 #endif
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(int 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 default:
217 *(int32_t *)to = val;
218 maxlen = 4;
219 break;
220 }
221
222 return (int)maxlen;
223 }
224
225 static int
226 getval(
227 char *s,
228 int *val)
229 {
230 unsigned int radix, intval;
231 unsigned char c;
232 int sign = 1;
233
234 if (*s == '=') {
235 s++;
236 if (*s == '-')
237 sign = -1, s++;
238 intval = *s++-'0';
239 radix = 10;
240 if (intval == 0) {
241 switch(*s) {
242
243 case 'x':
244 radix = 16;
245 s++;
246 break;
247
248 case 'b':
249 radix = 2;
250 s++;
251 break;
252
253 case '0': case '1': case '2': case '3':
254 case '4': case '5': case '6': case '7':
255 intval = *s-'0';
256 s++;
257 radix = 8;
258 break;
259
260 default:
261 if (!isargsep(*s))
262 return (STR);
263 }
264 } else if (intval >= radix) {
265 return (STR);
266 }
267 for(;;) {
268 c = *s++;
269 if (isargsep(c))
270 break;
271 if ((radix <= 10) &&
272 ((c >= '0') && (c <= ('9' - (10 - radix))))) {
273 c -= '0';
274 } else if ((radix == 16) &&
275 ((c >= '0') && (c <= '9'))) {
276 c -= '0';
277 } else if ((radix == 16) &&
278 ((c >= 'a') && (c <= 'f'))) {
279 c -= 'a' - 10;
280 } else if ((radix == 16) &&
281 ((c >= 'A') && (c <= 'F'))) {
282 c -= 'A' - 10;
283 } else if (c == 'k' || c == 'K') {
284 sign *= 1024;
285 break;
286 } else if (c == 'm' || c == 'M') {
287 sign *= 1024 * 1024;
288 break;
289 } else if (c == 'g' || c == 'G') {
290 sign *= 1024 * 1024 * 1024;
291 break;
292 } else {
293 return (STR);
294 }
295 if (c >= radix)
296 return (STR);
297 intval *= radix;
298 intval += c;
299 }
300 if (!isargsep(c) && !isargsep(*s))
301 return STR;
302 *val = intval * sign;
303 return (NUM);
304 }
305 *val = 1;
306 return (NUM);
307 }
308
309 boolean_t
310 PE_imgsrc_mount_supported()
311 {
312 return TRUE;
313 }
314
315 boolean_t
316 PE_get_default(
317 const char *property_name,
318 void *property_ptr,
319 unsigned int max_property)
320 {
321 DTEntry dte;
322 void **property_data;
323 unsigned int property_size;
324
325 /*
326 * Look for the property using the PE DT support.
327 */
328 if (kSuccess == DTLookupEntry(NULL, "/defaults", &dte)) {
329
330 /*
331 * We have a /defaults node, look for the named property.
332 */
333 if (kSuccess != DTGetProperty(dte, property_name, (void **)&property_data, &property_size))
334 return FALSE;
335
336 /*
337 * This would be a fine place to do smart argument size management for 32/64
338 * translation, but for now we'll insist that callers know how big their
339 * default values are.
340 */
341 if (property_size > max_property)
342 return FALSE;
343
344 /*
345 * Copy back the precisely-sized result.
346 */
347 memcpy(property_ptr, property_data, property_size);
348 return TRUE;
349 }
350
351 /*
352 * Look for the property using I/O Kit's DT support.
353 */
354 return IODTGetDefault(property_name, property_ptr, max_property) ? FALSE : TRUE;
355 }