From 7a51b6745d785f0a003a81c4d1fb819620224154 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Mon, 10 Apr 2023 14:58:46 +0200 Subject: first standalone version --- README | 482 ++++ ...useum.com_wp_a-brief-history-of-unreal-mode.txt | 1626 ++++++++++++++ src/boot.asm | 1408 ++++++++++++ src/lstar.c | 102 + tests/run_qemu.sh | 7 + tests/test_a20.asm | 61 + tests/test_unreal.asm | 49 + ...x-insides_content_Booting_linux-bootstrap-1.txt | 897 ++++++++ ...x-insides_content_Booting_linux-bootstrap-2.txt | 937 ++++++++ ...com_2010_06_real-mode-in-c-with-gcc-writing.txt | 892 ++++++++ ...s-linux-kernel-5-8-0-rc2-floppy-intel-80486.txt | 339 +++ ...narmstrong_meson_drm_doc_admin-guide_initrd.txt | 453 ++++ .../www.kernel.org_doc_html_latest_x86_boot.txt | 2349 ++++++++++++++++++++ ...ww.kernel.org_doc_html_latest_x86_zero-page.txt | 424 ++++ 14 files changed, 10026 insertions(+) create mode 100644 README create mode 100644 doc/www.os2museum.com_wp_a-brief-history-of-unreal-mode.txt create mode 100644 src/boot.asm create mode 100644 src/lstar.c create mode 100755 tests/run_qemu.sh create mode 100644 tests/test_a20.asm create mode 100644 tests/test_unreal.asm create mode 100644 todo/doc/0xax.gitbooks.io_linux-insides_content_Booting_linux-bootstrap-1.txt create mode 100644 todo/doc/0xax.gitbooks.io_linux-insides_content_Booting_linux-bootstrap-2.txt create mode 100644 todo/doc/dc0d32.blogspot.com_2010_06_real-mode-in-c-with-gcc-writing.txt create mode 100644 todo/doc/fossbytes_com_redditor-boots-linux-kernel-5-8-0-rc2-floppy-intel-80486.txt create mode 100644 todo/doc/people.freedesktop.org_~narmstrong_meson_drm_doc_admin-guide_initrd.txt create mode 100644 todo/doc/www.kernel.org_doc_html_latest_x86_boot.txt create mode 100644 todo/doc/www.kernel.org_doc_html_latest_x86_zero-page.txt diff --git a/README b/README new file mode 100644 index 0000000..115f768 --- /dev/null +++ b/README @@ -0,0 +1,482 @@ +uflbbl - USTAR Floppy Linux BIOS Boot Loader +-------------------------------------------- + +For old BIOS based booting, loading a set of floppies which contain +the kernel, the ramdisk, etc. in USTAR format. It can only load +Linux kernels and ramdisks currently. And though it might be able +to boot a AMD64 kernel this is not the primary focus. It is there +to boot on old IA-32 based machines which have an original floppy +drive. + +The filenames recognized are: +- 'bzImage': the Linux kernel +- 'ramdisk.img': the initial ramdisk +- 'EOF': an empty file indicating the end of the tar file + +Customization of boot parameters must be done in source currently +in 'KERNEL_CMD_LINE' in 'boot.asm'. + +You can also change the greeting mesage in varialble 'MESSAGE_GREETING' +in 'boot.asm' to your likeing. + +An example boot sequence looks as follows: + +Booting from Floppy... +UFLBB loading... +Checking A20 address gate.. + enabled +Switching to unreadl mode.. enabled +Boot parameters 0x00 0x04 0x02 0x13 + bzImage 00004727760 0013AFF0! +Number of real-mode kernel sectors: 1D +Number of protected-mode kernel sectors: 09BA +Linux boot protocol version: 02.0F +Linux kernel version: 6.2.10 (user@machine) #1 Mon Apr 10 11:33:20 CET 2023 + ramdisk.img 00012114554 0028996C! +Insert next floppy and press any key to continue.. +Insert next floppy and press any key to continue.. +Insert next floppy and press any key to continue.. + EOF 00000000000 00000000 +Reached end of tar file.. +Ramdisk address: 008000000 +Ramdisk size: 0028996C +Booting kernel.. +early console in setup code +early console in extract_kernel +input_data: 0x01328079 +input_len: 0x00132e1c +output: 0x01000000 +output_len: 0x0032ce60 +kernel_total_size: 0x00472000 +needed_size: 0x00472000 +Decompressing Linux... +... + +requirements +------------ + +nasm + +how to build a set of bootable floppies +--------------------------------------- + +Create a 'bzImage' kernel and an initial ramdisk 'ramdisk.img'. + +Assemble 'boot.asm', put it to start of 'floppy.img', tar the kernel, +the 'ramdisk.img' and the 'EOF' file into a 'data.tar' file, concatenate +the boot loader file 'boot.img' and the 'data.tar' file, then +split into floppy size (assuming you have 3 1/4" 1.44MB floppies). + +nasm -o boot.img boot.asm +touch EOF +tar -cvf data.tar -b1 bzImage ramdisk.img EOF +cat boot.img data.tar > floppy.img +./lstar floppy.img +split -d -b 1474560 floppy.img floppy +dd if=floppy00 of=/dev/fd0 bs=512 +dd if=floppy01 of=/dev/fd0 bs=512 +.. + +Boot the floppies in order, insert next floppy if asked by the boot +loader. + +'lstar' is a small convenience program to list the entries in the tar +(of course also 'tar xvf' works for this). + +gcc -lbsd -o lstar src/lstar.c +./lstar floppy.img + +testing +------- + +tests/run_qemu.sh + +when asked to change the floppy change to the Qemu console and +type 'change floppy0 floppy01' (same for all other floppies). + +floppy format +------------- + +512 bytes MBR stage 1 simple boot loader and magic boot string + loads stage 2 directly following stage 1, also assumes + stage 2 fits on one track of the floppy, so we don't + need a complicated loading method probing tracks per sector +1024 bytes stage 2 boot loader, interprets tar format one sector after + stage 2 and reads files into memory (vmlinuz, ramdisk.img) +N tar file format (no compression, we expect the files to + be well compressed). 2 blocks .ustar format, file names + are easy accessible (vmlinuz, ramdisk.img). We sacrifice 512 + bytes for easier reading in multiple disks (for instance + a kernel disk, an initial ramdisk, a driver disk for + SCSI, a root file system, etc.), we could even do multi-floppy + kernels, so we can read the kernel distributed on more than + one floppy. + +ustar/tar format +---------------- + +offset length description example +byte 0 100 filename in ascii, zero-term string "bzImage" +byte 0x7c (124) 12 length in octal, zero-term string "00004014360" +byte 0x94 (148) 8 checksum in octal, zero-term string "012757" + with an ending space for some reason + sum the header bytes with the checksum + bytes as spaces (0x20) +byte 0x101 (257) 6 UStar indicator, zero-term string "ustar" + one of the easiest ways to detect + a tar header sector + +ramdisk +------- + +find . | cpio -H newc -o -R root:root | xz --check=crc32 > ../ramdisk.img + +memory layout +------------- + +0x07c00 - 0x08fff boot loader +0x09000 - 0x091ff floppy read buffer +0x0e000 - 0x09200 stack of real mode kernel +0x10000 - 0x101ff Linux zero page (first part) +0x10200 - 0x103ff zero page (part two), real mode entry point at 0x10200 +0x10400 - xxx continue code of real mode kernel +0x1e000 - 0xe0ff cmd line for kernel +0x100000 - xxx protected mode kernel code (at 1 MB) +0x800000 - xxx ram disk (at 8 MB) + +state machine +------------- + +tar state machine: reading metadata, reading data, we know +whether we are in the kernel, ramdisk, etc. +kernel substates: +- sector 1: read number of real mode sectors +- sector 2: read and check params, set params +- sector >2: always read and copy data from floppy to destination area + +error codes +----------- + +error codes consist of a error class (DISK, KERN) and a code + +ERR DISK 0x01 stage 1 read error while reading stage 2 +ERR DISK 0x02 stage 1 short read error (we didn't read as many stage 2 + sectors as expected) +ERR DISK 0x03 reading and interpreting tar state machine error +ERR DISK 0xXX other read errors (BIOS int 0x13 codes), stage 2 +ERR A20 0x01 A20 address line not enabled +ERR KERN 0x01 kernel read state machine error +ERR KERN 0x02 kernel signature 'HdrS' not found +ERR KERN 0x03 kernel boot protocol too old +ERR KERN 0x04 kernel cannot be started (or better, we return from the + real mode jump) + +Linux IA-32 boot sequence +------------------------- + +- load Kernel boot sector at 0x10000 (first 512 bytes) +- read 0x10000+0x1f1 number of sectors + => minimal 4 sectors (if 0 is in 1f1), number of setup sectors +- read 0x10200 (second part of the zero page) +- compare 0x10202 to linux header 'HdrS', must be equal +- compare 0x10206 to linux boot protocol version, don't allow anything + below 0x215 (the newest one) for now +- set various zero page data + - test for KASLR enabled + 0x10211 has bit 1 set? + (this we might not want to do for old i486 kernels and systems) + - set 0xFF for non-registered boot loader in 0x10210 + - set 0x80 in loadflags 0x10211 + - CAN_USE_HEAP (bit 7) + - LOADED_HIGH? where do we load protected mode code? + - set head_end_ptr 0x10224 to 0xde00 + ; heap_end = 0xe000 + ; heap_end_ptr = heap_end - 0x200 = 0xde00 + mov word [es:0x224], 0xde00 ;head_end_ptr + "Set this field to the offset (from the beginning of the real-mode + code) of the end of the setup stack/heap, minus 0x0200." + - set 0x10228 to 0x1e000 + set to mov dword [es:0x228], 0x1e000 ;cmd line ptr + mov dword [es:0x228], 0x1e000 ; set cmd_line_ptr + also copy your command line to 0x1e000, for now from the boot loader + data segment (initialized data) area. + At offset 0x0020 (word), “cmd_line_magic”, enter the magic number 0xA33F. + At offset 0x0022 (word), “cmd_line_offset”, enter the offset of the kernel command line (relative to the start of the real-mode kernel). + The kernel command line must be within the memory region covered by setup_move_size, so you may need to adjust this field. +- read to 0x10400 N-1 sectors (as much as we calculated above) as the + real mode kernel part +- 0x1001f4 is the 16-byte paragraphs of 32-bit code for protected mode + kernel to load -> transform to 512 byte sectors to read +- eventually get the prefered loading location for the kernel +- load the protected part to 0x100000 by loading it to low memory and + copy it to high memory in unreal mode +- print kernel version number, 020E, offset, but we must load the complete + kernel first +- at end of kernel PM code read check if we have the same size as the tar + entry +- run_kernel (real mode) + cli + mov ax, 0x1000 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov sp, 0xe000 + jmp 0x1020:0 +- eventually get the prefered loading location for the ramdisk + or highest possible location (should make the kernel happy), but + then we have to know a little bit about the memory layout and size of + the machine.. +- read ram image + - read octal size in tar metadata of ramdisk, convert do decimal + - set address and size in kernel zero page + - 0x218/4 ramdisk image address + - 0x21c/4 ramdisk image size + +Bochs commands +-------------- + +# have a look at the boot.map file for the address of a symbol +# set breakpoint +b 0x7F93 + +# dump memory in floppy read buffer +x /30b 0x0008800 + +# dump real mode kernel code/data +x /30b 0x0010000 + +interrupts +---------- + +Relevant interrupts as documented in http://www.cs.cmu.edu/~ralf/files.html: + +--------B-1302------------------------------- +INT 13 - DISK - READ SECTOR(S) INTO MEMORY + AH = 02h + AL = number of sectors to read (must be nonzero) + CH = low eight bits of cylinder number + CL = sector number 1-63 (bits 0-5) + high two bits of cylinder (bits 6-7, hard disk only) + DH = head number + DL = drive number (bit 7 set for hard disk) + ES:BX -> data buffer +Return: CF set on error + if AH = 11h (corrected ECC error), AL = burst length + CF clear if successful + AH = status (see #00234) + AL = number of sectors transferred (only valid if CF set for some + BIOSes) +Notes: errors on a floppy may be due to the motor failing to spin up quickly + enough; the read should be retried at least three times, resetting + the disk with AH=00h between attempts + most BIOSes support "multitrack" reads, where the value in AL + exceeds the number of sectors remaining on the track, in which + case any additional sectors are read beginning at sector 1 on + the following head in the same cylinder; the MSDOS CONFIG.SYS command + MULTITRACK (or the Novell DOS DEBLOCK=) can be used to force DOS to + split disk accesses which would wrap across a track boundary into two + separate calls + the IBM AT BIOS and many other BIOSes use only the low four bits of + DH (head number) since the WD-1003 controller which is the standard + AT controller (and the controller that IDE emulates) only supports + 16 heads + AWARD AT BIOS and AMI 386sx BIOS have been extended to handle more + than 1024 cylinders by placing bits 10 and 11 of the cylinder number + into bits 6 and 7 of DH + under Windows95, a volume must be locked (see INT 21/AX=440Dh/CX=084Bh) + in order to perform direct accesses such as INT 13h reads and writes + all versions of MS-DOS (including MS-DOS 7 [Windows 95]) have a bug + which prevents booting on hard disks with 256 heads (FFh), so many + modern BIOSes provide mappings with at most 255 (FEh) heads + some cache drivers flush their buffers when detecting that DOS is + bypassed by directly issuing INT 13h from applications. A dummy + read can be used as one of several methods to force cache + flushing for unknown caches (e.g. before rebooting). +BUGS: When reading from floppies, some AMI BIOSes (around 1990-1991) trash + the byte following the data buffer, if it is not arranged to an even + memory boundary. A workaround is to either make the buffer word + aligned (which may also help to speed up things), or to add a dummy + byte after the buffer. + MS-DOS may leave interrupts disabled on return from this function. + Apparently some BIOSes or intercepting resident software have bugs + that may destroy DX on return or not properly set the Carry flag. + At least some Microsoft software frames calls to this function with + PUSH DX, STC, INT 13h, STI, POP DX. + on the original IBM AT BIOS (1984/01/10) this function does not disable + interrupts for harddisks (DL >= 80h). On these machines the MS-DOS/ + PC DOS IO.SYS/IBMBIO.COM installs a special filter to bypass the + buggy code in the ROM (see CALL F000h:211Eh) +SeeAlso: AH=03h,AH=0Ah,AH=06h"V10DISK.SYS",AH=21h"PS/1",AH=42h"IBM" +SeeAlso: INT 21/AX=440Dh/CX=084Bh,INT 4D/AH=02h + +--------B-1300------------------------------- +INT 13 - DISK - RESET DISK SYSTEM + AH = 00h + DL = drive (if bit 7 is set both hard disks and floppy disks reset) +Return: AH = status (see #00234) + CF clear if successful (returned AH=00h) + CF set on error +Note: forces controller to recalibrate drive heads (seek to track 0) + for PS/2 35SX, 35LS, 40SX and L40SX, as well as many other systems, + both the master drive and the slave drive respond to the Reset + function that is issued to either drive +SeeAlso: AH=0Dh,AH=11h,INT 21/AH=0Dh,INT 4D/AH=00h"TI Professional" +SeeAlso: INT 56"Tandy 2000",MEM 0040h:003Eh + +--------B-1308------------------------------- +INT 13 - DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI) + AH = 08h + DL = drive (bit 7 set for hard disk) + ES:DI = 0000h:0000h to guard against BIOS bugs +Return: CF set on error + AH = status (07h) (see #00234) + CF clear if successful + AH = 00h + AL = 00h on at least some BIOSes + BL = drive type (AT/PS2 floppies only) (see #00242) + CH = low eight bits of maximum cylinder number + CL = maximum sector number (bits 5-0) + high two bits of maximum cylinder number (bits 7-6) + DH = maximum head number + DL = number of drives + ES:DI -> drive parameter table (floppies only) +Notes: may return successful even though specified drive is greater than the + number of attached drives of that type (floppy/hard); check DL to + ensure validity + for systems predating the IBM AT, this call is only valid for hard + disks, as it is implemented by the hard disk BIOS rather than the + ROM BIOS + the IBM ROM-BIOS returns the total number of hard disks attached + to the system regardless of whether DL >= 80h on entry. + Toshiba laptops with HardRAM return DL=02h when called with DL=80h, + but fail on DL=81h. The BIOS data at 40h:75h correctly reports 01h. + may indicate only two drives present even if more are attached; to + ensure a correct count, one can use AH=15h to scan through possible + drives + Reportedly some Compaq BIOSes with more than one hard disk controller + return only the number of drives DL attached to the corresponding + controller as specified by the DL value on entry. However, on + Compaq machines with "COMPAQ" signature at F000h:FFEAh, + MS-DOS/PC DOS IO.SYS/IBMBIO.COM call INT 15/AX=E400h and + INT 15/AX=E480h to enable Compaq "mode 2" before retrieving the count + of hard disks installed in the system (DL) from this function. + the maximum cylinder number reported in CX is usually two less than + the total cylinder count reported in the fixed disk parameter table + (see INT 41h,INT 46h) because early hard disks used the last cylinder + for testing purposes; however, on some Zenith machines, the maximum + cylinder number reportedly is three less than the count in the fixed + disk parameter table. + for BIOSes which reserve the last cylinder for testing purposes, the + cylinder count is automatically decremented + on PS/1s with IBM ROM DOS 4, nonexistent drives return CF clear, + BX=CX=0000h, and ES:DI = 0000h:0000h + machines with lost CMOS memory may return invalid data for floppy + drives. In this situation CF is cleared, but AX,BX,CX,DX,DH,DI, + and ES contain only 0. At least under some circumstances, MS-DOS/ + PC DOS IO.SYS/IBMBIO.COM just assumes a 360 KB floppy if it sees + CH to be zero for a floppy. + the PC-Tools PCFORMAT program requires that AL=00h before it will + proceed with the formatting + if this function fails, an alternative way to retrieve the number + of floppy drives installed in the system is to call INT 11h. + In fact, the MS-DOS/PC-DOS IO.SYS/IBMBIO.COM attempts to get the + number of floppy drives installed from INT 13/AH=08h, when INT 11h + AX bit 0 indicates there are no floppy drives installed. In addition + to testing the CF flag, it only trusts the result when the number of + sectors (CL preset to zero) is non-zero after the call. +BUGS: several different Compaq BIOSes incorrectly report high-numbered + drives (such as 90h, B0h, D0h, and F0h) as present, giving them the + same geometry as drive 80h; as a workaround, scan through disk + numbers, stopping as soon as the number of valid drives encountered + equals the value in 0040h:0075h + a bug in Leading Edge 8088 BIOS 3.10 causes the DI,SI,BP,DS, and ES + registers to be destroyed + some Toshiba BIOSes (at least before 1995, maybe some laptops??? + with 1.44 MB floppies) have a bug where they do not set the ES:DI + vector even for floppy drives. Hence these registers should be + preset with zero before the call and checked to be non-zero on + return before using them. Also it seems these BIOSes can return + wrong info in BL and CX, as S/DOS 1.0 can be configured to preset + these registers as for an 1.44 MB floppy. + the PS/2 Model 30 fails to reset the bus after INT 13/AH=08h and + INT 13/AH=15h. A workaround is to monitor for these functions + and perform a transparent INT 13/AH=01h status read afterwards. + This will reset the bus. The MS-DOS 6.0 IO.SYS takes care of + this by installing a special INT 13h interceptor for this purpose. + AD-DOS may leave interrupts disabled on return from this function. + Some Microsoft software explicitly sets STI after return. +SeeAlso: AH=06h"Adaptec",AH=13h"SyQuest",AH=48h,AH=15h,INT 1E +SeeAlso: INT 41"HARD DISK 0" + +(Table 00242) +Values for diskette drive type: + 01h 360K + 02h 1.2M + 03h 720K + 04h 1.44M + 05h ??? (reportedly an obscure drive type shipped on some IBM machines) + 2.88M on some machines (at least AMI 486 BIOS) + 06h 2.88M + 10h ATAPI Removable Media Device +--------d-1308------------------------------- +INT 13 - V10DISK.SYS - SET FORMAT + AH = 08h + AL = number of sectors + CH = cylinder number (bits 8,9 in high bits of CL) + CL = sector number + DH = head + DL = drive +Return: AH = status code (see #00234) +Program: V10DISK.SYS is a driver for the Flagstaff Engineering 8" floppies +Note: details not available +SeeAlso: AH=03h,AH=06h"V10DISK.SYS" + +references +---------- + +- kernel boot up in all it's details, really nice documentation: + - https://www.kernel.org/doc/html/latest/x86/boot.html + - https://www.kernel.org/doc/html/latest/x86/zero-page.html + - https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + - https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html +- debug kernel with bochs + - https://bochs.sourceforge.io/doc/docbook/user/debugging-with-gdb.html + - https://www.kernel.org/doc/html/v4.12/dev-tools/gdb-kernel-debugging.html + - https://www.cs.princeton.edu/courses/archive/fall09/cos318/precepts/bochs_gdb.html +- interrupt list and BIOS documentation + - http://www.cs.cmu.edu/~ralf/files.html + - https://members.tripod.com/vitaly_filatov/ng/asm/ +- Linux boot protocol + - https://docs.kernel.org/x86/boot.html + - https://www.spinics.net/lists/linux-integrity/msg14580.html: version string +- get available memory + - http://www.uruk.org/orig-grub/mem64mb.html + - https://wiki.osdev.org/Detecting_Memory_(x86) +- create ramdisk.img: + https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html +- tar format + - https://wiki.osdev.org/USTAR + - https://en.wikipedia.org/wiki/Tar_(computing)#UStar_format + - https://github.com/calccrypto/tar + - https://github.com/Papierkorb/tarfs +- other minimal bootloader projects + - https://github.com/wikkyk/mlb + - https://github.com/owenson/tiny-linux-bootloader and + https://github.com/guineawheek/tiny-floppy-bootloader + - http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html (Small C and 16-bit code, + leads to a quite big boot loader, in the end we didn't use C but Unreal mode 16/32-bittish assembly) + - https://wiki.syslinux.org/wiki/index.php?title=The_Syslinux_Project + - Lilo (but the code is hard to read and looks quite chaotic) + - Linux 1.x old boot floppy code + +todos +----- + +- have an early console also for serial (uart8250 in assembly, yuck) +- the kernel parameters are in boot.asm hard-coded, cannot be passed + from outside +- test more A20 switching stuff on real hardware +- better detection of swapped disks (but do we want a special sector + with disk 2 of 5? This is much harder to create) +- test other floppy sizes diff --git a/doc/www.os2museum.com_wp_a-brief-history-of-unreal-mode.txt b/doc/www.os2museum.com_wp_a-brief-history-of-unreal-mode.txt new file mode 100644 index 0000000..a02d0be --- /dev/null +++ b/doc/www.os2museum.com_wp_a-brief-history-of-unreal-mode.txt @@ -0,0 +1,1626 @@ + #[1]OS/2 Museum Feed [2]OS/2 Museum Comments Feed [3]OS/2 Museum + A Brief History of Unreal Mode Comments Feed [4]alternate [5]alternate + [6]alternate + + [7]OS/2 Museum + OS/2, vintage PC computing, and random musings + [8]Skip to content + * [9]Home + * [10]About + + [11]Wanted List + * [12]OS/2 History + + [13]OS/2 Beginnings + + [14]OS/2 1.0 + + [15]OS/2 1.1 + + [16]OS/2 1.2 and 1.3 + + [17]OS/2 16-bit Server + + [18]OS/2 2.0 + + [19]OS/2 2.1 and 2.11 + + [20]OS/2 Warp + + [21]OS/2 Warp, PowerPC Edition + + [22]OS/2 Warp 4 + + [23]OS/2 Timeline + + [24]OS/2 Library + o [25]OS/2 1.x SDK + o [26]OS/2 1.x Programming + o [27]OS/2 2.0 Technical Library + + [28]OS/2 Videos, 1987 + * [29]DOS History + + [30]DOS Beginnings + + [31]DOS 1.0 and 1.1 + + [32]DOS 2.0 and 2.1 + + [33]DOS 3.0, 3.1, and 3.2 + + [34]DOS 3.3 + + [35]DOS 4.0 + + [36]DOS Library + * [37]NetWare History + + [38]NetWare Timeline + + [39]NetWare Library + * [40]Windows History + + [41]Windows Library + * [42]PC UNIX History + + [43]Solaris 2.1 for x86 + + [44]<- USB 0.9 + [45]ANOMALY: meaningless REX prefix used -> + +A Brief History of Unreal Mode + + Posted on [46]June 15, 2018 by [47]Michal Necasek + + After a run-in with a particularly crazy manifestation of unreal mode + (Flat Assembler, or [48]fasm), I decided to dig deeper into the history + of this undocumented yet very widely used feature of 32-bit x86 + processors. + + For the purposes of this discussion, unreal mode is a variant of the + x86 real mode with non-standard segment limits and/or attributes, + different from the processor state at reset. To recap, real mode on the + 286 and later CPUs has much more in common with protected mode than + with the real (and only) mode of the 8086. Notably, undefined opcodes + raise exceptions, segment limit overruns cause general protection or + stack faults, and (on the 386 and later) 32-bit registers and 32-bit + addressing can be used--subject to limit checks. + + The origins of unreal mode are shrouded in the mists of time. But + enough is known that certain outlines are quite clearly defined. Let's + present a rough timeline of unreal mode. + * 1985--the Intel 386 became available in silicon. Like the 286, the + 386 was not designed to switch from protected back to real mode. + Intel's idea was presumably that users should either leave the 386 + in real mode, reset the CPU to get back to it (like a 286), or use + the 386's new V86 mode. This may sound like a crazy claim, but it's + not. In the October 15, 1991 issue of PC Magazine, page 436 + ("Stepping Up"), Jeff Prosise [49]wrote quite clearly: "The very + first 80386 chips that rolled off the line (A-step chips) could not + be switched from protected to real mode." Indeed the confidential + Intel iAPX 386 Architecture Specification, revision 1.8 from June + 1985, had only this to say on the subject of switching from + protected back to real mode: "Disabling protection by loading a 0 + into the PE bit in CR0 (assuming the current value is 1) will have + unpredictable effects." In other words, the original 386 design + tracked the 286: in real mode, segment limits and attributes retain + their initial reset values and cannot be changed. + * 1985?--someone or someones (Microsoft? Compaq?) convinced Intel to + relent and allow switching from protected to real mode by clearing + the PE bit in control register CR0; this was no doubt inspired by + the headaches the 286 was causing. It is unclear if there was + actual silicon change or only a documentation change. While a + transition to V86 mode always carefully loads all segment + registers, making any funny business impossible, the act of + clearing the PE bit in CR0 does almost nothing. It affects future + segment register loads in real mode, it affects interrupt and + exception dispatching, but it has near zero impact on the immediate + CPU state. Crucially, it does not change the current segment limits + or attributes, which allows the currently executing code to + continue running. Note that the I/O Permission Bitmap (applicable + in protected mode) was an even later addition to the 386 design. + * October 1985--The 386 datasheet (80386 High Performance + Microprocessor with Integrated Memory Management, Intel order no. + 231630-001), says in section 2.3.5: "In Real Address Mode, only the + base address is updated directly (by shifting the selector value + four bits to the left) [when loading segment registers], since the + segment maximum limit and attributes are fixed in Real Mode." In + section 2.3.4, the document says: "In Real Address Mode, the + maximum segment size is fixed at 64 Kbytes." In other words, this + document both explains why unreal mode works and claims that it + does not exist. The datasheet also declares in section 2.3.6 that + switching back to real mode is possible, but no additional detail + is given: "If PE [bit in CR0 register] is reset, the processor + operates again in Real Mode. PE may be set by loading MSW or CR0. + PE can be reset only by a load into CR0." + * January 8, 1986--Intel writes a confidential memo titled Returning + to real mode on the 80386. This memo explains not only how to set + up a canonical real-mode environment on return from real mode, but + also why it is necessary: "While operating in REAL mode, the 80386 + uses exactly the same memory management functions as in protected + mode. However, when the part resets into real mode the values + loaded into the descriptors appear as if they were 8086 style + segments. In real mode, when a segment register is loaded, only the + base field is changed, in particular the value placed into the base + is selector*16. Since only the base is changed, it is necessary to + set the access rights while still in protected mode." The memo + proceeds to explain the required segment attribute setup, + information which appeared in the official 1986 PRM (Programmer's + Reference Manual) for the 80386. What the memo also says, and the + PRM does not, is that the code segment (CS) cannot be made writable + in protected mode, but "an architectural feature reloads real mode + attributes into the CS descriptor during real mode far jumps". This + memo explains real-mode operation of the 386 far better than the + official documentation, and serves unreal mode on a silver platter + to anyone willing to experiment even just a little. + * April 1986--The updated 386 datasheet, Intel order no. 231630-002, + offers a tantalizing hint of unreal mode in section 2.3.6: + "Resetting the PE bit [in CR0] is typically part of a longer + instruction sequence needed for proper transition from Protected + Mode to Real Mode." The quoted text was not present in the original + October 1985 edition of the datasheet, and presumably refers to the + information first published in the Jan '86 memo. + * 1986--The 1986 Intel 80386 Programmer's Reference Manual says that + to switch from protected to real mode, the programmer must among + other things transfer control to a code segment with 64K limit, and + load SS, DS, ES, FS, and GS segment registers with selectors that + have a 64K limit, are byte granular, expand-up, writable, and + present. Only then can CR0.PE be cleared. In other words, Intel was + practically begging programmers to see what happens when they don't + do that. The PRM publishes the how-to information from the Jan '86 + memo, but none of the background explanation. + * 1987--In the 1987 edition of the 80386 System Software Writer's + Guide (Intel order no. 231499-001), in section 9.2 on page 9-3 (4th + para), Intel hints: "Because, except for base address, descriptor + register values cannot be loaded in real mode, 8086-compatible + attributes must be loaded into the data segment descriptor + registers before switching to real mode." + * January 15, 1988--Phoenix 386 BIOS with this date employs unreal + mode to emulate some aspects of the 286 LOADALL instruction, by + returning to real mode with segment bases not corresponding to the + segment register value. The date is tentative; this was the oldest + 386 BIOS using this technique available for analysis. More below. + * August 4, 1988--Microsoft adds 386 "Big Mode" or "Real Big Mode" + code to implement 386 extended memory moves in HIMEM.SYS 2.04. + Microsoft's method is quite clever, using an exception handler to + recover from anyone resetting the segment limits behind HIMEM's + back. Extended memory copying can thus be run with interrupts + enabled, with no impact on interrupt latency (that was a + significant problem on 286 CPUs). The term "unreal mode" is not + used. This change can be dated exactly, thanks to comments in + HIMEM.ASM. At the same time, LOADALL support was added to the HIMEM + 286 extended memory move. + * August 15, 1988--Microsoft makes an archive of the HIMEM.SYS 2.04 + source code, with LOADALL usage removed but unreal mode code left + in place. It is unclear how widely this code was distributed at the + time. In 1992, the source archive from 1988 was published on + Softlib as part of [50]XMS.EXE, which contains the new XMS 3.0 + specification. In the late 1980s and early 1990s, Microsoft + published the HIMEM.SYS source code together with the XMS 2.0 + specification (the first published version was 2.01, before the + unreal mode code was added). + * February 7, 1989--Microsoft [51]publishes HIMEM.SYS version 2.06 + source code as XMS20.ARC; unlike the previous release, this one + produces an exact match of the official binary, because the source + code includes 386 Real Big Mode and 286 LOADALL (yes, really!) + support. + * March 21, 1989--Microsoft publishes an updated HIMEM.SYS version + 2.06 source archive as S12023.EXE, formerly XMS20.ARC. This one + [52]survived to the present. Although the 1989 source code releases + were public, they seem to have gone more or less completely + unnoticed. + * 1989--In the 386 SX Microprocessor Programmer's Reference + Manual (order no. 140331-001), section 14.5 (Switching Back to + Real-Address Mode), Intel drops another big hint. To the paragraph + describing how to load segment registers when transitioning from + protected back to real mode, the following sentence is added: "Note + that if the segment registers are not reloaded, execution continues + using the descriptors loaded during protected mode." The same text + is also added to the updated 1990 edition of the 386 DX PRM, and + appears in the 1990 i486 PRM and all subsequent Intel programming + manuals. + * November 1989--In the November/December issue of Programmer's + Journal, Thomas Roden (a software engineer at AST Research, one of + the big PC OEMs) publishes an article titled Four Gigabytes in Real + Mode (page 89). This is the oldest known public description of + unreal mode, although the term "unreal mode" is never used. Unreal + mode is described, including the exception handler technique to + handle other code resetting the segment limits. Thanks to his + position at AST Research, Mr. Roden was already able to confirm + that unreal mode works not only on the 386DX and SX, but also on + the then-brand-new Intel 80486. The article mentions that it may be + possible to set the D-bit of the code segment to run in real mode + with 32-bit CS. There is no explicit mention or even a hint that + Mr. Roden was aware that HIMEM.SYS was already using unreal mode. + * January 1990--In the German c't magazine, Harald Albrecht publishes + an article titled Grenzenlos: Vier Gigabyte im Real Mode des 80386 + adressieren (Boundless: Addressing four gigabytes in 80386's real + mode). Mr. Albrecht suggests that the 386 documentation directly + challenges programmers to not follow the prescribed + return-to-real-mode method exactly. The article is notable for + documenting that in real mode, a far jump partially changes CS + attributes, and also that after a switch to/from protected mode, a + near jump is sufficient to flush the prefetch queue (a far jump is + not necessary). Mr. Albrecht does not name the non-standard real + mode but presents a TSR which implements a fast INT 15h/87h block + move routine which uses 4GB selector limits, runs with interrupts + enabled, and does not disable the A20 gate when done. The author + incorrectly claims that (paraphrasing) no one needs the A20 gate + disabled, something that others learned the hard way not to be + true. Mr. Albrecht also notes that the segment limit extension + technique is unusable in V86 mode, and that 32-bit code or stack + segments are not practical due to corruption of the high word of + EIP/ESP. The article was probably written at about the same time as + Mr. Roden's PJ article; it may be an independent discovery, + although Mr. Albrecht's earlier article in the November 1989 issue + of c't (Odyssee im Adressraum) explicitly mentions the HIMEM.SYS + source code provided in Microsoft's XMS Developer's Kit. + * July 1990--In the July 1990 issue of Dr. Dobb's Journal, Al + Williams publishes an article titled DOS + 386 = 4 Gigabytes! (page + 62), again describing unreal mode. The article is by all + appearances another independent discovery of unreal mode, as there + are no hints Mr. Williams was aware of either HIMEM.SYS or the + Nov/Dec '89 PJ article. Again, the term unreal mode is not used. + * October 1990--In the October 1990 issue of DDJ (page 12), a reader + letter from Thomas Roden appears, pointing out minor problems with + the July '90 DDJ article about unreal mode. It is clear from the + letter that Mr. Roden had access to an ICE (In-Circuit Emulator), + which no doubt greatly eased unreal mode experimentation. An + editor's note identifies Mr. Roden as the author of the Nov/Dec '89 + PJ article. + * January 1991--On page 176 of the 1/91 issue of German DOS + International magazine, an article titled Vier GByte im Real Mode + unter MS-DOS (Four Gigabytes in Real Mode under MS-DOS) by Martin + Althaus explains in detail how to change segment limits to enable + full 4GB addressing in real mode. The necessity of enabling the A20 + gate is discussed, and complete example code is presented; the + article also notes that the technique does not work when EMM386 (or + V86 mode in general) is in use. The article does not explore what + might happen if segment attributes in real mode are changed in + other ways, beyond setting the G bit. The author does not claim to + have invented the unnamed technique, but also does not give any + references to earlier publications. + * March 1991--In Chapter 18 of Assembly Language Programming for the + Intel 80XXX Family, William B. Giles describes in detail (page 676 + and following) how to program 386 real-mode selectors such that + they cover the entire 4GB address space. Example code is also + presented. The [53]code samples are dated September 4, 1990. The + '89 PJ article is referenced as the source of information on + expanding real-mode selector limits. + * March 1991--In Chapter 18 of DOS 5: A Developer's Guide, Al + Williams again describes unreal mode, with code examples. Note that + the exact publication date is unclear; March, August, September, + and October 1991 are given. A [54]1992 review of the book discusses + Chapter 18 in some detail, together with referencing the '90 DDJ + and '89 PJ articles. + * 1991--In 8086 Architecture & Programming Volume II: Architecture + Reference (page 72), Rakesh K. Agarwal (a former member of the + 80386 design team) clearly explains what all the official Intel + documentation carefully doesn't: "When [switching from protected to + real mode] is done, the only action taken by the 8086 is to clear + the PE flag. In particular, the current state of the descriptor + registers is left undisturbed." And further: "Such a pseudo REAL, + or UNREAL, execution mode can cause a REAL mode system to crash, + unless used very carefully" (capitalization in original). This may + be the first published use of the term "unreal mode". + * April 16, 1992--Origin releases [55]Ultima VII: The Black Gate, a + game using a custom DOS extender appropriately named "Voodoo". + Ultima VII is a proof that unreal mode is a terrible idea for DOS + applications; the game requires a significant amount of free + conventional memory, but is incompatible with 386-based DOS + extenders, as well as with any DOS-compatible advanced operating + systems. + * 1992--German DOS Extra Nr. 20 (supplement of the DOS International + magazine) publishes the HugeRealMode driver, enabling larger than + 64K code segments in unreal mode, with restrictions (more below). + * June 29, 1993--In his Tutor column starting on page 302, Jeff + Prosise [56]wrote a section on "accessing 4GB from real mode" + without using LOADALL. "Recently, another method of accessing 4GB + [...] was brought to my attention by a reader on PC MagNet." The + text gives a brief overview of unreal mode and refers to Chapter 18 + of DOS 5: A Developer's Guide by Al Williams (also the author of + the 1990 DDJ article). + * January 1994--Chapter 8 (Extended Memory Access from Real Mode) of + Geoff Chappell's DOS Internals provides a very detailed description + of unreal mode and HIMEM's use of it. There is talk of "unreal" + segment properties (quotes in original, page 356), but the chapter + is about "real-mode Flat Memory Model", and "Big Real Mode" is also + gets a mention. The chapter also provides a detailed treatment of + 286 and 386 LOADALL. It is probably the best description of the + inner workings of HIMEM.SYS. Curiously, in Chapter 12 (page 443) + Mr. Chappell grumbles that only the outdated HIMEM.SYS 2.01 source + code is available on CompuServe (apparently uploaded by Steve + Gibson of InfoWorld). Clearly, Microsoft's 1989 and 1992 HIMEM.SYS + source code releases did a very good job of flying under the radar + when they escaped Mr. Chappell's laser-like attention. + * September 21, 1994--IBM files patent application 309,862 titled + Method for expanding addressable memory range in real-mode + processing to facilitate loading of large programs into high + memory. [57]U.S. patent 5,642,491 was granted on June 24, 1997. The + patent describes unreal mode, and mentions Chappell's DOS + Internals, pages 355-385. The patent makes strange references to a + "64-kbyte wrapping feature associated with true 8086 real mode"; + that might refer to stack wrapping when PUSH and POP instruction + are used, but no such wrapping is used for data segments. The + patent suggests using unreal mode during operating system + initialization only, not at run-time. + * 1993-1995--Unreal mode becomes a thing and every up-and-coming + programmer writes a [58]utility or [59]library to use it. It is + popular among demo coders, who are dismayed when [60]EMM386 use is + mandated for Assembly '95, interfering with unreal mode. + * November 11, 1994--Italian programmer Daniele Paccaloni + [61]publishes UNREAL.EXE, a utility to enable unreal mode on a 386 + or later CPU, and UNREAL.DOC, a document explaining how unreal mode + works. In a continuation of the recurring theme, Mr. Paccaloni + appears to have been completely unaware of the fact that unreal + mode had been in use for years, or the growing body of literature + about it. It appears that Mr. Paccaloni also independently + re-invented the term "unreal mode". + * September 1995--Robert R. Collins writes an article (NB: The exact + date is uncertain, Sep '95 is a guess based on source file + timestamps) titled [62]Descriptor Cache Register Anomalies; this is + probably the definitive description of unreal mode. Mr. Collins + thoroughly explored the CPU behavior using LOADALL for 386 CPUs, + and also using SMM together with an ICE on 486, Pentium, and + Pentium Pro CPUs. Mr. Collins showed that real mode is much closer + to protected mode than one would be led to believe, and most + protections are in fact in place. Mr. Collins also found that CS + register attributes are handled differently on different CPUs + generations. On older processors, far jumps change the CS + attributes as described in the Jan '86 memo, while newer CPUs + preserve the CS attributes but ignore them in real mode. + * February 1996--In the book Protected Mode Software + Architecture (chapter 5, page 61), Tom Shanley purportedly + describes "Big Real Mode", yet makes the ridiculous claim that + segment offsets are still restricted to 64K (while the segment base + can be set to any 32-bit address before returning to real mode). + Perhaps this is just shows that unreal mode is not well understood, + despite numerous authors' attempts to explain it. + * September 20, 1996--Phoenix and Intel publish the POST Memory + Manager Specification version 1.0 (PMM specification), which + mandates the use of "big real mode" (aka unreal mode). Big Real + Mode is not explained in detail, presumably because readers already + know how it works. The PMM specification is later adopted by the + PXE and PCI firmware 3.0 standards. Intel thus manages the + astonishing feat of specifying and mandating the use of unreal + mode, while simultaneously denying that it exists. Although the + original 1.0 PMM specification may be lost, the touched-up [63]PMM + 1.01 is available. + * August 1998--Dr. Dobb's Journal does not publish an article titled + [64]The Segment Descriptor Cache by Robert R. Collins. The article + says that "[u]nreal mode has been used commonly since it was + discovered on the 80386. Unreal mode is so commonly used, in fact, + that Intel has been forced to support this mode as part of legacy + 8086 behavior, though it's never been documented." + * August 2004--(This entry is only included for completeness.) In The + Unabridged Pentium 4, Tom Shanley correctly describes unreal mode, + saying that it "is sometimes referred to as Big Real Mode, Flat + Real Mode, Real Big Mode and UnReal Mode" (italics in original). + Unfortunately the author makes new, although minor, incorrect + claims, namely that CS:IP and SS:SP are always used in real mode, + precluding larger than 64K code and stack segments. Larger than 64K + code and stack segments are indeed in practice unusable in unreal + mode, but for different reasons. + +But... Is Unreal Mode Any Good? + + Yes and no. As a general-purpose programming technique it is unusable, + because it absolutely cannot function in V86 mode. Transitions to V86 + mode always force real-mode compatible segment limits and attributes. + That means unreal mode cannot be used together with EMM386 or other DOS + memory managers utilizing V86 mode. Unreal mode also cannot be used in + the DOS boxes of 386 Enhanced Mode Windows 3.x, in the DOS boxes of + OS/2 2.x, Windows NT, or Windows 9x. That is an extremely serious + drawback. + + The reason why the Voodoo memory manager in Origin's Ultima VII games + is unique is that no one else wanted to repeat the same mistake. The + Ultima VII: The Black Isle credits capture the situation rather well: + Ultima VII's Voodoo Memory Management System + + On the other hand, when unreal mode can be used, it is very useful. + HIMEM.SYS uses unreal mode to speed up extended memory access, and + perhaps more importantly, preserve normal interrupt latency. Firmware + can and does use unreal mode for accessing memory beyond 1 MB during + initialization; it avoids switching between real and protected mode, + and in firmware there is no danger of segment limits being reset. + + Basic unreal mode (data segments with up to 4G limits, as well as data + segments with non-standard base) has become a standard part of the x86 + architecture. + +Unreal LOADALL + + At least as far back as January 1988, Phoenix 386 BIOS combined two + undocumented favorites, using unreal mode to emulate the 286 LOADALL + instruction. When handling an invalid opcode fault, the BIOS checks + whether the faulting instruction is a 286 LOADALL (opcode 0Fh 05h); if + so, it examines the provided LOADALL state buffer at address 800h and + checks whether the segment bases for ES and/or DS are 1MB or higher. If + so, the BIOS builds descriptors with the appropriate bases, loads them + in protected mode, and returns to real mode with these "unreal" values + in the segment descriptor cache (segment base other than 16 times + segment value). The segment bases will get overwritten as soon as ES or + DS gets reloaded in real mode, but that is entirely consistent with + LOADALL behavior. + + The LOADALL emulation is very limited, but it is sufficient to support + the [65]use of LOADALL in OS/2, and possibly others. + + The detailed history of this method is unclear. What's known is that + the first 386 BIOS, shipped with the Compaq DeskPro 386 in 1986, did + not use unreal mode. Compaq was clearly on good terms with Intel and + got the secret memo describing the 386 LOADALL instruction. The Compaq + 386 BIOS emulated 286 LOADALL rather accurately using the 386 LOADALL + instruction, going at least as far back as September 1986 and + continuing to use the same method at least until 1989 (it would no + longer work on a 486 CPU). + + IBM's PS/2 Model 80 BIOS did not emulate LOADALL at all, and is + therefore uninteresting. + + There are also known to have been more or less no-name 386 systems sold + around 1987 which used effectively a 286 BIOS and had no provisions to + emulate LOADALL, nor did they use 386 instructions at all. + + It is unknown when Phoenix first introduced unreal mode usage to + emulate LOADALL, or if other vendors did that before Phoenix. Clone 386 + BIOS images from before 1988 are rather difficult to find. + +Unreal Mode Compatibility + + Basic unreal mode with extended DS, ES, FS, and/or GS segment limits is + widely compatible across all 32-bit x86 CPU implementations. After all + that's what is mandated by PMM and by extension, PXE and PCI 3.0 + Firmware specifications, all standards created with a significant + involvement of Intel. + + Extending data segment limits in fact causes shockingly few problems, + as evidenced by the fact that HIMEM.SYS does just that. On an 8086, + referencing a word at offset 0FFFFh causes a wrap-around and the second + byte is fetched from offset zero. The 286 is already incompatible with + this behavior, causing a #GP fault. On a 386, any attempt to address + beyond 64K likewise causes #GP faults, which are typically fatal. + Therefore, functioning software does not do it and extending the + segment limit has no visible impact. + + Anything else gets more complicated, and interrupts are the number one + enemy. For example, Intel CPUs typically support non-standard data + segment attributes; it's possible to make DS read-only, but that won't + be terribly useful when running real-mode software. It is likewise + possible to set the segment limit smaller than 64K, but that won't make + 16-bit software happy. + + It is possible to extend the CS limit up to 4GB and use 32-bit EIP in + unreal mode. In practice that is not very usable because interrupts in + real mode only save 16-bit IP and restore it on return. The German DOS + Extra magazine presented a [66]hair-raising scheme to solve the + problem, using the CR3 register to store the high word of EIP so that + it could be restored on return from interrupts, but this requires + software to manually keep track of the high word. In practice, larger + than 64K code segments are unusable in unreal mode because the + complications very quickly outweigh any benefits unreal mode might + have. + + It is also possible to set the D bit in CS, changing the default + operand size to 32-bit. This may reduce the size of unreal code if it + is largely 32-bit (by obviating the need for overrides). Unfortunately, + this again causes serious trouble with interrupts, because existing + 16-bit code cannot run correctly with the D bit set. It is possible to + switch to protected mode, clear the D bit, and execute the 16-bit + handler every time an interrupt occurs, and in fact it's [67]exactly + what fasm does (or at least did in some versions), but with so much + mode switching and complexity, the advantages of unreal mode are + rapidly lost. + + Similar trouble strikes when attempting to use larger than 64K stack + segments. It is possible, but again destroys compatibility with + existing 16-bit real-mode code. The complications are such that one + might as well use a regular DOS extender and skip all the unreal mode + incompatibilities. + + A larger problem is that the "advanced" aspects of unreal mode may not + be implemented identically across CPU generations and vendors, + precisely because they have never been documented. It is not specified + anywhere exactly which segment attributes are ignored and which are + honored in real mode. Protected mode, on the other hand, works + consistently. + +What Does It All Mean? + + Unreal mode is almost certainly an accident of history, a side effect + of the fact that the initial 386 design had no architected way of + switching from protected mode back to real mode. Once the technique + started being used, instead of clearly documenting how it works, Intel + in its typical fashion documented only certain aspects of it, such that + only programmers who already know about unreal mode find traces of it + in the official documentation. + + On the other hand, Intel did leave enough hints in the public + documentation that unreal mode appears to have been independently + discovered a number of times. What is fascinating is that Microsoft + apparently implemented unreal mode support in HIMEM.SYS and made its + source code available before any literature on unreal mode was + published. Starting in late 1989, articles describing unreal mode were + written without knowing of each other, and likely without knowing of + Microsoft's prior published work. Reinventing wheels may be satisfying, + but in the end it's just not very productive. + + PS: Images of 386 clone BIOSes (other than Compaq and IBM) from 1987 + and earlier would be worth checking for LOADALL emulation and possible + other unreal mode use. + + Feb 2021 Update: The original 231630-001 datasheet has now been + recovered and this post updated accordingly. + This entry was posted in [68]386, [69]Corrections, [70]Microsoft, + [71]PC history, [72]Undocumented. Bookmark the [73]permalink. + [74]<- USB 0.9 + [75]ANOMALY: meaningless REX prefix used -> + +43 Responses to A Brief History of Unreal Mode + + 1. [76]Neozeed says: + [77]June 15, 2018 at 5:38 am + The PCem folks are doing a good job of getting numerous 286/386 + BIOS running on their framework, they ought to have quite a number + of images. + 2. [78]Yuhong Bao says: + [79]June 15, 2018 at 6:35 am + The fun thing is that they never changed the LMSW instruction. I + wonder why/ + 3. dosfan says: + [80]June 15, 2018 at 8:33 am + Good article but why were you using fasm ? What fasm is doing + (32-bit real mode and relocating the IVT via LIDT) is crazy as it's + too much effort for too little gain and too many compatibility + issues. I'm not sure which is crazier, that or attempting to use + real mode paging on the 386 (which isn't allowed on 486 or later + CPUs). + 4. God says: + [81]June 15, 2018 at 1:59 pm + Love these sorts of "software archaeology" articles Michal - always + informative (and a pleasure) to read. However, something of a typo + jumped out at me: + >August 1998--Dr. Dobb's Journal does NOT publish an article titled + The Segment Descriptor Cache + 5. Michal Necasek says: + [82]June 15, 2018 at 7:07 pm + Presumably because someone was calling it in protected mode with + the PM bit clear, and expected to stay in protected mode... + 6. Michal Necasek says: + [83]June 15, 2018 at 7:07 pm + Oh, there are zillions of BIOS images out there. But 386 BIOS + images from 1986-87? Nada... + 7. Michal Necasek says: + [84]June 15, 2018 at 7:09 pm + I wasn't, I think the author is certifiably insane But someone else + using it made me aware of certain curious behaviors. + 8. Michal Necasek says: + [85]June 15, 2018 at 7:09 pm + It's not a typo. I could find no evidence that the article was ever + published in DDJ. + 9. Richard Wells says: + [86]June 15, 2018 at 9:18 pm + Early 386 BIOSes: Don Maslin's collection of ROMs includes the AMI + BIOS copyright 1987. I don't believe anyone has collected the + Phoenix BIOS used in the 1986 ALR 386 system. + While an interesting collection of the history, I believe you + overlooked one minor article. The October 1988 issue of Doctor + Dobbs had an article entitled "80386 PROTECTED MODE INITIALIZATION" + by Neal Marguiles (Intel employee). That title is a misnomer. It + covers the allocation of a 4 GB address space followed by a return + to real mode plus some other interesting concepts. + [87]http://www.drdobbs.com/80386-protected-mode-initialization/1844 + 08010 + 10. Rugxulo says: + [88]June 16, 2018 at 1:37 am + Actually, latest stable FASM seems to be 1.73.04, which silently + omits the unreal hack, hence you basically have to always use the + DPMI fallback nowadays. Not exactly sure why, he didn't (AFAIR) + publicly mention dropping it or why, nor whether it will come back + (somewhat unlikely, but he was always proud of his hack). Maybe it + (again) conflicted with his (Linux) 64-bit hosted version hack + (fasm.x64). Dunno, it's very complicated! + 11. dosfan says: + [89]June 16, 2018 at 2:17 am + A gross hack like that belongs in a technology demo, not production + software. + I'm not sure why anyone would bother with fasm in the first place ? + If you're writing assembly language code for DOS or Windows then + there's no reason not to use MASM which was *the* industry standard + or the highly MASM-compatible JWasm (or whatever its successor is). + 12. [90]Yuhong Bao says: + [91]June 18, 2018 at 2:47 am + Thinking about it, I wonder if reloading the real mode CS + attributes was the main change that allowed switching back to real + mode. It is unfortunate that writable code segments did not make + even the 80386 BTW. + 13. techfury90 says: + [92]June 18, 2018 at 3:33 am + Unreal mode seems to have been known to PC-98 programmers to an + extent as well. Oldest reference I can find is from April 1995: + [93]http://www.tsg.ne.jp/buho/189/tsg189.html#8086 + Author may have discovered it independently. There may be earlier + examples in books and/or magazines, but I have yet to uncover them. + Their description of their first cited source is slightly + ambiguous: it's possible that they learned about unreal mode from + them. The stumbling block is that I cannot seem to find their name + for unreal mode in general. I don't think they adopted the name we + assigned to it, if there is even a "well-known" name. + 14. dosfan says: + [94]June 18, 2018 at 5:11 am + Why is it referred to as "unreal mode" anyway ? That's a foolish + and terrible name. Considering that it is referred to as "big real + mode" in an Intel doc and it involves setting the big bit in the + segment descriptor that should be the official name (not that it + really matters today). Certainly "flat real mode" is reasonable + alternative since you have direct access to the entire flat 4GB + address space. + 15. Richard Wells says: + [95]June 18, 2018 at 8:53 am + "Big real mode" suggests that existing code works exactly the same + except that the segments can be larger. "Unreal mode" showcases the + differences. + Those interested in a more intentional version of a similar concept + of accessing 32-bit memory for >64K allocations from 16-bit code + could look at 1980 Data General MV 8000 documentation especially + the section "MV/8000 C/350 Program Combinations" and the following + section "Anomolies."(sic) Some of the issues DG discovered were + similar to ones that programmers using Intel chip noticed a decade + later. + 16. [96]Yuhong Bao says: + [97]June 18, 2018 at 11:38 am + In this case, the only difference is that the segment limit is + larger, and existing real mode code do work the same. + 17. Michal Necasek says: + [98]June 18, 2018 at 3:03 pm + Hmm, I don't see anything about unreal mode in that article. It + only says that "to assure proper operation after returning to real + mode, the segment registers must be loaded with real mode type + selectors while still in protected mode", which is the official + Intel party line. And the sample code does exactly that. + I think I looked at that AMI BIOS and it's much newer than 1987. + It's somewhat common that the copyright message is older than the + BIOS date. The opposite also happens. I'm sure there had to be + clone BIOSes in 1986-87 but so far I've been unable to locate any. + 18. Michal Necasek says: + [99]June 18, 2018 at 3:06 pm + I know why, It's actually automatic. The unreal mode stuff is only + used if the code segment is smaller than 64K. In the newer fasm + versions there's more code than that, so the unreal mode code path + doesn't get compiled in (or at least not used). For that reason + it's very unlikely to come back, because using > 64K unreal mode + code segments brings another, much nastier layer of complications. + 19. Michal Necasek says: + [100]June 18, 2018 at 4:12 pm + That sounds quite plausible. It would be a silicon change, but a + very localized one, and only visible from switching from protected + back to real mode. + 20. Michal Necasek says: + [101]June 18, 2018 at 4:18 pm + Unreal mode because it's real mode, but not conforming to Intel's + definition of real mode. "Big real mode" is descriptive but it's + unclear whether it covers 32-bit code segments, or code or stack + segments with > 64K limits. Same problem with "flat real mode". I + suppose you could call it "not-real" mode, or "non-protected mode", + but "unreal mode" is really better. + To be clear, at least in this article, I use the term "unreal mode" + to mean any non-canonical real mode usage. I don't think the terms + "big real mode" or "flat real mode" were used to mean anything + other than 4G data segment limits, but there's more to unreal mode + than that. For example, unreal mode would cover running with + segment limits smaller than 64K (just because it's useless doesn't + mean it can't be done). + 21. Michal Necasek says: + [102]June 18, 2018 at 4:20 pm + "Breaking the wall", I kind of like that. + 22. dosfan says: + [103]June 18, 2018 at 8:08 pm + Big real mode (4GB address space) is the only thing that was ever + useful. Changing the default bit of the code segment would break + everything. If anything should be called "unreal mode" it's that + since it's still real mode per-se (no protections) but no regular + 16-bit real mode program would run properly. + 23. Michal Necasek says: + [104]June 19, 2018 at 2:02 pm + The other thing that was clearly useful (as in widely utilized) was + 64K segments with bases at or beyond 1MB. The rest is more about + understanding how the damn architecture actually works than about + having practical value. + 24. dosfan says: + [105]June 19, 2018 at 8:22 pm + I thought that particular trick was only done via 286 LOADALL. It + is of limited use since interrupts have to be disabled because once + the segment register is reloaded the base is changed and access + beyond 1MB is lost. Big real mode makes that trick impractical. + 25. Michal Necasek says: + [106]June 19, 2018 at 10:34 pm + 286 LOADALL... and the emulation thereof on 386s. Just about every + BIOS in the late 1980s and in the 1990s does that. Disabling + interrupts for a short time is still much better than resetting the + CPU, which isn't fast. Big real mode is certainly much better, but + doesn't emulate 286 LOADALL. + 26. M says: + [107]June 20, 2018 at 12:16 pm + I am wondering if the 64K wrap-around alluded to in the IBM patents + could be a clumsy reference to A20-behavior? + 27. Michal Necasek says: + [108]June 20, 2018 at 3:33 pm + That would be really clumsy, but as an explanation it makes as much + sense as anything + 28. M says: + [109]June 20, 2018 at 10:34 pm + @Michal: Yes - and it is inconsistent with what they write about + being compatible with only pmode and real-mode apps not relying on + the wrap-around etc. and the A20 wrap-around indeed does exist (and + would not be possible to emulate w paging in unreal-mode, as is + done in V86). But yeah, definitely clumsy + 29. Richard Wells says: + [110]June 20, 2018 at 11:13 pm + All 16-bit segments wrap around unless concealed behind the complex + logic of a 16-bit huge library. Some programs depended on it; + sometimes, it just concealed a bug. IBM's note in the patent on + wrap around boils down to keeping the standard 16-bit behavior for + all programs except those that specifically expect the big segments + of unreal mode. Otherwise, a program may be caught accessing memory + it didn't plan to leading to interesting results. + [111]https://www.pcjs.org/pubs/pc/reference/microsoft/kb/Q58987/ + shows that wrap around has nothing to do with A20. + 30. Michal Necasek says: + [112]June 21, 2018 at 12:00 am + No, 16-bit segments do not wrap on a 286 or later (except for a + special case with stack pushes and pops). If you try to address + past the end of a segment, you get a #GP fault. The KB article + talks about 16-bit pointers wrapping around, which is a different + issue, and more likely than not avoids addressing past the end of a + segment. + 31. Chris M. says: + [113]June 21, 2018 at 4:11 am + AMI used dates instead of version numbers for their HiFlex BIOS + cores, hence why you would see two dates on a POST screen. One was + the "core" date/revision, and one was the built date/revision that + the vendor created. I think this changed when the WinBIOS was + introduced, but so many vendors went running to Award after that + disaster that nobody really noticed when they released a new + revision! + That 1988 Phoenix core was around for a long time, that 486 + EISA/VLB board has it despite being from 1993! (it also has the + stupid 16MB RAM limitation when ROM shadowing is enabled) I think + Dell might have used it for a long time on their custom + motherboards as well (later stuff was mostly Intel OEM). + 32. Richard Wells says: + [114]June 22, 2018 at 11:45 pm + 16-bit relative near jumps will be done modulo 64k. That happens + according to the documentation even with latest chips. There may be + an exception triggered but most real mode systems should wind up + ignoring the exception. Otherwise, code involving relative 16-bit + jumps would have failed since it required overflow/underflow + wrapping to get to the more distant parts of the segment. + Memory access is a bit different because Intel decided not to + follow the 8086 practice of turning any incorrectly aligned word + access into a pair of byte accesses which had a side effect of + handling a word that occupied both the first and last bytes of a + segment. Speed beat out correctly handling an edge case. Some + programs seemed to still work with the exception being ignored + because I remember 1990s reports of people finally noticing the + exception. (Seemed to work because who knows what was in the second + byte of that word.) + 33. Michal Necasek says: + [115]June 24, 2018 at 2:22 pm + Relative jumps are signed and sign-extended, so there's normally no + overflow and no truncation. #GP faults are fatal, in real mode they + lead to hangs (the BIOS does nothing special, the + interrupt/exception handler will likely return but it will just + re-trigger the exception immediately) or visible fatal errors + (EMM386, QEMM, NTVDM). + I don't know if with the split-word access speed beat out + compatibility or if Intel decided that it was a quirk not worth + preserving. At any rate it was a well documented difference between + the 8086 and later CPUs; how much software it affected in practice + I don't know. + 34. Pingback: [116]Michael Tsai - Blog - A Brief History of Unreal Mode + 35. [117]Yuhong Bao says: + [118]July 8, 2018 at 1:00 am + Thinking about it, I think virtual 8086 mode was designed before + they officially supported switching the 80386 to real mode, right? + 36. Michal Necasek says: + [119]July 8, 2018 at 11:31 am + Yes, definitely. And the transitions into and out of V86 mode are + clean, with no way to leave junk in segment registers. It's + apparent that Intel's idea was that with V86 mode, no one needed + real mode anymore. But in the absence of a V86 monitor built into + the BIOS(?), that wasn't so simple. + 37. Michal Necasek says: + [120]July 10, 2018 at 4:16 pm + Found this in a 1985 IEEE Micro paper by El-Ayat and Agarwal called + The Intel 80386-Architecture and Implementation: "Real mode is + useful for initialization and for configuration of the processor + data structures needed to run in native 80386 protected mode. The + recommended method for running 8086 code is called virtual 86 + mode." Intel's idea clearly was that real mode was for bring-up + only and no one would want to switch in and out. If you wanted to + run 8086 code, you were supposed to do that in a V86 monitor. Yet + another plan that did not survive first contact with reality. + 38. Al Williams says: + [121]July 29, 2018 at 7:47 am + Nice walk down memory lane. The original DDJ article was written on + my Intel Inboard 386 plugged into an XT-style motherboard. This did + not switch A20 like a "real" PC/AT and so my original code actually + would only work on the Inboard but I didn't know that. Later + versions (like in the book) would correct that. + I was looking. I got an e-mail from an Italian researcher that had + used the technique in some scholarly paper and referenced my + article for some kind of SEM or spectroscopy, but I couldn't find + that and I don't remember the exact year. + In addition -- and again, I can't remember the year -- a guy at + Software Development cornered me to tell me how he had started a + company based on the mode. I think he was selling a library or + something. I don't think he had much success. That had to be right + after it published within a year or so. I think he advertised with + a small ad in a couple of DDJs. + As for Necasek's comment, my DOS Extender PROT did run all the real + mode code like BIOS/DOS calls in V86 mode. As far as I know, it may + have been the first to do that in a nontrivial way. + 39. Michal Necasek says: + [122]July 31, 2018 at 4:14 pm + I saw the updates to your article... as I like to say, the A20 gate + is the most expensive bit in history. It never occurred to me but + of course the Inboard had to have a different A20 gate control + mechanism. + Do you remember anything about the unreal mode origins? Was that + something you independently discovered, or was it something that + was already common knowledge in certain circles? + 40. [123]Myself says: + [124]August 30, 2018 at 12:09 am + Bummer, I only have the third edition of the i386 datasheet + (231630-003, Nov. 1986). + In page 2, there is the "update notice" which lists updated + paragraphs. + If you have the version -002, maybe there are hints about changes + in the paragraphs you are emphasizing. + 41. [125]Al Williams says: + [126]August 30, 2018 at 5:19 pm + No I had been tantalized by the discussions in the Intel doc + warning you to set up the segment registers before switching. Like + you mentioned, they all but told you how to do it and then stopped + short. It reminded me of the old story about during prohibition + where you could buy a "grape block" that had a warning label: + Warning: Do not place in 2 quarts of water in a cool dark place for + 3 weeks or an illegal alcoholic beverage will result." + I have been experimenting with protected mode programs and + naturally had to try it out. The lead times in the publishing + business at the time means I probably was writing that about the + time the PJ article hit the streets if not a little before. + Consider it took us 3 months to publish a letter to the editor! By + the time an article went through the snail mail, the contracts came + back, then the editing and typesetting with galleys in the mail. So + I don't remember an exact date, but I do remember being surprised + when the PJ article was called out. None of us had heard of it as + PJ was not a major competitor so we were not tracking them the way + we did some of the other magazines. + 42. Michal Necasek says: + [127]August 31, 2018 at 10:16 am + Indeed there is. The -002 edition is at + [128]http://www.bitsavers.org/components/intel/80386/231746-001_Int + roduction_to_the_80386_Apr86.pdf and page 63 in the PDF (page 2 of + the actual datasheet) lists the changes, though with no detail. + Some of the relevant sections were "revised", but that's all we + know until the -001 edition turns up. + 43. Michal Necasek says: + [129]August 31, 2018 at 12:17 pm + Thanks for remembering! And the grape block bit, I've not heard of + that. Yeah, the Intel docs were like that, daring developers to see + what happens if they don't follow the recipe exactly. + It's hard to imagine how long the publishing turnaround was was + back then, but that's how it was. Entirely possible that someone + wrote an article and someone else independently came up with the + same thing before it was published. It's quite likely that the + articles in foreign press were also independent discoveries; I dug + into the German archives a little but I doubt they were the only + ones. + +Leave a Reply + + Your email address will not be published. Required fields are marked * + + Comment * + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + + Name * ______________________________ + + Email * ______________________________ + + Website ______________________________ + + Post Comment + + D + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + + This site uses Akismet to reduce spam. [130]Learn how your comment data + is processed. + * Archives + + [131]June 2022 + + [132]May 2022 + + [133]April 2022 + + [134]March 2022 + + [135]February 2022 + + [136]January 2022 + + [137]December 2021 + + [138]November 2021 + + [139]October 2021 + + [140]September 2021 + + [141]August 2021 + + [142]July 2021 + + [143]June 2021 + + [144]May 2021 + + [145]April 2021 + + [146]March 2021 + + [147]February 2021 + + [148]January 2021 + + [149]December 2020 + + [150]November 2020 + + [151]October 2020 + + [152]September 2020 + + [153]August 2020 + + [154]July 2020 + + [155]June 2020 + + [156]May 2020 + + [157]April 2020 + + [158]March 2020 + + [159]February 2020 + + [160]January 2020 + + [161]December 2019 + + [162]November 2019 + + [163]October 2019 + + [164]September 2019 + + [165]August 2019 + + [166]July 2019 + + [167]June 2019 + + [168]May 2019 + + [169]April 2019 + + [170]March 2019 + + [171]February 2019 + + [172]January 2019 + + [173]December 2018 + + [174]November 2018 + + [175]October 2018 + + [176]August 2018 + + [177]July 2018 + + [178]June 2018 + + [179]May 2018 + + [180]April 2018 + + [181]March 2018 + + [182]February 2018 + + [183]January 2018 + + [184]December 2017 + + [185]November 2017 + + [186]October 2017 + + [187]August 2017 + + [188]July 2017 + + [189]June 2017 + + [190]May 2017 + + [191]April 2017 + + [192]March 2017 + + [193]February 2017 + + [194]January 2017 + + [195]December 2016 + + [196]November 2016 + + [197]October 2016 + + [198]September 2016 + + [199]August 2016 + + [200]July 2016 + + [201]June 2016 + + [202]May 2016 + + [203]April 2016 + + [204]March 2016 + + [205]February 2016 + + [206]January 2016 + + [207]December 2015 + + [208]November 2015 + + [209]October 2015 + + [210]September 2015 + + [211]August 2015 + + [212]July 2015 + + [213]June 2015 + + [214]May 2015 + + [215]April 2015 + + [216]March 2015 + + [217]February 2015 + + [218]January 2015 + + [219]December 2014 + + [220]November 2014 + + [221]October 2014 + + [222]September 2014 + + [223]August 2014 + + [224]July 2014 + + [225]June 2014 + + [226]May 2014 + + [227]April 2014 + + [228]March 2014 + + [229]February 2014 + + [230]January 2014 + + [231]December 2013 + + [232]November 2013 + + [233]October 2013 + + [234]September 2013 + + [235]August 2013 + + [236]July 2013 + + [237]June 2013 + + [238]May 2013 + + [239]April 2013 + + [240]March 2013 + + [241]February 2013 + + [242]January 2013 + + [243]December 2012 + + [244]November 2012 + + [245]October 2012 + + [246]September 2012 + + [247]August 2012 + + [248]July 2012 + + [249]June 2012 + + [250]May 2012 + + [251]April 2012 + + [252]March 2012 + + [253]February 2012 + + [254]January 2012 + + [255]December 2011 + + [256]November 2011 + + [257]October 2011 + + [258]September 2011 + + [259]August 2011 + + [260]July 2011 + + [261]June 2011 + + [262]May 2011 + + [263]April 2011 + + [264]March 2011 + + [265]January 2011 + + [266]November 2010 + + [267]October 2010 + + [268]August 2010 + + [269]July 2010 + + * Categories + + [270]286 + + [271]386 + + [272]3Com + + [273]3Dfx + + [274]486 + + [275]8086/8088 + + [276]Adaptec + + [277]AGP + + [278]AMD + + [279]AMD64 + + [280]Apple + + [281]Archiving + + [282]Assembler + + [283]ATi + + [284]BIOS + + [285]Books + + [286]Borland + + [287]BSD + + [288]Bugs + + [289]BusLogic + + [290]C + + [291]C&T + + [292]CD-ROM + + [293]Cirrus Logic + + [294]CompactFlash + + [295]Compaq + + [296]Compression + + [297]Conner + + [298]Corrections + + [299]CP/M + + [300]Creative Labs + + [301]Crystal Semi + + [302]Cyrix + + [303]DDR RAM + + [304]Debugging + + [305]DEC + + [306]Development + + [307]Digital Research + + [308]Documentation + + [309]DOS + + [310]DOS Extenders + + [311]Dream + + [312]E-mu + + [313]Editors + + [314]EISA + + [315]Ensoniq + + [316]ESDI + + [317]Ethernet + + [318]Fakes + + [319]Fixes + + [320]Floppies + + [321]Graphics + + [322]Hardware Hacks + + [323]I18N + + [324]IBM + + [325]IDE + + [326]Intel + + [327]Internet + + [328]Keyboard + + [329]Kryoflux + + [330]Kurzweil + + [331]LAN Manager + + [332]Legal + + [333]Linux + + [334]MCA + + [335]Microsoft + + [336]MIDI + + [337]NetWare + + [338]Networking + + [339]NeXTSTEP + + [340]NFS + + [341]Novell + + [342]NT + + [343]OS X + + [344]OS/2 + + [345]PC architecture + + [346]PC hardware + + [347]PC history + + [348]PC press + + [349]PCI + + [350]PCMCIA + + [351]Pentium + + [352]Pentium 4 + + [353]Pentium II + + [354]Pentium III + + [355]Pentium Pro + + [356]Plug and Play + + [357]PowerPC + + [358]Pre-release + + [359]PS/2 + + [360]QNX + + [361]Quantum + + [362]Random Thoughts + + [363]RDRAM + + [364]Roland + + [365]Ryzen + + [366]S3 + + [367]SCO + + [368]SCSI + + [369]Seagate + + [370]Security + + [371]Site Management + + [372]SMP + + [373]Software Hacks + + [374]Solaris + + [375]Sound + + [376]Sound Blaster + + [377]Source code + + [378]Standards + + [379]Storage + + [380]Supermicro + + [381]TCP/IP + + [382]ThinkPad + + [383]Trident + + [384]UltraSound + + [385]Uncategorized + + [386]Undocumented + + [387]UNIX + + [388]UnixWare + + [389]USB + + [390]VGA + + [391]VirtualBox + + [392]Virtualization + + [393]VLB + + [394]Watcom + + [395]Wave Blaster + + [396]Western Digital + + [397]Windows + + [398]Windows 95 + + [399]Windows XP + + [400]Wireless + + [401]WordStar + + [402]x86 + + [403]Xenix + + [404]Xeon + + [405]Yamaha + + [406]OS/2 Museum + [407]Proudly powered by WordPress. + +References + + Visible links: + 1. http://www.os2museum.com/wp/feed/ + 2. http://www.os2museum.com/wp/comments/feed/ + 3. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/feed/ + 4. http://www.os2museum.com/wp/wp-json/wp/v2/posts/4169 + 5. http://www.os2museum.com/wp/wp-json/oembed/1.0/embed?url=http%3A%2F%2Fwww.os2museum.com%2Fwp%2Fa-brief-history-of-unreal-mode%2F + 6. http://www.os2museum.com/wp/wp-json/oembed/1.0/embed?url=http%3A%2F%2Fwww.os2museum.com%2Fwp%2Fa-brief-history-of-unreal-mode%2F&format=xml + 7. http://www.os2museum.com/wp/ + 8. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#content + 9. http://www.os2museum.com/wp/ + 10. http://www.os2museum.com/wp/about/ + 11. http://www.os2museum.com/wp/about/wanted-list/ + 12. http://www.os2museum.com/wp/os2-history/ + 13. http://www.os2museum.com/wp/os2-history/os2-beginnings/ + 14. http://www.os2museum.com/wp/os2-history/os2-1-0/ + 15. http://www.os2museum.com/wp/os2-history/os2-1-1/ + 16. http://www.os2museum.com/wp/os2-history/os2-1-2-and-1-3/ + 17. http://www.os2museum.com/wp/os2-history/os2-16-bit-server/ + 18. http://www.os2museum.com/wp/os2-history/os2-2-0/ + 19. http://www.os2museum.com/wp/os2-history/os2-2-1-and-2-11/ + 20. http://www.os2museum.com/wp/os2-history/os2-warp/ + 21. http://www.os2museum.com/wp/os2-history/os2-warp-powerpc-edition/ + 22. http://www.os2museum.com/wp/os2-history/os2-warp-4/ + 23. http://www.os2museum.com/wp/os2-history/os2-timeline/ + 24. http://www.os2museum.com/wp/os2-history/os2-library/ + 25. http://www.os2museum.com/wp/os2-history/os2-library/os2-1-x-sdk/ + 26. http://www.os2museum.com/wp/os2-history/os2-library/os2-1-x-programming/ + 27. http://www.os2museum.com/wp/os2-history/os2-library/os2-2-0-technical-library/ + 28. http://www.os2museum.com/wp/os2-history/os2-videos-1987/ + 29. http://www.os2museum.com/wp/dos/ + 30. http://www.os2museum.com/wp/dos/dos-beginnings/ + 31. http://www.os2museum.com/wp/dos/dos-1-0-and-1-1/ + 32. http://www.os2museum.com/wp/dos/dos-2-0-and-2-1/ + 33. http://www.os2museum.com/wp/dos/dos-3-0-3-2/ + 34. http://www.os2museum.com/wp/dos/dos-3-3/ + 35. http://www.os2museum.com/wp/dos/dos-4-0/ + 36. http://www.os2museum.com/wp/dos/dos-library/ + 37. http://www.os2museum.com/wp/netware-history/ + 38. http://www.os2museum.com/wp/netware-history/netware-timeline/ + 39. http://www.os2museum.com/wp/netware-history/netware-library/ + 40. http://www.os2museum.com/wp/windows-history/ + 41. http://www.os2museum.com/wp/windows-history/windows-library/ + 42. http://www.os2museum.com/wp/pc-unix-history/ + 43. http://www.os2museum.com/wp/pc-unix-history/solaris-2-1-for-x86/ + 44. http://www.os2museum.com/wp/usb-0-9/ + 45. http://www.os2museum.com/wp/anomaly-meaningless-rex-prefix-used/ + 46. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/ + 47. http://www.os2museum.com/wp/author/michaln/ + 48. https://en.wikipedia.org/wiki/FASM + 49. https://books.google.de/books?id=tSLe3yMjc-AC&lpg=PP1&pg=PT437#v=onepage&q&f=false + 50. http://www.gaby.de/ftp/pub/win3x/archive/softlib/xms.exe + 51. http://www.megalextoria.com/usenet-archive/news095f1/b118/comp/binaries/ibm/pc/d/00002158.html + 52. https://archives.scovetta.com/pub/power_programming/MICROSFT/ + 53. https://vetusware.com/download/Assembly%20Language%20Programming%20for%20the%20Intel%2080XXX%20Family%201/?id=15869 + 54. https://link.springer.com/content/pdf/10.3758/BF03203592.pdf + 55. https://en.wikipedia.org/wiki/Ultima_VII:_The_Black_Gate + 56. https://books.google.com/books?id=gCfzPMoPJWgC&pg=PA304&lpg=PA304&source=bl&ots=rnelM7Nq98&sig=NwfNst9V6yPrUqTMu4oSayD2594&hl=en&sa=X&ved=0ahUKEwinjISbjKjbAhXQZ1AKHfF3D3UQ6AEIPDAC#v=onepage&f=false + 57. https://patents.google.com/patent/US5642491 + 58. http://ftp.lanet.lv/ftp/mirror/x2ftp/msdos/programming/memory/ + 59. http://ftp.lanet.lv/ftp/mirror/x2ftp/msdos/programming/libs/ + 60. http://dgi_il.tripod.com/gemmis.txt + 61. https://ftp.sunet.se/mirror/archive/ftp.sunet.se/pub/simtelnet/msdos/asmutl/unreal10.zip + 62. http://www.rcollins.org/Productivity/DescriptorCache.html + 63. https://web.archive.org/web/20051111084304/http://www.phoenix.com/NR/rdonlyres/873A00CF-33AC-4775-B77E-08E7B9754993/0/specspmm101.pdf + 64. http://www.rcollins.org/ddj/Aug98/Aug98.html + 65. http://www.os2museum.com/wp/more-on-loadall-and-os2/ + 66. http://www.delorie.com/djgpp/doc/rbinter/it/91/37.html + 67. https://board.flatassembler.net/topic.php?t=11940 + 68. http://www.os2museum.com/wp/category/386/ + 69. http://www.os2museum.com/wp/category/corrections/ + 70. http://www.os2museum.com/wp/category/microsoft/ + 71. http://www.os2museum.com/wp/category/pc-history/ + 72. http://www.os2museum.com/wp/category/undocumented/ + 73. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/ + 74. http://www.os2museum.com/wp/usb-0-9/ + 75. http://www.os2museum.com/wp/anomaly-meaningless-rex-prefix-used/ + 76. http://virtuallyfun.com/ + 77. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347786 + 78. https://yuhongbao.blogspot.com/ + 79. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347787 + 80. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347790 + 81. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347796 + 82. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347801 + 83. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347802 + 84. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347803 + 85. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347804 + 86. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347808 + 87. http://www.drdobbs.com/80386-protected-mode-initialization/184408010 + 88. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347810 + 89. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347812 + 90. https://yuhongbao.blogspot.com/ + 91. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347858 + 92. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347860 + 93. http://www.tsg.ne.jp/buho/189/tsg189.html#8086 + 94. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347861 + 95. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347862 + 96. https://yuhongbao.blogspot.com/ + 97. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347864 + 98. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347865 + 99. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347866 + 100. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347867 + 101. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347868 + 102. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347869 + 103. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347872 + 104. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347964 + 105. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347974 + 106. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347978 + 107. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-347996 + 108. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348003 + 109. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348035 + 110. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348037 + 111. https://www.pcjs.org/pubs/pc/reference/microsoft/kb/Q58987/ + 112. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348040 + 113. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348048 + 114. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348117 + 115. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348188 + 116. https://mjtsai.com/blog/2018/07/03/a-brief-history-of-unreal-mode/ + 117. https://yuhongbao.blogspot.com/ + 118. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348565 + 119. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348575 + 120. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348630 + 121. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-348979 + 122. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-349002 + 123. http://temlib.org/ + 124. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-349848 + 125. http://www.awce.com/ + 126. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-349870 + 127. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-349883 + 128. http://www.bitsavers.org/components/intel/80386/231746-001_Introduction_to_the_80386_Apr86.pdf + 129. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/#comment-349890 + 130. https://akismet.com/privacy/ + 131. http://www.os2museum.com/wp/2022/06/ + 132. http://www.os2museum.com/wp/2022/05/ + 133. http://www.os2museum.com/wp/2022/04/ + 134. http://www.os2museum.com/wp/2022/03/ + 135. http://www.os2museum.com/wp/2022/02/ + 136. http://www.os2museum.com/wp/2022/01/ + 137. http://www.os2museum.com/wp/2021/12/ + 138. http://www.os2museum.com/wp/2021/11/ + 139. http://www.os2museum.com/wp/2021/10/ + 140. http://www.os2museum.com/wp/2021/09/ + 141. http://www.os2museum.com/wp/2021/08/ + 142. http://www.os2museum.com/wp/2021/07/ + 143. http://www.os2museum.com/wp/2021/06/ + 144. http://www.os2museum.com/wp/2021/05/ + 145. http://www.os2museum.com/wp/2021/04/ + 146. http://www.os2museum.com/wp/2021/03/ + 147. http://www.os2museum.com/wp/2021/02/ + 148. http://www.os2museum.com/wp/2021/01/ + 149. http://www.os2museum.com/wp/2020/12/ + 150. http://www.os2museum.com/wp/2020/11/ + 151. http://www.os2museum.com/wp/2020/10/ + 152. http://www.os2museum.com/wp/2020/09/ + 153. http://www.os2museum.com/wp/2020/08/ + 154. http://www.os2museum.com/wp/2020/07/ + 155. http://www.os2museum.com/wp/2020/06/ + 156. http://www.os2museum.com/wp/2020/05/ + 157. http://www.os2museum.com/wp/2020/04/ + 158. http://www.os2museum.com/wp/2020/03/ + 159. http://www.os2museum.com/wp/2020/02/ + 160. http://www.os2museum.com/wp/2020/01/ + 161. http://www.os2museum.com/wp/2019/12/ + 162. http://www.os2museum.com/wp/2019/11/ + 163. http://www.os2museum.com/wp/2019/10/ + 164. http://www.os2museum.com/wp/2019/09/ + 165. http://www.os2museum.com/wp/2019/08/ + 166. http://www.os2museum.com/wp/2019/07/ + 167. http://www.os2museum.com/wp/2019/06/ + 168. http://www.os2museum.com/wp/2019/05/ + 169. http://www.os2museum.com/wp/2019/04/ + 170. http://www.os2museum.com/wp/2019/03/ + 171. http://www.os2museum.com/wp/2019/02/ + 172. http://www.os2museum.com/wp/2019/01/ + 173. http://www.os2museum.com/wp/2018/12/ + 174. http://www.os2museum.com/wp/2018/11/ + 175. http://www.os2museum.com/wp/2018/10/ + 176. http://www.os2museum.com/wp/2018/08/ + 177. http://www.os2museum.com/wp/2018/07/ + 178. http://www.os2museum.com/wp/2018/06/ + 179. http://www.os2museum.com/wp/2018/05/ + 180. http://www.os2museum.com/wp/2018/04/ + 181. http://www.os2museum.com/wp/2018/03/ + 182. http://www.os2museum.com/wp/2018/02/ + 183. http://www.os2museum.com/wp/2018/01/ + 184. http://www.os2museum.com/wp/2017/12/ + 185. http://www.os2museum.com/wp/2017/11/ + 186. http://www.os2museum.com/wp/2017/10/ + 187. http://www.os2museum.com/wp/2017/08/ + 188. http://www.os2museum.com/wp/2017/07/ + 189. http://www.os2museum.com/wp/2017/06/ + 190. http://www.os2museum.com/wp/2017/05/ + 191. http://www.os2museum.com/wp/2017/04/ + 192. http://www.os2museum.com/wp/2017/03/ + 193. http://www.os2museum.com/wp/2017/02/ + 194. http://www.os2museum.com/wp/2017/01/ + 195. http://www.os2museum.com/wp/2016/12/ + 196. http://www.os2museum.com/wp/2016/11/ + 197. http://www.os2museum.com/wp/2016/10/ + 198. http://www.os2museum.com/wp/2016/09/ + 199. http://www.os2museum.com/wp/2016/08/ + 200. http://www.os2museum.com/wp/2016/07/ + 201. http://www.os2museum.com/wp/2016/06/ + 202. http://www.os2museum.com/wp/2016/05/ + 203. http://www.os2museum.com/wp/2016/04/ + 204. http://www.os2museum.com/wp/2016/03/ + 205. http://www.os2museum.com/wp/2016/02/ + 206. http://www.os2museum.com/wp/2016/01/ + 207. http://www.os2museum.com/wp/2015/12/ + 208. http://www.os2museum.com/wp/2015/11/ + 209. http://www.os2museum.com/wp/2015/10/ + 210. http://www.os2museum.com/wp/2015/09/ + 211. http://www.os2museum.com/wp/2015/08/ + 212. http://www.os2museum.com/wp/2015/07/ + 213. http://www.os2museum.com/wp/2015/06/ + 214. http://www.os2museum.com/wp/2015/05/ + 215. http://www.os2museum.com/wp/2015/04/ + 216. http://www.os2museum.com/wp/2015/03/ + 217. http://www.os2museum.com/wp/2015/02/ + 218. http://www.os2museum.com/wp/2015/01/ + 219. http://www.os2museum.com/wp/2014/12/ + 220. http://www.os2museum.com/wp/2014/11/ + 221. http://www.os2museum.com/wp/2014/10/ + 222. http://www.os2museum.com/wp/2014/09/ + 223. http://www.os2museum.com/wp/2014/08/ + 224. http://www.os2museum.com/wp/2014/07/ + 225. http://www.os2museum.com/wp/2014/06/ + 226. http://www.os2museum.com/wp/2014/05/ + 227. http://www.os2museum.com/wp/2014/04/ + 228. http://www.os2museum.com/wp/2014/03/ + 229. http://www.os2museum.com/wp/2014/02/ + 230. http://www.os2museum.com/wp/2014/01/ + 231. http://www.os2museum.com/wp/2013/12/ + 232. http://www.os2museum.com/wp/2013/11/ + 233. http://www.os2museum.com/wp/2013/10/ + 234. http://www.os2museum.com/wp/2013/09/ + 235. http://www.os2museum.com/wp/2013/08/ + 236. http://www.os2museum.com/wp/2013/07/ + 237. http://www.os2museum.com/wp/2013/06/ + 238. http://www.os2museum.com/wp/2013/05/ + 239. http://www.os2museum.com/wp/2013/04/ + 240. http://www.os2museum.com/wp/2013/03/ + 241. http://www.os2museum.com/wp/2013/02/ + 242. http://www.os2museum.com/wp/2013/01/ + 243. http://www.os2museum.com/wp/2012/12/ + 244. http://www.os2museum.com/wp/2012/11/ + 245. http://www.os2museum.com/wp/2012/10/ + 246. http://www.os2museum.com/wp/2012/09/ + 247. http://www.os2museum.com/wp/2012/08/ + 248. http://www.os2museum.com/wp/2012/07/ + 249. http://www.os2museum.com/wp/2012/06/ + 250. http://www.os2museum.com/wp/2012/05/ + 251. http://www.os2museum.com/wp/2012/04/ + 252. http://www.os2museum.com/wp/2012/03/ + 253. http://www.os2museum.com/wp/2012/02/ + 254. http://www.os2museum.com/wp/2012/01/ + 255. http://www.os2museum.com/wp/2011/12/ + 256. http://www.os2museum.com/wp/2011/11/ + 257. http://www.os2museum.com/wp/2011/10/ + 258. http://www.os2museum.com/wp/2011/09/ + 259. http://www.os2museum.com/wp/2011/08/ + 260. http://www.os2museum.com/wp/2011/07/ + 261. http://www.os2museum.com/wp/2011/06/ + 262. http://www.os2museum.com/wp/2011/05/ + 263. http://www.os2museum.com/wp/2011/04/ + 264. http://www.os2museum.com/wp/2011/03/ + 265. http://www.os2museum.com/wp/2011/01/ + 266. http://www.os2museum.com/wp/2010/11/ + 267. http://www.os2museum.com/wp/2010/10/ + 268. http://www.os2museum.com/wp/2010/08/ + 269. http://www.os2museum.com/wp/2010/07/ + 270. http://www.os2museum.com/wp/category/286/ + 271. http://www.os2museum.com/wp/category/386/ + 272. http://www.os2museum.com/wp/category/3com/ + 273. http://www.os2museum.com/wp/category/3dfx/ + 274. http://www.os2museum.com/wp/category/486/ + 275. http://www.os2museum.com/wp/category/8086-8088/ + 276. http://www.os2museum.com/wp/category/adaptec/ + 277. http://www.os2museum.com/wp/category/agp/ + 278. http://www.os2museum.com/wp/category/amd/ + 279. http://www.os2museum.com/wp/category/amd64/ + 280. http://www.os2museum.com/wp/category/apple/ + 281. http://www.os2museum.com/wp/category/archiving/ + 282. http://www.os2museum.com/wp/category/assembler/ + 283. http://www.os2museum.com/wp/category/ati/ + 284. http://www.os2museum.com/wp/category/bios/ + 285. http://www.os2museum.com/wp/category/books/ + 286. http://www.os2museum.com/wp/category/borland/ + 287. http://www.os2museum.com/wp/category/bsd/ + 288. http://www.os2museum.com/wp/category/bugs/ + 289. http://www.os2museum.com/wp/category/buslogic/ + 290. http://www.os2museum.com/wp/category/c/ + 291. http://www.os2museum.com/wp/category/ct/ + 292. http://www.os2museum.com/wp/category/cd-rom/ + 293. http://www.os2museum.com/wp/category/cirrus-logic/ + 294. http://www.os2museum.com/wp/category/compactflash/ + 295. http://www.os2museum.com/wp/category/compaq/ + 296. http://www.os2museum.com/wp/category/compression/ + 297. http://www.os2museum.com/wp/category/conner/ + 298. http://www.os2museum.com/wp/category/corrections/ + 299. http://www.os2museum.com/wp/category/cp-m/ + 300. http://www.os2museum.com/wp/category/creative-labs/ + 301. http://www.os2museum.com/wp/category/crystal-semi/ + 302. http://www.os2museum.com/wp/category/cyrix/ + 303. http://www.os2museum.com/wp/category/ddr-ram/ + 304. http://www.os2museum.com/wp/category/debugging/ + 305. http://www.os2museum.com/wp/category/dec/ + 306. http://www.os2museum.com/wp/category/development/ + 307. http://www.os2museum.com/wp/category/digital-research/ + 308. http://www.os2museum.com/wp/category/documentation/ + 309. http://www.os2museum.com/wp/category/dos/ + 310. http://www.os2museum.com/wp/category/dos-extenders/ + 311. http://www.os2museum.com/wp/category/dream/ + 312. http://www.os2museum.com/wp/category/e-mu/ + 313. http://www.os2museum.com/wp/category/editors/ + 314. http://www.os2museum.com/wp/category/eisa/ + 315. http://www.os2museum.com/wp/category/ensoniq/ + 316. http://www.os2museum.com/wp/category/esdi/ + 317. http://www.os2museum.com/wp/category/ethernet/ + 318. http://www.os2museum.com/wp/category/fakes/ + 319. http://www.os2museum.com/wp/category/fixes/ + 320. http://www.os2museum.com/wp/category/floppies/ + 321. http://www.os2museum.com/wp/category/graphics/ + 322. http://www.os2museum.com/wp/category/hardware-hacks/ + 323. http://www.os2museum.com/wp/category/i18n/ + 324. http://www.os2museum.com/wp/category/ibm/ + 325. http://www.os2museum.com/wp/category/ide/ + 326. http://www.os2museum.com/wp/category/intel/ + 327. http://www.os2museum.com/wp/category/internet/ + 328. http://www.os2museum.com/wp/category/keyboard/ + 329. http://www.os2museum.com/wp/category/kryoflux/ + 330. http://www.os2museum.com/wp/category/kurzweil/ + 331. http://www.os2museum.com/wp/category/lan-manager/ + 332. http://www.os2museum.com/wp/category/legal/ + 333. http://www.os2museum.com/wp/category/linux/ + 334. http://www.os2museum.com/wp/category/mca/ + 335. http://www.os2museum.com/wp/category/microsoft/ + 336. http://www.os2museum.com/wp/category/midi/ + 337. http://www.os2museum.com/wp/category/netware/ + 338. http://www.os2museum.com/wp/category/networking/ + 339. http://www.os2museum.com/wp/category/nextstep/ + 340. http://www.os2museum.com/wp/category/nfs/ + 341. http://www.os2museum.com/wp/category/novell/ + 342. http://www.os2museum.com/wp/category/nt/ + 343. http://www.os2museum.com/wp/category/os-x/ + 344. http://www.os2museum.com/wp/category/os2/ + 345. http://www.os2museum.com/wp/category/pc-architecture/ + 346. http://www.os2museum.com/wp/category/pc-hardware/ + 347. http://www.os2museum.com/wp/category/pc-history/ + 348. http://www.os2museum.com/wp/category/pc-press/ + 349. http://www.os2museum.com/wp/category/pci/ + 350. http://www.os2museum.com/wp/category/pcmcia/ + 351. http://www.os2museum.com/wp/category/pentium/ + 352. http://www.os2museum.com/wp/category/pentium-4/ + 353. http://www.os2museum.com/wp/category/pentium-ii/ + 354. http://www.os2museum.com/wp/category/pentium-iii/ + 355. http://www.os2museum.com/wp/category/pentium-pro/ + 356. http://www.os2museum.com/wp/category/plug-and-play/ + 357. http://www.os2museum.com/wp/category/powerpc/ + 358. http://www.os2museum.com/wp/category/pre-release/ + 359. http://www.os2museum.com/wp/category/ps2/ + 360. http://www.os2museum.com/wp/category/qnx/ + 361. http://www.os2museum.com/wp/category/quantum/ + 362. http://www.os2museum.com/wp/category/random-thoughts/ + 363. http://www.os2museum.com/wp/category/rdram/ + 364. http://www.os2museum.com/wp/category/roland/ + 365. http://www.os2museum.com/wp/category/ryzen/ + 366. http://www.os2museum.com/wp/category/s3/ + 367. http://www.os2museum.com/wp/category/sco/ + 368. http://www.os2museum.com/wp/category/scsi/ + 369. http://www.os2museum.com/wp/category/seagate/ + 370. http://www.os2museum.com/wp/category/security/ + 371. http://www.os2museum.com/wp/category/site-management/ + 372. http://www.os2museum.com/wp/category/smp/ + 373. http://www.os2museum.com/wp/category/software-hacks/ + 374. http://www.os2museum.com/wp/category/solaris/ + 375. http://www.os2museum.com/wp/category/sound/ + 376. http://www.os2museum.com/wp/category/sound-blaster/ + 377. http://www.os2museum.com/wp/category/source-code/ + 378. http://www.os2museum.com/wp/category/standards/ + 379. http://www.os2museum.com/wp/category/storage/ + 380. http://www.os2museum.com/wp/category/supermicro/ + 381. http://www.os2museum.com/wp/category/tcp-ip/ + 382. http://www.os2museum.com/wp/category/thinkpad/ + 383. http://www.os2museum.com/wp/category/trident/ + 384. http://www.os2museum.com/wp/category/ultrasound/ + 385. http://www.os2museum.com/wp/category/uncategorized/ + 386. http://www.os2museum.com/wp/category/undocumented/ + 387. http://www.os2museum.com/wp/category/unix/ + 388. http://www.os2museum.com/wp/category/unixware/ + 389. http://www.os2museum.com/wp/category/usb/ + 390. http://www.os2museum.com/wp/category/vga/ + 391. http://www.os2museum.com/wp/category/virtualbox/ + 392. http://www.os2museum.com/wp/category/virtualization/ + 393. http://www.os2museum.com/wp/category/vlb/ + 394. http://www.os2museum.com/wp/category/watcom/ + 395. http://www.os2museum.com/wp/category/wave-blaster/ + 396. http://www.os2museum.com/wp/category/western-digital/ + 397. http://www.os2museum.com/wp/category/windows/ + 398. http://www.os2museum.com/wp/category/windows-95/ + 399. http://www.os2museum.com/wp/category/windows-xp/ + 400. http://www.os2museum.com/wp/category/wireless/ + 401. http://www.os2museum.com/wp/category/wordstar/ + 402. http://www.os2museum.com/wp/category/x86/ + 403. http://www.os2museum.com/wp/category/xenix/ + 404. http://www.os2museum.com/wp/category/xeon/ + 405. http://www.os2museum.com/wp/category/yamaha/ + 406. http://www.os2museum.com/wp/ + 407. https://wordpress.org/ + + Hidden links: + 409. http://www.os2museum.com/wp/a-brief-history-of-unreal-mode/ultima-vii-voodoo/ diff --git a/src/boot.asm b/src/boot.asm new file mode 100644 index 0000000..e96237d --- /dev/null +++ b/src/boot.asm @@ -0,0 +1,1408 @@ +; stage 1 + +; 16-bit real-mode +[bits 16] + +; BIOS always loads us to this location +[org 0x7c00] + +; export a map of boot loader symbols for debugging +[map symbols boot.map] + +stage1: + +; no interrupts, initializing segment registers and a real mode stack +; growing downwards from 0x7c00 where the stage 1 code and data lives + cli + cld + xor ax, ax + mov ds, ax + mov ss, ax + mov sp, 0x7c00 + mov bp, sp + sti + +; dl contains the boot drive, primarily because that's the last function +; called by the BIOS MBR loader, we remember that for loading additional +; blocks from the boot medium + mov [BOOT_DRIVE], dl + +; print greeting message + mov si, MESSAGE_GREETING + call print_string + +; size of stage 2 in sectors (3584-512 bytes, size of boot.img minus stage 1) +NOF_SECTORS_STAGE2 equ 6 + +; load stage 2 with simple load method to 0x7e00 (directly +; after the boot sector), we assume stage 2 fits on a track + mov ah, 0x02 ; read sectors from drive + mov al, NOF_SECTORS_STAGE2 ; read sectors of stage 2 + mov ch, 0 ; select first cylinder + mov dl, [BOOT_DRIVE] ; drive to read from + mov dh, 0 ; first head + mov cl, 2 ; second sector after boot sector + mov bx, 0 ; where to store the data + mov es, bx + mov bx, 0x7e00 ; 512 bytes after first sector + int 0x13 + jc .read_error + jmp .read_ok + +.read_error: + mov di, ERR_DISK + mov ax, 0x01 + call print_error +.read_ok: + cmp al, NOF_SECTORS_STAGE2 ; correct number of sectors read? + jne .short_read_error ; if not, short read + jmp .short_read_ok +.short_read_error: + mov di, ERR_DISK + mov ax, 0x02 + call print_error +.short_read_ok: + jmp stage2 + +; di: pointer to additional message +; ax: error code in ASCII, never returns +print_error: + mov si, NL + call print_string + mov si, MESSAGE_ERROR + call print_string + mov si, di + call print_string + call print_hex_nice + call kill_motor + mov si, NL + call print_string + jmp reboot + +; IN si +print_string: + push ax + push bx +.loop: + lodsb + cmp al, 0 + je .fini + call print_char + jmp .loop +.fini: + pop bx + pop ax + ret + +; IN al: character to print +; MOD ah +print_char: + mov ah, 0x0e + int 0x10 + ret + +; IN ah: hex value to print +print_hex_nice: + push si + mov si, HEX_PREFIX + call print_string + call print_hex + mov si, SPACE + call print_string + pop si + ret + +; IN ah: hex value to print +print_hex: + push bx + push si + mov si, HEX_TEMPLATE + mov bx, ax + and bx, 0x00FF + shr bx, 4 + mov bx, [HEXABET+bx] + mov [HEX_TEMPLATE], bl + mov bx, ax + and bx, 0x000F + mov bx, [HEXABET+bx] + mov [HEX_TEMPLATE+1], bl + call print_string + pop si + pop bx + ret + +; IN: eax: value to print in hex +print_hex_dword: + push eax + push ebx + mov ebx, eax + mov eax, ebx + shr eax, 24 + call print_hex + mov eax, ebx + shr eax, 16 + call print_hex + mov eax, ebx + shr eax, 8 + call print_hex + mov eax, ebx + call print_hex + pop ebx + pop eax + ret + +kill_motor: + push dx + mov dx, 0x3F2 + mov al, 0x00 + out dx, al + pop dx + ret + +reset_drive: + push ax + push dx + mov ax, 0x00 + mov dl, [BOOT_DRIVE] + int 0x13 + pop dx + pop ax + ret + +HEX_TEMPLATE: + db '??', 0 + +HEX_PREFIX: + db '0x', 0 + +HEXABET: + db '0123456789ABCDEF' + +MESSAGE_GREETING: + db "UFLBBL loading...", 13, 10, 0 + +MESSAGE_ERROR: + db "ERR ", 0 + +SPACE: + db " ", 0 + +NL: + db 13, 10, 0 + +BOOT_DRIVE: + db 0 + +; pad rest of sector with zeroes so we get 512 bytes in the end + times 510-($-$$) db 0 + +; magic number of a boot sector + dw 0xaa55 + +; stage 2 +stage2: + +; check A20 gate + mov si, MESSAGE_CHECKING_A20 + call print_string + call check_and_enable_A20 + cmp ax, 1 + je .A20_enabled + mov si, MESSAGE_DISABLED + call print_string + mov di, ERR_A20 + mov ax, 0x01 + call print_error + +.A20_enabled: + mov si, MESSAGE_ENABLED + call print_string + +unreal_mode: +; now switching to bigger data and extra segments (so copying kernels and ramdisks +; is not overly painful) + mov si, MESSAGE_SWITCHING_TO_UNREAL_MODE + call print_string + +; disable interrupts for now as we do mode switching and segment manipulations + cli + +; load GDT (global descriptor table) + lgdt [gdt_descriptor] + +; switch to protected mode + mov eax, cr0 + or eax, 0x1 + mov cr0, eax + +; unconditional far jump into code segment, +; wipes the instruction prefetch pipeline + jmp $+2 + +; data descriptor in GDT + mov ax, CODE_DATA_SEGMENT + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + +; back to real mode + and al, 0xFE + mov cr0, eax + +; restore segment values - now limits are removed but seg regs still work as normal +; we keep cs and ss in real mode locations as before, code is small and stack +; is not expected to get big, besides they stop working above 1 MB as SP and IP +; are used and not ESP and EIP! + xor ax,ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + +; now we are in UNREAL mode, we can also reenable real mode interrupts, as the +; code segment is still small, so saving IP should work just fine + sti + mov si, MESSAGE_ENABLED + call print_string + +; detect disk geometry +; IN dl: drive +detect_disk_geometry: + xor ax, ax + mov es, ax + mov di, ax + mov ah, 0x08 + mov dl, [BOOT_DRIVE] + int 0x13 + jc .error + jmp .ok + +.error: +; AH contains return code + mov si, ERR_DISK + call print_error + +; all went well, remember and print drive parameters +.ok: + mov si, MESSAGE_DRIVE_PARAMETERS + call print_string + mov ax, [BOOT_DRIVE] + call print_hex_nice + xor ax, ax + mov [FLOPPY_TYPE], BYTE bl + mov al, [FLOPPY_TYPE] + call print_hex_nice + add dh, 1 + mov [NOF_HEADS], BYTE dh + add cl, 1 + mov [SECTORS_PER_CYLINDER], BYTE cl + mov al, [NOF_HEADS] + call print_hex_nice + xor ax, ax + mov al, [SECTORS_PER_CYLINDER] + call print_hex_nice + mov si, NL + call print_string + + call reset_drive + +; read now sectors after stage 2 as long as we can find +; tar index sectors containing filenames, +; depending on the filename we have to load things to different places +; (and move them to memory above 1MB) +; start to read after stage 1 (512 on sector 1) and stage 2 (starting on sector 2) + mov [CURRENT_SECTOR], byte NOF_SECTORS_STAGE2 + 2 + +read_next_sector: + + mov bx, 0x0900 ; where to store the data (our floppy data read buffer) + mov es, bx + mov bx, 0x0 + +; print (C/H/S) info where we are currently reading and in which state +; and how many data sectors are left in the current tar entry + jmp .no_verbose + +; states + mov al, 0x0d + call print_char + mov al, byte [READ_STATE] + call print_hex + mov al, ' ' + call print_char + mov al, byte [KERNEL_STATE] + call print_hex + mov al, ' ' + call print_char + +; tar data sectors to read for current file + mov dx, word [READ_DATA_SECTORS] + mov ax, dx + shr ax, 8 + call print_hex + mov ax, dx + call print_hex + mov al, ' ' + call print_char + +; disk geometry (current position on the floppy) + mov al, '(' + call print_char + xor ax, ax + mov al, byte [CURRENT_CYLINDER] + call print_hex + mov al, '/' + call print_char + xor ax, ax + mov al, byte [CURRENT_HEAD] + call print_hex + mov al, '/' + call print_char + xor ax, ax + mov al, byte [CURRENT_SECTOR] + call print_hex + mov al, ')' + call print_char + +.no_verbose: + call read_one_sector_from_disk + +; states in the main sector read loop +STATE_READ_METADATA equ 0 +STATE_READ_KERNEL equ 1 +STATE_READ_INITRD equ 2 +STATE_KERNEL_READ_SECTOR_0 equ 1 +STATE_KERNEL_READ_SECTOR_1 equ 2 +STATE_KERNEL_READ_SECTORS_REAL_MODE equ 3 +STATE_KERNEL_READ_SECTORS_PROTECTED_MODE equ 4 +STATE_KERNEL_FINISHED equ 5 + +; depending on the read state we have to do different stuff now + mov ah, byte [READ_STATE] + cmp ah, STATE_READ_METADATA + je handle_read_metadata + cmp ah, STATE_READ_KERNEL + je handle_read_kernel + cmp ah, STATE_READ_INITRD + je handle_read_initrd + mov di, ERR_DISK + mov ax, 0x03 + call print_error + +; state: STATE_READ_METADATA +handle_read_metadata: + push bx + mov esi, 0x09000 + 0x101 ; 5 chars must match 'ustar' for being a tar metadata block + mov edi, USTAR_MAGIC + mov bx, 5 + call strncmp + pop bx + cmp ax, 0 + je .print_tar_metadata + jmp advance_to_next_sector ; read over unknown data or non-tar entries + +.print_tar_metadata: + mov al, ' ' + call print_char + mov si, 0x09000 + 0x00 ; the filename in the tar + call print_string + mov al, ' ' + call print_char + mov si, 0x09000 + 0x7c ; the size in ASCII octal + call print_string + mov si, SPACE + call print_string + mov si, 0x09000 + 0x7c + mov ecx, 11 + + ; compute size in decimal and compute number of data sectors we have to read + call octal_string_to_int + a32 mov [READ_DATA_SIZE], eax + call print_hex_dword + + mov ecx, eax ; ecx contains the number of 512 byte sectors + shr ecx, 9 ; number of sectors a 512 bytes + mov edx, ebx ; compute if we have a remainder + and edx, 0x01FF + cmp edx, 0 ; no remainder, ending at full sector + je .full_sector + inc ecx ; one non-full sector more to read +.full_sector: + mov [READ_DATA_SECTORS], ecx + + ; enable to debug metadata in tar + ;~ mov si, NL + ;~ call print_string + ;~ mov ax, 0x0900 + ;~ mov es, ax + ;~ call print_memory + +.search_kernel: + mov esi, 0x09000 + 0x00 + mov edi, FILE_BZIMAGE + call strcmp + cmp ax, 0 + je .found_kernel + jmp .search_initrd + +.found_kernel: + mov [READ_STATE], byte STATE_READ_KERNEL + mov [KERNEL_STATE], byte STATE_KERNEL_READ_SECTOR_0 + mov [READ_DESTINATION_PTR], dword 0x10000 + mov al, '!' + call print_char + mov si, NL + call print_string + jmp advance_to_next_sector + +.search_initrd: + mov esi, 0x09000 + 0x00 + mov edi, FILE_RAMDISK + call strcmp + cmp ax, 0 + je .found_initrd + jmp .search_eof + +.found_initrd: + mov [READ_STATE], byte STATE_READ_INITRD +; qemu initrd start location 7fab000, 133869568 (this is 128MB) too high for us, +; kernel gives us alignment hints and hints where to load initrd to? +; let's use 8MB, TODO: does the kernel release the initial ramdisk? I think so. is +; it relocating it's structures? or do we get fragmented heap and stuff? + a32 mov [READ_DESTINATION_PTR], dword 0x00800000 + a32 mov [INITRD_ADDRESS], dword 0x00800000 + a32 mov eax, [READ_DATA_SIZE] + a32 mov [INITRD_SIZE], eax + mov al, '!' + call print_char + mov si, NL + call print_string + + jmp advance_to_next_sector + +.search_eof: + mov esi, 0x09000 + 0x00 + mov edi, FILE_EOF + call strcmp + cmp ax, 0 + je .found_eof + jmp .unknown_file + +.found_eof: + mov si, NL + call print_string + mov si, MESSAGE_EOF_REACHED + call print_string + jmp finished_reading + +.unknown_file: + mov al, '?' + call print_char + mov si, NL + call print_string + jmp advance_to_next_sector + +; STATE: STATE_READ_KERNEL +handle_read_kernel: + + ; move kernel code/data from 0x09000 (our disk read scratch space + ; in low memory to 0x10000 (which is the real mode location for the + ; kernel code) + mov ax, ds + mov es, ax + mov esi, 0x09000 + mov edi, dword [READ_DESTINATION_PTR] + mov ecx, 512 + cld + a32 rep movsb + mov [READ_DESTINATION_PTR], edi + + mov ax, word [READ_DATA_SECTORS] + dec ax + mov word [READ_DATA_SECTORS], ax + cmp ax, 0 + je .data_end + jmp kernel_switch +.data_end: + mov [READ_STATE], byte STATE_READ_METADATA + jmp advance_to_next_sector + + ; depending on the kernel substate +kernel_switch: + xor ax, ax + mov ah, byte [KERNEL_STATE] + cmp ah, STATE_KERNEL_READ_SECTOR_0 + je handle_data_kernel_sector_0 + cmp ah, STATE_KERNEL_READ_SECTOR_1 + je handle_data_kernel_sector_1 + cmp ah, STATE_KERNEL_READ_SECTORS_REAL_MODE + je handle_data_kernel_real_mode + cmp ah, STATE_KERNEL_READ_SECTORS_PROTECTED_MODE + je handle_data_kernel_protected_mode + mov di, ERR_KERN + mov ax, 0x01 + call print_error + +; STATE: STATE_KERNEL_READ_SECTOR_0 +handle_data_kernel_sector_0: + +; first sector if real mode kernel + + ; enable to debug real mode zero page metadata + ;~ mov si, NL + ;~ call print_string + ;~ mov ax, 0x1000 + ;~ mov es, ax + ;~ call print_memory + + ; get the number of real mode kernel sectors to read + ; (or mininmally 4 if 0 is returned), each 512 bytes + mov si, NL + call print_string + a32 mov al, byte [0x10000+0x1f1] + cmp al, 0 + jne .nof_sectors_ok + mov al, 4 ; minimally 4 sectors + +.nof_sectors_ok: + mov si, MESSAGE_KERNEL_NOF_REAL_SECTORS + call print_string + mov [KERNEL_NOF_REAL_MODE_SECTORS], al + call print_hex + mov si, NL + call print_string + + ; get size of protected mode kernel in 16 bytes + a32 mov eax, [0x10000+0x1f4] + mov ecx, eax + shr ecx, 5 ; 16-pages, shifting by 5 to the right gives + ; us the number of sectors a 512 bytes + mov ebx, eax ; compute if we have to read one sector more with partial data + and ebx, 0x001F ; 32 times 16 bytes per page + cmp ebx, 0 + je .full_sector + inc ecx +.full_sector: + mov [KERNEL_NOF_PROTECTED_MODE_SECTORS], word cx + mov si, MESSAGE_KERNEL_NOF_PROTECTED_SECTORS + call print_string + mov bx, [KERNEL_NOF_PROTECTED_MODE_SECTORS] + mov ax, bx + and ax, 0xFF00 + shr ax, 8 + call print_hex + mov ax, bx + and ax, 0x00FF + call print_hex + mov si, NL + call print_string + + mov [KERNEL_STATE], byte STATE_KERNEL_READ_SECTOR_1 + + jmp advance_to_next_sector + +; STATE: STATE_KERNEL_READ_SECTOR_1 +handle_data_kernel_sector_1: + ; enable to debug real mode zero page metadata + ;~ mov si, NL + ;~ call print_string + ;~ mov ax, 0x1020 + ;~ mov es, ax + ;~ call print_memory + + ; compare header + mov esi, 0x10000 + 0x202 + mov edi, KERNEL_MAGIC + mov bx, 4 + call strncmp + cmp ax, 0 + je .kernel_HdrS_found + mov di, ERR_KERN + mov ax, 0x02 + call print_error + +.kernel_HdrS_found: + ; get protocol version, don't allow anothing below 2.15 (which + ; os kernel 5.5 or above) + mov al, 0x0d + call print_char + mov si, NL + call print_string + mov si, MESSAGE_KERNEL_BOOT_PROTOCOL + call print_string + a32 mov al, byte [0x10000+0x207] + mov byte [KERNEL_BOOT_PROTOCOL_MAJOR], al + call print_hex + mov al, '.' + call print_char + a32 mov al, byte [0x10000+0x206] + mov byte [KERNEL_BOOT_PROTOCOL_MINOR], al + call print_hex + mov si, NL + call print_string + xor ax, ax + mov al, byte [KERNEL_BOOT_PROTOCOL_MAJOR] + cmp al, 2 + jl .protocol_error + xor ax, ax + mov al, byte [KERNEL_BOOT_PROTOCOL_MINOR] + cmp al, 15 + jl .protocol_error + jmp .get_kernel_version_offset + +.protocol_error: + mov di, ERR_KERN + mov ax, 0x03 + call print_error + + ; get offset pointing to human readable kernel message, + ; we can print it only after having read the real mode part + ; of the kernel (or just before we actually start the kernel) +.get_kernel_version_offset: + a32 mov ax, word [0x10000+0x20e] + mov [KERNEL_VERSION_PTR], ax + jmp .set_boot_data + +.set_boot_data: + ; not quite clear what the kernel does with this data, TODO: must read kernel code + a32 mov byte [0x10000+0x210], 0xe1 ; Extended bootloader type + a32 mov byte [0x10000+0x226], 0x00 ; ext_loader_ver + a32 mov byte [0x10000+0x227], 0x01 ; ext_loader_type (id: 0x11) + a32 or byte [0x10000+0x211], 0x80 ; set CAN_USE_HEAP + a32 mov word [0x10000+0x224], 0xde00 ; head_end_ptr + + ; set up area and copy command line from the boot loader area to + ; a area registered with the kernel (0x1e000) + a32 mov dword [0x10000+0x228], 0x1e000 ; set cmd_line_ptr + xor ax, ax + mov es, ax + mov esi, KERNEL_CMD_LINE + mov edi, 0x1e000 + mov ecx, KERNEL_CMD_SIZE + cld + a32 rep movsb + + jmp .change_state + +.change_state: + ; enable to debug real mode zero page metadata after modifying and setting parameters + ;~ mov si, NL + ;~ call print_string + ;~ mov ax, 0x1020 + ;~ mov es, ax + ;~ call print_memory + + mov [KERNEL_STATE], byte STATE_KERNEL_READ_SECTORS_REAL_MODE + ; intentional fallthrough, decrement real mode sectors below + +; STATE: STATE_KERNEL_READ_SECTORS_REAL_MODE +handle_data_kernel_real_mode: + ; read at most KERNEL_NOF_REAL_MODE_SECTORS sectors for real + ; mode code/data + mov al, byte [KERNEL_NOF_REAL_MODE_SECTORS] + dec al + mov byte [KERNEL_NOF_REAL_MODE_SECTORS], al + cmp al, 0 + je .last_real_mode_sector_read + jmp advance_to_next_sector + +.last_real_mode_sector_read: + ; show kernel version + mov al, 0x0d + call print_char + mov si, NL + call print_string + mov si, MESSAGE_KERNEL_VERSION + call print_string + mov esi, [KERNEL_VERSION_PTR] + add esi, 0x200 + push ds + mov ax, 0x1000 + mov ds, ax + call print_string + pop ds + mov si, NL + call print_string + + ; change load pointer to protected mode area 0x100000 + mov [KERNEL_STATE], byte STATE_KERNEL_READ_SECTORS_PROTECTED_MODE + mov [READ_DESTINATION_PTR], dword 0x100000 + + jmp advance_to_next_sector + +; STATE: STATE_KERNEL_READ_SECTORS_PROTECTED_MODE +handle_data_kernel_protected_mode: + ; read at most KERNEL_NOF_PROTECTED_MODE_SECTORS sectors for protected + ; mode code/data + mov ax, word [KERNEL_NOF_PROTECTED_MODE_SECTORS] + dec ax + mov word [KERNEL_NOF_PROTECTED_MODE_SECTORS], ax + cmp ax, 0 + je .last_protected_mode_sector_read + jmp advance_to_next_sector +.last_protected_mode_sector_read: + mov [READ_STATE], byte STATE_READ_METADATA + mov [KERNEL_STATE], byte STATE_KERNEL_FINISHED + jmp advance_to_next_sector + +; STATE: STATE_READ_INITRD +handle_read_initrd: + ; move ramdisk data from 0x09000 (our disk read scratch space + ; in low memory to high memory 0xaaaa0000 + mov ax, ds + mov es, ax + mov esi, 0x09000 + + mov edi, dword [READ_DESTINATION_PTR] + mov ecx, 512 + cld + a32 rep movsb + mov [READ_DESTINATION_PTR], edi + + mov ax, word [READ_DATA_SECTORS] + dec ax + mov word [READ_DATA_SECTORS], ax + cmp ax, 0 + je .data_end + jmp .nothing_todo +.data_end: + mov [READ_STATE], byte STATE_READ_METADATA + jmp advance_to_next_sector + +.nothing_todo: + +advance_to_next_sector: + add [CURRENT_SECTOR], byte 1 ; next sector + mov ch, [SECTORS_PER_CYLINDER] + cmp [CURRENT_SECTOR], ch ; after the end of the current track? + je .next_head + jmp read_next_sector + +.next_head: + shr bx, 4 ; make it a segment offset.. + mov ax, es + add ax, bx + mov es, ax ; ..and add it to ES + mov bx, 0x0 ; we also reset bx and update es to avoid hitting the 64k wrap around point + mov [CURRENT_SECTOR], byte 1 ; start from first sector again + add [CURRENT_HEAD], byte 1 ; advance head + mov ch, [NOF_HEADS] + cmp [CURRENT_HEAD], ch ; after the number of heads? + je .next_track + jmp read_next_sector + +.next_track: + mov [CURRENT_HEAD], byte 0 ; start from head 0 again + add [CURRENT_CYLINDER], byte 1 ; advance track + ; TODO depends on boot parameters (the floppy media, add a table) + cmp [CURRENT_CYLINDER], byte 80 + jae .next_floppy + jmp read_next_sector + +.next_floppy: + call kill_motor + mov si, NL + call print_string + mov si, MESSAGE_NEXT_FLOPPY + call print_string + call wait_for_keypress + call reset_drive + ; TODO: check for floppy disk change (is there a BIOS function for this?) + ; TODO: maybe also check some checksum or so of the floppy data and see + ; if we indeed have a new floppy + mov [CURRENT_SECTOR], byte 0 ; will be incremented at advance_to_next_sector + mov [CURRENT_HEAD], byte 0 + mov [CURRENT_CYLINDER], byte 0 + jmp advance_to_next_sector + +finished_reading: + ; make sure the floppy is not spinnig (also in print_error) + call kill_motor + +start_kernel: + + ; set ramdisk + a32 mov eax, [INITRD_ADDRESS] ; ramdisk size in bytes + a32 mov [0x10000+0x218], eax + mov si, MESSAGE_INITRD_ADDRESS + call print_string + a32 mov eax, [INITRD_ADDRESS] + call print_hex_dword + mov si, NL + call print_string + a32 mov eax, [INITRD_SIZE] ; ramdisk address in bytes + a32 mov [0x10000+0x21c], eax + mov si, MESSAGE_INITRD_SIZE + call print_string + a32 mov eax, [INITRD_SIZE] + call print_hex_dword + mov si, NL + call print_string + + ; TODO: check if we actually do have reached the KERNEL_FINISHED state + mov si, MESSAGE_BOOTING_KERNEL + call print_string + + ; set up segments for running the real mode kernel + cli + mov ax, 0x1000 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov sp, 0xe000 + + ; jump to kernel real mode entry + jmp 0x1020:0 + +; we should not return here, rather the machine will reset, hang or kernel will OUPS, +; just in case, restore segments and print an error message just in case it happens.. + mov ax, CODE_DATA_SEGMENT + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov sp, 0x7c00 + + mov si, ERR_KERN + mov ax, 0x01 + call print_error + +; allow rebooting if something goes sour in the kernel +reboot: + mov si, MESSAGE_REBOOT + call print_string + + call wait_for_keypress + +; reboot (cannot use jmp here) + db 0xea + dw 0x0000 + dw 0xFFFF + +; endless loop if reboot fails + jmp $ + +; wait for key to be pressed +wait_for_keypress: + push ax + xor ax, ax + int 0x16 + pop ax + ret + +; GDT global descriptor table + +gdt_start: + +; mandatory null entry +gdt_null: + dd 0x0 + dd 0x0 + +; on big unreal segment, code and data are in the same unprotected segment +gdt_code_data: + dw 0xffff ; limit (bits 0-15) + dw 0x0 ; base (bits 0-15) + db 0x0 ; base (bits 16-23) + db 10010010b ; flags + db 11001111b ; flags, limit (bits 16-19) + db 0x0 ; base (bit 24-31) + +gdt_end: + +gdt_descriptor: + dw gdt_end - gdt_start - 1 ; size + dd gdt_start ; start address of the GDT + +; constants representing the segment bases +CODE_DATA_SEGMENT equ gdt_code_data - gdt_start + +check_and_enable_A20: + call check_A20_enabled + cmp ax, 1 + je A20_ENABLED + +A20_FAST_SPECIAL_PORT: + + mov al, 'F' + call print_char + + in al, 0x92 + or al, 2 + out 0x92, al + + call check_A20_enabled + cmp ax, 1 + je A20_ENABLED + +A20_ENABLE_KBD_PORT: + mov al, 'K' + call print_char + mov al, 0xdd + out 0x64, al + + call check_A20_enabled + cmp ax, 1 + je A20_ENABLED + +A20_ENABLE_VIA_BIOS: + mov al, 'B' + call print_char + mov ax, 0x2401 + int 0x15 + + call check_A20_enabled + cmp ax, 1 + +A20_ENABLE_KBD_OUT: + + mov al, 'k' + call print_char + + cli ; disable interrupts, we talk directly to the keyboard ports + + call .wait_input + mov al,0xAD + out 0x64,al ; disable keyboard + call .wait_input + + mov al,0xD0 + out 0x64,al ; tell controller to read output port + call .wait_output + + in al,0x60 + push eax ; get output port data and store it + call .wait_input + + mov al,0xD1 + out 0x64,al ; tell controller to write output port + call .wait_input + + pop eax + or al,2 ; set bit 1 (enable a20) + out 0x60,al ; write out data back to the output port + + call .wait_input + mov al,0xAE ; enable keyboard + out 0x64,al + + call .wait_input + + sti + + jmp .retest + +; wait for input buffer to be clear +.wait_input: + in al,0x64 + test al,2 + jnz .wait_input + ret + +; wait for output buffer to be clear +.wait_output: + in al,0x64 + test al,1 + jz .wait_output + ret + +.retest: + call check_A20_enabled + cmp ax, 1 + je A20_ENABLED + +A20_ENABLED: + ret + +; returns 0 if not A20_ENABLED, 1 if A20_ENABLED in AX +check_A20_enabled: + pushf + push ds + push es + push di + push si + + cli + + xor ax, ax + mov es, ax + mov di, 0x0500 ; es:di = 0000:0500 + + mov ax, 0xffff + mov ds, ax + mov si, 0x0510 ; ds:si = ffff:0510 + + mov al, byte [es:di] ; preserve values in memory + push ax ; on stack + mov al, byte [ds:si] + push ax + + mov byte [es:di], 0x00 ; now the test: write 0x00 to 0000:0500 + mov byte [ds:si], 0xFF ; write 0xff to ffff:0510 + + cmp byte [es:di], 0xFF ; memory wrap? A20 not enabled + je .disabled + jmp .enabled + +.restore: + pop bx ; restore original memory contents + mov byte [ds:si], bl + pop bx + mov byte [es:di], bl + jmp .exit + +.enabled: + mov al, '+' + call print_char + mov ax, 1 ; not wrapped around + jmp .restore + +.disabled: + mov al, '-' + call print_char + mov ax, 0 ; wrapped around (last cmp) + jmp .restore + +.exit: + pop si + pop di + pop es + pop ds + popf + + ret + +; Read one sector from floppy using CHS adressing +read_one_sector_from_disk: + + mov ah, 0x02 ; read sectors from drive + mov al, 1 ; read 1 sector + mov ch, BYTE [CURRENT_CYLINDER] + mov dh, BYTE [CURRENT_HEAD] + mov dl, BYTE [BOOT_DRIVE] + mov cl, BYTE [CURRENT_SECTOR] + mov BYTE [CURRENT_RETRIES], 0 + + int 0x13 + + jc .read_error + + cmp al, 1 ; 1 sector read? + jne .short_read ; if not, short read + + ret + +.read_error: + cmp BYTE [CURRENT_RETRIES], 3 + jl .read_again + jmp .print_error +.read_again: + dec BYTE [CURRENT_RETRIES] + call reset_drive + jmp read_one_sector_from_disk + +.print_error: + ;~ xor ax, ax + ;~ mov dh, 0 + ;~ mov dl, ah + mov di, ERR_DISK + call print_error + +.short_read: + mov di, ERR_DISK + call print_string + +; IN al: character to print if printable, dot otherwise +; MOD ah +print_dump_char: + cmp byte al, 0x20 ; space + jl .print_dot + test byte al, al ; above 0x7f ~ + js .print_dot + call print_char + jmp .done +.print_dot: + mov al, 0x2e ; . + call print_char +.done: + ret + +; print a dump of 512 bytes in memory (a sector) for debugging purposes +; IN: es base address (as segment) where to start printing +print_memory: + xor bx, bx +.next_line: + xor cx, cx + mov ax, es + and ax, 0xFF00 + shr ax, 8 + call print_hex + mov ax, es + and ax, 0x00FF + call print_hex + xor ax, ax + mov ah, ':' + call print_char + mov al, bh + call print_hex + mov al, bl + call print_hex + mov si, DUMP_SEP + call print_string +.next_byte: + mov al, [es:bx] + call print_hex + mov si, SPACE + call print_string + inc bx + inc cx + cmp cx, 8 + je .gap + jmp .after_gap +.gap: + mov si, SPACE + call print_string +.after_gap: + cmp cx, 16 + jne .next_byte +.print_chars: + xor cx, cx + sub bx, 16 +.next_char: + mov al, [es:bx] + call print_dump_char + inc bx + inc cx + cmp cx, 16 + jne .next_char +.newline: + mov si, NL + call print_string + cmp bx, 256 + je .wait + jmp .cont +.wait: + mov si, MESSAGE_PRESS_KEY_TO_CONTINUE + call print_string + call wait_for_keypress +.cont: + cmp bx, 512 + jne .next_line + ret + +DUMP_SEP: + db ": ", 0 + +; compare strings +; IN: si, di: start of two zero terminated strings +; OUT: ax <0 si < di, >0 si > di; =0 si = di +; CLOBBERS: si, di +strcmp: + push dx +.loop: + a32 mov dl, [esi] + a32 mov dh, [edi] + cmp dh, $0 + je .done + cmp dl, $0 + je .done + cmp dh, dl + jne .done + inc si + inc di + jmp .loop +.done: + xor ax, ax + mov al, byte dh + sub al, byte dl +.end: + pop dx + ret + +; compare strings up to a maximal number of characters +; IN: si, di: start of two zero terminated strings, bx: number of chars +; OUT: ax <0 si < di, >0 si > di; =0 si = di +; CLOBBERS: si, di, bx +strncmp: + push dx +.loop: + a32 mov dl, [esi] + a32 mov dh, [edi] + cmp dh, $0 + je .done + cmp dl, $0 + je .done + cmp dh, dl + jne .done + inc si + inc di + dec bx + jz .done + jmp .loop +.done: + xor ax, ax + mov al, byte dh + sub al, byte dl +.end: + pop dx + ret + +; convert octal string to integer +; IN: si, cx: pointer to the string and length of the string +; OUT: eax: converted integer +; clobbers: ebx +octal_string_to_int: + xor ebx, ebx +.next: + movzx eax, byte [esi] + inc esi + sub al, '0' ; assuming ASCII + shl ebx, 3 ; octal, multiply by 8 + add ebx, eax ; add current digit + loop .next ; cx-- + mov eax, ebx + ret + +MESSAGE_CHECKING_A20: + db "Checking A20 address gate.. ", 0 + +MESSAGE_ENABLED: + db " enabled", 13, 10, 0 + +MESSAGE_DISABLED: + db " disabled", 13, 10, 0 + +MESSAGE_SWITCHING_TO_UNREAL_MODE: + db "Switching to unreal mode..", 0 + +MESSAGE_DRIVE_PARAMETERS: + db "Boot parameters ", 0 + +MESSAGE_EOF_REACHED: + db "Reached end of tar file..", 13, 10, 0 + +MESSAGE_BOOTING_KERNEL: + db "Booting kernel..", 13, 10, 0 + +MESSAGE_REBOOT: + db "Press any key for rebooting..", 13, 10, 0 + +MESSAGE_NEXT_FLOPPY: + db "Insert next floppy and press any key to continue..", 13, 10, 0 + +MESSAGE_PRESS_KEY_TO_CONTINUE: + db "Press any key to continue..", 13, 10, 0 + +MESSAGE_KERNEL_NOF_REAL_SECTORS: + db "Number of real-mode kernel sectors: ", 0 + +MESSAGE_KERNEL_NOF_PROTECTED_SECTORS: + db "Number of protected-mode kernel sectors: ", 0 + +MESSAGE_KERNEL_BOOT_PROTOCOL: + db "Linux boot protocol version: ", 0 + +MESSAGE_KERNEL_VERSION: + db "Linux kernel version: ", 0 + +MESSAGE_INITRD_ADDRESS: + db "Ramdisk address: ", 0 + +MESSAGE_INITRD_SIZE: + db "Ramdisk size: ", 0 + +ERR_A20: + db "A20 ", 0 + +ERR_DISK: + db "DISK ", 0 + +ERR_KERN: + db "KERN ", 0 + +USTAR_MAGIC: + db "ustar", 0 + +KERNEL_MAGIC: + db 'HdrS', 0 + +; data sections used for reading from floppy, default to some sane values +; get probed and filled in during floppy drive probing +FLOPPY_TYPE: + db 0x00 ; drive type, usually 0x04 after probing for 3 1/4" 1.44MB + +SECTORS_PER_CYLINDER: + db 0x3F ; detect parameters enters the correct value here (sectors + 1) + ; if detection fails, force int13 to read ahead +NOF_HEADS: + db 0x01 ; number of heads + 1 + +; read route reads and updates those values while reading from floppy +CURRENT_SECTOR: + db 1 + +CURRENT_CYLINDER: + db 0 + +CURRENT_HEAD: + db 0 + +CURRENT_RETRIES: + db 0 + +FILE_BZIMAGE: + db "bzImage", 0 + +FILE_RAMDISK: + db "ramdisk.img", 0 + +FILE_EOF: + db "EOF", 0 + +READ_STATE: + db STATE_READ_METADATA + +READ_DATA_SECTORS: + dd 0 + +READ_DESTINATION_PTR: + dd 0x10000 + +READ_DATA_SIZE: + dd 0 + +KERNEL_STATE: + db STATE_KERNEL_READ_SECTOR_0 + +KERNEL_NOF_REAL_MODE_SECTORS: + db 0 + +KERNEL_NOF_PROTECTED_MODE_SECTORS: + dw 0 + +KERNEL_CMD_LINE: + db "debug loglevel=7 earlycon=uart8250,io,0x3f8,9600n8 console=tty0 console=ttyS0,9600n8 rdinit=/bin/sinit root=/dev/ram0 rootfstype=ramfs iommu=off", 0 + +KERNEL_CMD_SIZE equ $-KERNEL_CMD_LINE + +KERNEL_BOOT_PROTOCOL_MAJOR: + db 0 + +KERNEL_BOOT_PROTOCOL_MINOR: + db 0 + +KERNEL_VERSION_PTR: + dw 0 + +INITRD_ADDRESS: + dd 0 + +INITRD_SIZE: + dd 0 + +; make sure we have full sectors +times (NOF_SECTORS_STAGE2+1)*512-($-$$) db 0 diff --git a/src/lstar.c b/src/lstar.c new file mode 100644 index 0000000..2a7d541 --- /dev/null +++ b/src/lstar.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include + +static int octal_to_int( char *s, int size ) +{ + int n = 0; + char *c = s; + while( size > 0 ) { + n *= 8; + n += *c - '0'; + c++; + size--; + } + + return n; +} + +int main( int argc, char *argv[] ) +{ + FILE *f = NULL; + char buf[512]; + char filename[100]; + char size_octal[12]; + char cksum_octal[8]; + int size; + unsigned int cksum; + unsigned int computed_cksum; + int i, n; + int terminate = 0; + + if( argc != 2 ) { + fprintf( stderr, "usage: %s \n", argv[0] ); + exit( EXIT_FAILURE ); + } + + f = fopen( argv[1], "r" ); + if( f == NULL ) { + fprintf( stderr, "ERROR: failed to open file '%s'\n", argv[1] ); + exit( EXIT_FAILURE ); + } + + do { + clearerr( f ); + n = fread( buf, 512, 1, f ); + if( n == 0 ) { + if( ferror( f ) ) { + fprintf( stderr, "ERR: read error\n" ); + terminate = 1; + } else if( feof( f ) ) { + terminate = 1; + break; + } + } + + if( memcmp( &buf[257], "ustar", 5 ) == 0 ) { + strlcpy( filename, buf, 100 ); + + if( strcmp( filename, "" ) != 0 ) { + + printf( "file: %s\n", filename ); + + strlcpy( size_octal, &buf[124], 12 ); + printf( "size (octal): %s\n", size_octal ); + + size = octal_to_int( size_octal, 11 ); + printf( "size (decimal): %d\n", size ); + + strlcpy( cksum_octal, &buf[148], 8 ); + printf( "cksum (octal): %s\n", cksum_octal ); + cksum = octal_to_int( cksum_octal, 6 ); + printf( "cksum (decimal): %d\n", cksum ); + + for( i = 148; i < 148+8; i++ ) { + buf[i] = ' '; + } + computed_cksum = 0; + for( i = 0; i < 512; i++ ) { + computed_cksum += (unsigned char)buf[i]; + } + printf( "cksum (computed): %d\n", computed_cksum ); + if( cksum != computed_cksum ) { + fprintf( stderr, "ERR: checksum mismatch in header!\n" ); + } + + while( size > 0 ) { + fread( buf, 512, 1, f ); + size -= 512; + } + } else { + fprintf( stderr, "INFO: the end\n" ); + } + } else { + fprintf( stderr, "WARN: skipping non TAR header\n" ); + } + } while( !terminate ); + + fclose( f ); + + exit( EXIT_SUCCESS ); +} diff --git a/tests/run_qemu.sh b/tests/run_qemu.sh new file mode 100755 index 0000000..5c825f1 --- /dev/null +++ b/tests/run_qemu.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +sleep 2 && \ +qemu-system-i386 -cpu 486 -m 128M \ + -drive "file=floppy00,if=floppy,format=raw" \ + -netdev user,id=net0,net=10.0.0.0/24,host=10.0.0.2,dhcpstart=10.0.0.16,hostfwd=tcp::8080-:80,hostfwd=udp::8081-:81 \ + -device rtl8139,netdev=net0 diff --git a/tests/test_a20.asm b/tests/test_a20.asm new file mode 100644 index 0000000..43da6e3 --- /dev/null +++ b/tests/test_a20.asm @@ -0,0 +1,61 @@ +; The following code is public domain licensed + +[bits 16] + +; Function: check_a20 +; +; Purpose: to check the status of the a20 line in a completely self-contained state-preserving way. +; The function can be modified as necessary by removing push's at the beginning and their +; respective pop's at the end if complete self-containment is not required. +; +; Returns: 0 in ax if the a20 line is disabled (memory wraps around) +; 1 in ax if the a20 line is enabled (memory does not wrap around) + +check_a20: + pushf + push ds + push es + push di + push si + + cli + + xor ax, ax ; ax = 0 + mov es, ax + + not ax ; ax = 0xFFFF + mov ds, ax + + mov di, 0x0500 + mov si, 0x0510 + + mov al, byte [es:di] + push ax + + mov al, byte [ds:si] + push ax + + mov byte [es:di], 0x00 + mov byte [ds:si], 0xFF + + cmp byte [es:di], 0xFF + + pop ax + mov byte [ds:si], al + + pop ax + mov byte [es:di], al + + mov ax, 0 + je check_a20__exit + + mov ax, 1 + +check_a20__exit: + pop si + pop di + pop es + pop ds + popf + + ret diff --git a/tests/test_unreal.asm b/tests/test_unreal.asm new file mode 100644 index 0000000..687a528 --- /dev/null +++ b/tests/test_unreal.asm @@ -0,0 +1,49 @@ +; Assembly example + +; nasm boot.asm -o boot.bin +; partcopy boot.bin 0 200 -f0 + +[ORG 0x7c00] ; add to offsets + +start: xor ax, ax ; make it zero + mov ds, ax ; DS=0 + mov ss, ax ; stack starts at seg 0 + mov sp, 0x9c00 ; 2000h past code start, + ; making the stack 7.5k in size + + cli ; no interrupts + push ds ; save real mode + + lgdt [gdtinfo] ; load gdt register + + mov eax, cr0 ; switch to pmode by + or al,1 ; set pmode bit + mov cr0, eax + + jmp $+2 ; tell 386/486 to not crash + + mov bx, 0x08 ; select descriptor 1 + mov ds, bx ; 8h = 1000b + + and al,0xFE ; back to realmode + mov cr0, eax ; by toggling bit again + + pop ds ; get back old segment + sti + + mov bx, 0x0f01 ; attrib/char of smiley + mov eax, 0x0b8000 ; note 32 bit offset + mov word [ds:eax], bx + + jmp $ ; loop forever + +gdtinfo: + dw gdt_end - gdt - 1 ;last byte in table + dd gdt ;start of table + +gdt dd 0,0 ; entry 0 is always unused +flatdesc db 0xff, 0xff, 0, 0, 0, 10010010b, 11001111b, 0 +gdt_end: + + times 510-($-$$) db 0 ; fill sector w/ 0's + dw 0xAA55 ; Required by some BIOSes diff --git a/todo/doc/0xax.gitbooks.io_linux-insides_content_Booting_linux-bootstrap-1.txt b/todo/doc/0xax.gitbooks.io_linux-insides_content_Booting_linux-bootstrap-1.txt new file mode 100644 index 0000000..d1e1971 --- /dev/null +++ b/todo/doc/0xax.gitbooks.io_linux-insides_content_Booting_linux-bootstrap-1.txt @@ -0,0 +1,897 @@ + #[1]next [2]prev + + IFRAME: + [3]https://archive.org/includes/donate.php?as_page=1&platform=wb&refere + r=https%3A//web.archive.org/web/20230308144716/https%3A//0xax.gitbooks. + io/linux-insides/content/Booting/linux-bootstrap-1.html + + [4]Wayback Machine + https://0xax.gitbook Go + [5]86 captures + 01 Feb 2015 - 22 Mar 2023 + [6]Jan MAR Apr + [7]Previous capture 08 [8]Next capture + [9]2022 2023 2024 + success + fail + [10]About this capture + COLLECTED BY + Collection: [11]mega002 + TIMESTAMPS + loading + + The Wayback Machine - + https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/lin + ux-insides/content/Booting/linux-bootstrap-1.html + + ____________________ + + * [12]Linux Inside + * + * Summary + * [13]Introduction + * [14]Booting + + [15]From bootloader to kernel + + [16]First steps in the kernel setup code + + [17]Video mode initialization and transition to protected mode + + [18]Transition to 64-bit mode + + [19]Kernel decompression + + [20]Kernel load address randomization + * [21]Initialization + + [22]First steps in the kernel + + [23]Early interrupts handler + + [24]Last preparations before the kernel entry point + + [25]Kernel entry point + + [26]Continue architecture-specific boot-time initializations + + [27]Architecture-specific initializations, again... + + [28]End of the architecture-specific initializations, + almost... + + [29]Scheduler initialization + + [30]RCU initialization + + [31]End of initialization + * [32]Interrupts + + [33]Introduction + + [34]Start to dive into interrupts + + [35]Interrupt handlers + + [36]Initialization of non-early interrupt gates + + [37]Implementation of some exception handlers + + [38]Handling Non-Maskable interrupts + + [39]Dive into external hardware interrupts + + [40]Initialization of external hardware interrupts structures + + [41]Softirq, Tasklets and Workqueues + + [42]Last part + * [43]System calls + + [44]Introduction to system calls + + [45]How the Linux kernel handles a system call + + [46]vsyscall and vDSO + + [47]How the Linux kernel runs a program + + [48]Implementation of the open system call + + [49]Limits on resources in Linux + * [50]Timers and time management + + [51]Introduction + + [52]Clocksource framework + + [53]The tick broadcast framework and dyntick + + [54]Introduction to timers + + [55]Clockevents framework + + [56]x86 related clock sources + + [57]Time related system calls + * [58]Synchronization primitives + + [59]Introduction to spinlocks + + [60]Queued spinlocks + + [61]Semaphores + + [62]Mutex + + [63]Reader/Writer semaphores + + [64]SeqLock + + RCU + + Lockdep + * [65]Memory management + + [66]Memblock + + [67]Fixmaps and ioremap + + [68]kmemcheck + * [69]Cgroups + + [70]Introduction to Control Groups + * SMP + * [71]Concepts + + [72]Per-CPU variables + + [73]Cpumasks + + [74]The initcall mechanism + + [75]Notification Chains + * [76]Data Structures in the Linux Kernel + + [77]Doubly linked list + + [78]Radix tree + + [79]Bit arrays + * [80]Theory + + [81]Paging + + [82]Elf64 + + [83]Inline assembly + + CPUID + + MSR + * Initial ram disk + + initrd + * [84]Misc + + [85]Linux kernel development + + [86]How the kernel is compiled + + [87]Linkers + + [88]Program startup process in userspace + + Write and Submit your first Linux kernel Patch + + Data types in the kernel + * [89]KernelStructures + + [90]IDT + * [91]Useful links + * [92]Contributors + * + + Powered by GitBook + +[93]From bootloader to kernel + +Kernel booting process. Part 1. + +From the bootloader to the kernel + + If you read my previous [94]blog posts, you might have noticed that I + have been involved with low-level programming for some time. I wrote + some posts about assembly programming for x86_64 Linux and, at the same + time, started to dive into the Linux kernel source code. + + I have a great interest in understanding how low-level things work, how + programs run on my computer, how they are located in memory, how the + kernel manages processes and memory, how the network stack works at a + low level, and many many other things. So, I decided to write yet + another series of posts about the Linux kernel for the x86_64 + architecture. + + Note that I'm not a professional kernel hacker and I don't write code + for the kernel at work. It's just a hobby. I just like low-level stuff, + and it is interesting for me to see how these things work. So if you + notice anything confusing, or if you have any questions/remarks, ping + me on Twitter [95]0xAX, drop me an [96]email or just create an + [97]issue. I appreciate it. + + All posts will also be accessible at [98]github repo and, if you find + something wrong with my English or the post content, feel free to send + a pull request. + + Note that this isn't official documentation, just learning and sharing + knowledge. + + Required knowledge + * Understanding C code + * Understanding assembly code (AT&T syntax) + + Anyway, if you're just starting to learn such tools, I will try to + explain some parts during this and the following posts. Alright, this + is the end of the simple introduction. Let's start to dive into the + Linux kernel and low-level stuff! + + I started writing these posts at the time of the 3.18 Linux kernel, and + many things have changed since that time. If there are changes, I will + update the posts accordingly. + +The Magical Power Button, What happens next? + + Although this is a series of posts about the Linux kernel, we won't + start directly from the kernel code. As soon as you press the magical + power button on your laptop or desktop computer, it starts working. The + motherboard sends a signal to the [99]power supply device. After + receiving the signal, the power supply provides the proper amount of + electricity to the computer. Once the motherboard receives the + [100]power good signal, it tries to start the CPU. The CPU resets all + leftover data in its registers and sets predefined values for each of + them. + + The [101]80386 and later CPUs define the following predefined data in + CPU registers after the computer resets: +IP 0xfff0 +CS selector 0xf000 +CS base 0xffff0000 + + The processor starts working in [102]real mode. Let's back up a little + and try to understand [103]memory segmentation in this mode. Real mode + is supported on all x86-compatible processors, from the [104]8086 CPU + all the way to the modern Intel 64-bit CPUs. The 8086 processor has a + 20-bit address bus, which means that it could work with a 0-0xFFFFF or + 1 megabyte address space. But it only has 16-bit registers, which have + a maximum address of 2^16 - 1 or 0xffff (64 kilobytes). + + [105]Memory segmentation is used to make use of all the address space + available. All memory is divided into small, fixed-size segments of + 65536 bytes (64 KB). Since we cannot address memory above 64 KB with + 16-bit registers, an alternate method was devised. + + An address consists of two parts: a segment selector, which has a base + address; and an offset from this base address. In real mode, the + associated base address of a segment selector is Segment Selector * 16. + Thus, to get a physical address in memory, we need to multiply the + segment selector part by 16 and add the offset to it: +PhysicalAddress = Segment Selector * 16 + Offset + + For example, if CS:IP is 0x2000:0x0010, then the corresponding physical + address will be: +>>> hex((0x2000 << 4) + 0x0010) +'0x20010' + + But, if we take the largest segment selector and offset, 0xffff:0xffff, + then the resulting address will be: +>>> hex((0xffff << 4) + 0xffff) +'0x10ffef' + + which is 65520 bytes past the first megabyte. Since only one megabyte + is accessible in real mode, 0x10ffef becomes 0x00ffef with the [106]A20 + line disabled. + + Ok, now we know a little bit about real mode and its memory addressing. + Let's get back to discussing register values after reset. + + The CS register consists of two parts: the visible segment selector and + the hidden base address. While the base address is normally formed by + multiplying the segment selector value by 16, during a hardware reset + the segment selector in the CS register is loaded with 0xf000 and the + base address is loaded with 0xffff0000. The processor uses this special + base address until CS changes. + + The starting address is formed by adding the base address to the value + in the EIP register: +>>> 0xffff0000 + 0xfff0 +'0xfffffff0' + + We get 0xfffffff0, which is 16 bytes below 4GB. This point is called + the [107]reset vector. It's the memory location at which the CPU + expects to find the first instruction to execute after reset. It + contains a [108]jump (jmp) instruction that usually points to the + [109]BIOS (Basic Input/Output System) entry point. For example, if we + look in the [110]coreboot source code (src/cpu/x86/16bit/reset16.inc), + we see: + .section ".reset", "ax", %progbits + .code16 +.globl _start +_start: + .byte 0xe9 + .int _start16bit - ( . + 2 ) + ... + + Here we can see the jmp instruction [111]opcode, which is 0xe9, and its + destination address at _start16bit - ( . + 2). + + We also see that the reset section is 16 bytes and is compiled to start + from the address 0xfffffff0 (src/cpu/x86/16bit/reset16.ld): +SECTIONS { + /* Trigger an error if I have an unuseable start address */ + _bogus = ASSERT(_start16bit >= 0xffff0000, "_start16bit too low. Please repo +rt."); + _ROMTOP = 0xfffffff0; + . = _ROMTOP; + .reset . : { + *(.reset); + . = 15; + BYTE(0x00); + } +} + + Now the BIOS starts. After initializing and checking the hardware, the + BIOS needs to find a bootable device. A boot order is stored in the + BIOS configuration, controlling which devices the BIOS attempts to boot + from. When attempting to boot from a hard drive, the BIOS tries to find + a boot sector. On hard drives partitioned with an [112]MBR partition + layout, the boot sector is stored in the first 446 bytes of the first + sector, where each sector is 512 bytes. The final two bytes of the + first sector are 0x55 and 0xaa, which designates to the BIOS that this + device is bootable. + + For example: +; +; Note: this example is written in Intel Assembly syntax +; +[BITS 16] + +boot: + mov al, '!' + mov ah, 0x0e + mov bh, 0x00 + mov bl, 0x07 + + int 0x10 + jmp $ + +times 510-($-$$) db 0 + +db 0x55 +db 0xaa + + Build and run this with: +nasm -f bin boot.nasm && qemu-system-x86_64 boot + + This will instruct [113]QEMU to use the boot binary that we just built + as a disk image. Since the binary generated by the assembly code above + fulfills the requirements of the boot sector (the origin is set to + 0x7c00 and we end it with the magic sequence), QEMU will treat the + binary as the master boot record (MBR) of a disk image. + + You will see: + + Simple bootloader which prints only `!` + + In this example, we can see that the code will be executed in 16-bit + real mode and will start at 0x7c00 in memory. After starting, it calls + the [114]0x10 interrupt, which just prints the ! symbol. It fills the + remaining 510 bytes with zeros and finishes with the two magic bytes + 0xaa and 0x55. + + You can see a binary dump of this using the objdump utility: +nasm -f bin boot.nasm +objdump -D -b binary -mi386 -Maddr16,data16,intel boot + + A real-world boot sector has code for continuing the boot process and a + partition table instead of a bunch of 0's and an exclamation mark. :) + From this point onwards, the BIOS hands control over to the bootloader. + + NOTE: As explained above, the CPU is in real mode. In real mode, + calculating the physical address in memory is done as follows: +PhysicalAddress = Segment Selector * 16 + Offset + + just as explained above. We have only 16-bit general purpose registers, + which has a maximum value of 0xffff, so if we take the largest values + the result will be: +>>> hex((0xffff * 16) + 0xffff) +'0x10ffef' + + where 0x10ffef is equal to 1MB + 64KB - 16b. An [115]8086 processor + (which was the first processor with real mode), in contrast, has a + 20-bit address line. Since 2^20 = 1048576 is 1MB, this means that the + actual available memory is 1MB. + + In general, real mode's memory map is as follows: +0x00000000 - 0x000003FF - Real Mode Interrupt Vector Table +0x00000400 - 0x000004FF - BIOS Data Area +0x00000500 - 0x00007BFF - Unused +0x00007C00 - 0x00007DFF - Our Bootloader +0x00007E00 - 0x0009FFFF - Unused +0x000A0000 - 0x000BFFFF - Video RAM (VRAM) Memory +0x000B0000 - 0x000B7777 - Monochrome Video Memory +0x000B8000 - 0x000BFFFF - Color Video Memory +0x000C0000 - 0x000C7FFF - Video ROM BIOS +0x000C8000 - 0x000EFFFF - BIOS Shadow Area +0x000F0000 - 0x000FFFFF - System BIOS + + At the beginning of this post, I wrote that the first instruction + executed by the CPU is located at address 0xFFFFFFF0, which is much + larger than 0xFFFFF (1MB). How can the CPU access this address in real + mode? The answer is in the [116]coreboot documentation: +0xFFFE_0000 - 0xFFFF_FFFF: 128 kilobyte ROM mapped into address space + + At the start of execution, the BIOS is not in RAM, but in ROM. + +Bootloader + + There are a number of bootloaders that can boot Linux, such as + [117]GRUB 2 and [118]syslinux. The Linux kernel has a [119]Boot + protocol which specifies the requirements for a bootloader to implement + Linux support. This example will describe GRUB 2. + + Continuing from before, now that the BIOS has chosen a boot device and + transferred control to the boot sector code, execution starts from + [120]boot.img. Its code is very simple, due to the limited amount of + space available. It contains a pointer which is used to jump to the + location of GRUB 2's core image. The core image begins with + [121]diskboot.img, which is usually stored immediately after the first + sector in the unused space before the first partition. The above code + loads the rest of the core image, which contains GRUB 2's kernel and + drivers for handling filesystems, into memory. After loading the rest + of the core image, it executes the [122]grub_main function. + + The grub_main function initializes the console, gets the base address + for modules, sets the root device, loads/parses the grub configuration + file, loads modules, etc. At the end of execution, the grub_main + function moves grub to normal mode. The grub_normal_execute function + (from the grub-core/normal/main.c source code file) completes the final + preparations and shows a menu to select an operating system. When we + select one of the grub menu entries, the grub_menu_execute_entry + function runs, executing the grub boot command and booting the selected + operating system. + + As we can read in the kernel boot protocol, the bootloader must read + and fill some fields of the kernel setup header, which starts at offset + 0x01f1 from the kernel setup code. You may look at the boot [123]linker + script to confirm the value of this offset. The kernel header + [124]arch/x86/boot/header.S starts from: + .globl hdr +hdr: + setup_sects: .byte 0 + root_flags: .word ROOT_RDONLY + syssize: .long 0 + ram_size: .word 0 + vid_mode: .word SVGA_MODE + root_dev: .word 0 + boot_flag: .word 0xAA55 + + The bootloader must fill this and the rest of the headers (which are + only marked as being type write in the Linux boot protocol, such as in + [125]this example) with values either received from the command line or + calculated during booting. (We will not go over full descriptions and + explanations for all fields of the kernel setup header for now, but we + shall do so when discussing how the kernel uses them. You can find a + description of all fields in the [126]boot protocol.) + + As we can see in the kernel boot protocol, memory will be mapped as + follows after loading the kernel: + | Protected-mode kernel | +100000 +------------------------+ + | I/O memory hole | +0A0000 +------------------------+ + | Reserved for BIOS | Leave as much as possible unused + ~ ~ + | Command line | (Can also be below the X+10000 mark) +X+10000 +------------------------+ + | Stack/heap | For use by the kernel real-mode code. +X+08000 +------------------------+ + | Kernel setup | The kernel real-mode code. + | Kernel boot sector | The kernel legacy boot sector. + X +------------------------+ + | Boot loader | <- Boot sector entry point 0x7C00 +001000 +------------------------+ + | Reserved for MBR/BIOS | +000800 +------------------------+ + | Typically used by MBR | +000600 +------------------------+ + | BIOS use only | +000000 +------------------------+ + + When the bootloader transfers control to the kernel, it starts at: +X + sizeof(KernelBootSector) + 1 + + where X is the address of the kernel boot sector being loaded. In my + case, X is 0x10000, as we can see in a memory dump: + + kernel first address + + The bootloader has now loaded the Linux kernel into memory, filled the + header fields, and then jumped to the corresponding memory address. We + now move directly to the kernel setup code. + +The Beginning of the Kernel Setup Stage + + Finally, we are in the kernel! Technically, the kernel hasn't run yet. + First, the kernel setup part must configure stuff such as the + decompressor and some memory management related things, to name a few. + After all these things are done, the kernel setup part will decompress + the actual kernel and jump to it. Execution of the setup part starts + from [127]arch/x86/boot/header.S at the [128]_start symbol. + + It may look a bit strange at first sight, as there are several + instructions before it. A long time ago, the Linux kernel had its own + bootloader. Now, however, if you run, for example, +qemu-system-x86_64 vmlinuz-3.18-generic + + then you will see: + + Try vmlinuz in qemu + + Actually, the file header.S starts with the magic number [129]MZ (see + image above), the error message that displays and, following that, the + [130]PE header: +#ifdef CONFIG_EFI_STUB +# "MZ", MS-DOS header +.byte 0x4d +.byte 0x5a +#endif +... +... +... +pe_header: + .ascii "PE" + .word 0 + + It needs this to load an operating system with [131]UEFI support. We + won't be looking into its inner workings right now but will cover it in + upcoming chapters. + + The actual kernel setup entry point is: +// header.S line 292 +.globl _start +_start: + + The bootloader (GRUB 2 and others) knows about this point (at an offset + of 0x200 from MZ) and jumps directly to it, despite the fact that + header.S starts from the .bstext section, which prints an error + message: +// +// arch/x86/boot/setup.ld +// +. = 0; // current position +.bstext : { *(.bstext) } // put .bstext section to position 0 +.bsdata : { *(.bsdata) } + + The kernel setup entry point is: + .globl _start +_start: + .byte 0xeb + .byte start_of_setup-1f +1: + // + // rest of the header + // + + Here we can see a jmp instruction opcode (0xeb) that jumps to the + start_of_setup-1f point. In Nf notation, 2f, for example, refers to the + local label 2:. In our case, it's label 1: that is present right after + the jump, and contains the rest of the setup [132]header. Right after + the setup header, we see the .entrytext section, which starts at the + start_of_setup label. + + This is the first code that actually runs (aside from the previous jump + instructions, of course). After the kernel setup part receives control + from the bootloader, the first jmp instruction is located at the 0x200 + offset from the start of the kernel real mode, i.e., after the first + 512 bytes. This can be seen in both the Linux kernel boot protocol and + the GRUB 2 source code: +segment = grub_linux_real_target >> 4; +state.gs = state.fs = state.es = state.ds = state.ss = segment; +state.cs = segment + 0x20; + + In my case, the kernel is loaded at the physical address 0x10000. This + means that segment registers have the following values after kernel + setup starts: +gs = fs = es = ds = ss = 0x1000 +cs = 0x1020 + + After the jump to start_of_setup, the kernel needs to do the following: + * Make sure that all segment register values are equal + * Set up a correct stack, if needed + * Set up [133]bss + * Jump to the C code in [134]arch/x86/boot/main.c + + Let's look at the implementation. + +Aligning the Segment Registers + + First of all, the kernel ensures that the ds and es segment registers + point to the same address. Next, it clears the direction flag using the + cld instruction: + movw %ds, %ax + movw %ax, %es + cld + + As I wrote earlier, grub2 loads kernel setup code at address 0x10000 by + default and cs at 0x1020 because execution doesn't start from the start + of the file, but from the jump here: +_start: + .byte 0xeb + .byte start_of_setup-1f + + which is at a 512 byte offset from [135]4d 5a. We also need to align cs + from 0x1020 to 0x1000, as well as all other segment registers. After + that, we set up the stack: + pushw %ds + pushw $6f + lretw + + which pushes the value of ds to the stack, followed by the address of + the [136]6 label and executes the lretw instruction. When the lretw + instruction is called, it loads the address of label 6 into the + [137]instruction pointer register and loads cs with the value of ds. + Afterward, ds and cs will have the same values. + +Stack Setup + + Almost all of the setup code is for preparing the C language + environment in real mode. The next [138]step is checking the ss + register's value and setting up a correct stack if ss is wrong: + movw %ss, %dx + cmpw %ax, %dx + movw %sp, %dx + je 2f + + This can lead to 3 different scenarios: + * ss has a valid value 0x1000 (as do all the other segment registers + besides cs) + * ss is invalid and the CAN_USE_HEAP flag is set (see below) + * ss is invalid and the CAN_USE_HEAP flag is not set (see below) + + Let's look at all three of these scenarios in turn: + * ss has a correct address (0x1000). In this case, we go to label + [139]2: + +2: andw $~3, %dx + jnz 3f + movw $0xfffc, %dx +3: movw %ax, %ss + movzwl %dx, %esp + sti + + Here we set the alignment of dx (which contains the value of sp as + given by the bootloader) to 4 bytes and check if it is zero. If it is, + we set dx to 0xfffc (The last 4-byte aligned address in a 64KB + segment). If it is not zero, we continue to use the value of sp given + by the bootloader (0xf7f4 in my case). Afterwards, we put the value of + ax (0x1000) into ss. We now have a correct stack: + + stack + * The second scenario, (ss != ds). First, we put the value of + [140]_end (the address of the end of the setup code) into dx and + check the loadflags header field using the testb instruction to see + whether we can use the heap. [141]loadflags is a bitmask header + defined as: + +#define LOADED_HIGH (1<<0) +#define QUIET_FLAG (1<<5) +#define KEEP_SEGMENTS (1<<6) +#define CAN_USE_HEAP (1<<7) + + and as we can read in the boot protocol: +Field name: loadflags + + This field is a bitmask. + + Bit 7 (write): CAN_USE_HEAP + Set this bit to 1 to indicate that the value entered in the + heap_end_ptr is valid. If this field is clear, some setup code + functionality will be disabled. + + If the CAN_USE_HEAP bit is set, we put heap_end_ptr into dx (which + points to _end) and add STACK_SIZE (the minimum stack size, 1024 bytes) + to it. After this, if dx is not carried (it will not be carried, dx = + _end + 1024), jump to label 2 (as in the previous case) and make a + correct stack. + + stack + * When CAN_USE_HEAP is not set, we just use a minimal stack from _end + to _end + STACK_SIZE: + + minimal stack + +BSS Setup + + The last two steps that need to happen before we can jump to the main C + code are setting up the [142]BSS area and checking the "magic" + signature. First, signature checking: + cmpl $0x5a5aaa55, setup_sig + jne setup_bad + + This simply compares the [143]setup_sig with the magic number + 0x5a5aaa55. If they are not equal, a fatal error is reported. + + If the magic number matches, knowing we have a set of correct segment + registers and a stack, we only need to set up the BSS section before + jumping into the C code. + + The BSS section is used to store statically allocated, uninitialized + data. Linux carefully ensures this area of memory is first zeroed using + the following code: + movw $__bss_start, %di + movw $_end+3, %cx + xorl %eax, %eax + subw %di, %cx + shrw $2, %cx + rep; stosl + + First, the [144]__bss_start address is moved into di. Next, the _end + + 3 address (+3 - aligns to 4 bytes) is moved into cx. The eax register + is cleared (using the xor instruction), and the bss section size (cx - + di) is calculated and put into cx. Then, cx is divided by four (the + size of a 'word'), and the stosl instruction is used repeatedly, + storing the value of eax (zero) into the address pointed to by di, + automatically increasing di by four, repeating until cx reaches zero. + The net effect of this code is that zeros are written through all words + in memory from __bss_start to _end: + + bss + +Jump to main + + That's all! We have the stack and BSS, so we can jump to the main() C + function: + calll main + + The main() function is located in [145]arch/x86/boot/main.c. You can + read about what this does in the next part. + +Conclusion + + This is the end of the first part about Linux kernel insides. If you + have questions or suggestions, ping me on Twitter [146]0xAX, drop me an + [147]email, or just create an [148]issue. In the next part, we will see + the first C code that executes in the Linux kernel setup, the + implementation of memory routines such as memset, memcpy, earlyprintk, + early console implementation and initialization, and much more. + + Please note that English is not my first language and I am really sorry + for any inconvenience. If you find any mistakes please send me PR to + [149]linux-insides. + +Links + + * [150]Intel 80386 programmer's reference manual 1986 + * [151]Minimal Boot Loader for Intel Architecture + * [152]Minimal Boot Loader in Assembler with comments + * [153]8086 + * [154]80386 + * [155]Reset vector + * [156]Real mode + * [157]Linux kernel boot protocol + * [158]coreboot developer manual + * [159]Ralf Brown's Interrupt List + * [160]Power supply + * [161]Power good signal + +results matching "" + +No results matching "" + +References + + Visible links: + 1. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 2. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/ + 3. https://archive.org/includes/donate.php?as_page=1&platform=wb&referer=https%3A//web.archive.org/web/20230308144716/https%3A//0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 4. https://web.archive.org/web/ + 5. https://web.archive.org/web/20230308144716*/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 6. https://web.archive.org/web/20230125232251/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 7. https://web.archive.org/web/20230221231350/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 8. https://web.archive.org/web/20230322150040/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 9. https://web.archive.org/web/20220120153936/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 10. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html#expand + 11. https://archive.org/details/mega-002 + 12. https://web.archive.org/web/20230308144716/https://legacy.gitbook.com/book/0xax/linux-insides + 13. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/ + 14. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/ + 15. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 16. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 17. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-3.html + 18. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-4.html + 19. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-5.html + 20. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-6.html + 21. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/ + 22. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-1.html + 23. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-2.html + 24. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-3.html + 25. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-4.html + 26. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-5.html + 27. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-6.html + 28. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-7.html + 29. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-8.html + 30. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-9.html + 31. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-10.html + 32. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/ + 33. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-1.html + 34. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-2.html + 35. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-3.html + 36. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-4.html + 37. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-5.html + 38. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-6.html + 39. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-7.html + 40. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-8.html + 41. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-9.html + 42. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-10.html + 43. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SysCall/ + 44. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-1.html + 45. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-2.html + 46. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-3.html + 47. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-4.html + 48. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-5.html + 49. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-6.html + 50. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Timers/ + 51. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-1.html + 52. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-2.html + 53. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-3.html + 54. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-4.html + 55. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-5.html + 56. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-6.html + 57. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-7.html + 58. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/ + 59. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-1.html + 60. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-2.html + 61. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-3.html + 62. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-4.html + 63. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-5.html + 64. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-6.html + 65. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/MM/ + 66. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/MM/linux-mm-1.html + 67. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/MM/linux-mm-2.html + 68. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/MM/linux-mm-3.html + 69. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Cgroups/ + 70. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Cgroups/linux-cgroups-1.html + 71. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Concepts/ + 72. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-1.html + 73. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-2.html + 74. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-3.html + 75. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-4.html + 76. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/DataStructures/ + 77. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/DataStructures/linux-datastructures-1.html + 78. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/DataStructures/linux-datastructures-2.html + 79. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/DataStructures/linux-datastructures-3.html + 80. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Theory/ + 81. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Theory/linux-theory-1.html + 82. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Theory/linux-theory-2.html + 83. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Theory/linux-theory-3.html + 84. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Misc/ + 85. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Misc/linux-misc-1.html + 86. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Misc/linux-misc-2.html + 87. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Misc/linux-misc-3.html + 88. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Misc/linux-misc-4.html + 89. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/KernelStructures/ + 90. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/KernelStructures/linux-kernelstructure-1.html + 91. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/LINKS.html + 92. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/contributors.html + 93. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/ + 94. https://web.archive.org/web/20230308144716/https://0xax.github.io/categories/assembler/ + 95. https://web.archive.org/web/20230308144716/https://twitter.com/0xAX + 96. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/anotherworldofworld@gmail.com + 97. https://web.archive.org/web/20230308144716/https://github.com/0xAX/linux-insides/issues/new + 98. https://web.archive.org/web/20230308144716/https://github.com/0xAX/linux-insides + 99. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Power_supply + 100. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Power_good_signal + 101. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Intel_80386 + 102. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Real_mode + 103. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Memory_segmentation + 104. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Intel_8086 + 105. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Memory_segmentation + 106. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/A20_line + 107. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Reset_vector + 108. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/JMP_%28x86_instruction%29 + 109. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/BIOS + 110. https://web.archive.org/web/20230308144716/https://www.coreboot.org/ + 111. https://web.archive.org/web/20230308144716/http://ref.x86asm.net/coder32.html#xE9 + 112. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Master_boot_record + 113. https://web.archive.org/web/20230308144716/https://www.qemu.org/ + 114. https://web.archive.org/web/20230308144716/http://www.ctyme.com/intr/rb-0106.htm + 115. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Intel_8086 + 116. https://web.archive.org/web/20230308144716/https://www.coreboot.org/Developer_Manual/Memory_map + 117. https://web.archive.org/web/20230308144716/https://www.gnu.org/software/grub/ + 118. https://web.archive.org/web/20230308144716/http://www.syslinux.org/wiki/index.php/The_Syslinux_Project + 119. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/Documentation/x86/boot.txt + 120. https://web.archive.org/web/20230308144716/http://git.savannah.gnu.org/gitweb/?p=grub.git;a=blob;f=grub-core/boot/i386/pc/boot.S;hb=HEAD + 121. https://web.archive.org/web/20230308144716/http://git.savannah.gnu.org/gitweb/?p=grub.git;a=blob;f=grub-core/boot/i386/pc/diskboot.S;hb=HEAD + 122. https://web.archive.org/web/20230308144716/http://git.savannah.gnu.org/gitweb/?p=grub.git;a=blob;f=grub-core/kern/main.c + 123. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/setup.ld + 124. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S + 125. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/Documentation/x86/boot.txt#L354 + 126. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/Documentation/x86/boot.txt#L156 + 127. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S + 128. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S#L292 + 129. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/DOS_MZ_executable + 130. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Portable_Executable + 131. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface + 132. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/Documentation/x86/boot.txt#L156 + 133. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/.bss + 134. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/main.c + 135. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S#L46 + 136. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S#L602 + 137. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Program_counter + 138. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S#L575 + 139. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S#L589 + 140. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/setup.ld + 141. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S#L320 + 142. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/.bss + 143. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/setup.ld + 144. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/setup.ld + 145. https://web.archive.org/web/20230308144716/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/main.c + 146. https://web.archive.org/web/20230308144716/https://twitter.com/0xAX + 147. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/anotherworldofworld@gmail.com + 148. https://web.archive.org/web/20230308144716/https://github.com/0xAX/linux-internals/issues/new + 149. https://web.archive.org/web/20230308144716/https://github.com/0xAX/linux-internals + 150. https://web.archive.org/web/20230308144716/http://css.csail.mit.edu/6.858/2014/readings/i386.pdf + 151. https://web.archive.org/web/20230308144716/https://www.cs.cmu.edu/~410/doc/minimal_boot.pdf + 152. https://web.archive.org/web/20230308144716/https://github.com/Stefan20162016/linux-insides-code/blob/master/bootloader.asm + 153. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Intel_8086 + 154. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Intel_80386 + 155. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Reset_vector + 156. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Real_mode + 157. https://web.archive.org/web/20230308144716/https://www.kernel.org/doc/Documentation/x86/boot.txt + 158. https://web.archive.org/web/20230308144716/https://www.coreboot.org/Developer_Manual + 159. https://web.archive.org/web/20230308144716/http://www.ctyme.com/intr/int.htm + 160. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Power_supply + 161. https://web.archive.org/web/20230308144716/https://en.wikipedia.org/wiki/Power_good_signal + + Hidden links: + 163. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 164. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 165. https://archive.org/account/login.php + 166. http://faq.web.archive.org/ + 167. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html#close + 168. https://web.archive.org/web/20230308144716/http://web.archive.org/screenshot/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 169. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 170. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 171. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 172. https://web.archive.org/web/20230308144716/https://www.gitbook.com/?utm_source=public_site_legacy&utm_medium=referral&utm_campaign=trademark&utm_term=0xax&utm_content=powered_by + 173. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/ + 174. https://web.archive.org/web/20230308144716/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html diff --git a/todo/doc/0xax.gitbooks.io_linux-insides_content_Booting_linux-bootstrap-2.txt b/todo/doc/0xax.gitbooks.io_linux-insides_content_Booting_linux-bootstrap-2.txt new file mode 100644 index 0000000..c0663b3 --- /dev/null +++ b/todo/doc/0xax.gitbooks.io_linux-insides_content_Booting_linux-bootstrap-2.txt @@ -0,0 +1,937 @@ + #[1]next [2]prev + + IFRAME: + [3]https://archive.org/includes/donate.php?as_page=1&platform=wb&refere + r=https%3A//web.archive.org/web/20230308144724/https%3A//0xax.gitbooks. + io/linux-insides/content/Booting/linux-bootstrap-2.html + + [4]Wayback Machine + https://0xax.gitbook Go + [5]47 captures + 02 Feb 2015 - 22 Mar 2023 + [6]Dec MAR Apr + [7]Previous capture 08 [8]Next capture + [9]2022 2023 2024 + success + fail + [10]About this capture + COLLECTED BY + Collection: [11]mega002 + TIMESTAMPS + loading + + The Wayback Machine - + https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/lin + ux-insides/content/Booting/linux-bootstrap-2.html + + ____________________ + + * [12]Linux Inside + * + * Summary + * [13]Introduction + * [14]Booting + + [15]From bootloader to kernel + + [16]First steps in the kernel setup code + + [17]Video mode initialization and transition to protected mode + + [18]Transition to 64-bit mode + + [19]Kernel decompression + + [20]Kernel load address randomization + * [21]Initialization + + [22]First steps in the kernel + + [23]Early interrupts handler + + [24]Last preparations before the kernel entry point + + [25]Kernel entry point + + [26]Continue architecture-specific boot-time initializations + + [27]Architecture-specific initializations, again... + + [28]End of the architecture-specific initializations, + almost... + + [29]Scheduler initialization + + [30]RCU initialization + + [31]End of initialization + * [32]Interrupts + + [33]Introduction + + [34]Start to dive into interrupts + + [35]Interrupt handlers + + [36]Initialization of non-early interrupt gates + + [37]Implementation of some exception handlers + + [38]Handling Non-Maskable interrupts + + [39]Dive into external hardware interrupts + + [40]Initialization of external hardware interrupts structures + + [41]Softirq, Tasklets and Workqueues + + [42]Last part + * [43]System calls + + [44]Introduction to system calls + + [45]How the Linux kernel handles a system call + + [46]vsyscall and vDSO + + [47]How the Linux kernel runs a program + + [48]Implementation of the open system call + + [49]Limits on resources in Linux + * [50]Timers and time management + + [51]Introduction + + [52]Clocksource framework + + [53]The tick broadcast framework and dyntick + + [54]Introduction to timers + + [55]Clockevents framework + + [56]x86 related clock sources + + [57]Time related system calls + * [58]Synchronization primitives + + [59]Introduction to spinlocks + + [60]Queued spinlocks + + [61]Semaphores + + [62]Mutex + + [63]Reader/Writer semaphores + + [64]SeqLock + + RCU + + Lockdep + * [65]Memory management + + [66]Memblock + + [67]Fixmaps and ioremap + + [68]kmemcheck + * [69]Cgroups + + [70]Introduction to Control Groups + * SMP + * [71]Concepts + + [72]Per-CPU variables + + [73]Cpumasks + + [74]The initcall mechanism + + [75]Notification Chains + * [76]Data Structures in the Linux Kernel + + [77]Doubly linked list + + [78]Radix tree + + [79]Bit arrays + * [80]Theory + + [81]Paging + + [82]Elf64 + + [83]Inline assembly + + CPUID + + MSR + * Initial ram disk + + initrd + * [84]Misc + + [85]Linux kernel development + + [86]How the kernel is compiled + + [87]Linkers + + [88]Program startup process in userspace + + Write and Submit your first Linux kernel Patch + + Data types in the kernel + * [89]KernelStructures + + [90]IDT + * [91]Useful links + * [92]Contributors + * + + Powered by GitBook + +[93]First steps in the kernel setup code + +Kernel booting process. Part 2. + +First steps in the kernel setup + + We started to dive into the linux kernel's insides in the previous + [94]part and saw the initial part of the kernel setup code. We stopped + at the first call to the main function (which is the first function + written in C) from [95]arch/x86/boot/main.c. + + In this part, we will continue to research the kernel setup code and go + over + * what protected mode is, + * the transition into it, + * the initialization of the heap and the console, + * memory detection, CPU validation and keyboard initialization + * and much much more. + + So, let's go ahead. + +Protected mode + + Before we can move to the native Intel64 [96]Long Mode, the kernel must + switch the CPU into protected mode. + + What is [97]protected mode? Protected mode was first added to the x86 + architecture in 1982 and was the main mode of Intel processors from the + [98]80286 processor until Intel 64 and long mode came. + + The main reason to move away from [99]Real mode is that there is very + limited access to the RAM. As you may remember from the previous part, + there are only 2^20 bytes or 1 Megabyte, sometimes even only 640 + Kilobytes of RAM available in Real mode. + + Protected mode brought many changes, but the main one is the difference + in memory management. The 20-bit address bus was replaced with a 32-bit + address bus. It allowed access to 4 Gigabytes of memory vs the 1 + Megabyte in Real mode. Also, [100]paging support was added, which you + can read about in the next sections. + + Memory management in Protected mode is divided into two, almost + independent parts: + * Segmentation + * Paging + + Here we will only talk about segmentation. Paging will be discussed in + the next sections. + + As you can read in the previous part, addresses consist of two parts in + Real mode: + * Base address of the segment + * Offset from the segment base + + And we can get the physical address if we know these two parts by: +PhysicalAddress = Segment Base * 16 + Offset + + Memory segmentation was completely redone in protected mode. There are + no 64 Kilobyte fixed-size segments. Instead, the size and location of + each segment is described by an associated data structure called the + Segment Descriptor. These segment descriptors are stored in a data + structure called the Global Descriptor Table (GDT). + + The GDT is a structure which resides in memory. It has no fixed place + in the memory, so its address is stored in the special GDTR register. + Later we will see how the GDT is loaded in the Linux kernel code. There + will be an operation for loading it from memory, something like: +lgdt gdt + + where the lgdt instruction loads the base address and limit(size) of + the global descriptor table to the GDTR register. GDTR is a 48-bit + register and consists of two parts: + * the size(16-bit) of the global descriptor table; + * the address(32-bit) of the global descriptor table. + + As mentioned above, the GDT contains segment descriptors which describe + memory segments. Each descriptor is 64-bits in size. The general scheme + of a descriptor is: + 63 56 51 48 45 39 32 +------------------------------------------------------------ +| | |B| |A| | | | |0|E|W|A| | +| BASE 31:24 |G|/|L|V| LIMIT |P|DPL|S| TYPE | BASE 23:16 | +| | |D| |L| 19:16 | | | |1|C|R|A| | +------------------------------------------------------------ + + 31 16 15 0 +------------------------------------------------------------ +| | | +| BASE 15:0 | LIMIT 15:0 | +| | | +------------------------------------------------------------ + + Don't worry, I know it looks a little scary after Real mode, but it's + easy. For example LIMIT 15:0 means that bits 0-15 of the segment limit + are located at the beginning of the Descriptor. The rest of it is in + LIMIT 19:16, which is located at bits 48-51 of the Descriptor. So, the + size of Limit is 0-19 i.e 20-bits. Let's take a closer look at it: + 1. Limit[20-bits] is split between bits 0-15 and 48-51. It defines the + length_of_segment - 1. It depends on the G(Granularity) bit. + + if G (bit 55) is 0 and the segment limit is 0, the size of the + segment is 1 Byte + + if G is 1 and the segment limit is 0, the size of the segment + is 4096 Bytes + + if G is 0 and the segment limit is 0xfffff, the size of the + segment is 1 Megabyte + + if G is 1 and the segment limit is 0xfffff, the size of the + segment is 4 Gigabytes + So, what this means is + + if G is 0, Limit is interpreted in terms of 1 Byte and the + maximum size of the segment can be 1 Megabyte. + + if G is 1, Limit is interpreted in terms of 4096 Bytes = 4 + KBytes = 1 Page and the maximum size of the segment can be 4 + Gigabytes. Actually, when G is 1, the value of Limit is + shifted to the left by 12 bits. So, 20 bits + 12 bits = 32 + bits and 2^32 = 4 Gigabytes. + 2. Base[32-bits] is split between bits 16-31, 32-39 and 56-63. It + defines the physical address of the segment's starting location. + 3. Type/Attribute[5-bits] is represented by bits 40-44. It defines the + type of segment and how it can be accessed. + + The S flag at bit 44 specifies the descriptor type. If S is 0 + then this segment is a system segment, whereas if S is 1 then + this is a code or data segment (Stack segments are data + segments which must be read/write segments). + + To determine if the segment is a code or data segment, we can check its + Ex(bit 43) Attribute (marked as 0 in the above diagram). If it is 0, + then the segment is a Data segment, otherwise, it is a code segment. + + A segment can be of one of the following types: +-------------------------------------------------------------------------------- +------ +| Type Field | Descriptor Type | Description + | +|-----------------------------|-----------------|------------------------------- +-----| +| Decimal | | + | +| 0 E W A | | + | +| 0 0 0 0 0 | Data | Read-Only + | +| 1 0 0 0 1 | Data | Read-Only, accessed + | +| 2 0 0 1 0 | Data | Read/Write + | +| 3 0 0 1 1 | Data | Read/Write, accessed + | +| 4 0 1 0 0 | Data | Read-Only, expand-down + | +| 5 0 1 0 1 | Data | Read-Only, expand-down, access +ed | +| 6 0 1 1 0 | Data | Read/Write, expand-down + | +| 7 0 1 1 1 | Data | Read/Write, expand-down, acces +sed | +| C R A | | + | +| 8 1 0 0 0 | Code | Execute-Only + | +| 9 1 0 0 1 | Code | Execute-Only, accessed + | +| 10 1 0 1 0 | Code | Execute/Read + | +| 11 1 0 1 1 | Code | Execute/Read, accessed + | +| 12 1 1 0 0 | Code | Execute-Only, conforming + | +| 14 1 1 0 1 | Code | Execute-Only, conforming, acce +ssed | +| 13 1 1 1 0 | Code | Execute/Read, conforming + | +| 15 1 1 1 1 | Code | Execute/Read, conforming, acce +ssed | +-------------------------------------------------------------------------------- +------ + + As we can see the first bit(bit 43) is 0 for a data segment and 1 for a + code segment. The next three bits (40, 41, 42) are either EWA(Expansion + Writable Accessible) or CRA(Conforming Readable Accessible). + * if E(bit 42) is 0, expand up, otherwise, expand down. Read more + [101]here. + * if W(bit 41)(for Data Segments) is 1, write access is allowed, and + if it is 0, the segment is read-only. Note that read access is + always allowed on data segments. + * A(bit 40) controls whether the segment can be accessed by the + processor or not. + * C(bit 43) is the conforming bit(for code selectors). If C is 1, the + segment code can be executed from a lower level privilege (e.g. + user) level. If C is 0, it can only be executed from the same + privilege level. + * R(bit 41) controls read access to code segments; when it is 1, the + segment can be read from. Write access is never granted for code + segments. + + 1. DPL[2-bits] (Descriptor Privilege Level) comprises the bits 45-46. + It defines the privilege level of the segment. It can be 0-3 where + 0 is the most privileged level. + 2. The P flag(bit 47) indicates if the segment is present in memory or + not. If P is 0, the segment will be presented as invalid and the + processor will refuse to read from this segment. + 3. AVL flag(bit 52) - Available and reserved bits. It is ignored in + Linux. + 4. The L flag(bit 53) indicates whether a code segment contains native + 64-bit code. If it is set, then the code segment executes in 64-bit + mode. + 5. The D/B flag(bit 54) (Default/Big flag) represents the operand size + i.e 16/32 bits. If set, operand size is 32 bits. Otherwise, it is + 16 bits. + + Segment registers contain segment selectors as in real mode. However, + in protected mode, a segment selector is handled differently. Each + Segment Descriptor has an associated Segment Selector which is a 16-bit + structure: + 15 3 2 1 0 +----------------------------- +| Index | TI | RPL | +----------------------------- + + Where, + * Index stores the index number of the descriptor in the GDT. + * TI(Table Indicator) indicates where to search for the descriptor. + If it is 0 then the descriptor is searched for in the Global + Descriptor Table(GDT). Otherwise, it will be searched for in the + Local Descriptor Table(LDT). + * And RPL contains the Requester's Privilege Level. + + Every segment register has a visible and a hidden part. + * Visible - The Segment Selector is stored here. + * Hidden - The Segment Descriptor (which contains the base, limit, + attributes & flags) is stored here. + + The following steps are needed to get a physical address in protected + mode: + * The segment selector must be loaded in one of the segment + registers. + * The CPU tries to find a segment descriptor at the offset GDT + address + Index from the selector and then loads the descriptor + into the hidden part of the segment register. + * If paging is disabled, the linear address of the segment, or its + physical address, is given by the formula: Base address (found in + the descriptor obtained in the previous step) + Offset. + + Schematically it will look like this: + + linear address + + The algorithm for the transition from real mode into protected mode is: + * Disable interrupts + * Describe and load the GDT with the lgdt instruction + * Set the PE (Protection Enable) bit in CR0 (Control Register 0) + * Jump to protected mode code + + We will see the complete transition to protected mode in the linux + kernel in the next part, but before we can move to protected mode, we + need to do some more preparations. + + Let's look at [102]arch/x86/boot/main.c. We can see some routines there + which perform keyboard initialization, heap initialization, etc... + Let's take a look. + +Copying boot parameters into the "zeropage" + + We will start from the main routine in "main.c". The first function + which is called in main is [103]copy_boot_params(void). It copies the + kernel setup header into the corresponding field of the boot_params + structure which is defined in the + [104]arch/x86/include/uapi/asm/bootparam.h header file. + + The boot_params structure contains the struct setup_header hdr field. + This structure contains the same fields as defined in the [105]linux + boot protocol and is filled by the boot loader and also at kernel + compile/build time. copy_boot_params does two things: + 1. It copies hdr from [106]header.S to the setup_header field in + boot_params structure. + 2. It updates the pointer to the kernel command line if the kernel was + loaded with the old command line protocol. + + Note that it copies hdr with the memcpy function, defined in the + [107]copy.S source file. Let's have a look inside: +GLOBAL(memcpy) + pushw %si + pushw %di + movw %ax, %di + movw %dx, %si + pushw %cx + shrw $2, %cx + rep; movsl + popw %cx + andw $3, %cx + rep; movsb + popw %di + popw %si + retl +ENDPROC(memcpy) + + Yeah, we just moved to C code and now assembly again :) First of all, + we can see that memcpy and other routines which are defined here, start + and end with the two macros: GLOBAL and ENDPROC. GLOBAL is described in + [108]arch/x86/include/asm/linkage.h which defines the globl directive + and its label. ENDPROC is described in [109]include/linux/linkage.h and + marks the name symbol as a function name and ends with the size of the + name symbol. + + The implementation of memcpy is simple. At first, it pushes values from + the si and di registers to the stack to preserve their values because + they will change during the memcpy. As we can see in the + REALMODE_CFLAGS in arch/x86/Makefile, the kernel build system uses the + -mregparm=3 option of GCC, so functions get the first three parameters + from ax, dx and cx registers. Calling memcpy looks like this: +memcpy(&boot_params.hdr, &hdr, sizeof hdr); + + So, + * ax will contain the address of boot_params.hdr + * dx will contain the address of hdr + * cx will contain the size of hdr in bytes. + + memcpy puts the address of boot_params.hdr into di and saves cx on the + stack. After this it shifts the value right 2 times (or divides it by + 4) and copies four bytes from the address at si to the address at di. + After this, we restore the size of hdr again, align it by 4 bytes and + copy the rest of the bytes from the address at si to the address at di + byte by byte (if there is more). Now the values of si and di are + restored from the stack and the copying operation is finished. + +Console initialization + + After hdr is copied into boot_params.hdr, the next step is to + initialize the console by calling the console_init function, defined in + [110]arch/x86/boot/early_serial_console.c. + + It tries to find the earlyprintk option in the command line and if the + search was successful, it parses the port address and baud rate of the + serial port and initializes the serial port. The value of the + earlyprintk command line option can be one of these: + * serial,0x3f8,115200 + * serial,ttyS0,115200 + * ttyS0,115200 + + After serial port initialization we can see the first output: +if (cmdline_find_option_bool("debug")) + puts("early console in setup code\n"); + + The definition of puts is in [111]tty.c. As we can see it prints + character by character in a loop by calling the putchar function. Let's + look into the putchar implementation: +void __attribute__((section(".inittext"))) putchar(int ch) +{ + if (ch == '\n') + putchar('\r'); + + bios_putchar(ch); + + if (early_serial_base != 0) + serial_putchar(ch); +} + + __attribute__((section(".inittext"))) means that this code will be in + the .inittext section. We can find it in the linker file [112]setup.ld. + + First of all, putchar checks for the \n symbol and if it is found, + prints \r before. After that it prints the character on the VGA screen + by calling the BIOS with the 0x10 interrupt call: +static void __attribute__((section(".inittext"))) bios_putchar(int ch) +{ + struct biosregs ireg; + + initregs(&ireg); + ireg.bx = 0x0007; + ireg.cx = 0x0001; + ireg.ah = 0x0e; + ireg.al = ch; + intcall(0x10, &ireg, NULL); +} + + Here initregs takes the biosregs structure and first fills biosregs + with zeros using the memset function and then fills it with register + values. + memset(reg, 0, sizeof *reg); + reg->eflags |= X86_EFLAGS_CF; + reg->ds = ds(); + reg->es = ds(); + reg->fs = fs(); + reg->gs = gs(); + + Let's look at the implementation of [113]memset: +GLOBAL(memset) + pushw %di + movw %ax, %di + movzbl %dl, %eax + imull $0x01010101,%eax + pushw %cx + shrw $2, %cx + rep; stosl + popw %cx + andw $3, %cx + rep; stosb + popw %di + retl +ENDPROC(memset) + + As you can read above, it uses the same calling conventions as the + memcpy function, which means that the function gets its parameters from + the ax, dx and cx registers. + + The implementation of memset is similar to that of memcpy. It saves the + value of the di register on the stack and puts the value ofax, which + stores the address of the biosregs structure, into di . Next is the + movzbl instruction, which copies the value of dl to the lowermost byte + of the eax register. The remaining 3 high bytes of eax will be filled + with zeros. + + The next instruction multiplies eax with 0x01010101. It needs to + because memset will copy 4 bytes at the same time. For example, if we + need to fill a structure whose size is 4 bytes with the value 0x7 with + memset, eax will contain the 0x00000007. So if we multiply eax with + 0x01010101, we will get 0x07070707 and now we can copy these 4 bytes + into the structure. memset uses the rep; stosl instruction to copy eax + into es:di. + + The rest of the memset function does almost the same thing as memcpy. + + After the biosregs structure is filled with memset, bios_putchar calls + the [114]0x10 interrupt which prints a character. Afterwards it checks + if the serial port was initialized or not and writes a character there + with [115]serial_putchar and inb/outb instructions if it was set. + +Heap initialization + + After the stack and bss section have been prepared in [116]header.S + (see previous [117]part), the kernel needs to initialize the [118]heap + with the [119]init_heap function. + + First of all init_heap checks the [120]CAN_USE_HEAP flag from the + [121]loadflags structure in the kernel setup header and calculates the + end of the stack if this flag was set: + char *stack_end; + + if (boot_params.hdr.loadflags & CAN_USE_HEAP) { + asm("leal %P1(%%esp),%0" + : "=r" (stack_end) : "i" (-STACK_SIZE)); + + or in other words stack_end = esp - STACK_SIZE. + + Then there is the heap_end calculation: + heap_end = (char *)((size_t)boot_params.hdr.heap_end_ptr + 0x200); + + which means heap_end_ptr or _end + 512 (0x200h). The last check is + whether heap_end is greater than stack_end. If it is then stack_end is + assigned to heap_end to make them equal. + + Now the heap is initialized and we can use it using the GET_HEAP + method. We will see what it is used for, how to use it and how it is + implemented in the next posts. + +CPU validation + + The next step as we can see is cpu validation through the validate_cpu + function from [122]arch/x86/boot/cpu.c source code file. + + It calls the [123]check_cpu function and passes cpu level and required + cpu level to it and checks that the kernel launches on the right cpu + level. +check_cpu(&cpu_level, &req_level, &err_flags); +if (cpu_level < req_level) { + ... + return -1; +} + + The check_cpu function checks the CPU's flags, the presence of + [124]long mode in the case of x86_64(64-bit) CPU, checks the + processor's vendor and makes preparations for certain vendors like + turning off SSE+SSE2 for AMD if they are missing, etc. + + at the next step, we may see a call to the set_bios_mode function after + setup code found that a CPU is suitable. As we may see, this function + is implemented only for the x86_64 mode: +static void set_bios_mode(void) +{ +#ifdef CONFIG_X86_64 + struct biosregs ireg; + + initregs(&ireg); + ireg.ax = 0xec00; + ireg.bx = 2; + intcall(0x15, &ireg, NULL); +#endif +} + + The set_bios_mode function executes the 0x15 BIOS interrupt to tell the + BIOS that [125]long mode (if bx == 2) will be used. + +Memory detection + + The next step is memory detection through the detect_memory function. + detect_memory basically provides a map of available RAM to the CPU. It + uses different programming interfaces for memory detection like 0xe820, + 0xe801 and 0x88. We will see only the implementation of the 0xE820 + interface here. + + Let's look at the implementation of the detect_memory_e820 function + from the [126]arch/x86/boot/memory.c source file. First of all, the + detect_memory_e820 function initializes the biosregs structure as we + saw above and fills registers with special values for the 0xe820 call: + initregs(&ireg); + ireg.ax = 0xe820; + ireg.cx = sizeof buf; + ireg.edx = SMAP; + ireg.di = (size_t)&buf; + + * ax contains the number of the function (0xe820 in our case) + * cx contains the size of the buffer which will contain data about + the memory + * edx must contain the SMAP magic number + * es:di must contain the address of the buffer which will contain + memory data + * ebx has to be zero. + + Next is a loop where data about the memory will be collected. It starts + with a call to the 0x15 BIOS interrupt, which writes one line from the + address allocation table. For getting the next line we need to call + this interrupt again (which we do in the loop). Before the next call + ebx must contain the value returned previously: + intcall(0x15, &ireg, &oreg); + ireg.ebx = oreg.ebx; + + Ultimately, this function collects data from the address allocation + table and writes this data into the e820_entry array: + * start of memory segment + * size of memory segment + * type of memory segment (whether the particular segment is usable or + reserved) + + You can see the result of this in the dmesg output, something like: +[ 0.000000] e820: BIOS-provided physical RAM map: +[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable +[ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved +[ 0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved +[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000003ffdffff] usable +[ 0.000000] BIOS-e820: [mem 0x000000003ffe0000-0x000000003fffffff] reserved +[ 0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved + +Keyboard initialization + + The next step is the initialization of the keyboard with a call to the + [127]keyboard_init function. At first keyboard_init initializes + registers using the initregs function. It then calls the [128]0x16 + interrupt to query the status of the keyboard. + initregs(&ireg); + ireg.ah = 0x02; /* Get keyboard status */ + intcall(0x16, &ireg, &oreg); + boot_params.kbd_status = oreg.al; + + After this it calls [129]0x16 again to set the repeat rate and delay. + ireg.ax = 0x0305; /* Set keyboard repeat rate */ + intcall(0x16, &ireg, NULL); + +Querying + + The next couple of steps are queries for different parameters. We will + not dive into details about these queries but we will get back to them + in later parts. Let's take a short look at these functions: + + The first step is getting [130]Intel SpeedStep information by calling + the query_ist function. It checks the CPU level and if it is correct, + calls 0x15 to get the info and saves the result to boot_params. + + Next, the [131]query_apm_bios function gets [132]Advanced Power + Management information from the BIOS. query_apm_bios calls the 0x15 + BIOS interruption too, but with ah = 0x53 to check APM installation. + After 0x15 finishes executing, the query_apm_bios functions check the + PM signature (it must be 0x504d), the carry flag (it must be 0 if APM + supported) and the value of the cx register (if it's 0x02, the + protected mode interface is supported). + + Next, it calls 0x15 again, but with ax = 0x5304 to disconnect the APM + interface and connect the 32-bit protected mode interface. In the end, + it fills boot_params.apm_bios_info with values obtained from the BIOS. + + Note that query_apm_bios will be executed only if the CONFIG_APM or + CONFIG_APM_MODULE compile time flag was set in the configuration file: +#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) + query_apm_bios(); +#endif + + The last is the [133]query_edd function, which queries Enhanced Disk + Drive information from the BIOS. Let's look at how query_edd is + implemented. + + First of all, it reads the [134]edd option from the kernel's command + line and if it was set to off then query_edd just returns. + + If EDD is enabled, query_edd goes over BIOS-supported hard disks and + queries EDD information in the following loop: +for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) { + if (!get_edd_info(devno, &ei) && boot_params.eddbuf_entries < EDDMAXNR) { + memcpy(edp, &ei, sizeof ei); + edp++; + boot_params.eddbuf_entries++; + } + ... + ... + ... + } + + where 0x80 is the first hard drive and the value of the EDD_MBR_SIG_MAX + macro is 16. It collects data into an array of [135]edd_info + structures. get_edd_info checks that EDD is present by invoking the + 0x13 interrupt with ah as 0x41 and if EDD is present, get_edd_info + again calls the 0x13 interrupt, but with ah as 0x48 and si containing + the address of the buffer where EDD information will be stored. + +Conclusion + + This is the end of the second part about the insides of the Linux + kernel. In the next part, we will see video mode setting and the rest + of the preparations before the transition to protected mode and + directly transitioning into it. + + If you have any questions or suggestions write me a comment or ping me + at [136]twitter. + + Please note that English is not my first language, And I am really + sorry for any inconvenience. If you find any mistakes please send me a + PR to [137]linux-insides. + +Links + + * [138]Protected mode + * [139]Protected mode + * [140]Long mode + * [141]Nice explanation of CPU Modes with code + * [142]How to Use Expand Down Segments on Intel 386 and Later CPUs + * [143]earlyprintk documentation + * [144]Kernel Parameters + * [145]Serial console + * [146]Intel SpeedStep + * [147]APM + * [148]EDD specification + * [149]TLDP documentation for Linux Boot Process (old) + * [150]Previous Part + +results matching "" + +No results matching "" + +References + + Visible links: + 1. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-3.html + 2. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 3. https://archive.org/includes/donate.php?as_page=1&platform=wb&referer=https%3A//web.archive.org/web/20230308144724/https%3A//0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 4. https://web.archive.org/web/ + 5. https://web.archive.org/web/20230308144724*/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 6. https://web.archive.org/web/20221206122118/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 7. https://web.archive.org/web/20221206122118/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 8. https://web.archive.org/web/20230322150041/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 9. https://web.archive.org/web/20220123200511/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 10. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html#expand + 11. https://archive.org/details/mega-002 + 12. https://web.archive.org/web/20230308144724/https://legacy.gitbook.com/book/0xax/linux-insides + 13. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/ + 14. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/ + 15. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 16. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 17. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-3.html + 18. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-4.html + 19. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-5.html + 20. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-6.html + 21. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/ + 22. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-1.html + 23. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-2.html + 24. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-3.html + 25. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-4.html + 26. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-5.html + 27. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-6.html + 28. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-7.html + 29. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-8.html + 30. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-9.html + 31. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-10.html + 32. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/ + 33. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-1.html + 34. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-2.html + 35. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-3.html + 36. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-4.html + 37. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-5.html + 38. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-6.html + 39. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-7.html + 40. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-8.html + 41. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-9.html + 42. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-10.html + 43. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SysCall/ + 44. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-1.html + 45. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-2.html + 46. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-3.html + 47. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-4.html + 48. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-5.html + 49. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-6.html + 50. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Timers/ + 51. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-1.html + 52. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-2.html + 53. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-3.html + 54. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-4.html + 55. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-5.html + 56. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-6.html + 57. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-7.html + 58. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/ + 59. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-1.html + 60. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-2.html + 61. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-3.html + 62. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-4.html + 63. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-5.html + 64. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/SyncPrim/linux-sync-6.html + 65. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/MM/ + 66. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/MM/linux-mm-1.html + 67. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/MM/linux-mm-2.html + 68. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/MM/linux-mm-3.html + 69. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Cgroups/ + 70. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Cgroups/linux-cgroups-1.html + 71. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Concepts/ + 72. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-1.html + 73. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-2.html + 74. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-3.html + 75. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Concepts/linux-cpu-4.html + 76. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/DataStructures/ + 77. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/DataStructures/linux-datastructures-1.html + 78. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/DataStructures/linux-datastructures-2.html + 79. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/DataStructures/linux-datastructures-3.html + 80. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Theory/ + 81. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Theory/linux-theory-1.html + 82. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Theory/linux-theory-2.html + 83. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Theory/linux-theory-3.html + 84. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Misc/ + 85. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Misc/linux-misc-1.html + 86. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Misc/linux-misc-2.html + 87. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Misc/linux-misc-3.html + 88. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Misc/linux-misc-4.html + 89. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/KernelStructures/ + 90. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/KernelStructures/linux-kernelstructure-1.html + 91. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/LINKS.html + 92. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/contributors.html + 93. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/ + 94. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 95. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/main.c + 96. https://web.archive.org/web/20230308144724/http://en.wikipedia.org/wiki/Long_mode + 97. https://web.archive.org/web/20230308144724/https://en.wikipedia.org/wiki/Protected_mode + 98. https://web.archive.org/web/20230308144724/http://en.wikipedia.org/wiki/Intel_80286 + 99. https://web.archive.org/web/20230308144724/http://wiki.osdev.org/Real_Mode + 100. https://web.archive.org/web/20230308144724/http://en.wikipedia.org/wiki/Paging + 101. https://web.archive.org/web/20230308144724/http://www.sudleyplace.com/dpmione/expanddown.html + 102. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/main.c + 103. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/main.c + 104. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/include/uapi/asm/bootparam.h + 105. https://web.archive.org/web/20230308144724/https://www.kernel.org/doc/Documentation/x86/boot.txt + 106. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S#L280 + 107. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/copy.S + 108. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/include/asm/linkage.h + 109. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/include/linux/linkage.h + 110. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/early_serial_console.c + 111. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/tty.c + 112. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/setup.ld + 113. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/copy.S#L36 + 114. https://web.archive.org/web/20230308144724/http://www.ctyme.com/intr/rb-0106.htm + 115. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/tty.c + 116. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S + 117. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 118. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/main.c + 119. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/main.c + 120. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/include/uapi/asm/bootparam.h#L24 + 121. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S#L320 + 122. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/cpu.c + 123. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/cpucheck.c + 124. https://web.archive.org/web/20230308144724/http://en.wikipedia.org/wiki/Long_mode + 125. https://web.archive.org/web/20230308144724/https://en.wikipedia.org/wiki/Long_mode + 126. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/memory.c + 127. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/main.c + 128. https://web.archive.org/web/20230308144724/http://www.ctyme.com/intr/rb-1756.htm + 129. https://web.archive.org/web/20230308144724/http://www.ctyme.com/intr/rb-1757.htm + 130. https://web.archive.org/web/20230308144724/http://en.wikipedia.org/wiki/SpeedStep + 131. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/apm.c#L21 + 132. https://web.archive.org/web/20230308144724/http://en.wikipedia.org/wiki/Advanced_Power_Management + 133. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/edd.c#L122 + 134. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/Documentation/admin-guide/kernel-parameters.rst + 135. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/include/uapi/linux/edd.h + 136. https://web.archive.org/web/20230308144724/https://twitter.com/0xAX + 137. https://web.archive.org/web/20230308144724/https://github.com/0xAX/linux-internals + 138. https://web.archive.org/web/20230308144724/http://en.wikipedia.org/wiki/Protected_mode + 139. https://web.archive.org/web/20230308144724/http://wiki.osdev.org/Protected_Mode + 140. https://web.archive.org/web/20230308144724/http://en.wikipedia.org/wiki/Long_mode + 141. https://web.archive.org/web/20230308144724/http://www.codeproject.com/Articles/45788/The-Real-Protected-Long-mode-assembly-tutorial-for + 142. https://web.archive.org/web/20230308144724/http://www.sudleyplace.com/dpmione/expanddown.html + 143. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/Documentation/x86/earlyprintk.txt + 144. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/Documentation/admin-guide/kernel-parameters.rst + 145. https://web.archive.org/web/20230308144724/https://github.com/torvalds/linux/blob/v4.16/Documentation/admin-guide/serial-console.rst + 146. https://web.archive.org/web/20230308144724/http://en.wikipedia.org/wiki/SpeedStep + 147. https://web.archive.org/web/20230308144724/https://en.wikipedia.org/wiki/Advanced_Power_Management + 148. https://web.archive.org/web/20230308144724/http://www.t13.org/documents/UploadedDocuments/docs2004/d1572r3-EDD3.pdf + 149. https://web.archive.org/web/20230308144724/http://www.tldp.org/HOWTO/Linux-i386-Boot-Code-HOWTO/setup.html + 150. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + + Hidden links: + 152. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 153. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 154. https://archive.org/account/login.php + 155. http://faq.web.archive.org/ + 156. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html#close + 157. https://web.archive.org/web/20230308144724/http://web.archive.org/screenshot/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 158. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 159. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 160. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-2.html + 161. https://web.archive.org/web/20230308144724/https://www.gitbook.com/?utm_source=public_site_legacy&utm_medium=referral&utm_campaign=trademark&utm_term=0xax&utm_content=powered_by + 162. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html + 163. https://web.archive.org/web/20230308144724/https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-3.html diff --git a/todo/doc/dc0d32.blogspot.com_2010_06_real-mode-in-c-with-gcc-writing.txt b/todo/doc/dc0d32.blogspot.com_2010_06_real-mode-in-c-with-gcc-writing.txt new file mode 100644 index 0000000..6834acd --- /dev/null +++ b/todo/doc/dc0d32.blogspot.com_2010_06_real-mode-in-c-with-gcc-writing.txt @@ -0,0 +1,892 @@ + #[1]dc0d32 - Atom [2]dc0d32 - RSS [3]dc0d32 - Atom + +[4]dc0d32 + +Tuesday, June 15, 2010 + +Real mode in C with gcc : writing a bootloader + + Usually the x86 boot loader is written in assembler. We will be + exploring the possibility of writing one in C language (as much as + possible) compiled with gcc, and runs in real mode. Note that you can + also use the 16 bit bcc or TurboC compiler, but we will be focusing on + gcc in this post. Most open source kernels are compiled with gcc, and + it makes sense to write C bootloader with gcc instead of bcc as you get + a much cleaner toolchain :) + As of today (20100614), gcc 4.4.4 officially only emits code for + protected/long mode and does not support the real mode natively (this + may [5]change in future). + Also note that we will not discuss the very fundamentals of booting. + This article is fairly advanced and assumes that you know what it takes + to write a simple boot-loader in assembler. It is also expected that + you know how to write gcc inline assembly. Not everything can be done + in C! + +getting the tool-chain working + +.code16gcc + + As we will be running in 16 bit real mode, this tells gas that the + assembler was generated by gcc and is intended to be run in real mode. + With this directive, gas automatically adds addr32 prefix wherever + required. For each C file which contains code to be run in real mode, + this directive should be present at the top of effectively generated + assembler code. This can be ensured by defining in a header and + including it before any other. +#ifndef _CODE16GCC_H_ +#define _CODE16GCC_H_ +__asm__(".code16gcc\n"); +#endif + + This is great for bootloaders as well as parts of kernel that must run + in real mode but are desired written in C instead of asm. In my opinion + C code is a lot easier to debug and maintain than asm code, at expense + of code size and performance at times. + +Special linking + + As bootloader is supposed to run at physical 0x7C00, we need to tell + that to linker. The mbr/vbr should end with the proper boot signature + 0xaa55. + All this can be taken care of by a simple linker script. +ENTRY(main); +SECTIONS +{ + . = 0x7C00; + .text : AT(0x7C00) + { + _text = .; + *(.text); + _text_end = .; + } + .data : + { + _data = .; + *(.bss); + *(.bss*); + *(.data); + *(.rodata*); + *(COMMON) + _data_end = .; + } + .sig : AT(0x7DFE) + { + SHORT(0xaa55); + } + /DISCARD/ : + { + *(.note*); + *(.iplt*); + *(.igot*); + *(.rel*); + *(.comment); +/* add any unwanted sections spewed out by your version of gcc and flags here */ + } +} + + gcc emits elf binaries with sections, whereas a bootloader is a + monolithic plain binary with no sections. Conversion from elf to binary + can be done as follows: +$ objcopy -O binary vbr.elf vbr.bin + +The code + + With the toolchain set up, we can start writing our hello world + bootloader! + vbr.c (the only source file) looks something like this: +/* + * A simple bootloader skeleton for x86, using gcc. + * + * Prashant Borole (boroleprashant at Google mail) + * */ + +/* XXX these must be at top */ +#include "code16gcc.h" +__asm__ ("jmpl $0, $main\n"); + + +#define __NOINLINE __attribute__((noinline)) +#define __REGPARM __attribute__ ((regparm(3))) +#define __NORETURN __attribute__((noreturn)) + +/* BIOS interrupts must be done with inline assembly */ +void __NOINLINE __REGPARM print(const char *s){ + while(*s){ + __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)) +; + s++; + } +} +/* and for everything else you can use C! Be it traversing the filesystem, or ve +rifying the kernel image etc.*/ + +void __NORETURN main(){ + print("woo hoo!\r\n:)"); + while(1); +} + + + compile it as +$ gcc -c -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -o vbr.o vbr.c +$ ld -static -Tlinker.ld -nostdlib --nmagic -o vbr.elf vbr.o +$ objcopy -O binary vbr.elf vbr.bin + + and that should have created vbr.elf file (which you can use as a + symbols file with gdb for source level debugging the vbr with gdbstub + and qemu/bochs) as well as 512 byte vbr.bin. To test it, first create a + dummy 1.44M floppy image, and overwrite it's mbr by vbr.bin with dd. +$ dd if=/dev/zero of=floppy.img bs=1024 count=1440 +$ dd if=vbr.bin of=floppy.img bs=1 count=512 conv=notrunc + + and now we are ready to test it out :D +$ qemu -fda floppy.img -boot a + + and you should see the message! + Once you get to this stage, you are pretty much set with respect to the + tooling itself. Now you can go ahead and write code to read the + filesystem, search for next stage or kernel and pass control to it. + Here is a simple example of a floppy boot record with no filesystem, + and the next stage or kernel written to the floppy immediately after + the boot record. The next image LMA and entry are fixed in a bunch of + macros. It simply reads the image starting one sector after boot record + and passes control to it. There are many obvious holes, which I left + open for sake of brevity. +/* + * A simple bootloader skeleton for x86, using gcc. + * + * Prashant Borole (boroleprashant at Google mail) + * */ + +/* XXX these must be at top */ +#include "code16gcc.h" +__asm__ ("jmpl $0, $main\n"); + + +#define __NOINLINE __attribute__((noinline)) +#define __REGPARM __attribute__ ((regparm(3))) +#define __PACKED __attribute__((packed)) +#define __NORETURN __attribute__((noreturn)) + +#define IMAGE_SIZE 8192 +#define BLOCK_SIZE 512 +#define IMAGE_LMA 0x8000 +#define IMAGE_ENTRY 0x800c + +/* BIOS interrupts must be done with inline assembly */ +void __NOINLINE __REGPARM print(const char *s){ + while(*s){ + __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)) +; + s++; + } +} + +#if 0 +/* use this for the HD/USB/Optical boot sector */ +typedef struct __PACKED TAGaddress_packet_t{ + char size; + char :8; + unsigned short blocks; + unsigned short buffer_offset; + unsigned short buffer_segment; + unsigned long long lba; + unsigned long long flat_buffer; +}address_packet_t ; + +int __REGPARM lba_read(const void *buffer, unsigned int lba, unsigned short +blocks, unsigned char bios_drive){ + int i; + unsigned short failed = 0; + address_packet_t packet = {.size = sizeof(address_packet_t), .blocks += blocks, .buffer_offset = 0xFFFF, .buffer_segment = 0xFFFF, .lba = lba, .flat_b +uffer = (unsigned long)buffer}; + for(i = 0; i < 3; i++){ + packet.blocks = blocks; + __asm__ __volatile__ ( + "movw $0, %0\n" + "int $0x13\n" + "setcb %0\n" + :"=m"(failed) : "a"(0x4200), "d"(bios_drive), "S +"(&packet) : "cc" ); + /* do something with the error_code */ + if(!failed) + break; + } + return failed; +} +#else +/* use for floppy, or as a fallback */ +typedef struct { + unsigned char spt; + unsigned char numh; +}drive_params_t; + +int __REGPARM __NOINLINE get_drive_params(drive_params_t *p, unsigned char +bios_drive){ + unsigned short failed = 0; + unsigned short tmp1, tmp2; + __asm__ __volatile__ + ( + "movw $0, %0\n" + "int $0x13\n" + "setcb %0\n" + : "=m"(failed), "=c"(tmp1), "=d"(tmp2) + : "a"(0x0800), "d"(bios_drive), "D"(0) + : "cc", "bx" + ); + if(failed) + return failed; + p->spt = tmp1 & 0x3F; + p->numh = tmp2 >> 8; + return failed; +} + +int __REGPARM __NOINLINE lba_read(const void *buffer, unsigned int lba, uns +igned char blocks, unsigned char bios_drive, drive_params_t *p){ + unsigned char c, h, s; + c = lba / (p->numh * p->spt); + unsigned short t = lba % (p->numh * p->spt); + h = t / p->spt; + s = (t % p->spt) + 1; + unsigned char failed = 0; + unsigned char num_blocks_transferred = 0; + __asm__ __volatile__ + ( + "movw $0, %0\n" + "int $0x13\n" + "setcb %0" + : "=m"(failed), "=a"(num_blocks_transferred) + : "a"(0x0200 | blocks), "c"((s << 8) | s), "d"((h << 8) | bios_driv +e), "b"(buffer) + ); + return failed || (num_blocks_transferred != blocks); +} +#endif + +/* and for everything else you can use C! Be it traversing the filesystem, or ve +rifying the kernel image etc.*/ + +void __NORETURN main(){ + unsigned char bios_drive = 0; + __asm__ __volatile__("movb %%dl, %0" : "=r"(bios_drive)); /* the B +IOS drive number of the device we booted from is passed in dl register */ + + drive_params_t p = {}; + get_drive_params(&p, bios_drive); + + void *buff = (void*)IMAGE_LMA; + unsigned short num_blocks = ((IMAGE_SIZE / BLOCK_SIZE) + (IMAGE_SIZE % +BLOCK_SIZE == 0 ? 0 : 1)); + if(lba_read(buff, 1, num_blocks, bios_drive, &p) != 0){ + print("read error :(\r\n"); + while(1); + } + print("Running next image...\r\n"); + void* e = (void*)IMAGE_ENTRY; + __asm__ __volatile__("" : : "d"(bios_drive)); + goto *e; +} + + + removing __NOINLINE may result in even smaller code in this case. I had + it in place so that I could figure out what was happening. + +Concluding remarks + + C in no way matches the code size and performance of hand tuned + size/speed optimized assembler. Also, because of an extra byte (0x66, + 0x67) wasted (in addr32) with almost every instruction, it is highly + unlikely that you can cram up the same amount of functionality as + assembler. + Global and static variables, initialized as well as uninitialized, can + quickly fill those precious 446 bytes. Changing them to local and + passing around instead may increase or decrease size; there is no thumb + rule and it has to be worked out on per case basis. Same goes for + function in-lining. + You also need to be extremely careful with various gcc optimization + flags. For example, if you have a loop in your code whose number of + iterations are small and deducible at compile time, and the loop body + is relatively small (even 20 bytes), with default -Os, gcc will unroll + that loop. If the loop is not unrolled (-fno-tree-loop-optimize), you + might be able to shave off big chunk of bytes there. Same holds true + for frame setups on i386 - you may want to get rid of them whenever not + required using -fomit-frame-pointer. Moral of the story : you need to + be extra careful with gcc flags as well as version update. This is not + much of an issue for other real mode modules of the kernel where size + is not of this prime importance. + Also, you must be very cautious with assembler warnings when compiling + with .code16gcc. Truncation is common. It is a very good idea to use + --save-temp and analyze the assembler code generated from your C and + inline assembly. Always take care not to mess with the C calling + convention in inline assembly and meticulously check and update the + clobber list for inline assembly doing BIOS or APM calls (but you + already knew it, right?). + It is likely that you want to switch to protected/long mode as early as + possible, though. Even then, I still think that maintainability wins + over asm's size/speed in case of a bootloader as well as the real mode + portions of the kernel. + It would be interesting if someone could try this with + c++/java/fortran. Please let me know if you do! + at [6]June 15, 2010 + [7]Email This[8]BlogThis![9]Share to Twitter[10]Share to + Facebook[11]Share to Pinterest + Labels: [12]assembler, [13]bootloader, [14]c, [15]gas, [16]gcc, + [17]kernel, [18]osdev + +25 comments: + + 1. [19]Girija[20]Tuesday, June 15, 2010 at 6:12:00 PM GMT+5:30 + Dokyaawarun 10 foot.. kiwwa jaastach. + :-| + Reply[21]Delete + Replies + Reply + 2. [22]descent[23]Tuesday, December 21, 2010 at 1:10:00 PM GMT+5:30 + Hi, + Thank you for your sharing. + in void __NOINLINE __REGPARM print(const char *s) + I change the print function to access pointer, + like this: + videoram[0]='H'; + but I got the warning message: + /tmp/cc5qsy9l.s:33: Warning: 00000000000b8000 shortened to + 0000000000008000 + Do I miss something? + Reply[24]Delete + Replies + Reply + 3. [25]descent[26]Tuesday, December 21, 2010 at 2:05:00 PM GMT+5:30 + Hi, + I use gcc-3.4 to compile again. + I see no warning message, but in qemu, + I still cannot see char H. + videoram is static variable. + static unsigned char *videoram = (unsigned char *) 0xb8000; + Reply[27]Delete + Replies + Reply + 4. [28]descent[29]Tuesday, December 21, 2010 at 3:16:00 PM GMT+5:30 + Hi, + I got something. In 16bit mode, the pointer is 16bit length. So + 0xb8000 shortened to 0x8000. + I write a c file and a function, + void put_char() + { + unsigned char *videoram = (unsigned char *) 0xb8000; + videoram[0]='H'; + videoram[2]='H'; + videoram[40]='H'; + } + no include code16gcc.h, I think the pointer is 32bits length, but I + still can not see the H character. + Reply[30]Delete + Replies + Reply + 5. [31]Prashant[32]Tuesday, December 21, 2010 at 7:16:00 PM GMT+5:30 + @descent: check the '--save-temps' preserved assembler version of + the C function. + This article assumes that the reader has low level programming + experience with x86. + To access the vidmem with b8000h, you have 2 options: + 1. write inline assembly to set es to b800h, and di to the address + in the real mode segment. Then write byte/word to es:di. + 2. Enter unreal mode. Then you can use the full 4G memory, + one-to-one mapped. + I personally would not recommend any of these methods for printing + - BIOS int 10h is pretty good. Remember - do not try and do + anything fancy in the (m/v)br; do it in the next stage instead as + you have pretty much unconstrained image size in later stages. + Reply[33]Delete + Replies + Reply + 6. [34]descent[35]Wednesday, December 22, 2010 at 9:41:00 AM GMT+5:30 + Hi Prashant, + Thank you for your explanation. + Because in protected mode, I can use C, + and direct access 0xb8000, so I am confused. + real/protect mode, gcc/gas 16/32 bit also confuse me. + They are very complicate. + Reply[36]Delete + Replies + Reply + 7. [37]Sebastian[38]Saturday, March 12, 2011 at 6:26:00 PM GMT+5:30 + you are a genius! + Reply[39]Delete + Replies + Reply + 8. [40]Unknown[41]Sunday, April 17, 2011 at 5:48:00 AM GMT+5:30 + I've got that infamous runtime error... + bootloader.exe has encountered a problem and needs to close. We are + sorry for the inconvenience. + Reply[42]Delete + Replies + Reply + 9. [43]Unknown[44]Saturday, May 21, 2011 at 2:39:00 AM GMT+5:30 + Managed to do it in C++. + Code is the same. + Linker file needs to discard eh_frame. + When building on x86-64 add -m32 to g++ and -melf_i386 on ld + command line. + Trying to rewrite it in a more c++-ish style. + My e-mail is boskovits@cogito-top.hu . + Reply[45]Delete + Replies + Reply + 10. [46]Prashant[47]Saturday, May 21, 2011 at 3:02:00 AM GMT+5:30 + @abraker95: are you trying to run the MZ/PE image in windows? that + is like sinning and then spitting on the devil when in hell. + @boskov1985: cool man! let us know how it goes :D + Reply[48]Delete + Replies + Reply + 11. Anonymous[49]Friday, November 25, 2011 at 2:50:00 AM GMT+5:30 + It's easier to to this without objcopy. Modern ld versions support + --oformat=binary , so just one line does the direct compilation + job. + gcc -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -static + -nostdlib -Wl,-Tlinker.ld -Wl,--nmagic -Wl,--oformat=binary -o + loader.bin loader.c + Reply[50]Delete + Replies + Reply + 12. [51]Prashant[52]Friday, November 25, 2011 at 8:01:00 AM GMT+5:30 + I can't verify right now whether it works, but thanks for letting + us know, rpfh! + Reply[53]Delete + Replies + Reply + 13. [54]descent[55]Sunday, December 4, 2011 at 9:42:00 PM GMT+5:30 + Hi, + The c code uses function call, why need not set stack (ss:esp)? + Reply[56]Delete + Replies + Reply + 14. [57]Prashant[58]Tuesday, December 6, 2011 at 10:18:00 AM GMT+5:30 + good point @decent. I guess you will need to set up the stack first + in main, probably in assembler. + Reply[59]Delete + Replies + Reply + 15. [60]descent[61]Saturday, December 24, 2011 at 8:02:00 PM GMT+5:30 + I change %ss:%esp to 0x07a0:0000, + Is any side effect? + void __NORETURN main(){ + __asm__ ("mov %cs, %ax\n"); + __asm__ ("mov %ax, %ds\n"); + __asm__ ("mov $0x07a0, %ax\n"); + __asm__ ("mov %ax, %ss\n"); + __asm__ ("mov $0, %esp\n"); + print("woo hoo!\r\n:)"); + while(1); + } + Reply[62]Delete + Replies + Reply + 16. [63]descent[64]Monday, July 30, 2012 at 8:16:00 AM GMT+5:30 + Hi, + I test c bootloader in real machine, in my eeepc 904, need add some + code to setup stack. + http://descent-incoming.blogspot.tw/2012/05/x86-bootloader-hello-wo + rld.html + The article is written by Chinese, but the code, picture can give + some reference. + cppb.cpp is cpp version (compile by g++), it can work, I test it in + real machine(eeepc 904). + Reply[65]Delete + Replies + Reply + 17. [66]axiomfinity[67]Saturday, April 20, 2013 at 10:46:00 AM GMT+5:30 + linker fails whats up with it..? + Reply[68]Delete + Replies + Reply + 18. [69]Prashant[70]Sunday, April 21, 2013 at 9:34:00 AM GMT+5:30 + Fails how? Can you please elaborate? + Reply[71]Delete + Replies + Reply + 19. [72]Unknown[73]Wednesday, November 13, 2013 at 12:51:00 PM GMT+5:30 + Thank you for detaile explanation + Linker failed nt sure why..ld: error: load segment overlap [0x7c00 + -> 0x7e50] and [0x7dfe -> 0x7e00] + Reply[74]Delete + Replies + Reply + 20. [75]osdev[76]Saturday, May 31, 2014 at 1:35:00 AM GMT+5:30 + someone here? I need to test, but... + "c"((s << 8) | s) <-- duplicate s in CH and CL? + c = lba / (p->numh * p->spt); <-- 'c' is never used... + maybe -> "c"((c << 8) | s) + Reply[77]Delete + Replies + Reply + 21. [78]Unknown[79]Thursday, February 5, 2015 at 8:39:00 PM GMT+5:30 + Thank you for your nice post! I'm trying to run it on my x86-64 + linux box, but gcc reports errors like "bad register name rax", I'm + a little confused by the various compiler options here, could you + please give me suggestions on how to compile the C source file on + x86-64 machines? Thanks + Reply[80]Delete + Replies + 1. [81]Jose Fernando Lopez Fernandez[82]Friday, January 20, 2017 + at 2:56:00 PM GMT+5:30 + rax is a 64 bit register. A bootloader is running in 16 bits, + so you cannot use rax (64 bit) or eax (32 bit). You have to + use ax. + Also, you said your computer is an x86-64. Which one is it? + x86 (32 bit) or 64 (64 bit)? If you have an x86, it will have + no idea what rax is, since it has no knowledge of 64 bit + registers. + I'm just speculating as to your problem here, though. If + anything here is incorrect/misguided by all means let me know, + I'm only a beginner too + [83]Delete + Replies + Reply + 2. [84]Jose Fernando Lopez Fernandez[85]Friday, January 20, 2017 + at 2:57:00 PM GMT+5:30 + @Jing Peng + rax is a 64 bit register. A bootloader is running in 16 bits, + so you cannot use rax (64 bit) or eax (32 bit). You have to + use ax. + Also, you said your computer is an x86-64. Which one is it? + x86 (32 bit) or 64 (64 bit)? If you have an x86, it will have + no idea what rax is, since it has no knowledge of 64 bit + registers. + I'm just speculating as to your problem here, though. If + anything here is incorrect/misguided by all means let me know, + I'm only a beginner too + [86]Delete + Replies + Reply + Reply + 22. [87]Unknown[88]Thursday, February 5, 2015 at 8:40:00 PM GMT+5:30 + Thank you for your nice post! I'm trying to run it on my x86-64 + linux box, but gcc reports errors like "bad register name rax", I'm + a little confused by the various compiler options here, could you + please give me suggestions on how to compile the C source file on + x86-64 machines? Thanks + Reply[89]Delete + Replies + Reply + 23. [90]Unknown[91]Sunday, February 7, 2016 at 8:43:00 PM GMT+5:30 + hello i ma atif + Reply[92]Delete + Replies + Reply + + Add comment + Load more... + + [93]Newer Post [94]Older Post [95]Home + Subscribe to: [96]Post Comments (Atom) + * [97]Real mode in C with gcc : writing a bootloader + Usually the x86 boot loader is written in assembler. We will be + exploring the possibility of writing one in C language (as much as + possible)... + * [98]Writing kernel in Windows with Visual Studio C/C++ + Most hobby osdev projects prefer *nix+gcc combination these days, + primarily because there are a bunch of nice tutorials and examples + availab... + * [99]Debugging kernel with qemu and gdb + Assuming that you have your (or Linux/*BSD/Solaris/Windows or any + other) kernel on a bootable device, you can debug the kernel and + also the ... + +Blog Archive + + * [100]|> [101]2012 (1) + + [102]|> [103]Feb 2012 (1) + + * [104]v [105]2010 (7) + + [106]v [107]Jun 2010 (2) + o [108]Cold boot attack + o [109]Real mode in C with gcc : writing a bootloader + + [110]|> [111]May 2010 (2) + + [112]|> [113]Apr 2010 (1) + + [114]|> [115]Mar 2010 (1) + + [116]|> [117]Feb 2010 (1) + + * [118]|> [119]2009 (12) + + [120]|> [121]Dec 2009 (1) + + [122]|> [123]Nov 2009 (2) + + [124]|> [125]Sep 2009 (1) + + [126]|> [127]Aug 2009 (1) + + [128]|> [129]Jul 2009 (2) + + [130]|> [131]Feb 2009 (2) + + [132]|> [133]Jan 2009 (3) + + * [134]|> [135]2008 (9) + + [136]|> [137]Nov 2008 (2) + + [138]|> [139]Oct 2008 (3) + + [140]|> [141]Aug 2008 (1) + + [142]|> [143]Jun 2008 (3) + +Labels + + [144]linux [145]kernel [146]8800 [147]FreeBSD [148]gdb [149]nvidia + [150]osdev [151]windows 7 [152]bochs [153]boot [154]bootloader + [155]debug [156]dual boot [157]gas [158]gcc [159]overclock [160]pidgin + [161]windows [162]windows server 2008 [163]2k8 [164]3DMark [165]3DMark + vantage [166]820 [167]DRAM [168]Directx 10 [169]Dirext 11 [170]Java + [171]OpenJDK [172]OpenOffice [173]Pentium D [174]RAID [175]Sun + [176]UUID [177]Unicode [178]VirtualBox [179]X [180]Xorg [181]ageis + [182]assembler [183]authentication [184]bash [185]c [186]coolbits + [187]dx10 [188]fedora [189]fortune [190]gdm [191]ghostscript [192]gnome + [193]google [194]gs [195]gtalk [196]heat sink [197]invisible + [198]jabber [199]kde [200]latex [201]lvm [202]lyx [203]mount + [204]networked audio [205]networked sound [206]nvclock [207]oolatex + [208]ooolatex [209]perl [210]phonon [211]physics [212]physx [213]picasa + [214]plugin [215]proxy [216]pulseaudio [217]qemu [218]rsync [219]rtp + [220]scp [221]scp stdin [222]security [223]server [224]shell [225]squid + [226]ssh [227]sync [228]tar [229]udev [230]unix [231]xdm [232]xfce + [233]xmpp [234]xorg.conf [235]zsh + [236]visit counter for blogspot + + Theme images by [237]5ugarless. Powered by [238]Blogger. + +References + + Visible links: + 1. http://dc0d32.blogspot.com/feeds/posts/default + 2. http://dc0d32.blogspot.com/feeds/posts/default?alt=rss + 3. http://dc0d32.blogspot.com/feeds/6370208028763486595/comments/default + 4. http://dc0d32.blogspot.com/ + 5. http://gcc.gnu.org/ml/gcc/1999-07n/msg00483.html + 6. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html + 7. https://www.blogger.com/share-post.g?blogID=35813921&postID=6370208028763486595&target=email + 8. https://www.blogger.com/share-post.g?blogID=35813921&postID=6370208028763486595&target=blog + 9. https://www.blogger.com/share-post.g?blogID=35813921&postID=6370208028763486595&target=twitter + 10. https://www.blogger.com/share-post.g?blogID=35813921&postID=6370208028763486595&target=facebook + 11. https://www.blogger.com/share-post.g?blogID=35813921&postID=6370208028763486595&target=pinterest + 12. http://dc0d32.blogspot.com/search/label/assembler + 13. http://dc0d32.blogspot.com/search/label/bootloader + 14. http://dc0d32.blogspot.com/search/label/c + 15. http://dc0d32.blogspot.com/search/label/gas + 16. http://dc0d32.blogspot.com/search/label/gcc + 17. http://dc0d32.blogspot.com/search/label/kernel + 18. http://dc0d32.blogspot.com/search/label/osdev + 19. https://www.blogger.com/profile/06904019980664523275 + 20. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1276605767623#c7537756629084768590 + 21. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7537756629084768590 + 22. https://www.blogger.com/profile/17992312956580227764 + 23. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1292917257855#c7916645211913421716 + 24. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7916645211913421716 + 25. https://www.blogger.com/profile/17992312956580227764 + 26. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1292920505936#c6914976194912758237 + 27. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=6914976194912758237 + 28. https://www.blogger.com/profile/17992312956580227764 + 29. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1292924802000#c3509490007866551116 + 30. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=3509490007866551116 + 31. https://www.blogger.com/profile/15716533043357974705 + 32. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1292939196737#c8552773997968662641 + 33. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=8552773997968662641 + 34. https://www.blogger.com/profile/17992312956580227764 + 35. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1292991102048#c3691472389082213083 + 36. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=3691472389082213083 + 37. https://www.blogger.com/profile/04546527990311411722 + 38. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1299934567958#c8861407369344586215 + 39. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=8861407369344586215 + 40. https://www.blogger.com/profile/13931402888317484377 + 41. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1302999537204#c1796379189090357880 + 42. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=1796379189090357880 + 43. https://www.blogger.com/profile/10664008816666619973 + 44. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1305925792707#c309698377277262219 + 45. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=309698377277262219 + 46. https://www.blogger.com/profile/15716533043357974705 + 47. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1305927124224#c7619831240140737017 + 48. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7619831240140737017 + 49. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1322169605658#c1693276418345545837 + 50. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=1693276418345545837 + 51. https://www.blogger.com/profile/15716533043357974705 + 52. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1322188282688#c6259496576598783959 + 53. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=6259496576598783959 + 54. https://www.blogger.com/profile/17992312956580227764 + 55. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1323015134989#c3945832952459710949 + 56. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=3945832952459710949 + 57. https://www.blogger.com/profile/15716533043357974705 + 58. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1323146939454#c2066813635755540091 + 59. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=2066813635755540091 + 60. https://www.blogger.com/profile/17992312956580227764 + 61. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1324737140263#c7908397772486068687 + 62. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7908397772486068687 + 63. https://www.blogger.com/profile/17992312956580227764 + 64. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1343616406999#c8117194716929362278 + 65. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=8117194716929362278 + 66. https://www.blogger.com/profile/00410755183408310829 + 67. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1366435009449#c1258130037332531147 + 68. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=1258130037332531147 + 69. https://www.blogger.com/profile/15716533043357974705 + 70. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1366517094365#c8123329091843779139 + 71. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=8123329091843779139 + 72. https://www.blogger.com/profile/17234059656421576642 + 73. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1384327289704#c4134298820836763034 + 74. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=4134298820836763034 + 75. https://www.blogger.com/profile/16683260877229099988 + 76. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1401480336214#c455729903293178418 + 77. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=455729903293178418 + 78. https://www.blogger.com/profile/07765096042053323038 + 79. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1423148995473#c7126019925062815723 + 80. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7126019925062815723 + 81. https://www.blogger.com/profile/01833111909520604012 + 82. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1484904386672#c7038618115198897417 + 83. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7038618115198897417 + 84. https://www.blogger.com/profile/01833111909520604012 + 85. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1484904424918#c1284220459583274955 + 86. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=1284220459583274955 + 87. https://www.blogger.com/profile/07765096042053323038 + 88. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1423149010339#c2287827836063649127 + 89. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=2287827836063649127 + 90. https://www.blogger.com/profile/17596900636592437710 + 91. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1454858010555#c4198004625201390279 + 92. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=4198004625201390279 + 93. http://dc0d32.blogspot.com/2010/06/cold-boot-attack.html + 94. http://dc0d32.blogspot.com/2010/05/how-not-to-look-like-fool-on-facebook.html + 95. http://dc0d32.blogspot.com/ + 96. http://dc0d32.blogspot.com/feeds/6370208028763486595/comments/default + 97. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html + 98. http://dc0d32.blogspot.com/2012/02/writing-kernel-in-windows-with-visual.html + 99. http://dc0d32.blogspot.com/2010/03/debugging-kernel-with-qemu-and-gdb.html + 100. javascript:void(0) + 101. http://dc0d32.blogspot.com/2012/ + 102. javascript:void(0) + 103. http://dc0d32.blogspot.com/2012/02/ + 104. javascript:void(0) + 105. http://dc0d32.blogspot.com/2010/ + 106. javascript:void(0) + 107. http://dc0d32.blogspot.com/2010/06/ + 108. http://dc0d32.blogspot.com/2010/06/cold-boot-attack.html + 109. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html + 110. javascript:void(0) + 111. http://dc0d32.blogspot.com/2010/05/ + 112. javascript:void(0) + 113. http://dc0d32.blogspot.com/2010/04/ + 114. javascript:void(0) + 115. http://dc0d32.blogspot.com/2010/03/ + 116. javascript:void(0) + 117. http://dc0d32.blogspot.com/2010/02/ + 118. javascript:void(0) + 119. http://dc0d32.blogspot.com/2009/ + 120. javascript:void(0) + 121. http://dc0d32.blogspot.com/2009/12/ + 122. javascript:void(0) + 123. http://dc0d32.blogspot.com/2009/11/ + 124. javascript:void(0) + 125. http://dc0d32.blogspot.com/2009/09/ + 126. javascript:void(0) + 127. http://dc0d32.blogspot.com/2009/08/ + 128. javascript:void(0) + 129. http://dc0d32.blogspot.com/2009/07/ + 130. javascript:void(0) + 131. http://dc0d32.blogspot.com/2009/02/ + 132. javascript:void(0) + 133. http://dc0d32.blogspot.com/2009/01/ + 134. javascript:void(0) + 135. http://dc0d32.blogspot.com/2008/ + 136. javascript:void(0) + 137. http://dc0d32.blogspot.com/2008/11/ + 138. javascript:void(0) + 139. http://dc0d32.blogspot.com/2008/10/ + 140. javascript:void(0) + 141. http://dc0d32.blogspot.com/2008/08/ + 142. javascript:void(0) + 143. http://dc0d32.blogspot.com/2008/06/ + 144. http://dc0d32.blogspot.com/search/label/linux + 145. http://dc0d32.blogspot.com/search/label/kernel + 146. http://dc0d32.blogspot.com/search/label/8800 + 147. http://dc0d32.blogspot.com/search/label/FreeBSD + 148. http://dc0d32.blogspot.com/search/label/gdb + 149. http://dc0d32.blogspot.com/search/label/nvidia + 150. http://dc0d32.blogspot.com/search/label/osdev + 151. http://dc0d32.blogspot.com/search/label/windows%207 + 152. http://dc0d32.blogspot.com/search/label/bochs + 153. http://dc0d32.blogspot.com/search/label/boot + 154. http://dc0d32.blogspot.com/search/label/bootloader + 155. http://dc0d32.blogspot.com/search/label/debug + 156. http://dc0d32.blogspot.com/search/label/dual%20boot + 157. http://dc0d32.blogspot.com/search/label/gas + 158. http://dc0d32.blogspot.com/search/label/gcc + 159. http://dc0d32.blogspot.com/search/label/overclock + 160. http://dc0d32.blogspot.com/search/label/pidgin + 161. http://dc0d32.blogspot.com/search/label/windows + 162. http://dc0d32.blogspot.com/search/label/windows%20server%202008 + 163. http://dc0d32.blogspot.com/search/label/2k8 + 164. http://dc0d32.blogspot.com/search/label/3DMark + 165. http://dc0d32.blogspot.com/search/label/3DMark%20vantage + 166. http://dc0d32.blogspot.com/search/label/820 + 167. http://dc0d32.blogspot.com/search/label/DRAM + 168. http://dc0d32.blogspot.com/search/label/Directx%2010 + 169. http://dc0d32.blogspot.com/search/label/Dirext%2011 + 170. http://dc0d32.blogspot.com/search/label/Java + 171. http://dc0d32.blogspot.com/search/label/OpenJDK + 172. http://dc0d32.blogspot.com/search/label/OpenOffice + 173. http://dc0d32.blogspot.com/search/label/Pentium%20D + 174. http://dc0d32.blogspot.com/search/label/RAID + 175. http://dc0d32.blogspot.com/search/label/Sun + 176. http://dc0d32.blogspot.com/search/label/UUID + 177. http://dc0d32.blogspot.com/search/label/Unicode + 178. http://dc0d32.blogspot.com/search/label/VirtualBox + 179. http://dc0d32.blogspot.com/search/label/X + 180. http://dc0d32.blogspot.com/search/label/Xorg + 181. http://dc0d32.blogspot.com/search/label/ageis + 182. http://dc0d32.blogspot.com/search/label/assembler + 183. http://dc0d32.blogspot.com/search/label/authentication + 184. http://dc0d32.blogspot.com/search/label/bash + 185. http://dc0d32.blogspot.com/search/label/c + 186. http://dc0d32.blogspot.com/search/label/coolbits + 187. http://dc0d32.blogspot.com/search/label/dx10 + 188. http://dc0d32.blogspot.com/search/label/fedora + 189. http://dc0d32.blogspot.com/search/label/fortune + 190. http://dc0d32.blogspot.com/search/label/gdm + 191. http://dc0d32.blogspot.com/search/label/ghostscript + 192. http://dc0d32.blogspot.com/search/label/gnome + 193. http://dc0d32.blogspot.com/search/label/google + 194. http://dc0d32.blogspot.com/search/label/gs + 195. http://dc0d32.blogspot.com/search/label/gtalk + 196. http://dc0d32.blogspot.com/search/label/heat%20sink + 197. http://dc0d32.blogspot.com/search/label/invisible + 198. http://dc0d32.blogspot.com/search/label/jabber + 199. http://dc0d32.blogspot.com/search/label/kde + 200. http://dc0d32.blogspot.com/search/label/latex + 201. http://dc0d32.blogspot.com/search/label/lvm + 202. http://dc0d32.blogspot.com/search/label/lyx + 203. http://dc0d32.blogspot.com/search/label/mount + 204. http://dc0d32.blogspot.com/search/label/networked%20audio + 205. http://dc0d32.blogspot.com/search/label/networked%20sound + 206. http://dc0d32.blogspot.com/search/label/nvclock + 207. http://dc0d32.blogspot.com/search/label/oolatex + 208. http://dc0d32.blogspot.com/search/label/ooolatex + 209. http://dc0d32.blogspot.com/search/label/perl + 210. http://dc0d32.blogspot.com/search/label/phonon + 211. http://dc0d32.blogspot.com/search/label/physics + 212. http://dc0d32.blogspot.com/search/label/physx + 213. http://dc0d32.blogspot.com/search/label/picasa + 214. http://dc0d32.blogspot.com/search/label/plugin + 215. http://dc0d32.blogspot.com/search/label/proxy + 216. http://dc0d32.blogspot.com/search/label/pulseaudio + 217. http://dc0d32.blogspot.com/search/label/qemu + 218. http://dc0d32.blogspot.com/search/label/rsync + 219. http://dc0d32.blogspot.com/search/label/rtp + 220. http://dc0d32.blogspot.com/search/label/scp + 221. http://dc0d32.blogspot.com/search/label/scp%20stdin + 222. http://dc0d32.blogspot.com/search/label/security + 223. http://dc0d32.blogspot.com/search/label/server + 224. http://dc0d32.blogspot.com/search/label/shell + 225. http://dc0d32.blogspot.com/search/label/squid + 226. http://dc0d32.blogspot.com/search/label/ssh + 227. http://dc0d32.blogspot.com/search/label/sync + 228. http://dc0d32.blogspot.com/search/label/tar + 229. http://dc0d32.blogspot.com/search/label/udev + 230. http://dc0d32.blogspot.com/search/label/unix + 231. http://dc0d32.blogspot.com/search/label/xdm + 232. http://dc0d32.blogspot.com/search/label/xfce + 233. http://dc0d32.blogspot.com/search/label/xmpp + 234. http://dc0d32.blogspot.com/search/label/xorg.conf + 235. http://dc0d32.blogspot.com/search/label/zsh + 236. http://www.statcounter.com/blogger/ + 237. http://www.istockphoto.com/portfolio/5ugarless?platform=blogger + 238. https://www.blogger.com/ + + Hidden links: + 240. https://www.blogger.com/post-edit.g?blogID=35813921&postID=6370208028763486595&from=pencil + 241. https://www.blogger.com/comment/frame/35813921?po=6370208028763486595&hl=en diff --git a/todo/doc/fossbytes_com_redditor-boots-linux-kernel-5-8-0-rc2-floppy-intel-80486.txt b/todo/doc/fossbytes_com_redditor-boots-linux-kernel-5-8-0-rc2-floppy-intel-80486.txt new file mode 100644 index 0000000..72c3e20 --- /dev/null +++ b/todo/doc/fossbytes_com_redditor-boots-linux-kernel-5-8-0-rc2-floppy-intel-80486.txt @@ -0,0 +1,339 @@ + #[1]Fossbytes Feed [2]Fossbytes Comments Feed [3]Fossbytes + Redditor Boots Linux Kernel 5.8 On 30-Year-Old Intel Processor via + Floppy Disk Comments Feed [4]alternate [5]alternate [6]alternate + + [7]Skip to content + + [8]FOSSBYTES TECH SIMPLIFIED LOGO + [9]Facebook + [10]Twitter + [11]Instagram + + * [12]News + * [13]Geek + * [14]Hacked + * [15]Gaming + * [16]Drive X + * [17]How To + * [18]Top X + * [19]Tools + + Menu + + * [20]News + * [21]Geek + * [22]Hacked + * [23]Gaming + * [24]Drive X + * [25]How To + * [26]Top X + * [27]Tools + + Search + ____________________ + + Menu + + * [28]News + * [29]Geek + * [30]Hacked + * [31]Gaming + * [32]Drive X + * [33]How To + * [34]Top X + * [35]Tools + + [36]FOSSBYTES TECH SIMPLIFIED LOGO + Search + ____________________ + Close + + News + + * [37]Privacy + * [38]Facebook + * [39]Apple + * [40]Google + * [41]Microsoft + * [42]Linux + * [43]Tesla + * [44]EV + + Menu + + * [45]Privacy + * [46]Facebook + * [47]Apple + * [48]Google + * [49]Microsoft + * [50]Linux + * [51]Tesla + * [52]EV + + * [53]Geek, [54]News + +Redditor Boots Linux Kernel 5.8 On 30-Year-Old Intel Processor via Floppy +Disk + + * [55]Sarvottam Kumar + * [56]June 30, 2020 + + Redditor Booted Linux Kernel 5.8.0-rc2+ From A Floppy On Intel 80486 + + Do you remember your first PC on which you booted Linux from floppy? + Well, Floppy disk is almost dead. The majority of people now use USB + sticks or DVDs to install Linux distros on their PCs. However, retro + enthusiasts love to revive their old hardware and relive the flashback. + + Recently, a Redditor who goes by the name + `FozzTexx' [57]demonstrated the latest stable Linux Kernel 5.8.0-rc2+ + running from his floppy disk. He successfully booted a tiny kernel on a + 30-year-old 32-bit Intel 80486 (i486 or 486) CPU. + + Now, if you think Linux kernel has dropped support for anything older + than i686, it may prove you wrong. You know that freedom, + customization, and support for legacy hardware are the characteristics + of Linux. + + Speaking of booting OS, if you're 90s kid, you may remember installing + Linux with boot floppies or installation CDs offered by Linux distros. + Nowadays, the scenario has changed as people download the ISO from + official websites and install it by creating a bootable USB or DVD. + + In case you're still wondering about booting Linux from floppy, a retro + enthusiasts FozzTexx did it using a single 1.44MB floppy disk on his + i486 CPU. + Booting Linux from 1.44MB floppy Booting Linux from 1.44MB floppy + + He pulled the fresh Kernel 5.8.0-rc2+ from the git repo and shrank it + to fit on a floppy using make tinyconfig. Then, he booted it on 486 + into a busybox shell using rootfs.cpio.gz from Aboriginal Linux. + + The tiny kernel surely misses network support or any other functional + support. Though it may seem useless, the Redditor also added options + like IDE support. Surprisingly, when he attached a hard drive and + booted into the shell, he could see the drive as connected and its full + capacity. You can see the result in the picture below. + Hard disk attached to 486 CPU Hard disk attached to 486 CPU + + You can also read the Twitter [58]thread describing how he started + loading kernel 5.8 on a 486 from floppy. + + This is for all you [59]#floppy lovers out there: Linux 5.8.0-rc2+ + pulled fresh from the git repo this morning booting into a busybox + shell using the rootfs.cpio.gz from Aboriginal Linux. + [60]#RetroComputing [61]pic.twitter.com/zaB9lpggPX + -- FozzTexx (@FozzTexx) [62]June 28, 2020 + + If you also have a 486 system lying around and want to load Linux, you + can follow the tutorial which he'll put on his [63]blog site soon. + [64]Sarvottam Kumar + [65] + +Sarvottam Kumar + + Being a fossbyter, I cover the latest releases, news, information, and + trends in the world of Linux and Open source. + +Leave a Comment [66]Cancel Reply + + Your email address will not be published. Required fields are marked * + + Type here.. + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + _____________________________________________ + + Name* ______________________________ + + Email* ______________________________ + + Website ______________________________ + + [ ] Save my name, email, and website in this browser for the next time + I comment. + + Post Comment + +News & Opeds + + Tesla Model S and Model X + +[67]Why NHTSA Is Asking Tesla To Recall 158,000 Model S And Model X? + + Netflix Movies 2021 All 70 Movies Coming To Netflix This Year + +[68]Netflix Movies 2021: All 70 Movies Releasing On Netflix This Year + + Official Best of CES 2021 awards + +[69]CES 2021 Awards: This Is The Tech To Look Forward To In 2021 + + More From Fossbytes + +Popular In News + + How do electric cars work_ + +[70]How Do Electric Cars Work? Electric Motors And Batteries Explained + + Netflix Movies 2021 All 70 Movies Coming To Netflix This Year + +[71]Netflix Movies 2021: All 70 Movies Releasing On Netflix This Year + + Security-Focused Tails OS Plans To Switch From Xorg To Wayland + +[72]Security-Focused Tails OS Plans To Switch From Xorg To Wayland + +[73]CloudLinux Renames Its CentOS Alternative `Project Lenix' To `AlmaLinux' + + FOSSBYTES + + * [74]About Us + * [75]Privacy Policy + * [76]Cookie Policy + + [77]Facebook + [78]Twitter + [79]Instagram + * [80]Contact Us + * [81]Our Team + * [82]Work With Us + +Learn Something New Today + + [83]Academy + + Fossbytes Media Pvt Ltd 2021 + + FOSSBYTES + + [84]Facebook + [85]Twitter + [86]Instagram + +Learn Something New Today + + [87]Academy + * [88]About Us + * [89]Privacy Policy + * [90]Cookie Policy + + * [91]Contact Us + * [92]Our Team + * [93]Work With Us + + Fossbytes Media Pvt Ltd 2021 + + Scroll to Top + +References + + Visible links: + 1. https://fossbytes.com/feed/ + 2. https://fossbytes.com/comments/feed/ + 3. https://fossbytes.com/redditor-boots-linux-kernel-5-8-0-rc2-floppy-intel-80486/feed/ + 4. https://fossbytes.com/wp-json/wp/v2/posts/173003 + 5. https://fossbytes.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Ffossbytes.com%2Fredditor-boots-linux-kernel-5-8-0-rc2-floppy-intel-80486%2F + 6. https://fossbytes.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Ffossbytes.com%2Fredditor-boots-linux-kernel-5-8-0-rc2-floppy-intel-80486%2F&format=xml + 7. https://fossbytes.com/redditor-boots-linux-kernel-5-8-0-rc2-floppy-intel-80486/#content + 8. https://fossbytes.com/ + 9. https://www.facebook.com/fossbytes + 10. https://twitter.com/Fossbytes14 + 11. https://instagram.com/fossbytes + 12. https://fossbytes.com/category/news/ + 13. https://fossbytes.com/category/geek/ + 14. https://fossbytes.com/category/security/ + 15. https://fossbytes.com/category/entertainment/gaming-and-sports/ + 16. https://fossbytes.com/category/transportation/ + 17. https://fossbytes.com/category/how-to/ + 18. https://fossbytes.com/category/more/lists/ + 19. https://fossbytes.com/tools/ + 20. https://fossbytes.com/category/news/ + 21. https://fossbytes.com/category/geek/ + 22. https://fossbytes.com/category/security/ + 23. https://fossbytes.com/category/entertainment/gaming-and-sports/ + 24. https://fossbytes.com/category/transportation/ + 25. https://fossbytes.com/category/how-to/ + 26. https://fossbytes.com/category/more/lists/ + 27. https://fossbytes.com/tools/ + 28. https://fossbytes.com/category/news/ + 29. https://fossbytes.com/category/geek/ + 30. https://fossbytes.com/category/security/ + 31. https://fossbytes.com/category/entertainment/gaming-and-sports/ + 32. https://fossbytes.com/category/transportation/ + 33. https://fossbytes.com/category/how-to/ + 34. https://fossbytes.com/category/more/lists/ + 35. https://fossbytes.com/tools/ + 36. https://fossbytes.com/ + 37. https://fossbytes.com/tag/privacy/ + 38. https://fossbytes.com/tag/facebook/ + 39. https://fossbytes.com/tag/apple/ + 40. https://fossbytes.com/tag/google/ + 41. https://fossbytes.com/tag/microsoft/ + 42. https://fossbytes.com/tag/linux/ + 43. https://fossbytes.com/tag/tesla/ + 44. https://fossbytes.com/tag/electric-cars/ + 45. https://fossbytes.com/tag/privacy/ + 46. https://fossbytes.com/tag/facebook/ + 47. https://fossbytes.com/tag/apple/ + 48. https://fossbytes.com/tag/google/ + 49. https://fossbytes.com/tag/microsoft/ + 50. https://fossbytes.com/tag/linux/ + 51. https://fossbytes.com/tag/tesla/ + 52. https://fossbytes.com/tag/electric-cars/ + 53. https://fossbytes.com/category/geek/ + 54. https://fossbytes.com/category/news/ + 55. https://fossbytes.com/author/sarvottam/ + 56. https://fossbytes.com/2020/06/30/ + 57. https://www.reddit.com/r/retrobattlestations/comments/hi3kbq/booting_linux_kernel_580rc2_from_a_single_floppy/ + 58. https://twitter.com/FozzTexx/status/1277251556010676225 + 59. https://twitter.com/hashtag/floppy?src=hash&ref_src=twsrc%5Etfw + 60. https://twitter.com/hashtag/RetroComputing?src=hash&ref_src=twsrc%5Etfw + 61. https://t.co/zaB9lpggPX + 62. https://twitter.com/FozzTexx/status/1277296880813105152?ref_src=twsrc%5Etfw + 63. https://www.insentricity.com/ + 64. https://fossbytes.com/author/sarvottam/ + 65. https://fossbytes.com/author/sarvottam/ + 66. https://fossbytes.com/redditor-boots-linux-kernel-5-8-0-rc2-floppy-intel-80486/#respond + 67. https://fossbytes.com/why-nhtsa-is-asking-tesla-to-recall-158000-model-s-and-model-x/ + 68. https://fossbytes.com/netflix-movies-2021-all-70-movies-releasing-on-netflix-this-year/ + 69. https://fossbytes.com/official-best-of-ces-2021/ + 70. https://fossbytes.com/how-do-electric-cars-work-electric-motors-and-batteries-explained/ + 71. https://fossbytes.com/netflix-movies-2021-all-70-movies-releasing-on-netflix-this-year/ + 72. https://fossbytes.com/security-focused-tails-os-plans-to-switch-from-xorg-to-wayland/ + 73. https://fossbytes.com/cloudlinux-renames-centos-alternative-project-lenix-to-almalinux/ + 74. https://fossbytes.com/about/ + 75. https://fossbytes.com/privacy-policy/ + 76. https://fossbytes.com/cookie-policy-for-fossbytes/ + 77. https://www.facebook.com/fossbytes + 78. https://twitter.com/Fossbytes14 + 79. https://instagram.com/fossbytes + 80. https://fossbytes.com/contact-us/ + 81. https://fossbytes.com/fossbytes-team/ + 82. https://fossbytes.com/jobs/ + 83. https://academy.fossbytes.com/ + 84. https://www.facebook.com/fossbytes + 85. https://twitter.com/Fossbytes14 + 86. https://instagram.com/fossbytes + 87. https://academy.fossbytes.com/ + 88. https://fossbytes.com/about/ + 89. https://fossbytes.com/privacy-policy/ + 90. https://fossbytes.com/cookie-policy-for-fossbytes/ + 91. https://fossbytes.com/contact-us/ + 92. https://fossbytes.com/fossbytes-team/ + 93. https://fossbytes.com/jobs/ + + Hidden links: + 95. https://fossbytes.com/why-nhtsa-is-asking-tesla-to-recall-158000-model-s-and-model-x/ + 96. https://fossbytes.com/netflix-movies-2021-all-70-movies-releasing-on-netflix-this-year/ + 97. https://fossbytes.com/official-best-of-ces-2021/ + 98. https://fossbytes.com/how-do-electric-cars-work-electric-motors-and-batteries-explained/ + 99. https://fossbytes.com/netflix-movies-2021-all-70-movies-releasing-on-netflix-this-year/ + 100. https://fossbytes.com/security-focused-tails-os-plans-to-switch-from-xorg-to-wayland/ + 101. https://fossbytes.com/cloudlinux-renames-centos-alternative-project-lenix-to-almalinux/ diff --git a/todo/doc/people.freedesktop.org_~narmstrong_meson_drm_doc_admin-guide_initrd.txt b/todo/doc/people.freedesktop.org_~narmstrong_meson_drm_doc_admin-guide_initrd.txt new file mode 100644 index 0000000..0c2351e --- /dev/null +++ b/todo/doc/people.freedesktop.org_~narmstrong_meson_drm_doc_admin-guide_initrd.txt @@ -0,0 +1,453 @@ + #[1]The Linux Kernel 4.11.0-rc4-00191-g7de6e5d documentation [2]The + Linux kernel user's and administrator's guide [3]Linux Serial Console + [4]Rules on how to access information in sysfs + +Navigation + + * [5]index + * [6]next | + * [7]previous | + * [8]The Linux Kernel 4.11.0-rc4-00191-g7de6e5d documentation + * [9]The Linux kernel user's and administrator's guide + +Using the initial RAM disk (initrd)[10] + + Written 1996,2000 by Werner Almesberger + <[11]werner.almesberger@epfl.ch> and Hans Lermen <[12]lermen@fgan.de> + + initrd provides the capability to load a RAM disk by the boot loader. + This RAM disk can then be mounted as the root file system and programs + can be run from it. Afterwards, a new root file system can be mounted + from a different device. The previous root (from initrd) is then moved + to a directory and can be subsequently unmounted. + + initrd is mainly designed to allow system startup to occur in two + phases, where the kernel comes up with a minimum set of compiled-in + drivers, and where additional modules are loaded from initrd. + + This document gives a brief overview of the use of initrd. A more + detailed discussion of the boot process can be found in [13][1]. + +Operation[14] + + When using initrd, the system typically boots as follows: + + 1. the boot loader loads the kernel and the initial RAM disk + 2. the kernel converts initrd into a "normal" RAM disk and frees the + memory used by initrd + 3. if the root device is not /dev/ram0, the old (deprecated) + change_root procedure is followed. see the "Obsolete root change + mechanism" section below. + 4. root device is mounted. if it is /dev/ram0, the initrd image is + then mounted as root + 5. /sbin/init is executed (this can be any valid executable, including + shell scripts; it is run with uid 0 and can do basically everything + init can do). + 6. init mounts the "real" root file system + 7. init places the root file system at the root directory using the + pivot_root system call + 8. init execs the /sbin/init on the new root filesystem, performing + the usual boot sequence + 9. the initrd file system is removed + + Note that changing the root directory does not involve unmounting it. + It is therefore possible to leave processes running on initrd during + that procedure. Also note that file systems mounted under initrd + continue to be accessible. + +Boot command-line options[15] + + initrd adds the following new options: +initrd= (e.g. LOADLIN) + + Loads the specified file as the initial RAM disk. When using LILO, you + have to specify the RAM disk image file in /etc/lilo.conf, using the + INITRD configuration variable. + +noinitrd + + initrd data is preserved but it is not converted to a RAM disk and + the "normal" root file system is mounted. initrd data can be read + from /dev/initrd. Note that the data in initrd can have any structure + in this case and doesn't necessarily have to be a file system image. + This option is used mainly for debugging. + + Note: /dev/initrd is read-only and it can only be used once. As soon + as the last process has closed it, all data is freed and /dev/initrd + can't be opened anymore. + +root=/dev/ram0 + + initrd is mounted as root, and the normal boot procedure is followed, + with the RAM disk mounted as root. + +Compressed cpio images[16] + + Recent kernels have support for populating a ramdisk from a compressed + cpio archive. On such systems, the creation of a ramdisk image doesn't + need to involve special block devices or loopbacks; you merely create a + directory on disk with the desired initrd content, cd to that + directory, and run (as an example): +find . | cpio --quiet -H newc -o | gzip -9 -n > /boot/imagefile.img + + Examining the contents of an existing image file is just as simple: +mkdir /tmp/imagefile +cd /tmp/imagefile +gzip -cd /boot/imagefile.img | cpio -imd --quiet + +Installation[17] + + First, a directory for the initrd file system has to be created on the + "normal" root file system, e.g.: +# mkdir /initrd + + The name is not relevant. More details can be found on the + pivot_root(2) man page. + + If the root file system is created during the boot procedure (i.e. if + you're building an install floppy), the root file system creation + procedure should create the /initrd directory. + + If initrd will not be mounted in some cases, its content is still + accessible if the following device has been created: +# mknod /dev/initrd b 1 250 +# chmod 400 /dev/initrd + + Second, the kernel has to be compiled with RAM disk support and with + support for the initial RAM disk enabled. Also, at least all components + needed to execute programs from initrd (e.g. executable format and file + system) must be compiled into the kernel. + + Third, you have to create the RAM disk image. This is done by creating + a file system on a block device, copying files to it as needed, and + then copying the content of the block device to the initrd file. With + recent kernels, at least three types of devices are suitable for that: + + * a floppy disk (works everywhere but it's painfully slow) + * a RAM disk (fast, but allocates physical memory) + * a loopback device (the most elegant solution) + + We'll describe the loopback device method: + + 1. make sure loopback block devices are configured into the kernel + 2. create an empty file system of the appropriate size, e.g.: +# dd if=/dev/zero of=initrd bs=300k count=1 +# mke2fs -F -m0 initrd + + (if space is critical, you may want to use the Minix FS instead of + Ext2) + 3. mount the file system, e.g.: +# mount -t ext2 -o loop initrd /mnt + + 4. create the console device: +# mkdir /mnt/dev +# mknod /mnt/dev/console c 5 1 + + 5. copy all the files that are needed to properly use the initrd + environment. Don't forget the most important file, /sbin/init + Note + /sbin/init permissions must include "x" (execute). + 6. correct operation the initrd environment can frequently be tested + even without rebooting with the command: +# chroot /mnt /sbin/init + + This is of course limited to initrds that do not interfere with the + general system state (e.g. by reconfiguring network interfaces, + overwriting mounted devices, trying to start already running + demons, etc. Note however that it is usually possible to use + pivot_root in such a chroot'ed initrd environment.) + 7. unmount the file system: +# umount /mnt + + 8. the initrd is now in the file "initrd". Optionally, it can now be + compressed: +# gzip -9 initrd + + For experimenting with initrd, you may want to take a rescue floppy and + only add a symbolic link from /sbin/init to /bin/sh. Alternatively, you + can try the experimental newlib environment [18][2] to create a small + initrd. + + Finally, you have to boot the kernel and load initrd. Almost all Linux + boot loaders support initrd. Since the boot process is still compatible + with an older mechanism, the following boot command line parameters + have to be given: +root=/dev/ram0 rw + + (rw is only necessary if writing to the initrd file system.) + + With LOADLIN, you simply execute: +LOADLIN initrd= + + e.g.: +LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0 rw + + With LILO, you add the option INITRD= to either the global + section or to the section of the respective kernel in /etc/lilo.conf, + and pass the options using APPEND, e.g.: +image = /bzImage + initrd = /boot/initrd.gz + append = "root=/dev/ram0 rw" + + and run /sbin/lilo + + For other boot loaders, please refer to the respective documentation. + + Now you can boot and enjoy using initrd. + +Changing the root device[19] + + When finished with its duties, init typically changes the root device + and proceeds with starting the Linux system on the "real" root device. + + The procedure involves the following steps: + + + mounting the new root file system + + turning it into the root file system + + removing all accesses to the old (initrd) root file system + + unmounting the initrd file system and de-allocating the RAM + disk + + Mounting the new root file system is easy: it just needs to be mounted + on a directory under the current root. Example: +# mkdir /new-root +# mount -o ro /dev/hda1 /new-root + + The root change is accomplished with the pivot_root system call, which + is also available via the pivot_root utility (see pivot_root(8) man + page; pivot_root is distributed with util-linux version 2.10h or higher + [20][3]). pivot_root moves the current root to a directory under the + new root, and puts the new root at its place. The directory for the old + root must exist before calling pivot_root. Example: +# cd /new-root +# mkdir initrd +# pivot_root . initrd + + Now, the init process may still access the old root via its executable, + shared libraries, standard input/output/error, and its current root + directory. All these references are dropped by the following command: +# exec chroot . what-follows dev/console 2>&1 + + Where what-follows is a program under the new root, e.g. /sbin/init If + the new root file system will be used with udev and has no valid /dev + directory, udev must be initialized before invoking chroot in order to + provide /dev/console. + + Note: implementation details of pivot_root may change with time. In + order to ensure compatibility, the following points should be observed: + + * before calling pivot_root, the current directory of the invoking + process should point to the new root directory + * use . as the first argument, and the _relative_ path of the + directory for the old root as the second argument + * a chroot program must be available under the old and the new root + * chroot to the new root afterwards + * use relative paths for dev/console in the exec command + + Now, the initrd can be unmounted and the memory allocated by the RAM + disk can be freed: +# umount /initrd +# blockdev --flushbufs /dev/ram0 + + It is also possible to use initrd with an NFS-mounted root, see the + pivot_root(8) man page for details. + +Usage scenarios[21] + + The main motivation for implementing initrd was to allow for modular + kernel configuration at system installation. The procedure would work + as follows: + + 1. system boots from floppy or other media with a minimal kernel (e.g. + support for RAM disks, initrd, a.out, and the Ext2 FS) and loads + initrd + 2. /sbin/init determines what is needed to (1) mount the "real" root + FS (i.e. device type, device drivers, file system) and (2) the + distribution media (e.g. CD-ROM, network, tape, ...). This can be + done by asking the user, by auto-probing, or by using a hybrid + approach. + 3. /sbin/init loads the necessary kernel modules + 4. /sbin/init creates and populates the root file system (this doesn't + have to be a very usable system yet) + 5. /sbin/init invokes pivot_root to change the root file system and + execs - via chroot - a program that continues the installation + 6. the boot loader is installed + 7. the boot loader is configured to load an initrd with the set of + modules that was used to bring up the system (e.g. /initrd can be + modified, then unmounted, and finally, the image is written from + /dev/ram0 or /dev/rd/0 to a file) + 8. now the system is bootable and additional installation tasks can be + performed + + The key role of initrd here is to re-use the configuration data during + normal system operation without requiring the use of a bloated + "generic" kernel or re-compiling or re-linking the kernel. + + A second scenario is for installations where Linux runs on systems with + different hardware configurations in a single administrative domain. In + such cases, it is desirable to generate only a small set of kernels + (ideally only one) and to keep the system-specific part of + configuration information as small as possible. In this case, a common + initrd could be generated with all the necessary modules. Then, only + /sbin/init or a file read by it would have to be different. + + A third scenario is more convenient recovery disks, because information + like the location of the root FS partition doesn't have to be provided + at boot time, but the system loaded from initrd can invoke a + user-friendly dialog and it can also perform some sanity checks (or + even some form of auto-detection). + + Last not least, CD-ROM distributors may use it for better installation + from CD, e.g. by using a boot floppy and bootstrapping a bigger RAM + disk via initrd from CD; or by booting via a loader like LOADLIN or + directly from the CD-ROM, and loading the RAM disk from CD without need + of floppies. + +Obsolete root change mechanism[22] + + The following mechanism was used before the introduction of pivot_root. + Current kernels still support it, but you should _not_ rely on its + continued availability. + + It works by mounting the "real" root device (i.e. the one set with rdev + in the kernel image or with root=... at the boot command line) as the + root file system when linuxrc exits. The initrd file system is then + unmounted, or, if it is still busy, moved to a directory /initrd, if + such a directory exists on the new root file system. + + In order to use this mechanism, you do not have to specify the boot + command options root, init, or rw. (If specified, they will affect the + real root file system, not the initrd environment.) + + If /proc is mounted, the "real" root device can be changed from within + linuxrc by writing the number of the new root FS device to the special + file /proc/sys/kernel/real-root-dev, e.g.: +# echo 0x301 >/proc/sys/kernel/real-root-dev + + Note that the mechanism is incompatible with NFS and similar file + systems. + + This old, deprecated mechanism is commonly called change_root, while + the new, supported mechanism is called pivot_root. + +Mixed change_root and pivot_root mechanism[23] + + In case you did not want to use root=/dev/ram0 to trigger the + pivot_root mechanism, you may create both /linuxrc and /sbin/init in + your initrd image. + + /linuxrc would contain only the following: +#! /bin/sh +mount -n -t proc proc /proc +echo 0x0100 >/proc/sys/kernel/real-root-dev +umount -n /proc + + Once linuxrc exited, the kernel would mount again your initrd as root, + this time executing /sbin/init. Again, it would be the duty of this + init to build the right environment (maybe using the root= device + passed on the cmdline) before the final execution of the real + /sbin/init. + +Resources[24] + + [25][1] Almesberger, Werner; "Booting Linux: The History and the + Future" [26]http://www.almesberger.net/cv/papers/ols2k-9.ps.gz + [27][2] newlib package (experimental), with initrd example + [28]https://www.sourceware.org/newlib/ + [29][3] util-linux: Miscellaneous utilities for Linux + [30]https://www.kernel.org/pub/linux/utils/util-linux/ + +[31]Table Of Contents + + * [32]Using the initial RAM disk (initrd) + + [33]Operation + + [34]Boot command-line options + + [35]Compressed cpio images + + [36]Installation + + [37]Changing the root device + + [38]Usage scenarios + + [39]Obsolete root change mechanism + + [40]Mixed change_root and pivot_root mechanism + + [41]Resources + +Previous topic + + [42]Rules on how to access information in sysfs + +Next topic + + [43]Linux Serial Console + +This Page + + * [44]Show Source + +Quick search + + ____________________ Go + + Enter search terms or a module, class or function name. + +Navigation + + * [45]index + * [46]next | + * [47]previous | + * [48]The Linux Kernel 4.11.0-rc4-00191-g7de6e5d documentation + * [49]The Linux kernel user's and administrator's guide + + Copyright The kernel development community. Created using [50]Sphinx + 1.2.2. + +References + + 1. https://people.freedesktop.org/~narmstrong/meson_drm_doc/index.html + 2. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/index.html + 3. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/serial-console.html + 4. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/sysfs-rules.html + 5. https://people.freedesktop.org/~narmstrong/meson_drm_doc/genindex.html + 6. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/serial-console.html + 7. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/sysfs-rules.html + 8. https://people.freedesktop.org/~narmstrong/meson_drm_doc/index.html + 9. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/index.html + 10. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#using-the-initial-ram-disk-initrd + 11. mailto:werner.almesberger%40epfl.ch + 12. mailto:lermen%40fgan.de + 13. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#f1 + 14. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#operation + 15. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#boot-command-line-options + 16. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#compressed-cpio-images + 17. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#installation + 18. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#f2 + 19. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#changing-the-root-device + 20. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#f3 + 21. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#usage-scenarios + 22. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#obsolete-root-change-mechanism + 23. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#mixed-change-root-and-pivot-root-mechanism + 24. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#resources + 25. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#id1 + 26. http://www.almesberger.net/cv/papers/ols2k-9.ps.gz + 27. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#id2 + 28. https://www.sourceware.org/newlib/ + 29. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#id3 + 30. https://www.kernel.org/pub/linux/utils/util-linux/ + 31. https://people.freedesktop.org/~narmstrong/meson_drm_doc/index.html + 32. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html + 33. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#operation + 34. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#boot-command-line-options + 35. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#compressed-cpio-images + 36. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#installation + 37. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#changing-the-root-device + 38. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#usage-scenarios + 39. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#obsolete-root-change-mechanism + 40. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#mixed-change-root-and-pivot-root-mechanism + 41. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/initrd.html#resources + 42. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/sysfs-rules.html + 43. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/serial-console.html + 44. https://people.freedesktop.org/~narmstrong/meson_drm_doc/_sources/admin-guide/initrd.txt + 45. https://people.freedesktop.org/~narmstrong/meson_drm_doc/genindex.html + 46. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/serial-console.html + 47. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/sysfs-rules.html + 48. https://people.freedesktop.org/~narmstrong/meson_drm_doc/index.html + 49. https://people.freedesktop.org/~narmstrong/meson_drm_doc/admin-guide/index.html + 50. http://sphinx-doc.org/ diff --git a/todo/doc/www.kernel.org_doc_html_latest_x86_boot.txt b/todo/doc/www.kernel.org_doc_html_latest_x86_boot.txt new file mode 100644 index 0000000..0ef56f7 --- /dev/null +++ b/todo/doc/www.kernel.org_doc_html_latest_x86_boot.txt @@ -0,0 +1,2349 @@ + #[1]Index [2]Search [3]2. DeviceTree Booting [4]x86-specific + Documentation + +[5]The Linux Kernel + + 6.3.0-rc6 + +Quick search + + ____________________ Go + +Contents + + [X] + * [6]A guide to the Kernel Development Process + * [7]Submitting patches: the essential guide to getting your code + into the kernel + * [8]Code of conduct + * [9]Kernel Maintainer Handbook + * [10]All development-process docs + + * [11]Core API Documentation + * [12]Driver implementer's API guide + * [13]Kernel subsystem documentation + * [14]Locking in the kernel + + * [15]Linux kernel licensing rules + * [16]How to write kernel documentation + * [17]Development tools for the kernel + * [18]Kernel Testing Guide + * [19]Kernel Hacking Guides + * [20]Linux Tracing Technologies + * [21]fault-injection + * [22]Kernel Livepatching + * [23]Rust + + * [24]The Linux kernel user's and administrator's guide + * [25]The kernel build system + * [26]Reporting issues + * [27]User-space tools + * [28]The Linux kernel user-space API guide + + * [29]The Linux kernel firmware guide + * [30]Open Firmware and Devicetree + + * [31]CPU Architectures + + [32]ARC architecture + + [33]ARM Architecture + + [34]ARM64 Architecture + + [35]IA-64 Architecture + + [36]LoongArch Architecture + + [37]m68k Architecture + + [38]MIPS-specific Documentation + + [39]Nios II Specific Documentation + + [40]OpenRISC Architecture + + [41]PA-RISC Architecture + + [42]powerpc + + [43]RISC-V architecture + + [44]s390 Architecture + + [45]SuperH Interfaces Guide + + [46]Sparc Architecture + + [47]x86-specific Documentation + o [48]1. The Linux/x86 Boot Protocol + o [49]2. DeviceTree Booting + o [50]3. x86 Feature Flags + o [51]4. x86 Topology + o [52]5. Kernel level exception handling + o [53]6. Kernel Stacks + o [54]7. Kernel Entries + o [55]8. Early Printk + o [56]9. ORC unwinder + o [57]10. Zero Page + o [58]11. The TLB + o [59]12. MTRR (Memory Type Range Register) control + o [60]13. PAT (Page Attribute Table) + o [61]14. Hardware-Feedback Interface for scheduling on + Intel Hardware + o [62]15. x86 IOMMU Support + o [63]16. Intel(R) TXT Overview + o [64]17. AMD Memory Encryption + o [65]18. AMD HSMP interface + o [66]19. Intel Trust Domain Extensions (TDX) + o [67]20. Page Table Isolation (PTI) + o [68]21. Microarchitectural Data Sampling (MDS) mitigation + o [69]22. The Linux Microcode Loader + o [70]23. User Interface for Resource Control feature + o [71]24. TSX Async Abort (TAA) mitigation + o [72]25. Bus lock detection and handling + o [73]26. USB Legacy support + o [74]27. i386 Support + o [75]28. x86_64 Support + o [76]29. In-Field Scan + o [77]30. Shared Virtual Addressing (SVA) with ENQCMD + o [78]31. Software Guard eXtensions (SGX) + o [79]32. Feature status on x86 architecture + o [80]33. x86-specific ELF Auxiliary Vectors + o [81]34. Using XSTATE features in user space applications + + [82]Xtensa Architecture + + * [83]Unsorted Documentation + + * [84]Translations + +This Page + + * [85]Show Source + +1. The Linux/x86 Boot Protocol[86] + + On the x86 platform, the Linux kernel uses a rather complicated boot + convention. This has evolved partially due to historical aspects, as + well as the desire in the early days to have the kernel itself be a + bootable image, the complicated PC memory model and due to changed + expectations in the PC industry caused by the effective demise of + real-mode DOS as a mainstream operating system. + + Currently, the following versions of the Linux/x86 boot protocol exist. + + Old kernels + + zImage/Image support only. Some very early kernels may not even support + a command line. + + Protocol 2.00 + + (Kernel 1.3.73) Added bzImage and initrd support, as well as a + formalized way to communicate between the boot loader and the kernel. + setup.S made relocatable, although the traditional setup area still + assumed writable. + + Protocol 2.01 + + (Kernel 1.3.76) Added a heap overrun warning. + + Protocol 2.02 + + (Kernel 2.4.0-test3-pre3) New command line protocol. Lower the + conventional memory ceiling. No overwrite of the traditional setup + area, thus making booting safe for systems which use the EBDA from SMM + or 32-bit BIOS entry points. zImage deprecated but still supported. + + Protocol 2.03 + + (Kernel 2.4.18-pre1) Explicitly makes the highest possible initrd + address available to the bootloader. + + Protocol 2.04 + + (Kernel 2.6.14) Extend the syssize field to four bytes. + + Protocol 2.05 + + (Kernel 2.6.20) Make protected mode kernel relocatable. Introduce + relocatable_kernel and kernel_alignment fields. + + Protocol 2.06 + + (Kernel 2.6.22) Added a field that contains the size of the boot + command line. + + Protocol 2.07 + + (Kernel 2.6.24) Added paravirtualised boot protocol. Introduced + hardware_subarch and hardware_subarch_data and KEEP_SEGMENTS flag in + load_flags. + + Protocol 2.08 + + (Kernel 2.6.26) Added crc32 checksum and ELF format payload. Introduced + payload_offset and payload_length fields to aid in locating the + payload. + + Protocol 2.09 + + (Kernel 2.6.26) Added a field of 64-bit physical pointer to single + linked list of struct setup_data. + + Protocol 2.10 + + (Kernel 2.6.31) Added a protocol for relaxed alignment beyond the + kernel_alignment added, new init_size and pref_address fields. Added + extended boot loader IDs. + + Protocol 2.11 + + (Kernel 3.6) Added a field for offset of EFI handover protocol entry + point. + + Protocol 2.12 + + (Kernel 3.8) Added the xloadflags field and extension fields to struct + boot_params for loading bzImage and ramdisk above 4G in 64bit. + + Protocol 2.13 + + (Kernel 3.14) Support 32- and 64-bit flags being set in xloadflags to + support booting a 64-bit kernel from 32-bit EFI + + Protocol 2.14 + + BURNT BY INCORRECT COMMIT ae7e1238e68f2a472a125673ab506d49158c1889 + (x86/boot: Add ACPI RSDP address to setup_header) DO NOT USE!!! ASSUME + SAME AS 2.13. + + Protocol 2.15 + + (Kernel 5.5) Added the kernel_info and kernel_info.setup_type_max. + + Note + + The protocol version number should be changed only if the setup header + is changed. There is no need to update the version number if + boot_params or kernel_info are changed. Additionally, it is recommended + to use xloadflags (in this case the protocol version number should not + be updated either) or kernel_info to communicate supported Linux kernel + features to the boot loader. Due to very limited space available in the + original setup header every update to it should be considered with + great care. Starting from the protocol 2.15 the primary way to + communicate things to the boot loader is the kernel_info. + +1.1. Memory Layout[87] + + The traditional memory map for the kernel loader, used for Image or + zImage kernels, typically looks like: + | | +0A0000 +------------------------+ + | Reserved for BIOS | Do not use. Reserved for BIOS EBDA. +09A000 +------------------------+ + | Command line | + | Stack/heap | For use by the kernel real-mode code. +098000 +------------------------+ + | Kernel setup | The kernel real-mode code. +090200 +------------------------+ + | Kernel boot sector | The kernel legacy boot sector. +090000 +------------------------+ + | Protected-mode kernel | The bulk of the kernel image. +010000 +------------------------+ + | Boot loader | <- Boot sector entry point 0000:7C00 +001000 +------------------------+ + | Reserved for MBR/BIOS | +000800 +------------------------+ + | Typically used by MBR | +000600 +------------------------+ + | BIOS use only | +000000 +------------------------+ + + When using bzImage, the protected-mode kernel was relocated to 0x100000 + ("high memory"), and the kernel real-mode block (boot sector, setup, + and stack/heap) was made relocatable to any address between 0x10000 and + end of low memory. Unfortunately, in protocols 2.00 and 2.01 the + 0x90000+ memory range is still used internally by the kernel; the 2.02 + protocol resolves that problem. + + It is desirable to keep the "memory ceiling" - the highest point in low + memory touched by the boot loader - as low as possible, since some + newer BIOSes have begun to allocate some rather large amounts of + memory, called the Extended BIOS Data Area, near the top of low memory. + The boot loader should use the "INT 12h" BIOS call to verify how much + low memory is available. + + Unfortunately, if INT 12h reports that the amount of memory is too low, + there is usually nothing the boot loader can do but to report an error + to the user. The boot loader should therefore be designed to take up as + little space in low memory as it reasonably can. For zImage or old + bzImage kernels, which need data written into the 0x90000 segment, the + boot loader should make sure not to use memory above the 0x9A000 point; + too many BIOSes will break above that point. + + For a modern bzImage kernel with boot protocol version >= 2.02, a + memory layout like the following is suggested: + ~ ~ + | Protected-mode kernel | + 100000 +------------------------+ + | I/O memory hole | + 0A0000 +------------------------+ + | Reserved for BIOS | Leave as much as possible unused + ~ ~ + | Command line | (Can also be below the X+10000 mar +k) + X+10000 +------------------------+ + | Stack/heap | For use by the kernel real-mode co +de. + X+08000 +------------------------+ + | Kernel setup | The kernel real-mode code. + | Kernel boot sector | The kernel legacy boot sector. + X +------------------------+ + | Boot loader | <- Boot sector entry point 0000:7C +00 + 001000 +------------------------+ + | Reserved for MBR/BIOS | + 000800 +------------------------+ + | Typically used by MBR | + 000600 +------------------------+ + | BIOS use only | + 000000 +------------------------+ + +... where the address X is as low as the design of the boot loader permits. + +1.2. The Real-Mode Kernel Header[88] + + In the following text, and anywhere in the kernel boot sequence, "a + sector" refers to 512 bytes. It is independent of the actual sector + size of the underlying medium. + + The first step in loading a Linux kernel should be to load the + real-mode code (boot sector and setup code) and then examine the + following header at offset 0x01f1. The real-mode code can total up to + 32K, although the boot loader may choose to load only the first two + sectors (1K) and then examine the bootup sector size. + + The header looks like: + + Offset/Size + + Proto + + Name + + Meaning + + 01F1/1 + + ALL(1) + + setup_sects + + The size of the setup in sectors + + 01F2/2 + + ALL + + root_flags + + If set, the root is mounted readonly + + 01F4/4 + + 2.04+(2) + + syssize + + The size of the 32-bit code in 16-byte paras + + 01F8/2 + + ALL + + ram_size + + DO NOT USE - for bootsect.S use only + + 01FA/2 + + ALL + + vid_mode + + Video mode control + + 01FC/2 + + ALL + + root_dev + + Default root device number + + 01FE/2 + + ALL + + boot_flag + + 0xAA55 magic number + + 0200/2 + + 2.00+ + + jump + + Jump instruction + + 0202/4 + + 2.00+ + + header + + Magic signature "HdrS" + + 0206/2 + + 2.00+ + + version + + Boot protocol version supported + + 0208/4 + + 2.00+ + + realmode_swtch + + Boot loader hook (see below) + + 020C/2 + + 2.00+ + + start_sys_seg + + The load-low segment (0x1000) (obsolete) + + 020E/2 + + 2.00+ + + kernel_version + + Pointer to kernel version string + + 0210/1 + + 2.00+ + + type_of_loader + + Boot loader identifier + + 0211/1 + + 2.00+ + + loadflags + + Boot protocol option flags + + 0212/2 + + 2.00+ + + setup_move_size + + Move to high memory size (used with hooks) + + 0214/4 + + 2.00+ + + code32_start + + Boot loader hook (see below) + + 0218/4 + + 2.00+ + + ramdisk_image + + initrd load address (set by boot loader) + + 021C/4 + + 2.00+ + + ramdisk_size + + initrd size (set by boot loader) + + 0220/4 + + 2.00+ + + bootsect_kludge + + DO NOT USE - for bootsect.S use only + + 0224/2 + + 2.01+ + + heap_end_ptr + + Free memory after setup end + + 0226/1 + + 2.02+(3) + + ext_loader_ver + + Extended boot loader version + + 0227/1 + + 2.02+(3) + + ext_loader_type + + Extended boot loader ID + + 0228/4 + + 2.02+ + + cmd_line_ptr + + 32-bit pointer to the kernel command line + + 022C/4 + + 2.03+ + + initrd_addr_max + + Highest legal initrd address + + 0230/4 + + 2.05+ + + kernel_alignment + + Physical addr alignment required for kernel + + 0234/1 + + 2.05+ + + relocatable_kernel + + Whether kernel is relocatable or not + + 0235/1 + + 2.10+ + + min_alignment + + Minimum alignment, as a power of two + + 0236/2 + + 2.12+ + + xloadflags + + Boot protocol option flags + + 0238/4 + + 2.06+ + + cmdline_size + + Maximum size of the kernel command line + + 023C/4 + + 2.07+ + + hardware_subarch + + Hardware subarchitecture + + 0240/8 + + 2.07+ + + hardware_subarch_data + + Subarchitecture-specific data + + 0248/4 + + 2.08+ + + payload_offset + + Offset of kernel payload + + 024C/4 + + 2.08+ + + payload_length + + Length of kernel payload + + 0250/8 + + 2.09+ + + setup_data + + 64-bit physical pointer to linked list of struct setup_data + + 0258/8 + + 2.10+ + + pref_address + + Preferred loading address + + 0260/4 + + 2.10+ + + init_size + + Linear memory required during initialization + + 0264/4 + + 2.11+ + + handover_offset + + Offset of handover entry point + + 0268/4 + + 2.15+ + + kernel_info_offset + + Offset of the kernel_info + + Note + 1. For backwards compatibility, if the setup_sects field contains 0, + the real value is 4. + 2. For boot protocol prior to 2.04, the upper two bytes of the syssize + field are unusable, which means the size of a bzImage kernel cannot + be determined. + 3. Ignored, but safe to set, for boot protocols 2.02-2.09. + + If the "HdrS" (0x53726448) magic number is not found at offset 0x202, + the boot protocol version is "old". Loading an old kernel, the + following parameters should be assumed: +Image type = zImage +initrd not supported +Real-mode kernel must be located at 0x90000. + + Otherwise, the "version" field contains the protocol version, e.g. + protocol version 2.01 will contain 0x0201 in this field. When setting + fields in the header, you must make sure only to set fields supported + by the protocol version in use. + +1.3. Details of Header Fields[89] + + For each field, some are information from the kernel to the bootloader + ("read"), some are expected to be filled out by the bootloader + ("write"), and some are expected to be read and modified by the + bootloader ("modify"). + + All general purpose boot loaders should write the fields marked + (obligatory). Boot loaders who want to load the kernel at a nonstandard + address should fill in the fields marked (reloc); other boot loaders + can ignore those fields. + + The byte order of all fields is littleendian (this is x86, after all.) + + Field name: + + setup_sects + + Type: + + read + + Offset/size: + + 0x1f1/1 + + Protocol: + + ALL + + The size of the setup code in 512-byte sectors. If this field is 0, the + real value is 4. The real-mode code consists of the boot sector (always + one 512-byte sector) plus the setup code. + + Field name: + + root_flags + + Type: + + modify (optional) + + Offset/size: + + 0x1f2/2 + + Protocol: + + ALL + + If this field is nonzero, the root defaults to readonly. The use of + this field is deprecated; use the "ro" or "rw" options on the command + line instead. + + Field name: + + syssize + + Type: + + read + + Offset/size: + + 0x1f4/4 (protocol 2.04+) 0x1f4/2 (protocol ALL) + + Protocol: + + 2.04+ + + The size of the protected-mode code in units of 16-byte paragraphs. For + protocol versions older than 2.04 this field is only two bytes wide, + and therefore cannot be trusted for the size of a kernel if the + LOAD_HIGH flag is set. + + Field name: + + ram_size + + Type: + + kernel internal + + Offset/size: + + 0x1f8/2 + + Protocol: + + ALL + + This field is obsolete. + + Field name: + + vid_mode + + Type: + + modify (obligatory) + + Offset/size: + + 0x1fa/2 + + Please see the section on SPECIAL COMMAND LINE OPTIONS. + + Field name: + + root_dev + + Type: + + modify (optional) + + Offset/size: + + 0x1fc/2 + + Protocol: + + ALL + + The default root device device number. The use of this field is + deprecated, use the "root=" option on the command line instead. + + Field name: + + boot_flag + + Type: + + read + + Offset/size: + + 0x1fe/2 + + Protocol: + + ALL + + Contains 0xAA55. This is the closest thing old Linux kernels have to a + magic number. + + Field name: + + jump + + Type: + + read + + Offset/size: + + 0x200/2 + + Protocol: + + 2.00+ + + Contains an x86 jump instruction, 0xEB followed by a signed offset + relative to byte 0x202. This can be used to determine the size of the + header. + + Field name: + + header + + Type: + + read + + Offset/size: + + 0x202/4 + + Protocol: + + 2.00+ + + Contains the magic number "HdrS" (0x53726448). + + Field name: + + version + + Type: + + read + + Offset/size: + + 0x206/2 + + Protocol: + + 2.00+ + + Contains the boot protocol version, in (major << 8)+minor format, e.g. + 0x0204 for version 2.04, and 0x0a11 for a hypothetical version 10.17. + + Field name: + + realmode_swtch + + Type: + + modify (optional) + + Offset/size: + + 0x208/4 + + Protocol: + + 2.00+ + + Boot loader hook (see ADVANCED BOOT LOADER HOOKS below.) + + Field name: + + start_sys_seg + + Type: + + read + + Offset/size: + + 0x20c/2 + + Protocol: + + 2.00+ + + The load low segment (0x1000). Obsolete. + + Field name: + + kernel_version + + Type: + + read + + Offset/size: + + 0x20e/2 + + Protocol: + + 2.00+ + + If set to a nonzero value, contains a pointer to a NUL-terminated + human-readable kernel version number string, less 0x200. This can be + used to display the kernel version to the user. This value should be + less than (0x200*setup_sects). + + For example, if this value is set to 0x1c00, the kernel version number + string can be found at offset 0x1e00 in the kernel file. This is a + valid value if and only if the "setup_sects" field contains the value + 15 or higher, as: +0x1c00 < 15*0x200 (= 0x1e00) but +0x1c00 >= 14*0x200 (= 0x1c00) + +0x1c00 >> 9 = 14, So the minimum value for setup_secs is 15. + + Field name: + + type_of_loader + + Type: + + write (obligatory) + + Offset/size: + + 0x210/1 + + Protocol: + + 2.00+ + + If your boot loader has an assigned id (see table below), enter 0xTV + here, where T is an identifier for the boot loader and V is a version + number. Otherwise, enter 0xFF here. + + For boot loader IDs above T = 0xD, write T = 0xE to this field and + write the extended ID minus 0x10 to the ext_loader_type field. + Similarly, the ext_loader_ver field can be used to provide more than + four bits for the bootloader version. + + For example, for T = 0x15, V = 0x234, write: +type_of_loader <- 0xE4 +ext_loader_type <- 0x05 +ext_loader_ver <- 0x23 + + Assigned boot loader ids (hexadecimal): + + 0 + + LILO (0x00 reserved for pre-2.00 bootloader) + + 1 + + Loadlin + + 2 + + bootsect-loader (0x20, all other values reserved) + + 3 + + Syslinux + + 4 + + Etherboot/gPXE/iPXE + + 5 + + ELILO + + 7 + + GRUB + + 8 + + U-Boot + + 9 + + Xen + + A + + Gujin + + B + + Qemu + + C + + Arcturus Networks uCbootloader + + D + + kexec-tools + + E + + Extended (see ext_loader_type) + + F + + Special (0xFF = undefined) + + 10 + + Reserved + + 11 + + Minimal Linux Bootloader <[90]http://sebastian-plotz.blogspot.de> + + 12 + + OVMF UEFI virtualization stack + + 13 + + barebox + + Please contact <[91]hpa@zytor.com> if you need a bootloader ID value + assigned. + + Field name: + + loadflags + + Type: + + modify (obligatory) + + Offset/size: + + 0x211/1 + + Protocol: + + 2.00+ + + This field is a bitmask. + + Bit 0 (read): LOADED_HIGH + + * If 0, the protected-mode code is loaded at 0x10000. + * If 1, the protected-mode code is loaded at 0x100000. + + Bit 1 (kernel internal): KASLR_FLAG + + * Used internally by the compressed kernel to communicate KASLR + status to kernel proper. + + + If 1, KASLR enabled. + + If 0, KASLR disabled. + + Bit 5 (write): QUIET_FLAG + + * If 0, print early messages. + * If 1, suppress early messages. + + This requests to the kernel (decompressor and early kernel) to not + write early messages that require accessing the display hardware + directly. + + Bit 6 (obsolete): KEEP_SEGMENTS + + Protocol: 2.07+ + * This flag is obsolete. + + Bit 7 (write): CAN_USE_HEAP + + Set this bit to 1 to indicate that the value entered in the + heap_end_ptr is valid. If this field is clear, some setup code + functionality will be disabled. + + Field name: + + setup_move_size + + Type: + + modify (obligatory) + + Offset/size: + + 0x212/2 + + Protocol: + + 2.00-2.01 + + When using protocol 2.00 or 2.01, if the real mode kernel is not loaded + at 0x90000, it gets moved there later in the loading sequence. Fill in + this field if you want additional data (such as the kernel command + line) moved in addition to the real-mode kernel itself. + + The unit is bytes starting with the beginning of the boot sector. + + This field is can be ignored when the protocol is 2.02 or higher, or if + the real-mode code is loaded at 0x90000. + + Field name: + + code32_start + + Type: + + modify (optional, reloc) + + Offset/size: + + 0x214/4 + + Protocol: + + 2.00+ + + The address to jump to in protected mode. This defaults to the load + address of the kernel, and can be used by the boot loader to determine + the proper load address. + + This field can be modified for two purposes: + + 1. as a boot loader hook (see Advanced Boot Loader Hooks below.) + 2. if a bootloader which does not install a hook loads a relocatable + kernel at a nonstandard address it will have to modify this field + to point to the load address. + + Field name: + + ramdisk_image + + Type: + + write (obligatory) + + Offset/size: + + 0x218/4 + + Protocol: + + 2.00+ + + The 32-bit linear address of the initial ramdisk or ramfs. Leave at + zero if there is no initial ramdisk/ramfs. + + Field name: + + ramdisk_size + + Type: + + write (obligatory) + + Offset/size: + + 0x21c/4 + + Protocol: + + 2.00+ + + Size of the initial ramdisk or ramfs. Leave at zero if there is no + initial ramdisk/ramfs. + + Field name: + + bootsect_kludge + + Type: + + kernel internal + + Offset/size: + + 0x220/4 + + Protocol: + + 2.00+ + + This field is obsolete. + + Field name: + + heap_end_ptr + + Type: + + write (obligatory) + + Offset/size: + + 0x224/2 + + Protocol: + + 2.01+ + + Set this field to the offset (from the beginning of the real-mode code) + of the end of the setup stack/heap, minus 0x0200. + + Field name: + + ext_loader_ver + + Type: + + write (optional) + + Offset/size: + + 0x226/1 + + Protocol: + + 2.02+ + + This field is used as an extension of the version number in the + type_of_loader field. The total version number is considered to be + (type_of_loader & 0x0f) + (ext_loader_ver << 4). + + The use of this field is boot loader specific. If not written, it is + zero. + + Kernels prior to 2.6.31 did not recognize this field, but it is safe to + write for protocol version 2.02 or higher. + + Field name: + + ext_loader_type + + Type: + + write (obligatory if (type_of_loader & 0xf0) == 0xe0) + + Offset/size: + + 0x227/1 + + Protocol: + + 2.02+ + + This field is used as an extension of the type number in type_of_loader + field. If the type in type_of_loader is 0xE, then the actual type is + (ext_loader_type + 0x10). + + This field is ignored if the type in type_of_loader is not 0xE. + + Kernels prior to 2.6.31 did not recognize this field, but it is safe to + write for protocol version 2.02 or higher. + + Field name: + + cmd_line_ptr + + Type: + + write (obligatory) + + Offset/size: + + 0x228/4 + + Protocol: + + 2.02+ + + Set this field to the linear address of the kernel command line. The + kernel command line can be located anywhere between the end of the + setup heap and 0xA0000; it does not have to be located in the same 64K + segment as the real-mode code itself. + + Fill in this field even if your boot loader does not support a command + line, in which case you can point this to an empty string (or better + yet, to the string "auto".) If this field is left at zero, the kernel + will assume that your boot loader does not support the 2.02+ protocol. + + Field name: + + initrd_addr_max + + Type: + + read + + Offset/size: + + 0x22c/4 + + Protocol: + + 2.03+ + + The maximum address that may be occupied by the initial ramdisk/ramfs + contents. For boot protocols 2.02 or earlier, this field is not + present, and the maximum address is 0x37FFFFFF. (This address is + defined as the address of the highest safe byte, so if your ramdisk is + exactly 131072 bytes long and this field is 0x37FFFFFF, you can start + your ramdisk at 0x37FE0000.) + + Field name: + + kernel_alignment + + Type: + + read/modify (reloc) + + Offset/size: + + 0x230/4 + + Protocol: + + 2.05+ (read), 2.10+ (modify) + + Alignment unit required by the kernel (if relocatable_kernel is true.) + A relocatable kernel that is loaded at an alignment incompatible with + the value in this field will be realigned during kernel initialization. + + Starting with protocol version 2.10, this reflects the kernel alignment + preferred for optimal performance; it is possible for the loader to + modify this field to permit a lesser alignment. See the min_alignment + and pref_address field below. + + Field name: + + relocatable_kernel + + Type: + + read (reloc) + + Offset/size: + + 0x234/1 + + Protocol: + + 2.05+ + + If this field is nonzero, the protected-mode part of the kernel can be + loaded at any address that satisfies the kernel_alignment field. After + loading, the boot loader must set the code32_start field to point to + the loaded code, or to a boot loader hook. + + Field name: + + min_alignment + + Type: + + read (reloc) + + Offset/size: + + 0x235/1 + + Protocol: + + 2.10+ + + This field, if nonzero, indicates as a power of two the minimum + alignment required, as opposed to preferred, by the kernel to boot. If + a boot loader makes use of this field, it should update the + kernel_alignment field with the alignment unit desired; typically: +kernel_alignment = 1 << min_alignment + + There may be a considerable performance cost with an excessively + misaligned kernel. Therefore, a loader should typically try each + power-of-two alignment from kernel_alignment down to this alignment. + + Field name: + + xloadflags + + Type: + + read + + Offset/size: + + 0x236/2 + + Protocol: + + 2.12+ + + This field is a bitmask. + + Bit 0 (read): XLF_KERNEL_64 + + * If 1, this kernel has the legacy 64-bit entry point at 0x200. + + Bit 1 (read): XLF_CAN_BE_LOADED_ABOVE_4G + + * If 1, kernel/boot_params/cmdline/ramdisk can be above 4G. + + Bit 2 (read): XLF_EFI_HANDOVER_32 + + * If 1, the kernel supports the 32-bit EFI handoff entry point given + at handover_offset. + + Bit 3 (read): XLF_EFI_HANDOVER_64 + + * If 1, the kernel supports the 64-bit EFI handoff entry point given + at handover_offset + 0x200. + + Bit 4 (read): XLF_EFI_KEXEC + + * If 1, the kernel supports kexec EFI boot with EFI runtime support. + + Field name: + + cmdline_size + + Type: + + read + + Offset/size: + + 0x238/4 + + Protocol: + + 2.06+ + + The maximum size of the command line without the terminating zero. This + means that the command line can contain at most cmdline_size + characters. With protocol version 2.05 and earlier, the maximum size + was 255. + + Field name: + + hardware_subarch + + Type: + + write (optional, defaults to x86/PC) + + Offset/size: + + 0x23c/4 + + Protocol: + + 2.07+ + + In a paravirtualized environment the hardware low level architectural + pieces such as interrupt handling, page table handling, and accessing + process control registers needs to be done differently. + + This field allows the bootloader to inform the kernel we are in one one + of those environments. + + 0x00000000 + + The default x86/PC environment + + 0x00000001 + + lguest + + 0x00000002 + + Xen + + 0x00000003 + + Moorestown MID + + 0x00000004 + + CE4100 TV Platform + + Field name: + + hardware_subarch_data + + Type: + + write (subarch-dependent) + + Offset/size: + + 0x240/8 + + Protocol: + + 2.07+ + + A pointer to data that is specific to hardware subarch This field is + currently unused for the default x86/PC environment, do not modify. + + Field name: + + payload_offset + + Type: + + read + + Offset/size: + + 0x248/4 + + Protocol: + + 2.08+ + + If non-zero then this field contains the offset from the beginning of + the protected-mode code to the payload. + + The payload may be compressed. The format of both the compressed and + uncompressed data should be determined using the standard magic + numbers. The currently supported compression formats are gzip (magic + numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A), LZMA (magic number + 5D 00), XZ (magic number FD 37), LZ4 (magic number 02 21) and ZSTD + (magic number 28 B5). The uncompressed payload is currently always ELF + (magic number 7F 45 4C 46). + + Field name: + + payload_length + + Type: + + read + + Offset/size: + + 0x24c/4 + + Protocol: + + 2.08+ + + The length of the payload. + + Field name: + + setup_data + + Type: + + write (special) + + Offset/size: + + 0x250/8 + + Protocol: + + 2.09+ + + The 64-bit physical pointer to NULL terminated single linked list of + struct setup_data. This is used to define a more extensible boot + parameters passing mechanism. The definition of struct setup_data is as + follow: +struct setup_data { + u64 next; + u32 type; + u32 len; + u8 data[0]; +}; + + Where, the next is a 64-bit physical pointer to the next node of linked + list, the next field of the last node is 0; the type is used to + identify the contents of data; the len is the length of data field; the + data holds the real payload. + + This list may be modified at a number of points during the bootup + process. Therefore, when modifying this list one should always make + sure to consider the case where the linked list already contains + entries. + + The setup_data is a bit awkward to use for extremely large data + objects, both because the setup_data header has to be adjacent to the + data object and because it has a 32-bit length field. However, it is + important that intermediate stages of the boot process have a way to + identify which chunks of memory are occupied by kernel data. + + Thus setup_indirect struct and SETUP_INDIRECT type were introduced in + protocol 2.15: +struct setup_indirect { + __u32 type; + __u32 reserved; /* Reserved, must be set to zero. */ + __u64 len; + __u64 addr; +}; + + The type member is a SETUP_INDIRECT | SETUP_* type. However, it cannot + be SETUP_INDIRECT itself since making the setup_indirect a tree + structure could require a lot of stack space in something that needs to + parse it and stack space can be limited in boot contexts. + + Let's give an example how to point to SETUP_E820_EXT data using + setup_indirect. In this case setup_data and setup_indirect will look + like this: +struct setup_data { + __u64 next = 0 or ; + __u32 type = SETUP_INDIRECT; + __u32 len = sizeof(setup_indirect); + __u8 data[sizeof(setup_indirect)] = struct setup_indirect { + __u32 type = SETUP_INDIRECT | SETUP_E820_EXT; + __u32 reserved = 0; + __u64 len = ; + __u64 addr = ; + } +} + + Note + + SETUP_INDIRECT | SETUP_NONE objects cannot be properly distinguished + from SETUP_INDIRECT itself. So, this kind of objects cannot be provided + by the bootloaders. + + Field name: + + pref_address + + Type: + + read (reloc) + + Offset/size: + + 0x258/8 + + Protocol: + + 2.10+ + + This field, if nonzero, represents a preferred load address for the + kernel. A relocating bootloader should attempt to load at this address + if possible. + + A non-relocatable kernel will unconditionally move itself and to run at + this address. + + Field name: + + init_size + + Type: + + read + + Offset/size: + + 0x260/4 + + This field indicates the amount of linear contiguous memory starting at + the kernel runtime start address that the kernel needs before it is + capable of examining its memory map. This is not the same thing as the + total amount of memory the kernel needs to boot, but it can be used by + a relocating boot loader to help select a safe load address for the + kernel. + + The kernel runtime start address is determined by the following + algorithm: +if (relocatable_kernel) +runtime_start = align_up(load_address, kernel_alignment) +else +runtime_start = pref_address + + Field name: + + handover_offset + + Type: + + read + + Offset/size: + + 0x264/4 + + This field is the offset from the beginning of the kernel image to the + EFI handover protocol entry point. Boot loaders using the EFI handover + protocol to boot the kernel should jump to this offset. + + See EFI HANDOVER PROTOCOL below for more details. + + Field name: + + kernel_info_offset + + Type: + + read + + Offset/size: + + 0x268/4 + + Protocol: + + 2.15+ + + This field is the offset from the beginning of the kernel image to the + kernel_info. The kernel_info structure is embedded in the Linux image + in the uncompressed protected mode region. + +1.4. The kernel_info[92] + + The relationships between the headers are analogous to the various data + sections: + + setup_header = .data boot_params/setup_data = .bss + + What is missing from the above list? That's right: + + kernel_info = .rodata + + We have been (ab)using .data for things that could go into .rodata or + .bss for a long time, for lack of alternatives and - especially early + on - inertia. Also, the BIOS stub is responsible for creating + boot_params, so it isn't available to a BIOS-based loader (setup_data + is, though). + + setup_header is permanently limited to 144 bytes due to the reach of + the 2-byte jump field, which doubles as a length field for the + structure, combined with the size of the "hole" in struct boot_params + that a protected-mode loader or the BIOS stub has to copy it into. It + is currently 119 bytes long, which leaves us with 25 very precious + bytes. This isn't something that can be fixed without revising the boot + protocol entirely, breaking backwards compatibility. + + boot_params proper is limited to 4096 bytes, but can be arbitrarily + extended by adding setup_data entries. It cannot be used to communicate + properties of the kernel image, because it is .bss and has no + image-provided content. + + kernel_info solves this by providing an extensible place for + information about the kernel image. It is readonly, because the kernel + cannot rely on a bootloader copying its contents anywhere, but that is + OK; if it becomes necessary it can still contain data items that an + enabled bootloader would be expected to copy into a setup_data chunk. + + All kernel_info data should be part of this structure. Fixed size data + have to be put before kernel_info_var_len_data label. Variable size + data have to be put after kernel_info_var_len_data label. Each chunk of + variable size data has to be prefixed with header/magic and its size, + e.g.: +kernel_info: + .ascii "LToP" /* Header, Linux top (structure). */ + .long kernel_info_var_len_data - kernel_info + .long kernel_info_end - kernel_info + .long 0x01234567 /* Some fixed size data for the bootloaders. */ +kernel_info_var_len_data: +example_struct: /* Some variable size data for the bootloaders. +*/ + .ascii "0123" /* Header/Magic. */ + .long example_struct_end - example_struct + .ascii "Struct" + .long 0x89012345 +example_struct_end: +example_strings: /* Some variable size data for the bootloaders. +*/ + .ascii "ABCD" /* Header/Magic. */ + .long example_strings_end - example_strings + .asciz "String_0" + .asciz "String_1" +example_strings_end: +kernel_info_end: + + This way the kernel_info is self-contained blob. + + Note + + Each variable size data header/magic can be any 4-character string, + without 0 at the end of the string, which does not collide with + existing variable length data headers/magics. + +1.5. Details of the kernel_info Fields[93] + + Field name: + + header + + Offset/size: + + 0x0000/4 + + Contains the magic number "LToP" (0x506f544c). + + Field name: + + size + + Offset/size: + + 0x0004/4 + + This field contains the size of the kernel_info including + kernel_info.header. It does not count + kernel_info.kernel_info_var_len_data size. This field should be used by + the bootloaders to detect supported fixed size fields in the + kernel_info and beginning of kernel_info.kernel_info_var_len_data. + + Field name: + + size_total + + Offset/size: + + 0x0008/4 + + This field contains the size of the kernel_info including + kernel_info.header and kernel_info.kernel_info_var_len_data. + + Field name: + + setup_type_max + + Offset/size: + + 0x000c/4 + + This field contains maximal allowed type for setup_data and + setup_indirect structs. + +1.6. The Image Checksum[94] + + From boot protocol version 2.08 onwards the CRC-32 is calculated over + the entire file using the characteristic polynomial 0x04C11DB7 and an + initial remainder of 0xffffffff. The checksum is appended to the file; + therefore the CRC of the file up to the limit specified in the syssize + field of the header is always 0. + +1.7. The Kernel Command Line[95] + + The kernel command line has become an important way for the boot loader + to communicate with the kernel. Some of its options are also relevant + to the boot loader itself, see "special command line options" below. + + The kernel command line is a null-terminated string. The maximum length + can be retrieved from the field cmdline_size. Before protocol version + 2.06, the maximum was 255 characters. A string that is too long will be + automatically truncated by the kernel. + + If the boot protocol version is 2.02 or later, the address of the + kernel command line is given by the header field cmd_line_ptr (see + above.) This address can be anywhere between the end of the setup heap + and 0xA0000. + + If the protocol version is not 2.02 or higher, the kernel command line + is entered using the following protocol: + + * At offset 0x0020 (word), "cmd_line_magic", enter the magic number + 0xA33F. + * At offset 0x0022 (word), "cmd_line_offset", enter the offset of the + kernel command line (relative to the start of the real-mode + kernel). + * The kernel command line must be within the memory region covered by + setup_move_size, so you may need to adjust this field. + +1.8. Memory Layout of The Real-Mode Code[96] + + The real-mode code requires a stack/heap to be set up, as well as + memory allocated for the kernel command line. This needs to be done in + the real-mode accessible memory in bottom megabyte. + + It should be noted that modern machines often have a sizable Extended + BIOS Data Area (EBDA). As a result, it is advisable to use as little of + the low megabyte as possible. + + Unfortunately, under the following circumstances the 0x90000 memory + segment has to be used: + + * When loading a zImage kernel ((loadflags & 0x01) == 0). + * When loading a 2.01 or earlier boot protocol kernel. + + Note + + For the 2.00 and 2.01 boot protocols, the real-mode code can be loaded + at another address, but it is internally relocated to 0x90000. For the + "old" protocol, the real-mode code must be loaded at 0x90000. + + When loading at 0x90000, avoid using memory above 0x9a000. + + For boot protocol 2.02 or higher, the command line does not have to be + located in the same 64K segment as the real-mode setup code; it is thus + permitted to give the stack/heap the full 64K segment and locate the + command line above it. + + The kernel command line should not be located below the real-mode code, + nor should it be located in high memory. + +1.9. Sample Boot Configuartion[97] + + As a sample configuration, assume the following layout of the real mode + segment. + + When loading below 0x90000, use the entire segment: + + 0x0000-0x7fff + + Real mode kernel + + 0x8000-0xdfff + + Stack and heap + + 0xe000-0xffff + + Kernel command line + + When loading at 0x90000 OR the protocol version is 2.01 or earlier: + + 0x0000-0x7fff + + Real mode kernel + + 0x8000-0x97ff + + Stack and heap + + 0x9800-0x9fff + + Kernel command line + + Such a boot loader should enter the following fields in the header: +unsigned long base_ptr; /* base address for real-mode segment */ + +if ( setup_sects == 0 ) { + setup_sects = 4; +} + +if ( protocol >= 0x0200 ) { + type_of_loader = ; + if ( loading_initrd ) { + ramdisk_image = ; + ramdisk_size = ; + } + + if ( protocol >= 0x0202 && loadflags & 0x01 ) + heap_end = 0xe000; + else + heap_end = 0x9800; + + if ( protocol >= 0x0201 ) { + heap_end_ptr = heap_end - 0x200; + loadflags |= 0x80; /* CAN_USE_HEAP */ + } + + if ( protocol >= 0x0202 ) { + cmd_line_ptr = base_ptr + heap_end; + strcpy(cmd_line_ptr, cmdline); + } else { + cmd_line_magic = 0xA33F; + cmd_line_offset = heap_end; + setup_move_size = heap_end + strlen(cmdline)+1; + strcpy(base_ptr+cmd_line_offset, cmdline); + } +} else { + /* Very old kernel */ + + heap_end = 0x9800; + + cmd_line_magic = 0xA33F; + cmd_line_offset = heap_end; + + /* A very old kernel MUST have its real-mode code + loaded at 0x90000 */ + + if ( base_ptr != 0x90000 ) { + /* Copy the real-mode kernel */ + memcpy(0x90000, base_ptr, (setup_sects+1)*512); + base_ptr = 0x90000; /* Relocated */ + } + + strcpy(0x90000+cmd_line_offset, cmdline); + + /* It is recommended to clear memory up to the 32K mark */ + memset(0x90000 + (setup_sects+1)*512, 0, + (64-(setup_sects+1))*512); +} + +1.10. Loading The Rest of The Kernel[98] + + The 32-bit (non-real-mode) kernel starts at offset (setup_sects+1)*512 + in the kernel file (again, if setup_sects == 0 the real value is 4.) It + should be loaded at address 0x10000 for Image/zImage kernels and + 0x100000 for bzImage kernels. + + The kernel is a bzImage kernel if the protocol >= 2.00 and the 0x01 bit + (LOAD_HIGH) in the loadflags field is set: +is_bzImage = (protocol >= 0x0200) && (loadflags & 0x01); +load_address = is_bzImage ? 0x100000 : 0x10000; + + Note that Image/zImage kernels can be up to 512K in size, and thus use + the entire 0x10000-0x90000 range of memory. This means it is pretty + much a requirement for these kernels to load the real-mode part at + 0x90000. bzImage kernels allow much more flexibility. + +1.11. Special Command Line Options[99] + + If the command line provided by the boot loader is entered by the user, + the user may expect the following command line options to work. They + should normally not be deleted from the kernel command line even though + not all of them are actually meaningful to the kernel. Boot loader + authors who need additional command line options for the boot loader + itself should get them registered in [100]The kernel's command-line + parameters to make sure they will not conflict with actual kernel + options now or in the future. + + vga= + here is either an integer (in C notation, either decimal, + octal, or hexadecimal) or one of the strings "normal" (meaning + 0xFFFF), "ext" (meaning 0xFFFE) or "ask" (meaning 0xFFFD). This + value should be entered into the vid_mode field, as it is used + by the kernel before the command line is parsed. + + mem= + is an integer in C notation optionally followed by (case + insensitive) K, M, G, T, P or E (meaning << 10, << 20, << 30, << + 40, << 50 or << 60). This specifies the end of memory to the + kernel. This affects the possible placement of an initrd, since + an initrd should be placed near end of memory. Note that this is + an option to both the kernel and the bootloader! + + initrd= + An initrd should be loaded. The meaning of is obviously + bootloader-dependent, and some boot loaders (e.g. LILO) do not + have such a command. + + In addition, some boot loaders add the following options to the + user-specified command line: + + BOOT_IMAGE= + The boot image which was loaded. Again, the meaning of is + obviously bootloader-dependent. + + auto + The kernel was booted without explicit user intervention. + + If these options are added by the boot loader, it is highly recommended + that they are located first, before the user-specified or + configuration-specified command line. Otherwise, "init=/bin/sh" gets + confused by the "auto" option. + +1.12. Running the Kernel[101] + + The kernel is started by jumping to the kernel entry point, which is + located at segment offset 0x20 from the start of the real mode kernel. + This means that if you loaded your real-mode kernel code at 0x90000, + the kernel entry point is 9020:0000. + + At entry, ds = es = ss should point to the start of the real-mode + kernel code (0x9000 if the code is loaded at 0x90000), sp should be set + up properly, normally pointing to the top of the heap, and interrupts + should be disabled. Furthermore, to guard against bugs in the kernel, + it is recommended that the boot loader sets fs = gs = ds = es = ss. + + In our example from above, we would do: +/* Note: in the case of the "old" kernel protocol, base_ptr must + be == 0x90000 at this point; see the previous sample code */ + +seg = base_ptr >> 4; + +cli(); /* Enter with interrupts disabled! */ + +/* Set up the real-mode kernel stack */ +_SS = seg; +_SP = heap_end; + +_DS = _ES = _FS = _GS = seg; +jmp_far(seg+0x20, 0); /* Run the kernel */ + + If your boot sector accesses a floppy drive, it is recommended to + switch off the floppy motor before running the kernel, since the kernel + boot leaves interrupts off and thus the motor will not be switched off, + especially if the loaded kernel has the floppy driver as a + demand-loaded module! + +1.13. Advanced Boot Loader Hooks[102] + + If the boot loader runs in a particularly hostile environment (such as + LOADLIN, which runs under DOS) it may be impossible to follow the + standard memory location requirements. Such a boot loader may use the + following hooks that, if set, are invoked by the kernel at the + appropriate time. The use of these hooks should probably be considered + an absolutely last resort! + + IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and + %edi across invocation. + + realmode_swtch: + A 16-bit real mode far subroutine invoked immediately before + entering protected mode. The default routine disables NMI, so + your routine should probably do so, too. + + code32_start: + A 32-bit flat-mode routine jumped to immediately after the + transition to protected mode, but before the kernel is + uncompressed. No segments, except CS, are guaranteed to be set + up (current kernels do, but older ones do not); you should set + them up to BOOT_DS (0x18) yourself. + + After completing your hook, you should jump to the address that + was in this field before your boot loader overwrote it + (relocated, if appropriate.) + +1.14. 32-bit Boot Protocol[103] + + For machine with some new BIOS other than legacy BIOS, such as EFI, + LinuxBIOS, etc, and kexec, the 16-bit real mode setup code in kernel + based on legacy BIOS can not be used, so a 32-bit boot protocol needs + to be defined. + + In 32-bit boot protocol, the first step in loading a Linux kernel + should be to setup the boot parameters (struct boot_params, + traditionally known as "zero page"). The memory for struct boot_params + should be allocated and initialized to all zero. Then the setup header + from offset 0x01f1 of kernel image on should be loaded into struct + boot_params and examined. The end of setup header can be calculated as + follow: +0x0202 + byte value at offset 0x0201 + + In addition to read/modify/write the setup header of the struct + boot_params as that of 16-bit boot protocol, the boot loader should + also fill the additional fields of the struct boot_params as described + in chapter [104]Zero Page. + + After setting up the struct boot_params, the boot loader can load the + 32/64-bit kernel in the same way as that of 16-bit boot protocol. + + In 32-bit boot protocol, the kernel is started by jumping to the 32-bit + kernel entry point, which is the start address of loaded 32/64-bit + kernel. + + At entry, the CPU must be in 32-bit protected mode with paging + disabled; a GDT must be loaded with the descriptors for selectors + __BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G flat + segment; __BOOT_CS must have execute/read permission, and __BOOT_DS + must have read/write permission; CS must be __BOOT_CS and DS, ES, SS + must be __BOOT_DS; interrupt must be disabled; %esi must hold the base + address of the struct boot_params; %ebp, %edi and %ebx must be zero. + +1.15. 64-bit Boot Protocol[105] + + For machine with 64bit cpus and 64bit kernel, we could use 64bit + bootloader and we need a 64-bit boot protocol. + + In 64-bit boot protocol, the first step in loading a Linux kernel + should be to setup the boot parameters (struct boot_params, + traditionally known as "zero page"). The memory for struct boot_params + could be allocated anywhere (even above 4G) and initialized to all + zero. Then, the setup header at offset 0x01f1 of kernel image on should + be loaded into struct boot_params and examined. The end of setup header + can be calculated as follows: +0x0202 + byte value at offset 0x0201 + + In addition to read/modify/write the setup header of the struct + boot_params as that of 16-bit boot protocol, the boot loader should + also fill the additional fields of the struct boot_params as described + in chapter [106]Zero Page. + + After setting up the struct boot_params, the boot loader can load + 64-bit kernel in the same way as that of 16-bit boot protocol, but + kernel could be loaded above 4G. + + In 64-bit boot protocol, the kernel is started by jumping to the 64-bit + kernel entry point, which is the start address of loaded 64-bit kernel + plus 0x200. + + At entry, the CPU must be in 64-bit mode with paging enabled. The range + with setup_header.init_size from start address of loaded kernel and + zero page and command line buffer get ident mapping; a GDT must be + loaded with the descriptors for selectors __BOOT_CS(0x10) and + __BOOT_DS(0x18); both descriptors must be 4G flat segment; __BOOT_CS + must have execute/read permission, and __BOOT_DS must have read/write + permission; CS must be __BOOT_CS and DS, ES, SS must be __BOOT_DS; + interrupt must be disabled; %rsi must hold the base address of the + struct boot_params. + +1.16. EFI Handover Protocol (deprecated)[107] + + This protocol allows boot loaders to defer initialisation to the EFI + boot stub. The boot loader is required to load the kernel/initrd(s) + from the boot media and jump to the EFI handover protocol entry point + which is hdr->handover_offset bytes from the beginning of + startup_{32,64}. + + The boot loader MUST respect the kernel's PE/COFF metadata when it + comes to section alignment, the memory footprint of the executable + image beyond the size of the file itself, and any other aspect of the + PE/COFF header that may affect correct operation of the image as a + PE/COFF binary in the execution context provided by the EFI firmware. + + The function prototype for the handover entry point looks like this: +efi_main(void *handle, efi_system_table_t *table, struct boot_params *bp) + + `handle' is the EFI image handle passed to the boot loader by the EFI + firmware, `table' is the EFI system table - these are the first two + arguments of the "handoff state" as described in section 2.3 of the + UEFI specification. `bp' is the boot loader-allocated boot params. + + The boot loader must fill out the following fields in bp: +- hdr.cmd_line_ptr +- hdr.ramdisk_image (if applicable) +- hdr.ramdisk_size (if applicable) + + All other fields should be zero. + + NOTE: The EFI Handover Protocol is deprecated in favour of the ordinary + PE/COFF + entry point, combined with the LINUX_EFI_INITRD_MEDIA_GUID based + initrd loading protocol (refer to [0] for an example of the + bootloader side of this), which removes the need for any + knowledge on the part of the EFI bootloader regarding the + internal representation of boot_params or any + requirements/limitations regarding the placement of the command + line and ramdisk in memory, or the placement of the kernel image + itself. + + [0] + [108]https://github.com/u-boot/u-boot/commit/ec80b4735a593961fe701cc3a5 + d717d4739b0fd0 + + The kernel development community. | Powered by [109]Sphinx 5.0.1 & + [110]Alabaster 0.7.12 | [111]Page source + +References + + 1. https://www.kernel.org/doc/html/latest/genindex.html + 2. https://www.kernel.org/doc/html/latest/search.html + 3. https://www.kernel.org/doc/html/latest/x86/booting-dt.html + 4. https://www.kernel.org/doc/html/latest/x86/index.html + 5. https://www.kernel.org/doc/html/latest/index.html + 6. https://www.kernel.org/doc/html/latest/process/development-process.html + 7. https://www.kernel.org/doc/html/latest/process/submitting-patches.html + 8. https://www.kernel.org/doc/html/latest/process/code-of-conduct.html + 9. https://www.kernel.org/doc/html/latest/maintainer/index.html + 10. https://www.kernel.org/doc/html/latest/process/index.html + 11. https://www.kernel.org/doc/html/latest/core-api/index.html + 12. https://www.kernel.org/doc/html/latest/driver-api/index.html + 13. https://www.kernel.org/doc/html/latest/subsystem-apis.html + 14. https://www.kernel.org/doc/html/latest/locking/index.html + 15. https://www.kernel.org/doc/html/latest/process/license-rules.html + 16. https://www.kernel.org/doc/html/latest/doc-guide/index.html + 17. https://www.kernel.org/doc/html/latest/dev-tools/index.html + 18. https://www.kernel.org/doc/html/latest/dev-tools/testing-overview.html + 19. https://www.kernel.org/doc/html/latest/kernel-hacking/index.html + 20. https://www.kernel.org/doc/html/latest/trace/index.html + 21. https://www.kernel.org/doc/html/latest/fault-injection/index.html + 22. https://www.kernel.org/doc/html/latest/livepatch/index.html + 23. https://www.kernel.org/doc/html/latest/rust/index.html + 24. https://www.kernel.org/doc/html/latest/admin-guide/index.html + 25. https://www.kernel.org/doc/html/latest/kbuild/index.html + 26. https://www.kernel.org/doc/html/latest/admin-guide/reporting-issues.html + 27. https://www.kernel.org/doc/html/latest/tools/index.html + 28. https://www.kernel.org/doc/html/latest/userspace-api/index.html + 29. https://www.kernel.org/doc/html/latest/firmware-guide/index.html + 30. https://www.kernel.org/doc/html/latest/devicetree/index.html + 31. https://www.kernel.org/doc/html/latest/arch.html + 32. https://www.kernel.org/doc/html/latest/arc/index.html + 33. https://www.kernel.org/doc/html/latest/arm/index.html + 34. https://www.kernel.org/doc/html/latest/arm64/index.html + 35. https://www.kernel.org/doc/html/latest/ia64/index.html + 36. https://www.kernel.org/doc/html/latest/loongarch/index.html + 37. https://www.kernel.org/doc/html/latest/m68k/index.html + 38. https://www.kernel.org/doc/html/latest/mips/index.html + 39. https://www.kernel.org/doc/html/latest/nios2/index.html + 40. https://www.kernel.org/doc/html/latest/openrisc/index.html + 41. https://www.kernel.org/doc/html/latest/parisc/index.html + 42. https://www.kernel.org/doc/html/latest/powerpc/index.html + 43. https://www.kernel.org/doc/html/latest/riscv/index.html + 44. https://www.kernel.org/doc/html/latest/s390/index.html + 45. https://www.kernel.org/doc/html/latest/sh/index.html + 46. https://www.kernel.org/doc/html/latest/sparc/index.html + 47. https://www.kernel.org/doc/html/latest/x86/index.html + 48. https://www.kernel.org/doc/html/latest/x86/boot.html + 49. https://www.kernel.org/doc/html/latest/x86/booting-dt.html + 50. https://www.kernel.org/doc/html/latest/x86/cpuinfo.html + 51. https://www.kernel.org/doc/html/latest/x86/topology.html + 52. https://www.kernel.org/doc/html/latest/x86/exception-tables.html + 53. https://www.kernel.org/doc/html/latest/x86/kernel-stacks.html + 54. https://www.kernel.org/doc/html/latest/x86/entry_64.html + 55. https://www.kernel.org/doc/html/latest/x86/earlyprintk.html + 56. https://www.kernel.org/doc/html/latest/x86/orc-unwinder.html + 57. https://www.kernel.org/doc/html/latest/x86/zero-page.html + 58. https://www.kernel.org/doc/html/latest/x86/tlb.html + 59. https://www.kernel.org/doc/html/latest/x86/mtrr.html + 60. https://www.kernel.org/doc/html/latest/x86/pat.html + 61. https://www.kernel.org/doc/html/latest/x86/intel-hfi.html + 62. https://www.kernel.org/doc/html/latest/x86/iommu.html + 63. https://www.kernel.org/doc/html/latest/x86/intel_txt.html + 64. https://www.kernel.org/doc/html/latest/x86/amd-memory-encryption.html + 65. https://www.kernel.org/doc/html/latest/x86/amd_hsmp.html + 66. https://www.kernel.org/doc/html/latest/x86/tdx.html + 67. https://www.kernel.org/doc/html/latest/x86/pti.html + 68. https://www.kernel.org/doc/html/latest/x86/mds.html + 69. https://www.kernel.org/doc/html/latest/x86/microcode.html + 70. https://www.kernel.org/doc/html/latest/x86/resctrl.html + 71. https://www.kernel.org/doc/html/latest/x86/tsx_async_abort.html + 72. https://www.kernel.org/doc/html/latest/x86/buslock.html + 73. https://www.kernel.org/doc/html/latest/x86/usb-legacy-support.html + 74. https://www.kernel.org/doc/html/latest/x86/i386/index.html + 75. https://www.kernel.org/doc/html/latest/x86/x86_64/index.html + 76. https://www.kernel.org/doc/html/latest/x86/ifs.html + 77. https://www.kernel.org/doc/html/latest/x86/sva.html + 78. https://www.kernel.org/doc/html/latest/x86/sgx.html + 79. https://www.kernel.org/doc/html/latest/x86/features.html + 80. https://www.kernel.org/doc/html/latest/x86/elf_auxvec.html + 81. https://www.kernel.org/doc/html/latest/x86/xstate.html + 82. https://www.kernel.org/doc/html/latest/xtensa/index.html + 83. https://www.kernel.org/doc/html/latest/staging/index.html + 84. https://www.kernel.org/doc/html/latest/translations/index.html + 85. https://www.kernel.org/doc/html/latest/_sources/x86/boot.rst.txt + 86. https://www.kernel.org/doc/html/latest/x86/boot.html#the-linux-x86-boot-protocol + 87. https://www.kernel.org/doc/html/latest/x86/boot.html#memory-layout + 88. https://www.kernel.org/doc/html/latest/x86/boot.html#the-real-mode-kernel-header + 89. https://www.kernel.org/doc/html/latest/x86/boot.html#details-of-header-fields + 90. http://sebastian-plotz.blogspot.de/ + 91. mailto:hpa%40zytor.com + 92. https://www.kernel.org/doc/html/latest/x86/boot.html#the-kernel-info + 93. https://www.kernel.org/doc/html/latest/x86/boot.html#details-of-the-kernel-info-fields + 94. https://www.kernel.org/doc/html/latest/x86/boot.html#the-image-checksum + 95. https://www.kernel.org/doc/html/latest/x86/boot.html#the-kernel-command-line + 96. https://www.kernel.org/doc/html/latest/x86/boot.html#memory-layout-of-the-real-mode-code + 97. https://www.kernel.org/doc/html/latest/x86/boot.html#sample-boot-configuartion + 98. https://www.kernel.org/doc/html/latest/x86/boot.html#loading-the-rest-of-the-kernel + 99. https://www.kernel.org/doc/html/latest/x86/boot.html#special-command-line-options + 100. https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html + 101. https://www.kernel.org/doc/html/latest/x86/boot.html#running-the-kernel + 102. https://www.kernel.org/doc/html/latest/x86/boot.html#advanced-boot-loader-hooks + 103. https://www.kernel.org/doc/html/latest/x86/boot.html#bit-boot-protocol + 104. https://www.kernel.org/doc/html/latest/x86/zero-page.html + 105. https://www.kernel.org/doc/html/latest/x86/boot.html#id1 + 106. https://www.kernel.org/doc/html/latest/x86/zero-page.html + 107. https://www.kernel.org/doc/html/latest/x86/boot.html#efi-handover-protocol-deprecated + 108. https://github.com/u-boot/u-boot/commit/ec80b4735a593961fe701cc3a5d717d4739b0fd0 + 109. http://sphinx-doc.org/ + 110. https://github.com/bitprophet/alabaster + 111. https://www.kernel.org/doc/html/latest/_sources/x86/boot.rst.txt diff --git a/todo/doc/www.kernel.org_doc_html_latest_x86_zero-page.txt b/todo/doc/www.kernel.org_doc_html_latest_x86_zero-page.txt new file mode 100644 index 0000000..da384f1 --- /dev/null +++ b/todo/doc/www.kernel.org_doc_html_latest_x86_zero-page.txt @@ -0,0 +1,424 @@ + #[1]Index [2]Search [3]11. The TLB [4]9. ORC unwinder + +[5]The Linux Kernel + + 6.3.0-rc6 + +Quick search + + ____________________ Go + +Contents + + [X] + * [6]A guide to the Kernel Development Process + * [7]Submitting patches: the essential guide to getting your code + into the kernel + * [8]Code of conduct + * [9]Kernel Maintainer Handbook + * [10]All development-process docs + + * [11]Core API Documentation + * [12]Driver implementer's API guide + * [13]Kernel subsystem documentation + * [14]Locking in the kernel + + * [15]Linux kernel licensing rules + * [16]How to write kernel documentation + * [17]Development tools for the kernel + * [18]Kernel Testing Guide + * [19]Kernel Hacking Guides + * [20]Linux Tracing Technologies + * [21]fault-injection + * [22]Kernel Livepatching + * [23]Rust + + * [24]The Linux kernel user's and administrator's guide + * [25]The kernel build system + * [26]Reporting issues + * [27]User-space tools + * [28]The Linux kernel user-space API guide + + * [29]The Linux kernel firmware guide + * [30]Open Firmware and Devicetree + + * [31]CPU Architectures + + [32]ARC architecture + + [33]ARM Architecture + + [34]ARM64 Architecture + + [35]IA-64 Architecture + + [36]LoongArch Architecture + + [37]m68k Architecture + + [38]MIPS-specific Documentation + + [39]Nios II Specific Documentation + + [40]OpenRISC Architecture + + [41]PA-RISC Architecture + + [42]powerpc + + [43]RISC-V architecture + + [44]s390 Architecture + + [45]SuperH Interfaces Guide + + [46]Sparc Architecture + + [47]x86-specific Documentation + o [48]1. The Linux/x86 Boot Protocol + o [49]2. DeviceTree Booting + o [50]3. x86 Feature Flags + o [51]4. x86 Topology + o [52]5. Kernel level exception handling + o [53]6. Kernel Stacks + o [54]7. Kernel Entries + o [55]8. Early Printk + o [56]9. ORC unwinder + o [57]10. Zero Page + o [58]11. The TLB + o [59]12. MTRR (Memory Type Range Register) control + o [60]13. PAT (Page Attribute Table) + o [61]14. Hardware-Feedback Interface for scheduling on + Intel Hardware + o [62]15. x86 IOMMU Support + o [63]16. Intel(R) TXT Overview + o [64]17. AMD Memory Encryption + o [65]18. AMD HSMP interface + o [66]19. Intel Trust Domain Extensions (TDX) + o [67]20. Page Table Isolation (PTI) + o [68]21. Microarchitectural Data Sampling (MDS) mitigation + o [69]22. The Linux Microcode Loader + o [70]23. User Interface for Resource Control feature + o [71]24. TSX Async Abort (TAA) mitigation + o [72]25. Bus lock detection and handling + o [73]26. USB Legacy support + o [74]27. i386 Support + o [75]28. x86_64 Support + o [76]29. In-Field Scan + o [77]30. Shared Virtual Addressing (SVA) with ENQCMD + o [78]31. Software Guard eXtensions (SGX) + o [79]32. Feature status on x86 architecture + o [80]33. x86-specific ELF Auxiliary Vectors + o [81]34. Using XSTATE features in user space applications + + [82]Xtensa Architecture + + * [83]Unsorted Documentation + + * [84]Translations + +This Page + + * [85]Show Source + +10. Zero Page[86] + + The additional fields in struct boot_params as a part of 32-bit boot + protocol of kernel. These should be filled by bootloader or 16-bit + real-mode setup code of the kernel. References/settings to it mainly + are in: +arch/x86/include/uapi/asm/bootparam.h + + Offset/Size + + Proto + + Name + + Meaning + + 000/040 + + ALL + + screen_info + + Text mode or frame buffer information (struct screen_info) + + 040/014 + + ALL + + apm_bios_info + + APM BIOS information (struct apm_bios_info) + + 058/008 + + ALL + + tboot_addr + + Physical address of tboot shared page + + 060/010 + + ALL + + ist_info + + Intel SpeedStep (IST) BIOS support information (struct ist_info) + + 070/008 + + ALL + + acpi_rsdp_addr + + Physical address of ACPI RSDP table + + 080/010 + + ALL + + hd0_info + + hd0 disk parameter, OBSOLETE!! + + 090/010 + + ALL + + hd1_info + + hd1 disk parameter, OBSOLETE!! + + 0A0/010 + + ALL + + sys_desc_table + + System description table (struct sys_desc_table), OBSOLETE!! + + 0B0/010 + + ALL + + olpc_ofw_header + + OLPC's OpenFirmware CIF and friends + + 0C0/004 + + ALL + + ext_ramdisk_image + + ramdisk_image high 32bits + + 0C4/004 + + ALL + + ext_ramdisk_size + + ramdisk_size high 32bits + + 0C8/004 + + ALL + + ext_cmd_line_ptr + + cmd_line_ptr high 32bits + + 13C/004 + + ALL + + cc_blob_address + + Physical address of Confidential Computing blob + + 140/080 + + ALL + + edid_info + + Video mode setup (struct edid_info) + + 1C0/020 + + ALL + + efi_info + + EFI 32 information (struct efi_info) + + 1E0/004 + + ALL + + alt_mem_k + + Alternative mem check, in KB + + 1E4/004 + + ALL + + scratch + + Scratch field for the kernel setup code + + 1E8/001 + + ALL + + e820_entries + + Number of entries in e820_table (below) + + 1E9/001 + + ALL + + eddbuf_entries + + Number of entries in eddbuf (below) + + 1EA/001 + + ALL + + edd_mbr_sig_buf_entries + + Number of entries in edd_mbr_sig_buffer (below) + + 1EB/001 + + ALL + + kbd_status + + Numlock is enabled + + 1EC/001 + + ALL + + secure_boot + + Secure boot is enabled in the firmware + + 1EF/001 + + ALL + + sentinel + + Used to detect broken bootloaders + + 290/040 + + ALL + + edd_mbr_sig_buffer + + EDD MBR signatures + + 2D0/A00 + + ALL + + e820_table + + E820 memory map table (array of struct e820_entry) + + D00/1EC + + ALL + + eddbuf + + EDD data (array of struct edd_info) + + The kernel development community. | Powered by [87]Sphinx 5.0.1 & + [88]Alabaster 0.7.12 | [89]Page source + +References + + 1. https://www.kernel.org/doc/html/latest/genindex.html + 2. https://www.kernel.org/doc/html/latest/search.html + 3. https://www.kernel.org/doc/html/latest/x86/tlb.html + 4. https://www.kernel.org/doc/html/latest/x86/orc-unwinder.html + 5. https://www.kernel.org/doc/html/latest/index.html + 6. https://www.kernel.org/doc/html/latest/process/development-process.html + 7. https://www.kernel.org/doc/html/latest/process/submitting-patches.html + 8. https://www.kernel.org/doc/html/latest/process/code-of-conduct.html + 9. https://www.kernel.org/doc/html/latest/maintainer/index.html + 10. https://www.kernel.org/doc/html/latest/process/index.html + 11. https://www.kernel.org/doc/html/latest/core-api/index.html + 12. https://www.kernel.org/doc/html/latest/driver-api/index.html + 13. https://www.kernel.org/doc/html/latest/subsystem-apis.html + 14. https://www.kernel.org/doc/html/latest/locking/index.html + 15. https://www.kernel.org/doc/html/latest/process/license-rules.html + 16. https://www.kernel.org/doc/html/latest/doc-guide/index.html + 17. https://www.kernel.org/doc/html/latest/dev-tools/index.html + 18. https://www.kernel.org/doc/html/latest/dev-tools/testing-overview.html + 19. https://www.kernel.org/doc/html/latest/kernel-hacking/index.html + 20. https://www.kernel.org/doc/html/latest/trace/index.html + 21. https://www.kernel.org/doc/html/latest/fault-injection/index.html + 22. https://www.kernel.org/doc/html/latest/livepatch/index.html + 23. https://www.kernel.org/doc/html/latest/rust/index.html + 24. https://www.kernel.org/doc/html/latest/admin-guide/index.html + 25. https://www.kernel.org/doc/html/latest/kbuild/index.html + 26. https://www.kernel.org/doc/html/latest/admin-guide/reporting-issues.html + 27. https://www.kernel.org/doc/html/latest/tools/index.html + 28. https://www.kernel.org/doc/html/latest/userspace-api/index.html + 29. https://www.kernel.org/doc/html/latest/firmware-guide/index.html + 30. https://www.kernel.org/doc/html/latest/devicetree/index.html + 31. https://www.kernel.org/doc/html/latest/arch.html + 32. https://www.kernel.org/doc/html/latest/arc/index.html + 33. https://www.kernel.org/doc/html/latest/arm/index.html + 34. https://www.kernel.org/doc/html/latest/arm64/index.html + 35. https://www.kernel.org/doc/html/latest/ia64/index.html + 36. https://www.kernel.org/doc/html/latest/loongarch/index.html + 37. https://www.kernel.org/doc/html/latest/m68k/index.html + 38. https://www.kernel.org/doc/html/latest/mips/index.html + 39. https://www.kernel.org/doc/html/latest/nios2/index.html + 40. https://www.kernel.org/doc/html/latest/openrisc/index.html + 41. https://www.kernel.org/doc/html/latest/parisc/index.html + 42. https://www.kernel.org/doc/html/latest/powerpc/index.html + 43. https://www.kernel.org/doc/html/latest/riscv/index.html + 44. https://www.kernel.org/doc/html/latest/s390/index.html + 45. https://www.kernel.org/doc/html/latest/sh/index.html + 46. https://www.kernel.org/doc/html/latest/sparc/index.html + 47. https://www.kernel.org/doc/html/latest/x86/index.html + 48. https://www.kernel.org/doc/html/latest/x86/boot.html + 49. https://www.kernel.org/doc/html/latest/x86/booting-dt.html + 50. https://www.kernel.org/doc/html/latest/x86/cpuinfo.html + 51. https://www.kernel.org/doc/html/latest/x86/topology.html + 52. https://www.kernel.org/doc/html/latest/x86/exception-tables.html + 53. https://www.kernel.org/doc/html/latest/x86/kernel-stacks.html + 54. https://www.kernel.org/doc/html/latest/x86/entry_64.html + 55. https://www.kernel.org/doc/html/latest/x86/earlyprintk.html + 56. https://www.kernel.org/doc/html/latest/x86/orc-unwinder.html + 57. https://www.kernel.org/doc/html/latest/x86/zero-page.html + 58. https://www.kernel.org/doc/html/latest/x86/tlb.html + 59. https://www.kernel.org/doc/html/latest/x86/mtrr.html + 60. https://www.kernel.org/doc/html/latest/x86/pat.html + 61. https://www.kernel.org/doc/html/latest/x86/intel-hfi.html + 62. https://www.kernel.org/doc/html/latest/x86/iommu.html + 63. https://www.kernel.org/doc/html/latest/x86/intel_txt.html + 64. https://www.kernel.org/doc/html/latest/x86/amd-memory-encryption.html + 65. https://www.kernel.org/doc/html/latest/x86/amd_hsmp.html + 66. https://www.kernel.org/doc/html/latest/x86/tdx.html + 67. https://www.kernel.org/doc/html/latest/x86/pti.html + 68. https://www.kernel.org/doc/html/latest/x86/mds.html + 69. https://www.kernel.org/doc/html/latest/x86/microcode.html + 70. https://www.kernel.org/doc/html/latest/x86/resctrl.html + 71. https://www.kernel.org/doc/html/latest/x86/tsx_async_abort.html + 72. https://www.kernel.org/doc/html/latest/x86/buslock.html + 73. https://www.kernel.org/doc/html/latest/x86/usb-legacy-support.html + 74. https://www.kernel.org/doc/html/latest/x86/i386/index.html + 75. https://www.kernel.org/doc/html/latest/x86/x86_64/index.html + 76. https://www.kernel.org/doc/html/latest/x86/ifs.html + 77. https://www.kernel.org/doc/html/latest/x86/sva.html + 78. https://www.kernel.org/doc/html/latest/x86/sgx.html + 79. https://www.kernel.org/doc/html/latest/x86/features.html + 80. https://www.kernel.org/doc/html/latest/x86/elf_auxvec.html + 81. https://www.kernel.org/doc/html/latest/x86/xstate.html + 82. https://www.kernel.org/doc/html/latest/xtensa/index.html + 83. https://www.kernel.org/doc/html/latest/staging/index.html + 84. https://www.kernel.org/doc/html/latest/translations/index.html + 85. https://www.kernel.org/doc/html/latest/_sources/x86/zero-page.rst.txt + 86. https://www.kernel.org/doc/html/latest/x86/zero-page.html#zero-page + 87. http://sphinx-doc.org/ + 88. https://github.com/bitprophet/alabaster + 89. https://www.kernel.org/doc/html/latest/_sources/x86/zero-page.rst.txt -- cgit v1.2.3-54-g00ecf