Swap names of power_off and do_power_off().
[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/palloc.h"
21 #include "threads/test.h"
22 #include "threads/thread.h"
23 #ifdef USERPROG
24 #include "userprog/exception.h"
25 #include "userprog/gdt.h"
26 #include "userprog/syscall.h"
27 #include "userprog/tss.h"
28 #endif
29 #ifdef FILESYS
30 #include "devices/disk.h"
31 #include "filesys/filesys.h"
32 #include "filesys/fsutil.h"
33 #endif
34
35 /* Amount of physical memory, in 4 kB pages. */
36 size_t ram_pages;
37
38 /* Page directory with kernel mappings only. */
39 uint32_t *base_page_dir;
40
41 #ifdef FILESYS
42 /* -f: Format the filesystem? */
43 static bool format_filesys;
44 #endif
45
46 #ifdef USERPROG
47 /* -ex: Initial program to run. */
48 static char *initial_program;
49 #endif
50
51 /* -q: Power off after running requested actions? */
52 static bool do_power_off;
53
54 static void ram_init (void);
55 static void paging_init (void);
56 static void argv_init (void);
57
58 int main (void) NO_RETURN;
59
60 int
61 main (void)
62 {
63   /* Initialize everything needed for printf() first. */
64   ram_init ();
65   thread_init ();
66   vga_init ();
67   serial_init_poll ();
68   console_init ();
69
70   /* Greet user. */
71   printf ("Pintos booting with %'zd kB RAM...\n", ram_pages * (PGSIZE / 1024));
72
73   /* Parse command line. */
74   argv_init ();
75
76   /* Initialize memory system, segments, paging. */
77   palloc_init ();
78   paging_init ();
79 #ifdef USERPROG
80   tss_init ();
81   gdt_init ();
82 #endif
83   malloc_init ();
84
85   /* Set random seed if argv_init() didn't. */
86   random_init (0);
87
88   /* Initialize interrupt handlers. */
89   intr_init ();
90   timer_init ();
91   kbd_init ();
92 #ifdef USERPROG
93   exception_init ();
94   syscall_init ();
95 #endif
96
97   /* Start thread scheduler and enable interrupts. */
98   thread_start ();
99   serial_init_queue ();
100
101 #ifdef FILESYS
102   /* Initialize filesystem. */
103   disk_init ();
104   filesys_init (format_filesys);
105   fsutil_run ();
106 #endif
107
108   printf ("Boot complete.\n");
109   
110 #ifdef USERPROG
111   /* Run a user program. */
112   if (initial_program != NULL)
113     {
114       printf ("\nExecuting '%s':\n", initial_program);
115       thread_execute (initial_program); 
116     }
117 #else
118   test ();
119 #endif
120
121   if (do_power_off) 
122     power_off ();
123
124   /* Terminate this thread. */
125   thread_exit ();
126 }
127 \f
128 /* Clear BSS and obtain RAM size from loader. */
129 static void
130 ram_init (void) 
131 {
132   /* The "BSS" is a segment that should be initialized to zeros.
133      It isn't actually stored on disk or zeroed by the kernel
134      loader, so we have to zero it ourselves.
135
136      The start and end of the BSS segment is recorded by the
137      linker as _start_bss and _end_bss.  See kernel.lds. */
138   extern char _start_bss, _end_bss;
139   memset (&_start_bss, 0, &_end_bss - &_start_bss);
140
141   /* Get RAM size from loader.  See loader.S. */
142   ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
143 }
144
145 /* Populates the base page directory and page table with the
146    kernel virtual mapping, and then sets up the CPU to use the
147    new page directory.  Points base_page_dir to the page
148    directory it creates.
149
150    At the time this function is called, the active page table
151    (set up by loader.S) only maps the first 4 MB of RAM, so we
152    should not try to use extravagant amounts of memory.
153    Fortunately, there is no need to do so. */
154 static void
155 paging_init (void)
156 {
157   uint32_t *pd, *pt;
158   size_t page;
159
160   pd = base_page_dir = palloc_get (PAL_ASSERT | PAL_ZERO);
161   pt = NULL;
162   for (page = 0; page < ram_pages; page++) 
163     {
164       uintptr_t paddr = page * PGSIZE;
165       void *vaddr = ptov (paddr);
166       size_t pde_idx = pd_no (vaddr);
167       size_t pte_idx = pt_no (vaddr);
168
169       if (pd[pde_idx] == 0)
170         {
171           pt = palloc_get (PAL_ASSERT | PAL_ZERO);
172           pd[pde_idx] = pde_create (pt);
173         }
174
175       pt[pte_idx] = pte_create_kernel (vaddr, true);
176     }
177
178   asm volatile ("movl %0,%%cr3" :: "r" (vtop (base_page_dir)));
179 }
180
181 /* Parses the command line. */
182 static void
183 argv_init (void) 
184 {
185   char *cmd_line, *pos;
186   char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
187   int argc = 0;
188   int i;
189
190   /* The command line is made up of null terminated strings
191      followed by an empty string.  Break it up into words. */
192   cmd_line = pos = ptov (LOADER_CMD_LINE);
193   printf ("Kernel command line:");
194   while (pos < cmd_line + LOADER_CMD_LINE_LEN)
195     {
196       ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
197       if (*pos == '\0')
198         break;
199       argv[argc++] = pos;
200       printf (" %s", pos);
201       pos = strchr (pos, '\0') + 1;
202     }
203   printf ("\n");
204   argv[argc] = "";
205   argv[argc + 1] = "";
206
207   /* Parse the words. */
208   for (i = 0; i < argc; i++)
209     if (!strcmp (argv[i], "-rs")) 
210       random_init (atoi (argv[++i]));
211     else if (!strcmp (argv[i], "-d")) 
212       debug_enable (argv[++i]);
213     else if (!strcmp (argv[i], "-q"))
214       do_power_off = true;
215 #ifdef USERPROG
216     else if (!strcmp (argv[i], "-ex")) 
217       initial_program = argv[++i];
218 #endif
219 #ifdef FILESYS
220   else if (!strcmp (argv[i], "-f"))
221       format_filesys = true;
222     else if (!strcmp (argv[i], "-ci")) 
223       {
224         fsutil_copyin_file = argv[++i]; 
225         fsutil_copyin_size = atoi (argv[++i]); 
226       }
227     else if (!strcmp (argv[i], "-co"))
228       fsutil_copyout_file = argv[++i];
229     else if (!strcmp (argv[i], "-p")) 
230       fsutil_print_file = argv[++i];
231     else if (!strcmp (argv[i], "-r"))
232       fsutil_remove_file = argv[++i];
233     else if (!strcmp (argv[i], "-ls"))
234       fsutil_list_files = true;
235     else if (!strcmp (argv[i], "-D"))
236       fsutil_dump_filesys = true;
237 #endif
238     else if (!strcmp (argv[i], "-u"))
239       {
240         printf (
241           "Kernel options:\n"
242           " -rs SEED            Seed random seed to SEED.\n"
243           " -d CLASS[,...]      Enable the given classes of debug messages.\n"
244 #ifdef USERPROG
245           " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
246 #endif
247 #ifdef FILESYS
248           " -f                  Format the filesystem disk (hdb or hd0:1).\n"
249           " -ci FILENAME SIZE   Copy SIZE bytes from the scratch disk (hdc\n"
250           "                     or hd1:0) into the filesystem as FILENAME\n"
251           " -co FILENAME        Copy FILENAME to the scratch disk, with\n"
252           "                     size at start of sector 0 and data afterward\n"
253           " -p FILENAME         Print the contents of FILENAME\n"
254           " -r FILENAME         Delete FILENAME\n"
255           " -ls                 List the files in the filesystem\n"
256           " -D                  Dump complete filesystem contents\n"
257 #endif
258           " -q                  Power off after doing requested actions.\n"
259           " -u                  Print this help message and power off.\n"
260           );
261         power_off ();
262       }
263     else 
264       PANIC ("unknown option `%s' (use -u for help)", argv[i]);
265 }
266
267 /* Powers down the machine we're running on,
268    as long as we're running on Bochs or qemu. */
269 void
270 power_off (void) 
271 {
272   const char s[] = "Shutdown";
273   const char *p;
274
275 #ifdef FILESYS
276   filesys_done ();
277 #endif
278
279   printf ("Powering off...\n");
280   for (p = s; *p != '\0'; p++)
281     outb (0x8900, *p);
282   for (;;);
283 }