X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/21362eb3e66fd2c787aee132bce100a44d71a99c..e8c3f78193f1895ea514044358b93b1add9322f3:/pexpert/gen/bootargs.c?ds=sidebyside diff --git a/pexpert/gen/bootargs.c b/pexpert/gen/bootargs.c index 73b65b997..754513a5c 100644 --- a/pexpert/gen/bootargs.c +++ b/pexpert/gen/bootargs.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2016 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 @@ -11,10 +11,10 @@ * 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, @@ -22,49 +22,80 @@ * 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 + +typedef boolean_t (*argsep_func_t) (char c); + +static boolean_t isargsep( char c); +static boolean_t israngesep( char c); +#ifndef CONFIG_EMBEDDED +static int argstrcpy(char *from, char *to); +#endif +static int argstrcpy2(char *from,char *to, unsigned maxlen); +static int argnumcpy(long long val, void *to, unsigned maxlen); +static int getval(char *s, long long *val, argsep_func_t issep, boolean_t skip_equal_sign); +boolean_t get_range_bounds(char * c, int64_t * lower, int64_t * upper); -extern boolean_t isargsep( char c); -extern int argstrcpy(char *from, char *to); -extern 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 -boolean_t +#if !defined(__LP64__) && !defined(__arm__) +boolean_t PE_parse_boot_arg( const char *arg_string, void *arg_ptr) { - return PE_parse_boot_argn(arg_string, arg_ptr, -1); + 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) +static boolean_t +PE_parse_boot_argn_internal( + const char *arg_string, + void * arg_ptr, + int max_len, + boolean_t force_string) { char *args; char *cp, c; - int i; - int val; + uintptr_t i; + long long val = 0; boolean_t arg_boolean; boolean_t arg_found; args = PE_boot_args(); if (*args == '\0') return FALSE; +#ifdef CONFIG_EMBEDDED + if (max_len == -1) return FALSE; +#endif + arg_found = FALSE; - while(isargsep(*args)) args++; + while(*args && isargsep(*args)) args++; while (*args) { - if (*args == '-') + if (*args == '-') arg_boolean = TRUE; else arg_boolean = FALSE; @@ -81,12 +112,20 @@ PE_parse_boot_argn( if (strncmp(args, arg_string, i) || (i!=strlen(arg_string))) goto gotit; + if (arg_boolean) { - *(unsigned int *)arg_ptr = TRUE; - arg_found = TRUE; + if (!force_string) { + if (max_len > 0) { + argnumcpy(1, arg_ptr, max_len);/* max_len of 0 performs no copy at all*/ + arg_found = TRUE; + } + else if (max_len == 0) { + arg_found = TRUE; + } + } break; } else { - while (isargsep (*cp)) + while (*cp && isargsep (*cp)) cp++; if (*cp == '=' && c != '=') { args = cp+1; @@ -94,23 +133,41 @@ PE_parse_boot_argn( } if ('_' == *arg_string) /* Force a string copy if the argument name begins with an underscore */ { - int hacklen = 16 > max_len ? 16 : max_len; - argstrcpy2 (++cp, (char *)arg_ptr, hacklen); /* Hack - terminate after 16 characters */ - arg_found = TRUE; + if (max_len > 0) { + int hacklen = 17 > max_len ? 17 : max_len; + argstrcpy2 (++cp, (char *)arg_ptr, hacklen - 1); /* Hack - terminate after 16 characters */ + arg_found = TRUE; + } + else if (max_len == 0) { + arg_found = TRUE; + } break; } - switch (getval(cp, &val)) + switch ((force_string && *cp == '=') ? STR : getval(cp, &val, isargsep, FALSE)) { case NUM: - *(unsigned int *)arg_ptr = val; - arg_found = TRUE; + if (max_len > 0) { + argnumcpy(val, arg_ptr, max_len); + arg_found = TRUE; + } + else if (max_len == 0) { + 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); - else if(max_len == -1) + if (max_len > 0) { + argstrcpy2(++cp, (char *)arg_ptr, max_len - 1);/*max_len of 0 performs no copy at all*/ + arg_found = TRUE; + } + else if (max_len == 0) { + arg_found = TRUE; + } +#if !CONFIG_EMBEDDED + else if (max_len == -1) { /* unreachable on embedded */ argstrcpy(++cp, (char *)arg_ptr); - arg_found = TRUE; + arg_found = TRUE; + } +#endif break; } goto gotit; @@ -126,18 +183,46 @@ gotit: return(arg_found); } -boolean_t isargsep( - char c) +boolean_t +PE_parse_boot_argn( + const char *arg_string, + void *arg_ptr, + int max_len) +{ + return PE_parse_boot_argn_internal(arg_string, arg_ptr, max_len, FALSE); +} + +boolean_t +PE_parse_boot_arg_str( + const char *arg_string, + char *arg_ptr, + int strlen) +{ + return PE_parse_boot_argn_internal(arg_string, arg_ptr, strlen, TRUE); +} + +static boolean_t +isargsep(char c) { if (c == ' ' || c == '\0' || c == '\t') - return(TRUE); + return (TRUE); else - return(FALSE); + return (FALSE); } -int +static boolean_t +israngesep(char c) +{ + if (isargsep(c) || c == '_' || c == ',') + return (TRUE); + else + return (FALSE); +} + +#if !CONFIG_EMBEDDED +static int argstrcpy( - char *from, + char *from, char *to) { int i = 0; @@ -149,14 +234,15 @@ argstrcpy( *to = 0; return(i); } +#endif -int +static int argstrcpy2( - char *from, + char *from, char *to, unsigned maxlen) { - int i = 0; + unsigned int i = 0; while (!isargsep(*from) && i < maxlen) { i++; @@ -166,22 +252,62 @@ argstrcpy2( return(i); } -int +static int argnumcpy(long long 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: + *(int32_t *)to = val; + break; + case 8: + *(int64_t *)to = val; + break; + default: + *(int32_t *)to = val; + maxlen = 4; + break; + } + + return (int)maxlen; +} + +static int getval( - char *s, - int *val) + char *s, + long long *val, + argsep_func_t issep, + boolean_t skip_equal_sign ) { - register unsigned radix, intval; - register unsigned char c; + unsigned long long radix, intval; + unsigned char c; int sign = 1; + boolean_t has_value = FALSE; if (*s == '=') { s++; - if (*s == '-') - sign = -1, s++; + has_value = TRUE; + } + + if (has_value || skip_equal_sign) { + if (*s == '-') { + sign = -1; + s++; + } intval = *s++-'0'; radix = 10; - if (intval == 0) + if (intval == 0) { switch(*s) { case 'x': @@ -202,34 +328,133 @@ getval( break; default: - if (!isargsep(*s)) + if (!issep(*s)) return (STR); } + } else if (intval >= radix) { + return (STR); + } for(;;) { - if (((c = *s++) >= '0') && (c <= '9')) + c = *s++; + if (issep(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 ((c >= 'a') && (c <= 'f')) + } else if ((radix == 16) && + ((c >= 'a') && (c <= 'f'))) { c -= 'a' - 10; - else if ((c >= 'A') && (c <= 'F')) + } 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 if (isargsep(c)) + } else if (c == 'k' || c == 'K') { + sign *= 1024; break; - else + } 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 (!issep(c) && !issep(*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; +} + +/* function: get_range_bounds + * Parse a range string like "1_3,5_20" and return 1,3 as lower and upper. + * Note: '_' is separator for bounds integer delimiter and + * ',' is considered as separator for range pair. + * returns TRUE when both range values are found + */ +boolean_t +get_range_bounds(char *c, int64_t *lower, int64_t *upper) +{ + if (c == NULL || lower == NULL || upper == NULL) { + return FALSE; + } + + if (NUM != getval(c, lower, israngesep, TRUE)) { + return FALSE; + } + + while (*c != '\0') { + if (*c == '_') { + break; + } + c++; + } + + if (*c == '_') { + c++; + if (NUM != getval(c, upper, israngesep, TRUE)) { + return FALSE; + } + } else { + return FALSE; + } + return TRUE; +}