+#ifdef FILESYS
+ /* Initialize file system. */
+ usb_storage_init ();
+ ide_init ();
+ locate_block_devices ();
+ filesys_init (format_filesys);
+#endif
+
+ printf ("Boot complete.\n");
+
+ /* Run actions specified on kernel command line. */
+ run_actions (argv);
+
+ /* Finish up. */
+ if (reboot_when_done)
+ reboot ();
+
+ if (power_off_when_done)
+ power_off ();
+ thread_exit ();
+}
+\f
+/* Clear the "BSS", a segment that should be initialized to
+ zeros. It isn't actually stored on disk or zeroed by the
+ kernel loader, so we have to zero it ourselves.
+
+ The start and end of the BSS segment is recorded by the
+ linker as _start_bss and _end_bss. See kernel.lds. */
+static void
+bss_init (void)
+{
+ extern char _start_bss, _end_bss;
+ memset (&_start_bss, 0, &_end_bss - &_start_bss);
+}
+
+/* Populates the base page directory and page table with the
+ kernel virtual mapping, and then sets up the CPU to use the
+ new page directory. Points base_page_dir to the page
+ directory it creates. */
+static void
+paging_init (void)
+{
+ uint32_t *pd, *pt;
+ size_t page;
+ extern char _start, _end_kernel_text;
+
+ pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
+ pt = NULL;
+ for (page = 0; page < ram_pages; page++)
+ {
+ uintptr_t paddr = page * PGSIZE;
+ char *vaddr = ptov (paddr);
+ size_t pde_idx = pd_no (vaddr);
+ size_t pte_idx = pt_no (vaddr);
+ bool in_kernel_text = &_start <= vaddr && vaddr < &_end_kernel_text;
+
+ if (pd[pde_idx] == 0)
+ {
+ pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
+ pd[pde_idx] = pde_create_kernel (pt);
+ }
+
+ pt[pte_idx] = pte_create_kernel (vaddr, !in_kernel_text);
+ }
+
+ pci_zone_init ();
+
+ /* Store the physical address of the page directory into CR3
+ aka PDBR (page directory base register). This activates our
+ new page tables immediately. See [IA32-v2a] "MOV--Move
+ to/from Control Registers" and [IA32-v3a] 3.7.5 "Base Address
+ of the Page Directory". */
+ asm volatile ("movl %0, %%cr3" : : "r" (vtop (base_page_dir)));