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