-Because the PC BIOS loads the loader, the loader has to play by the
-BIOS's rules. In particular, the BIOS only loads 512 bytes (one disk
-sector) into memory. This is a severe restriction and it means that,
-practically speaking, the loader has to be written in assembly
-language.
-
-Pintos' loader first initializes the CPU. The first important part of
-this is to enable the A20 line, that is, the CPU's address line
-numbered 20. For historical reasons, PCs start out with this address
-line fixed at 0, which means that attempts to access memory beyond the
-first 1 MB (2 raised to the 20th power) will fail. Pintos wants to
-access more memory than this, so we have to enable it.
-
-Next, the loader asks the BIOS for the PC's memory size. Again for
-historical reasons, the function that we call in the BIOS to do this
-can only detect up to 64 MB of RAM, so that's the practical limit that
-Pintos can support. The memory size is stashed away in a location in
-the loader that the kernel can read after it boots.
-
-Third, the loader creates a basic page table. This page table maps
+The PC BIOS loads the loader from the first sector of the first hard
+disk, called the @dfn{master boot record} (MBR). PC conventions
+reserve 64 bytes of the MBR for the partition table, and Pintos uses
+about 128 additional bytes for kernel command-line arguments. This
+leaves a little over 300 bytes for the loader's own code. This is a
+severe restriction that means, practically speaking, the loader must
+be written in assembly language.
+
+The Pintos loader and kernel don't have to be on the same disk, nor
+does is the kernel required to be in any particular location on a
+given disk. The loader's first job, then, is to find the kernel by
+reading the partition table on each hard disk, looking for a bootable
+partition of the type used for a Pintos kernel.
+
+When the loader finds a bootable kernel partition, it reads the
+partition's contents into memory at physical address @w{128 kB}. The
+kernel is at the beginning of the partition, which might be larger
+than necessary due to partition boundary alignment conventions, so the
+loader reads no more than @w{512 kB} (and the Pintos build process
+will refuse to produce kernels larger than that). Reading more data
+than this would cross into the region from @w{640 kB} to @w{1 MB} that
+the PC architecture reserves for hardware and the BIOS, and a standard
+PC BIOS does not provide any means to load the kernel above @w{1 MB}.
+
+The loader's final job is to extract the entry point from the loaded
+kernel image and transfer control to it. The entry point is not at a
+predictable location, but the kernel's ELF header contains a pointer
+to it. The loader extracts the pointer and jumps to the location it
+points to.
+
+The Pintos kernel command line
+is stored in the boot loader. The @command{pintos} program actually
+modifies a copy of the boot loader on disk each time it runs the kernel,
+inserting whatever command-line arguments the user supplies to the kernel,
+and then the kernel at boot time reads those arguments out of the boot
+loader in memory. This is not an elegant solution, but it is simple
+and effective.
+
+@node Low-Level Kernel Initialization
+@subsection Low-Level Kernel Initialization
+
+The loader's last action is to transfer control to the kernel's entry
+point, which is @func{start} in @file{threads/start.S}. The job of
+this code is to switch the CPU from legacy 16-bit ``real mode'' into
+the 32-bit ``protected mode'' used by all modern 80@var{x}86 operating
+systems.
+
+The startup code's first task is actually to obtain the machine's
+memory size, by asking the BIOS for the PC's memory size. The
+simplest BIOS function to do this can only detect up to 64 MB of RAM,
+so that's the practical limit that Pintos can support. The function
+stores the memory size, in pages, in global variable
+@code{init_ram_pages}.
+
+The first part of CPU initialization is to enable the A20 line, that
+is, the CPU's address line numbered 20. For historical reasons, PCs
+boot with this address line fixed at 0, which means that attempts to
+access memory beyond the first 1 MB (2 raised to the 20th power) will
+fail. Pintos wants to access more memory than this, so we have to
+enable it.
+
+Next, the loader creates a basic page table. This page table maps