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