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 */