~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Minix Cross Reference
Minix/Solaris/minix.c


  1 static char *rcsid = "$Id: minix.c,v 1.4 1996/07/09 04:47:04 paul Exp $";
  2 
  3 /*
  4  * This program is responsible for booting Solaris Minix. The
  5  * code in config.c is resposible for reading the configuration file
  6  * and setting up all smx devices.  The code in minix_load.c is
  7  * responsible for loading Minix executable programs into smx
  8  * "physical" memory.  The code in this file coordinates the whole process.
  9  *
 10  * Two processes are involved in running smx.  The parent process (the one
 11  * that starts by running main) forks off the child, and it is the
 12  * child that actually becomes smx.  When the child exits, the parent
 13  * is there to cleanup.
 14  *
 15  * The bootstrapping process involves reading the configuration file,
 16  * establishing all smx devices, allocating the "physical" memory for smx,
 17  * loading four programs from the Minix image file (kernel, mm, fs, init)
 18  * into this memory, then switching execution into smx.
 19  */
 20                                              
 21 #include <stdio.h>
 22 #include <stdlib.h>
 23 #include <malloc.h>
 24 #include <signal.h>
 25 #include <unistd.h>
 26 #include <fcntl.h>
 27 #include <sys/wait.h>
 28 #include <sys/param.h>
 29 #include <sys/types.h>
 30 
 31 #include "../../include/minix/config.h"
 32 #undef HZ                       /* Defined again in minix/const.h */
 33 #undef NULL                     /* Defined again in minix/const.h */
 34 #include "../../include/minix/const.h"
 35 #include "../kernel/const.h"   /* Need RAM_FD */
 36 typedef unsigned char u8_t;
 37 typedef unsigned short u16_t, U16_t;
 38 #include "../../include/net/gen/ether.h"
 39 #include "../kernel/bootinfo.h"
 40 
 41 #undef PRIVATE                    /* Defined in <sys/mman.h? */
 42 #undef printf
 43 
 44 #include <sys/mman.h>
 45 
 46 
 47 #include "config.h"
 48 #include "minix_load.h"
 49 
 50 #define DEF_MEM_SIZE    3072    /* default number of kbytes of smx memory */
 51 #define DEF_PROTECT     1       /* default protection level */
 52 
 53 #define USAGE "%s [-d] [-m (none|half|full)] [config-file]\n"
 54 
 55 
 56 char *progname;
 57 static int debug = 0;      /* Used in this program, and propagated to smx */
 58 
 59 /*
 60  * Local functions.
 61  */
 62 static struct smx_bootinfo *load_image(const char *imagefile, long core_size);
 63 static void allocate_memory(unsigned long memory_base, long ram_size);
 64 
 65 static void smx_parent(void);
 66 
 67 static void usage(void);
 68 
 69 
 70 /*
 71  * Function: main
 72  * Parameters: argc, argv - command line argument summary appears in the USAGE
 73  *                          string
 74  *
 75  * The main function begins by processing the command line arguments.
 76  * It then calls config to have the configuration file read and
 77  * the smx devices opened.  It then calls fork, with the parent
 78  * waiting to clean up after smx and the child loading the four initial
 79  * programs and jumping inside smx.
 80  */
 81 int main(int argc, char *argv[])
 82 {
 83     char image_name[MAXPATHLEN];
 84     int protect, configdebug, configprotect;
 85     long core_size;                     /* how much memory is allocated */
 86     char *config_file;
 87     struct smx_bootinfo *bootp;         /* this will actually be part of the */
 88                                         /* kernel's data segment */
 89     ether_addr_t eaddr = { {0} };       /* all 0s means disabled */
 90 
 91     progname = argv[0];
 92 
 93     /*
 94      * Check that the click size is a multiple of the pagesize - otherwise
 95      * protection of segments using mprotect(2) will fail.
 96      */
 97     if (CLICK_SIZE % sysconf(_SC_PAGESIZE) != 0) {
 98         (void) fprintf(stderr,
 99     "%s: Minix aborted - clicksize (%d) is not a multiple of pagesize (%ld)\n",
100                        progname, CLICK_SIZE, sysconf(_SC_PAGESIZE));
101         exit(1);
102     }
103 
104     /*
105      * Process options. Only the debug (-d) and the three memory
106      * protection levels (-m none, -m half, -m full) are accepted
107      */
108     config_file = 0;       /* Initialise things that may be found .. */
109     debug = 0;             /* on the command line */
110     protect = -1;
111     {
112         int option;
113         extern char *optarg;
114         extern int optind;
115                               
116         while ((option = getopt(argc, argv, "dm:")) != -1) {
117             switch(option) {
118             case 'd':
119                 debug = 1;
120                 break;
121 
122             case 'm':
123                 protect = prot_atoi(optarg);
124                 break;
125 
126             default:
127                 /*
128                  * unknown argument.
129                  */
130                 usage();
131                 break;
132             }
133         }
134         argc -= optind;       /* set to the number of args remaining */
135         argv += optind;       /* step over already processed args */
136     }
137 
138     if (argc > 1) {
139         usage();
140     }
141     if (argc == 1) {
142         config_file = *argv;
143     }
144   
145 
146     /*
147      * Open all disk files etc. and get the desired memory size, image file
148      * name, protection level and debug mode.  Three things that might be
149      * specified in the config file are memory size, debug enable and
150      * protection.  Variables are set to defaults before the call
151      * to config, and if the relevant option is not specified in the config
152      * file, the value ofthe variable is not changed.
153      */
154     core_size = DEF_MEM_SIZE * 1024;
155     configprotect = DEF_PROTECT;
156     configdebug = 0;
157     config(config_file, &core_size, image_name, &configprotect, &configdebug,
158            &eaddr);
159     /*
160      * Round up core size to the next click
161      */
162     core_size = upclick(core_size);
163   
164     /*
165      * Config file protection and debug options are only used if the relevant
166      * command line option was not given.
167      * file options.
168      */
169     if (!debug) {
170         debug = configdebug;
171     }
172     if (protect == -1) {
173         protect = configprotect;
174     }
175 
176     /*
177      * Create the process to run smx.
178      */
179     switch (fork()) {
180     case -1:      /* error */
181         reset_devices();
182         fprintf(stderr, "%s: Unable to fork secondary Minix process\n",
183                 progname);
184         exit(1);
185     
186     case 0:       /* child */
187         break;
188     
189     default:      /* parent */
190         smx_parent();
191         /*NOTREACHED*/
192     } /* fork() switch */
193 
194     bootp = load_image(image_name, core_size);
195     bootp->debug = debug;
196     bootp->prot_lev = protect;
197     bootp->mem_bytes = core_size;
198     bootp->ether_addr = eaddr;
199   
200     enable_interrupts();
201 
202     /* start the kernel running */
203     ((void (*)()) bootp->prog[KERNEL_PROG].entry)();
204     /*NOTREACHED*/
205     exit(2);
206 }
207 
208 
209 /*
210  * Function: load_image
211  * Parameters: imagefile - file to load the 4 programs from
212  *             core_size - number of bytes of smx "physical" memory to allocate
213  * Returns: pointer to the smx_bootinfo struct which is at the start of the
214  *          kernel's data segment.
215  *
216  * Details of the kernel's text segment are retrieved so that we know where
217  * to position the smx memory, and where the kernel data segment starts
218  * so that we can determine where the smx_bootinfo struct is.  The memory
219  * is then allocated, and the four programs from the image loaded into it,
220  * with program details stored in the bootinfo struct.
221  */
222 static struct smx_bootinfo *load_image(const char *imagefile, long core_size)
223 {
224     int fd, prog;
225     struct smx_bootinfo *bootp;
226     unsigned long memory_base;
227     char *base;
228 
229     /*
230      * Open the image file.
231      */
232     if ((fd = open(imagefile, O_RDONLY)) < 0){
233         fprintf(stderr, "%s: Unable to open image file\n", progname);
234         exit(1);
235     }
236   
237     /*
238      * Find out where the kernel text segment starts (that's where we need
239      * to map smx memory) and where the kernel data segment starts
240      * (that's where the boot parameters go)
241      */
242     if (get_seg_details(fd, &memory_base, (unsigned long *)&bootp) < 0) {
243         fprintf(stderr, "%s: Failed to get address of kernel text segment\n",
244                 progname);
245         exit(1);
246     }
247     if (debug) {
248         fprintf(stderr, "bootp = 0x%x\n", (unsigned) bootp);
249     }
250 
251     allocate_memory(memory_base, core_size);
252     if (debug) {
253         (void) fprintf(stderr, "Core size = 0x%x\nMemory base = 0x%lx\n",
254                        (unsigned) core_size, memory_base);
255     }  
256 
257     /*
258      * For each program within the image file, load it, and
259      * record it's details.  kernel, mm and fs must be loaded
260      * into the expected virtual addresses, so this is checked
261      * by minix_load for those programs.
262      */
263     base = (char *) memory_base;
264     for (prog = 0; prog < NUM_PROGS; prog++)
265     {
266         if (minix_load(fd, base, &bootp->prog[prog], prog != INIT_PROG) < 0) {
267             fprintf(stderr, "%s: Unable to load program %d\n", progname,
268                     prog);
269             fprintf(stderr,
270       "\tRun make in src/tools to ensure that all ld map files are correct\n");
271             exit(1);
272         }
273 
274         if (debug) {
275             (void) fprintf(stderr,
276                          "Program %d, base 0x%x, t_size 0x%lx, d_size 0x%lx\n",
277                            prog, (unsigned) base,
278                            bootp->prog[prog].text_clicks << CLICK_SHIFT, 
279                            bootp->prog[prog].data_clicks << CLICK_SHIFT);
280         }
281         base += (bootp->prog[prog].text_clicks +
282                  bootp->prog[prog].data_clicks) << CLICK_SHIFT;
283     }
284 
285     return bootp;    /* main() has more stuff to record as boot parameters */
286 }
287 
288 
289 /*
290  * Function: allocate_memory
291  * Parameters: memory_base - address to map memory in at
292  *             ram_size - number of bytes to map
293  *
294  * We need to map a file in to act as smx memory because user programs
295  * need to be mapped into low memory.  A temporary file is created,
296  * extended to the appropriate size, and mapped into memory.  Files
297  * created by tmpfile are automatically deleted when the creating process
298  * exits.  The smx kernel expects the file to be open on descriptor
299  * RAM_FD so that it can call mmap on it to run user programs.
300  */
301 static void allocate_memory(unsigned long memory_base, long ram_size)
302 {
303     char *ret_val;
304     FILE *mem_file = tmpfile();
305 
306     if (mem_file == 0) {
307         fprintf(stderr, "%s: Unable to open RAM file\n", progname);
308         exit(1);
309     }
310     if (dup2(fileno(mem_file), RAM_FD) < 0) {
311         fprintf(stderr, "%s: Unable to dup RAM file fd\n", progname);
312         exit(1);
313     }
314     fclose(mem_file);
315 
316     if (ftruncate(RAM_FD, ram_size) < 0) {
317         fprintf(stderr, "%s: Unable to size RAM\n", progname);
318         exit(1);
319     }
320     ret_val = mmap((char *)memory_base, ram_size,
321                    PROT_READ | PROT_WRITE | PROT_EXEC,
322                    MAP_SHARED | MAP_FIXED, RAM_FD, 0);
323     if (ret_val == MAP_FAILED) {
324         fprintf(stderr, "%s: Unable to map RAM file into memory\n", progname);
325         exit(1);
326     }
327 }
328 
329 
330 /*
331  * Function: smx_parent
332  *
333  * Code executed by the parent process after the fork.  It blocks all
334  * but error signals while waiting for the child running smx to finish.
335  * Then it cleans up the smx devices and terminal settings and exits.
336  */
337 static void smx_parent(void)
338 {
339     sigset_t sigs;
340     int status;
341 
342     sigfillset(&sigs);
343     sigdelset(&sigs, SIGILL);
344     sigdelset(&sigs, SIGTRAP);
345     sigdelset(&sigs, SIGEMT);
346     sigdelset(&sigs, SIGFPE);
347     sigdelset(&sigs, SIGBUS);
348     sigdelset(&sigs, SIGSEGV);
349     sigdelset(&sigs, SIGSYS);
350     (void) sigprocmask(SIG_SETMASK, &sigs, NULL);
351 
352     wait(&status);
353     
354     /*
355      * Tidy up smx device files and settings.
356      */
357     reset_devices();
358     exit(0);
359 }
360 
361 
362 /*
363  * Function: usage
364  */
365 static void usage(void)
366 {
367     fprintf(stderr, USAGE, progname);
368     exit(1);
369 }
370 
371 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.