First stab at interrupt-driven serial.
[pintos-anon] / src / threads / init.c
1 #include "threads/init.h"
2 #include <debug.h>
3 #include <limits.h>
4 #include <random.h>
5 #include <stddef.h>
6 #include <stdint.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "devices/kbd.h"
11 #include "devices/serial.h"
12 #include "devices/timer.h"
13 #include "devices/vga.h"
14 #include "threads/interrupt.h"
15 #include "threads/io.h"
16 #include "threads/loader.h"
17 #include "threads/malloc.h"
18 #include "threads/mmu.h"
19 #include "threads/paging.h"
20 #include "threads/palloc.h"
21 #include "threads/thread.h"
22 #ifdef USERPROG
23 #include "userprog/exception.h"
24 #include "userprog/gdt.h"
25 #include "userprog/syscall.h"
26 #include "userprog/tss.h"
27 #endif
28 #ifdef FILESYS
29 #include "devices/disk.h"
30 #include "filesys/filesys.h"
31 #include "filesys/fsutil.h"
32 #endif
33
34 /* Amount of physical memory, in 4 kB pages. */
35 size_t ram_pages;
36
37 #ifdef FILESYS
38 /* Format the filesystem? */
39 static bool format_filesys;
40 #endif
41
42 #ifdef USERPROG
43 /* Initial program to run. */
44 static char *initial_program;
45 #endif
46
47 static void ram_init (void);
48 static void argv_init (void);
49
50 int main (void) NO_RETURN;
51
52 int
53 main (void)
54 {
55   /* Needed by printf(), so initialize them very early. */
56   ram_init ();
57   vga_init ();
58   serial_init (1);
59
60   /* Greet user. */
61   printf ("Booting cnachos86 with %'d kB RAM...\n", ram_pages * 4);
62
63   /* Parse command line. */
64   argv_init ();
65
66   /* Initialize memory system, segments, paging. */
67   thread_init ();
68   palloc_init ();
69   paging_init ();
70 #ifdef USERPROG
71   tss_init ();
72   gdt_init ();
73 #endif
74   malloc_init ();
75
76   /* Set random seed if not already done. */
77   random_init (0);
78
79   /* Initialize interrupt handlers. */
80   intr_init ();
81   timer_init ();
82   kbd_init ();
83 #ifdef USERPROG
84   exception_init ();
85   syscall_init ();
86 #endif
87
88   /* Start thread scheduler and enable interrupts. */
89   thread_start ();
90   serial_init (2);
91
92 #ifdef FILESYS
93   /* Initialize filesystem. */
94   disk_init ();
95   filesys_init (format_filesys);
96   fsutil_run ();
97 #endif
98
99   printf ("Boot complete.\n");
100   
101   for (;;) 
102     putchar (serial_getc ());
103
104 #ifdef USERPROG
105   /* Run a user program. */
106   if (initial_program != NULL)
107     {
108       printf ("\nExecuting '%s':\n", initial_program);
109       thread_execute (initial_program); 
110     }
111 #endif
112
113   /* Terminate this thread. */
114   thread_exit ();
115 }
116 \f
117 /* Clear BSS and obtain RAM size from loader. */
118 static void
119 ram_init (void) 
120 {
121   /* The "BSS" is a segment that should be initialized to zeros.
122      It isn't actually stored on disk or zeroed by the kernel
123      loader, so we have to zero it ourselves.
124
125      The start and end of the BSS segment is recorded by the
126      linker as _start_bss and _end_bss.  See kernel.lds. */
127   extern char _start_bss, _end_bss;
128   memset (&_start_bss, 0, &_end_bss - &_start_bss);
129
130   /* Get RAM size from loader.  See loader.S. */
131   ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
132 }
133
134 /* Parses the command line. */
135 static void
136 argv_init (void) 
137 {
138   char *cmd_line, *pos;
139   char *argv[LOADER_CMD_LINE_LEN / 2 + 1];
140   int argc = 0;
141   int i;
142
143   /* The command line is made up of null terminated strings
144      followed by an empty string.  Break it up into words. */
145   cmd_line = pos = ptov (LOADER_CMD_LINE);
146   while (pos < cmd_line + LOADER_CMD_LINE_LEN)
147     {
148       ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
149       if (*pos == '\0')
150         break;
151       argv[argc++] = pos;
152       pos = strchr (pos, '\0') + 1;
153     }
154   argv[argc] = "";
155
156   /* Parse the words. */
157   for (i = 0; i < argc; i++)
158     if (!strcmp (argv[i], "-rs")) 
159       random_init (atoi (argv[++i]));
160     else if (!strcmp (argv[i], "-d")) 
161       debug_enable (argv[++i]);
162 #ifdef USERPROG
163     else if (!strcmp (argv[i], "-ex")) 
164       initial_program = argv[++i];
165 #endif
166 #ifdef FILESYS
167   else if (!strcmp (argv[i], "-f"))
168       format_filesys = true;
169     else if (!strcmp (argv[i], "-cp")) 
170       fsutil_copy_arg = argv[++i];
171     else if (!strcmp (argv[i], "-p")) 
172       fsutil_print_file = argv[++i];
173     else if (!strcmp (argv[i], "-r"))
174       fsutil_remove_file = argv[++i];
175     else if (!strcmp (argv[i], "-ls"))
176       fsutil_list_files = true;
177     else if (!strcmp (argv[i], "-D"))
178       fsutil_dump_filesys = true;
179 #endif
180     else if (!strcmp (argv[i], "-u"))
181       {
182         printf (
183           "Kernel options:\n"
184           " -rs SEED            Seed random seed to SEED.\n"
185           " -d CLASS[,...]      Enable the given classes of debug messages.\n"
186 #ifdef USERPROG
187           " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
188 #endif
189 #ifdef FILESYS
190           " -f                  Format the filesystem disk (hdb or hd0:1).\n"
191           " -cp FILENAME:SIZE   Copy SIZE bytes from the scratch disk (hdc\n"
192           "                     or hd1:0) into the filesystem as FILENAME\n"
193           " -p FILENAME         Print the contents of FILENAME\n"
194           " -r FILENAME         Delete FILENAME\n"
195           " -ls                 List the files in the filesystem\n"
196           " -D                  Dump complete filesystem contents\n"
197 #endif
198           );
199       }
200     else 
201       PANIC ("unknown option `%s'", argv[i]);
202 }