=============================================================== THINGS A BOOTLOADER COULD/SHOULD DO =============================================================== STAND-ALONE LOADER is a conventional bootloader. This document also covers loaders which load and start an OS from DOS. Almost all of these operations are optional. The exact mix (and the order in which they are executed) is up to you. 1. (FLOPPY) Get the sectors/track value: 1a. From BIOS parameter block (BPB) of floppy. The BPB is a feature of DOS filesystems, and may not be present for other filesystems. 1b. Assume a value, e.g. 18 sectors/track for 1.44 meg disks. 1c. Set the BIOS sectors/track value to an inflated value ("High doesn't hurt. Low does." -- Linux BOOTSECT.S), then load sectors using INT 13h and a linear search to zero in on the actual sectors/track value. INT 13h AH=08h does not return accurate geometry information for floppies. 2. (STAND-ALONE LOADER) If the loader is larger than 512 bytes, it will have to finish loading itself from the disk. First, we have to FIND the "second stage" by one of three methods: 2a. (disk has no filesystem) Just assume that the second stage is adjacent to (and contiguous with) the first stage. 2b. (disk may or may not have a filesystem) Use a LILO-like block list to find the second stage file. 2c. (disk has a filesystem) Use the filesystem (FAT12, FAT16, ext2, FFS, etc). The filesystem code can be read-only and root-directory-only, for simplicity. 3. (STAND-ALONE LOADER) Now we LOAD the second stage: 3a. Using contiguous disk sectors. 3b. Using LILO-like block list. 3c. Using filesystem. 4. Get system info: 4a. Get conventional and extended memory sizes using BIOS calls. 4b. Check for 32-bit CPU. 4c. Detect drives, and get their geometries. 4d. (DOS LOADER; 32-BIT CPU; PMODE OS) Check if CPU is in Virtual 8086 mode (EMM386 loaded; or Windows DOS box). 5. (ADVANCED LOADER) FIND config file: 5a. Using DOS. 5b. Using contiguous disk sectors. 5c. Using LILO-like block list. 5d. Using filesystem. 6. (ADVANCED LOADER) LOAD config file: 6a. Using DOS. 6b. Using contiguous disk sectors. 6c. Using LILO-like block list. 6d. Using filesystem. 7. (ADVANCED LOADER) If no config file, let the user browse (kernel) files on the disk. 8. (ADVANCED LOADER) Present an optional boot menu to the user. Have an optional timeout, which loads a default kernel unless the user choses another OS. Dim out the names of kernels in the menu if they are unbootable (and display an error message). Disable the timeout if the default kernel is unbootable. 9. Find the kernel: 9a. Using DOS. 9b. Using contiguous disk sectors. 9c. Using LILO-like block list. 9d. Using filesystem. 10. Validate kernel file: 10a. Correct/supported file format (DJGPP COFF, ELF, BSD a.out, Win32 PE .EXE, Multiboot, RDSK, etc.) 10b. Ensure kernel is not dynamically-linked, in need of relocation, or a .o file 10c. See if enough memory to load it. Note that some kernels (like mine :) can be loaded to any 4K boundary. 10d. Need/got 32-bit CPU? 10e. (BLOCK LIST BOOTLOADER ONLY) CRC the first and last sectors of kernel, to see if it was deleted/modified/moved since the block list installer was last run. 11. Prepare to copy the kernel: 11a. (286+) Enable the A20 gate. 11b. (286+) Verify A20 is on. 11c. (386+) Enable "unreal" mode. Since this lets you copy data without worrying about 64K segment limits or boundaries, it's useful even if you don't copy to extended memory. It may be better to use INT 15h AH=87h (copy extended memory) because it controls the A20 gate automatically. 12. Load the kernel 12a. Using DOS. 12b. Using contiguous disk sectors. 12c. Using LILO-like block list. 12d. Using filesystem. 13. Decompress the kernel: 13a. (no compression) 13b. gzip/zlib/lz77 compression. 13c. bzip compression. 13d. LZO, lzop, NRV, or UPX compression (http://wildsau.idv.uni-linz.ac.at/mfx) 14. Copy kernel: 14a. (no copy needed) 14b. To alternate location in conventional memory. 14c. To extended memory. For a kernel meant to run on an XT (8088 CPU), a "copy_huge" function would be nice. It handles segment wrap-around when copying more than 64K of data. 15. (FLOPPY) Done loading, turn off the motor :) 16. Zero the kernel BSS. This assumes the kernel has some kind of header that lets you know where the BSS is, and how big it is. 17. Store machine info (e.g. RAM sizes) and boot info (e.g. kernel command line): 17a. In a fixed memory location, such as address 90000h (Linux) 17b. In the kernel BSS (Cosmos) 17c. In a variable location, but pass a pointer to the data to the kernel (Multiboot) Some information being stored here is information (such as that obtained with 16-bit BIOS calls) which would be difficult to obtain after a 32-bit kernel has started. 18. Video: 18a. Probe BIOS and/or hardware to see what modes are available. 18b. Prompt user to select a video mode. 18c. Set the video mode (using 16-bit BIOS call). 19. Make other 16-bit BIOS calls that would be difficult to do from a pure 32-bit OS: 19a. Advanced power management (APM) 19b. Plug and play (PnP) (My BIOS has 16-bit PnP but not 32-bit) 19c. BIOS calls to locate text-mode fonts in video ROM. 20. (DOS LOADER) If booting pmode OS from DOS, and the CPU is in V86 pmode because of EMM386, use VCPI to switch out of V86 mode 21. Put some information into registers: 21a. Magic value indicating the bootloader used (Multiboot). 21b. Drive we booted from. 21c. An address that lets the kernel return to the bootloader. 21d. other? An earlier version of this document suggesting storing some other values: Virtual-to-physical conversion value: The kernel itself can compute this value, using a code snippet such as: call where_am_i where_am_i: pop ebx sub ebx,where_am_i Pmode data segment selector: The data segment registers can be loaded BEFORE jumping to the kernel. 22. If booting pmode os, enable pmode. 23. Jump to loaded kernel.