1 #include "threads/init.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"
24 #include "userprog/process.h"
25 #include "userprog/exception.h"
26 #include "userprog/gdt.h"
27 #include "userprog/syscall.h"
28 #include "userprog/tss.h"
31 #include "devices/disk.h"
32 #include "filesys/filesys.h"
33 #include "filesys/fsutil.h"
36 /* Amount of physical memory, in 4 kB pages. */
39 /* Page directory with kernel mappings only. */
40 uint32_t *base_page_dir;
43 /* -f: Format the filesystem? */
44 static bool format_filesys;
48 /* -ex: Initial program to run. */
49 static char *initial_program;
52 /* -q: Power off after running requested actions? */
53 static bool do_power_off;
55 static void ram_init (void);
56 static void paging_init (void);
57 static void argv_init (void);
59 int main (void) NO_RETURN;
64 /* Initialize everything needed for printf() first. */
72 printf ("Pintos booting with %'zd kB RAM...\n", ram_pages * (PGSIZE / 1024));
74 /* Parse command line. */
77 /* Initialize memory system, segments, paging. */
86 /* Set random seed if argv_init() didn't. */
89 /* Initialize interrupt handlers. */
98 /* Start thread scheduler and enable interrupts. */
100 serial_init_queue ();
103 /* Initialize filesystem. */
105 filesys_init (format_filesys);
109 printf ("Boot complete.\n");
112 /* Run a user program. */
113 if (initial_program != NULL)
116 printf ("\nExecuting '%s':\n", initial_program);
117 tid = process_execute (initial_program);
118 #ifdef THREAD_JOIN_IMPLEMENTED
119 if (tid != TID_ERROR)
130 /* Terminate this thread. */
134 /* Clear BSS and obtain RAM size from loader. */
138 /* The "BSS" is a segment that should be initialized to zeros.
139 It isn't actually stored on disk or zeroed by the kernel
140 loader, so we have to zero it ourselves.
142 The start and end of the BSS segment is recorded by the
143 linker as _start_bss and _end_bss. See kernel.lds. */
144 extern char _start_bss, _end_bss;
145 memset (&_start_bss, 0, &_end_bss - &_start_bss);
147 /* Get RAM size from loader. See loader.S. */
148 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
151 /* Populates the base page directory and page table with the
152 kernel virtual mapping, and then sets up the CPU to use the
153 new page directory. Points base_page_dir to the page
154 directory it creates.
156 At the time this function is called, the active page table
157 (set up by loader.S) only maps the first 4 MB of RAM, so we
158 should not try to use extravagant amounts of memory.
159 Fortunately, there is no need to do so. */
166 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
168 for (page = 0; page < ram_pages; page++)
170 uintptr_t paddr = page * PGSIZE;
171 void *vaddr = ptov (paddr);
172 size_t pde_idx = pd_no (vaddr);
173 size_t pte_idx = pt_no (vaddr);
175 if (pd[pde_idx] == 0)
177 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
178 pd[pde_idx] = pde_create (pt);
181 pt[pte_idx] = pte_create_kernel (vaddr, true);
184 asm volatile ("movl %0,%%cr3" :: "r" (vtop (base_page_dir)));
187 /* Parses the command line. */
191 char *cmd_line, *pos;
192 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
196 /* The command line is made up of null terminated strings
197 followed by an empty string. Break it up into words. */
198 cmd_line = pos = ptov (LOADER_CMD_LINE);
199 printf ("Kernel command line:");
200 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
202 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
207 pos = strchr (pos, '\0') + 1;
213 /* Parse the words. */
214 for (i = 0; i < argc; i++)
215 if (!strcmp (argv[i], "-rs"))
216 random_init (atoi (argv[++i]));
217 else if (!strcmp (argv[i], "-d"))
218 debug_enable (argv[++i]);
219 else if (!strcmp (argv[i], "-q"))
222 else if (!strcmp (argv[i], "-ex"))
223 initial_program = argv[++i];
226 else if (!strcmp (argv[i], "-f"))
227 format_filesys = true;
228 else if (!strcmp (argv[i], "-ci"))
230 fsutil_copyin_file = argv[++i];
231 fsutil_copyin_size = atoi (argv[++i]);
233 else if (!strcmp (argv[i], "-co"))
234 fsutil_copyout_file = argv[++i];
235 else if (!strcmp (argv[i], "-p"))
236 fsutil_print_file = argv[++i];
237 else if (!strcmp (argv[i], "-r"))
238 fsutil_remove_file = argv[++i];
239 else if (!strcmp (argv[i], "-ls"))
240 fsutil_list_files = true;
241 else if (!strcmp (argv[i], "-D"))
242 fsutil_dump_filesys = true;
244 else if (!strcmp (argv[i], "-u"))
248 " -rs SEED Seed random seed to SEED.\n"
249 " -d CLASS[,...] Enable the given classes of debug messages.\n"
251 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
254 " -f Format the filesystem disk (hdb or hd0:1).\n"
255 " -ci FILENAME SIZE Copy SIZE bytes from the scratch disk (hdc\n"
256 " or hd1:0) into the filesystem as FILENAME\n"
257 " -co FILENAME Copy FILENAME to the scratch disk, with\n"
258 " size at start of sector 0 and data afterward\n"
259 " -p FILENAME Print the contents of FILENAME\n"
260 " -r FILENAME Delete FILENAME\n"
261 " -ls List the files in the filesystem\n"
262 " -D Dump complete filesystem contents\n"
264 " -q Power off after doing requested actions.\n"
265 " -u Print this help message and power off.\n"
270 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
273 /* Powers down the machine we're running on,
274 as long as we're running on Bochs or qemu. */
278 const char s[] = "Shutdown";
285 printf ("Powering off...\n");
288 for (p = s; *p != '\0'; p++)