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); 32static int argstrcpy(char *from, char *to); 33static int argstrcpy2(char *from,char *to, unsigned maxlen); 34static int argnumcpy(int val, void *to, unsigned maxlen); 35static int getval(char *s, int *val); 36 37extern int IODTGetDefault(const char *key, void *infoAddr, unsigned int infoSize); 38 39 40struct 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__) 49boolean_t 50PE_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 61boolean_t 62PE_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 } 135gotit: 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 146static boolean_t 147isargsep( 148 char c) 149{ 150 if (c == ' ' || c == '\0' || c == '\t') 151 return(TRUE); 152 else 153 return(FALSE); 154} 155 156static int 157argstrcpy( 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 171static int 172argstrcpy2( 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 187static 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 213static int 214getval( 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 297boolean_t 298PE_imgsrc_mount_supported() 299{ 300 return TRUE; 301} 302 303boolean_t 304PE_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} 344