/* * Copyright (c) 2000-2008 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #include #include static boolean_t isargsep( char c); #if !CONFIG_EMBEDDED static int argstrcpy(char *from, char *to); #endif static int argstrcpy2(char *from,char *to, unsigned maxlen); static int argnumcpy(int val, void *to, unsigned maxlen); static int getval(char *s, int *val); extern int IODTGetDefault(const char *key, void *infoAddr, unsigned int infoSize); struct i24 { int32_t i24 : 24; int32_t _pad : 8; }; #define NUM 0 #define STR 1 #if !defined(__LP64__) && !defined(__arm__) boolean_t PE_parse_boot_arg( const char *arg_string, void *arg_ptr) { int max_len = -1; #if CONFIG_EMBEDDED /* Limit arg size to 4 byte when no size is given */ max_len = 4; #endif return PE_parse_boot_argn(arg_string, arg_ptr, max_len); } #endif boolean_t PE_parse_boot_argn( const char *arg_string, void *arg_ptr, int max_len) { char *args; char *cp, c; uintptr_t i; int val; boolean_t arg_boolean; boolean_t arg_found; args = PE_boot_args(); if (*args == '\0') return FALSE; #if CONFIG_EMBEDDED if (max_len == -1) return FALSE; #endif arg_found = FALSE; while(*args && isargsep(*args)) args++; while (*args) { if (*args == '-') arg_boolean = TRUE; else arg_boolean = FALSE; cp = args; while (!isargsep (*cp) && *cp != '=') cp++; if (*cp != '=' && !arg_boolean) goto gotit; c = *cp; i = cp-args; if (strncmp(args, arg_string, i) || (i!=strlen(arg_string))) goto gotit; if (arg_boolean) { argnumcpy(1, arg_ptr, max_len); arg_found = TRUE; break; } else { while (*cp && isargsep (*cp)) cp++; if (*cp == '=' && c != '=') { args = cp+1; goto gotit; } if ('_' == *arg_string) /* Force a string copy if the argument name begins with an underscore */ { int hacklen = 17 > max_len ? 17 : max_len; argstrcpy2 (++cp, (char *)arg_ptr, hacklen - 1); /* Hack - terminate after 16 characters */ arg_found = TRUE; break; } switch (getval(cp, &val)) { case NUM: argnumcpy(val, arg_ptr, max_len); arg_found = TRUE; break; case STR: if(max_len > 0) //max_len of 0 performs no copy at all argstrcpy2(++cp, (char *)arg_ptr, max_len - 1); #if !CONFIG_EMBEDDED else if(max_len == -1) // unreachable on embedded argstrcpy(++cp, (char *)arg_ptr); #endif arg_found = TRUE; break; } goto gotit; } gotit: /* Skip over current arg */ while(!isargsep(*args)) args++; /* Skip leading white space (catch end of args) */ while(*args && isargsep(*args)) args++; } return(arg_found); } static boolean_t isargsep( char c) { if (c == ' ' || c == '\0' || c == '\t') return(TRUE); else return(FALSE); } #if !CONFIG_EMBEDDED static int argstrcpy( char *from, char *to) { int i = 0; while (!isargsep(*from)) { i++; *to++ = *from++; } *to = 0; return(i); } #endif static int argstrcpy2( char *from, char *to, unsigned maxlen) { unsigned int i = 0; while (!isargsep(*from) && i < maxlen) { i++; *to++ = *from++; } *to = 0; return(i); } static int argnumcpy(int val, void *to, unsigned maxlen) { switch (maxlen) { case 0: /* No write-back, caller just wants to know if arg was found */ break; case 1: *(int8_t *)to = val; break; case 2: *(int16_t *)to = val; break; case 3: /* Unlikely in practice */ ((struct i24 *)to)->i24 = val; break; case 4: default: *(int32_t *)to = val; maxlen = 4; break; } return (int)maxlen; } static int getval( char *s, int *val) { unsigned int radix, intval; unsigned char c; int sign = 1; if (*s == '=') { s++; if (*s == '-') sign = -1, s++; intval = *s++-'0'; radix = 10; if (intval == 0) { switch(*s) { case 'x': radix = 16; s++; break; case 'b': radix = 2; s++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': intval = *s-'0'; s++; radix = 8; break; default: if (!isargsep(*s)) return (STR); } } else if (intval >= radix) { return (STR); } for(;;) { c = *s++; if (isargsep(c)) break; if ((radix <= 10) && ((c >= '0') && (c <= ('9' - (10 - radix))))) { c -= '0'; } else if ((radix == 16) && ((c >= '0') && (c <= '9'))) { c -= '0'; } else if ((radix == 16) && ((c >= 'a') && (c <= 'f'))) { c -= 'a' - 10; } else if ((radix == 16) && ((c >= 'A') && (c <= 'F'))) { c -= 'A' - 10; } else if (c == 'k' || c == 'K') { sign *= 1024; break; } else if (c == 'm' || c == 'M') { sign *= 1024 * 1024; break; } else if (c == 'g' || c == 'G') { sign *= 1024 * 1024 * 1024; break; } else { return (STR); } if (c >= radix) return (STR); intval *= radix; intval += c; } if (!isargsep(c) && !isargsep(*s)) return STR; *val = intval * sign; return (NUM); } *val = 1; return (NUM); } boolean_t PE_imgsrc_mount_supported() { return TRUE; } boolean_t PE_get_default( const char *property_name, void *property_ptr, unsigned int max_property) { DTEntry dte; void **property_data; unsigned int property_size; /* * Look for the property using the PE DT support. */ if (kSuccess == DTLookupEntry(NULL, "/defaults", &dte)) { /* * We have a /defaults node, look for the named property. */ if (kSuccess != DTGetProperty(dte, property_name, (void **)&property_data, &property_size)) return FALSE; /* * This would be a fine place to do smart argument size management for 32/64 * translation, but for now we'll insist that callers know how big their * default values are. */ if (property_size > max_property) return FALSE; /* * Copy back the precisely-sized result. */ memcpy(property_ptr, property_data, property_size); return TRUE; } /* * Look for the property using I/O Kit's DT support. */ return IODTGetDefault(property_name, property_ptr, max_property) ? FALSE : TRUE; }