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/exception.h"
25 #include "userprog/gdt.h"
26 #include "userprog/syscall.h"
27 #include "userprog/tss.h"
30 #include "devices/disk.h"
31 #include "filesys/filesys.h"
32 #include "filesys/fsutil.h"
35 /* Amount of physical memory, in 4 kB pages. */
38 /* Page directory with kernel mappings only. */
39 uint32_t *base_page_dir;
42 /* -f: Format the filesystem? */
43 static bool format_filesys;
47 /* -ex: Initial program to run. */
48 static char *initial_program;
51 /* -q: Power off after running requested actions? */
52 static bool do_power_off;
54 static void ram_init (void);
55 static void paging_init (void);
56 static void argv_init (void);
58 int main (void) NO_RETURN;
63 /* Initialize everything needed for printf() first. */
71 printf ("Pintos booting with %'zd kB RAM...\n", ram_pages * (PGSIZE / 1024));
73 /* Parse command line. */
76 /* Initialize memory system, segments, paging. */
85 /* Set random seed if argv_init() didn't. */
88 /* Initialize interrupt handlers. */
97 /* Start thread scheduler and enable interrupts. */
102 /* Initialize filesystem. */
104 filesys_init (format_filesys);
108 printf ("Boot complete.\n");
111 /* Run a user program. */
112 if (initial_program != NULL)
114 printf ("\nExecuting '%s':\n", initial_program);
115 thread_execute (initial_program);
124 /* Terminate this thread. */
128 /* Clear BSS and obtain RAM size from loader. */
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.
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);
141 /* Get RAM size from loader. See loader.S. */
142 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
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.
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. */
160 pd = base_page_dir = palloc_get (PAL_ASSERT | PAL_ZERO);
162 for (page = 0; page < ram_pages; page++)
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);
169 if (pd[pde_idx] == 0)
171 pt = palloc_get (PAL_ASSERT | PAL_ZERO);
172 pd[pde_idx] = pde_create (pt);
175 pt[pte_idx] = pte_create_kernel (vaddr, true);
178 asm volatile ("movl %0,%%cr3" :: "r" (vtop (base_page_dir)));
181 /* Parses the command line. */
185 char *cmd_line, *pos;
186 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
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)
196 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
201 pos = strchr (pos, '\0') + 1;
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"))
216 else if (!strcmp (argv[i], "-ex"))
217 initial_program = argv[++i];
220 else if (!strcmp (argv[i], "-f"))
221 format_filesys = true;
222 else if (!strcmp (argv[i], "-ci"))
224 fsutil_copyin_file = argv[++i];
225 fsutil_copyin_size = atoi (argv[++i]);
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;
238 else if (!strcmp (argv[i], "-u"))
242 " -rs SEED Seed random seed to SEED.\n"
243 " -d CLASS[,...] Enable the given classes of debug messages.\n"
245 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
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"
258 " -q Power off after doing requested actions.\n"
259 " -u Print this help message and power off.\n"
264 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
267 /* Powers down the machine we're running on,
268 as long as we're running on Bochs or qemu. */
272 const char s[] = "Shutdown";
279 printf ("Powering off...\n");
280 for (p = s; *p != '\0'; p++)