1: /* This file contains a collection of miscellaneous procedures: 2: * mem_init: initialize memory tables. 3: * env_parse parse environment variable. 4: * bad_assertion for debugging 5: * bad_compare for debugging 6: */ 7: 8: #include "kernel.h" 9: #include "assert.h" 10: #include <stdlib.h> 11: #include <minix/com.h> 12: 13: #if (CHIP == INTEL) 14: 15: /* In real mode only 1M can be addressed, and in 16-bit protected we can go 16: * no further than we can count in clicks. (The 286 is further limited by 17: * its 24 bit address bus, but we can assume in that case that no more than 18: * 16M memory is reported by the BIOS.) 19: */ 20: #define MAX_REAL 0x00100000L 21: #define MAX_16BIT (0xFFF0L << CLICK_SHIFT) 22: 23: /*=========================================================================* 24: * mem_init * 25: *=========================================================================*/ 26: PUBLIC void mem_init() 27: { 28: /* Initialize the free memory list from the 'memory' boot variable. Translate 29: * the byte offsets and sizes in this list to clicks, properly truncated. Also 30: * make sure that we don't exceed the maximum address space of the 286 or the 31: * 8086, i.e. when running in 16-bit protected mode or real mode. 32: */ 33: long base, size, limit; 34: static char env[] = "memory"; 35: static char fmt[] = "x:x,\4"; 36: int i; 37: struct memory *memp; 38: #if _WORD_SIZE == 2 39: unsigned long max_address; 40: #endif 41: 42: tot_mem_size = 0; 43: for (i = 0; i < NR_MEMS; i++) { 44: memp = &mem[i]; 45: base = size = 0; 46: env_parse(env, fmt, 2*i+0, &base, 0L, LONG_MAX); 47: env_parse(env, fmt, 2*i+1, &size, 0L, LONG_MAX); 48: limit = base + size; 49: #if _WORD_SIZE == 2 50: max_address = protected_mode ? MAX_16BIT : MAX_REAL; 51: if (limit > max_address) limit = max_address; 52: #endif 53: base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1); 54: limit &= ~(long)(CLICK_SIZE-1); 55: if (limit <= base) continue; 56: memp->base = base >> CLICK_SHIFT; 57: memp->size = (limit - base) >> CLICK_SHIFT; 58: tot_mem_size += memp->size; 59: } 60: } 61: #endif /* (CHIP == INTEL) */ 62: 63: PRIVATE char PUNCT[] = ":,;."; 64: 65: /*=========================================================================* 66: * env_parse * 67: *=========================================================================*/ 68: PUBLIC int env_parse(env, fmt, field, param, min, max) 69: char *env; /* environment variable to inspect */ 70: char *fmt; /* template to parse it with */ 71: int field; /* field number of value to return */ 72: long *param; /* address of parameter to get */ 73: long min, max; /* minimum and maximum values for the parameter */ 74: { 75: /* Parse an environment variable setting, something like "DPETH0=300:3". 76: * Panic if the parsing fails. Return EP_UNSET if the environment variable 77: * is not set, EP_OFF if it is set to "off", EP_ON if set to "on" or a 78: * field is left blank, or EP_SET if a field is given (return value through 79: * *param). Punctuation may be used in the environment and format string, 80: * fields in the environment string may be empty, and punctuation may be 81: * missing to skip fields. The format string contains characters 'd', 'o', 82: * 'x' and 'c' to indicate that 10, 8, 16, or 0 is used as the last argument 83: * to strtol(). A '*' means that a field should be skipped. If the format 84: * string contains something like "\4" then the string is repeated 4 characters 85: * to the left. 86: */ 87: 88: char *val, *end; 89: long newpar; 90: int i = 0, radix, r; 91: 92: if ((val = getenv(env)) == NIL_PTR) return(EP_UNSET); 93: if (strcmp(val, "off") == 0) return(EP_OFF); 94: if (strcmp(val, "on") == 0) return(EP_ON); 95: 96: r = EP_ON; 97: for (;;) { 98: while (*val == ' ') val++; 99: 100: if (*val == 0) return(r); /* the proper exit point */ 101: 102: if (*fmt == 0) break; /* too many values */ 103: 104: if (strchr(PUNCT, *val) != NULL) { 105: /* Time to go to the next field. */ 106: if (strchr(PUNCT, *fmt) != NULL) i++; 107: if (*fmt++ == *val) val++; 108: if (*fmt < 32) fmt -= *fmt; /* step back? */ 109: } else { 110: /* Environment contains a value, get it. */ 111: switch (*fmt) { 112: case '*': radix = -1; break; 113: case 'd': radix = 10; break; 114: case 'o': radix = 010; break; 115: case 'x': radix = 0x10; break; 116: case 'c': radix = 0; break; 117: default: goto badenv; 118: } 119: 120: if (radix < 0) { 121: /* Skip. */ 122: while (strchr(PUNCT, *val) == NULL) val++; 123: continue; 124: } else { 125: /* A number. */ 126: newpar = strtol(val, &end, radix); 127: 128: if (end == val) break; /* not a number */ 129: val = end; 130: } 131: 132: if (i == field) { 133: /* The field requested. */ 134: if (newpar < min || newpar > max) break; 135: *param = newpar; 136: r = EP_SET; 137: } 138: } 139: } 140: badenv: 141: env_panic(env); 142: } 143: 144: /*=========================================================================* 145: * env_panic * 146: *=========================================================================*/ 147: PUBLIC void env_panic(env) 148: char *env; /* environment variable whose value is bogus */ 149: { 150: printf("Bad environment setting: '%s = %s'\n", env, getenv(env)); 151: panic("", NO_NUM); 152: /*NOTREACHED*/ 153: } 154: 155: /*=========================================================================* 156: * env_prefix * 157: *=========================================================================*/ 158: PUBLIC int env_prefix(env, prefix) 159: char *env; /* environment variable to inspect */ 160: char *prefix; /* prefix to test for */ 161: { 162: /* An environment setting may be prefixed by a word, usually "pci". Return 163: * true if a given prefix is used. 164: */ 165: char *val; 166: size_t n; 167: 168: val = getenv(env); 169: n = strlen(prefix); 170: return(val != NIL_PTR 171: && strncmp(val, prefix, n) == 0 172: && strchr(PUNCT, val[n]) != NULL); 173: } 174: 175: #if !NDEBUG 176: /*=========================================================================* 177: * bad_assertion * 178: *=========================================================================*/ 179: PUBLIC void bad_assertion(file, line, what) 180: char *file; 181: int line; 182: char *what; 183: { 184: printf("panic at %s(%d): assertion \"%s\" failed\n", file, line, what); 185: panic(NULL, NO_NUM); 186: } 187: 188: /*=========================================================================* 189: * bad_compare * 190: *=========================================================================*/ 191: PUBLIC void bad_compare(file, line, lhs, what, rhs) 192: char *file; 193: int line; 194: int lhs; 195: char *what; 196: int rhs; 197: { 198: printf("panic at %s(%d): compare (%d) %s (%d) failed\n", 199: file, line, lhs, what, rhs); 200: panic(NULL, NO_NUM); 201: } 202: #endif /* !NDEBUG */