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 31static boolean_t isargsep( char c); 32#if !CONFIG_EMBEDDED 33static int argstrcpy(char *from, char *to); 34#endif 35static int argstrcpy2(char *from,char *to, unsigned maxlen); 36static int argnumcpy(int val, void *to, unsigned maxlen); 37static int getval(char *s, int *val); 38 39extern int IODTGetDefault(const char *key, void *infoAddr, unsigned int infoSize); 40 41 42struct 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__) 51boolean_t 52PE_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 67boolean_t 68PE_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 } 146gotit: 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 157static boolean_t 158isargsep( 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 168static int 169argstrcpy( 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 184static int 185argstrcpy2( 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 200static 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 226static int 227getval( 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 310boolean_t 311PE_imgsrc_mount_supported() 312{ 313 return TRUE; 314} 315 316boolean_t 317PE_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} 357