1: /* This file contains the main program of MINIX.  The routine main()
   2:  * initializes the system and starts the ball rolling by setting up the proc
   3:  * table, interrupt vectors, and scheduling each task to run to initialize
   4:  * itself.
   5:  *
   6:  * The entries into this file are:
   7:  *   main:              MINIX main program
   8:  *   panic:             abort MINIX due to a fatal error
   9:  */
  10: 
  11: #include "kernel.h"
  12: #include <signal.h>
  13: #include <unistd.h>
  14: #include <a.out.h>
  15: #include <minix/callnr.h>
  16: #include <minix/com.h>
  17: #include "proc.h"
  18: 
  19: 
  20: /*===========================================================================*
  21:  *                                   main                                    *
  22:  *===========================================================================*/
  23: PUBLIC void main()
  24: {
  25: /* Start the ball rolling. */
  26: 
  27:   register struct proc *rp;
  28:   register int t;
  29:   int hdrindex;
  30:   phys_clicks text_base;
  31:   vir_clicks text_clicks;
  32:   vir_clicks data_clicks;
  33:   reg_t ktsb;                   /* kernel task stack base */
  34:   struct memory *memp;
  35:   struct tasktab *ttp;
  36:   struct exec e_hdr;
  37: 
  38:   /* Initialize the interrupt controller. */
  39:   intr_init(1);
  40: 
  41:   /* Interpret memory sizes. */
  42:   mem_init();
  43: 
  44:   /* Clear the process table.
  45:    * Set up mappings for proc_addr() and proc_number() macros.
  46:    */
  47:   for (rp = BEG_PROC_ADDR, t = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++t) {
  48:         rp->p_nr = t;            /* proc number from ptr */
  49:         (pproc_addr + NR_TASKS)[t] = rp;        /* proc ptr from number */
  50:   }
  51: 
  52:   /* Resolve driver selections in the task table. */
  53:   mapdrivers();
  54: 
  55:   /* Set up proc table entries for tasks and servers.  The stacks of the
  56:    * kernel tasks are initialized to an array in data space.  The stacks
  57:    * of the servers have been added to the data segment by the monitor, so
  58:    * the stack pointer is set to the end of the data segment.  All the
  59:    * processes are in low memory on the 8086.  On the 386 only the kernel
  60:    * is in low memory, the rest is loaded in extended memory.
  61:    */
  62: 
  63:   /* Task stacks. */
  64:   ktsb = (reg_t) t_stack;
  65: 
  66:   for (t = -NR_TASKS; t <= LOW_USER; ++t) {
  67:         rp = proc_addr(t);                      /* t's process slot */
  68:         ttp = &tasktab[t + NR_TASKS];            /* t's task attributes */
  69:         strcpy(rp->p_name, ttp->name);
  70:         if (t < 0) {
  71:                 if (ttp->stksize > 0) {
  72:                         rp->p_stguard = (reg_t *) ktsb;
  73:                         *rp->p_stguard = STACK_GUARD;
  74:                 }
  75:                 ktsb += ttp->stksize;
  76:                 rp->p_reg.sp = ktsb;
  77:                 text_base = code_base >> CLICK_SHIFT;
  78:                                         /* tasks are all in the kernel */
  79:                 hdrindex = 0;           /* and use the first a.out header */
  80:                 rp->p_priority = PPRI_TASK;
  81:         } else {
  82:                 hdrindex = 1 + t;       /* MM, FS, INIT follow the kernel */
  83:                 rp->p_priority = t < LOW_USER ? PPRI_SERVER : PPRI_USER;
  84:         }
  85: 
  86:         /* The bootstrap loader has created an array of the a.out headers at
  87:          * absolute address 'aout'.
  88:          */
  89:         phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr),
  90:                                                         (phys_bytes) A_MINHDR);
  91:         text_base = e_hdr.a_syms >> CLICK_SHIFT;
  92:         text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
  93:         if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0;   /* Common I&D */
  94:         data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
  95:         rp->p_map[T].mem_phys = text_base;
  96:         rp->p_map[T].mem_len  = text_clicks;
  97:         rp->p_map[D].mem_phys = text_base + text_clicks;
  98:         rp->p_map[D].mem_len  = data_clicks;
  99:         rp->p_map[S].mem_phys = text_base + text_clicks + data_clicks;
 100:         rp->p_map[S].mem_vir  = data_clicks;     /* empty - stack is in data */
 101: 
 102:         /* Remove server memory from the free memory list.  The boot monitor
 103:          * promises to put processes at the start of memory chunks.
 104:          */
 105:         for (memp = mem; memp < &mem[NR_MEMS]; memp++) {
 106:                 if (memp->base == text_base) {
 107:                         memp->base += text_clicks + data_clicks;
 108:                         memp->size -= text_clicks + data_clicks;
 109:                 }
 110:         }
 111: 
 112:         /* Set initial register values. */
 113:         rp->p_reg.pc = (reg_t) ttp->initial_pc;
 114:         rp->p_reg.psw = istaskp(rp) ? INIT_TASK_PSW : INIT_PSW;
 115: 
 116:         if (t >= 0) {
 117:                 /* Initialize the server stack pointer.  Take it down one word
 118:                  * to give crtso.s something to use as "argc".
 119:                  */
 120:                 rp->p_reg.sp = (rp->p_map[S].mem_vir +
 121:                                 rp->p_map[S].mem_len) << CLICK_SHIFT;
 122:                 rp->p_reg.sp -= sizeof(reg_t);
 123:         }
 124: 
 125:         if (!isidlehardware(t)) lock_ready(rp); /* IDLE, HARDWARE neveready */
 126:         rp->p_flags = 0;
 127: 
 128:         alloc_segments(rp);
 129:   }
 130: 
 131:   proc[NR_TASKS+INIT_PROC_NR].p_pid = 1;/* INIT of course has pid 1 */
 132:   bill_ptr = proc_addr(IDLE);           /* it has to point somewhere */
 133:   proc_addr(IDLE)->p_priority = PPRI_IDLE;
 134:   lock_pick_proc();
 135: 
 136:   /* Now go to the assembly code to start running the current process. */
 137:   restart();
 138: }
 139: 
 140: 
 141: /*===========================================================================*
 142:  *                                   panic                                   *
 143:  *===========================================================================*/
 144: PUBLIC void panic(s,n)
 145: _CONST char *s;
 146: int n;
 147: {
 148: /* The system has run aground of a fatal error.  Terminate execution.
 149:  * If the panic originated in MM or FS, the string will be empty and the
 150:  * file system already syncked.  If the panic originates in the kernel, we are
 151:  * kind of stuck.
 152:  */
 153: 
 154:   if (s != NULL) {
 155:         printf("\nKernel panic: %s",s);
 156:         if (n != NO_NUM) printf(" %d", n);
 157:         printf("\n");
 158:   }
 159:   wreboot(RBT_PANIC);
 160: }