[DOCUMENT] Re: Intel Macs that boot FreeBSD?
Bruce M Simpson
bms at spc.org
Sat Apr 8 10:32:31 UTC 2006
I wrote a document which explains exactly which BIOS calls FreeBSD
uses to boot.
Unfortunately there is a bit of an ongoing re-jig with my web stuff so
it isn't up anywhere but I will repost it here.
BMS
-------------- next part --------------
-----------------------------------------
FreeBSD BIOS Coupling on i386
Bruce M. Simpson <bms at spc.org> 2002-12-27
-----------------------------------------
Copyright (c) 2002 Bruce M. Simpson, All rights reserved.
Redistribution and use are freely permitted provided that the above
copyright notice and this paragraph are duplicated in all forms.
Introduction
------------
This file is intended purely as a source of technical information
on how closely coupled the FreeBSD/i386 boot process is to the BIOS
and legacy i386 hardware.
It should be of interest to anybody considering implementing their
own BIOS and who wishes to be able to boot FreeBSD with it.
FreeBSD Boot Process
--------------------
The FreeBSD OS employs a three stage boot loader. Here we consider the
most common case: booting from a hard disk recognised by the BIOS.
The flow of execution runs thus: boot0 is loaded from the MBR, which then
looks for the first FreeBSD DOS partition; boot1 is loaded from the BPB,
which then loads and invokes boot2 from the boot sectors inside the FreeBSD
disk label; then boot2 attempts to load and invoke the FreeBSD Loader from
the root slice. Finally, the loader invokes the kernel.
boot0/boot0sio
--------------
- Master Boot Record (MBR) boot loader
- Permits selection of DOS partition to boot from
- Loaded from INT 19h (Bootstrap Loader) by BIOS
- Self-relocates to 0000:7C00 (well clear of BIOS Data Area)
- Loads boot sector from selected partition into segment 0, and
performs a near jmp through BX to it
BIOS functions used:
Int Fn SFn Description
------------------------------------------------------------------
10h 0Eh n/a Write Character in Teletype Mode (boot0)
13h 02h n/a Read Disk Sectors
13h 03h n/a Write Disk Sectors
13h 42h n/a Extended Read Sectors
13h 43h n/a Extended Write Sectors
14h 00h n/a Initialize Serial Port (boot0sio)
14h 01h n/a Send Byte (boot0sio)
14h 02h n/a Receive Byte (boot0sio)
14h 03h n/a Read Status (boot0sio)
16h 00h n/a Read Keyboard Input (boot0)
16h 01h n/a Check Keyboard Status (boot0)
1Ah 00h n/a Get System Time
BIOS parameters accepted:
Register Description
-------------------------------
dl BIOS Drive Number (when invoked via INT 19h IPL)
boot1
-----
- BIOS Parameter Block (BPB) boot loader
- Resides in the BPB of the first FreeBSD partition on the disk
- Loaded and invoked by boot0 at 0000:7C00
- Self-relocates on load to 0000:0700 (above BIOS data area and IDT)
- Enables A20 by itself using the AT keyboard controller method
- Reads and relocates boot2 to low memory to continue boot process
- boot1 is kept resident in memory, and V86 mode is used to call into
the real mode xread routine in this segment.
BIOS functions used:
Int Fn SFn Description
------------------------------------------------------------------
10h 0Eh n/a Write Character in Teletype Mode
13h 00h n/a Disk Controller Reset
13h 02h n/a Read Disk Sectors
13h 08h n/a Read Disk Drive Parameters
13h 41h n/a Check If Extensions Present
13h 42h n/a Extended Read Sectors
13h 43h n/a Extended Write Sectors
16h 00h n/a Read Keyboard Input
boot2 meta-binary
-----------------
btxldr, btx, and boot2 are actually compiled into the same binary.
Many things are going on in here.
BTXLDR
------
- This is used to load the BTX framework.
- It enters 'unreal' mode to allow the use of a 32-bit flat address
space, thus permitting boot2 to be compiled using gcc.
BIOS Data Area locations referenced:
Address Description
------------------------------------------------------------------
40:13h Main Memory Size
40:49h Video Mode
40:50h Video -- Cursor Position Page 0
BTXLDR addresses the VGA video memory at B8000h directly.
BTXLDR does not make any BIOS calls.
BTX and boot2
-------------
- BTX sets up a small protected mode kernel. It's actually quite a good
example of how to drive the i386.
- A V86 monitor is used to redirect calls into the BIOS (and capture some),
whilst remaining in protected mode.
- INT 19h is used by the BTX client to reset the machine.
BIOS Data Area locations referenced:
Address Description
------------------------------------------------------------------
40:13h Main Memory Size
40:17h Keyboard Shift Flags 1
40:49h Video Mode
40:50h Video -- Cursor Position Page 0
40:72h Warm Boot Flag
Direct I/O Port Hardware Accesses:
Port Description
------------------------------------------------------------------
0x20 8259 Master Interrupt Command Register
0x21 8259 Master Interrupt Mask Register
0xA0 8259 Slave Interrupt Command Register
0xA1 8259 Slave Interrupt Mask Register
0x3F8 UART 0 Transmit/Receive Buffer and Divisor LSB
0x3F9 UART 0 Divisor MSB
0x3FB UART 0 Line Control
0x3FC UART 0 Modem Control
0x3FD UART 0 Line Status
BIOS Calls intercepted by the V86 Monitor:
Int Fn SFn Description
------------------------------------------------------------------
15h 87h n/a Access Extended Memory
19h n/a n/a Bootstrap Loader
BIOS Calls passed through by the V86 Monitor:
Int Fn SFn Description
------------------------------------------------------------------
10h 0Eh n/a Write Character in Teletype Mode
12h 88h n/a Base Memory Size
13h 08h n/a Read Disk Drive Parameters
15h 88h n/a Extended Memory Size
16h 00h n/a Read Keyboard Input
16h 01h n/a Check Keyboard Status
boot2
-----
boot2 is the BTX client. It uses the protected-mode kernel to call into
the BIOS through the V86 monitor. It understands enough of FreeBSD FFS
to load /boot/loader or /kernel on its own. The FORTH loader is preferable
for modern FreeBSD configurations. It uses the /boot.config file for
some settings of its own (such as forcing an autoboot on a CD installation).
It knows enough to load an ELF or an a.out executable.
loader
------
- This is the newer, advanced FreeBSD third stage bootstrap which has
an embedded, Forth-like interpreter called FICL.
- It is actually referred to as BOOT3 in the boot2 source.
- Source is found under: /usr/src/sys/boot
- Picks up i386 specific functions from i386/libi386, these handle
interaction with the platform hardware, and the BIOS.
BIOS Calls passed through by the V86 Monitor:
Int Fn SFn Description
------------------------------------------------------------------
10h 02h n/a Set Cursor Position (from vidconsole.c)
10h 03h n/a Read Cursor Position and Type (from vidconsole.c)
10h 06h n/a Scroll Active Page Up (from vidconsole.c)
10h 08h n/a Read Character and Attribute (from vidconsole.c)
10h 09h n/a Write Character and Attribute (from vidconsole.c)
10h 0Eh n/a Write Character in Teletype Mode (from vidconsole.c)
12h 88h n/a Base Memory Size (from biosmem.c)
13h 00h n/a Disk Controller Reset (from bioscd.c, biosdisk.c)
13h 02h n/a Read Disk Sectors (from biosdisk.c)
13h 08h n/a Read Disk Drive Parameters (from biosdisk.c)
13h 42h n/a Extended Read Sectors (from bioscd.c, biosdisk.c)
13h 4Bh 01h Terminate Disk Emulation (from bioscd.c)
15h 86h n/a Wait (from time.c)
15h 88h n/a Extended Memory Size (from biosmem.c)
15h E8h 01h Get Extended Memory Info (from biosmem.c)
15h E8h 20h Get System Memory Map (from biosmem.c)
16h 00h n/a Read Keyboard Input (from vidconsole.c)
16h 01h n/a Check Keyboard Status (from vidconsole.c)
1Ah 02h n/a Read CMOS Time (from time.c)
1Ah B1h 01h PCI Test for PCI BIOS Present (from biospci.c)
1Ah B1h 03h PCI Find Device Matching Class Code (from biospci.c)
1Ah B1h 0Ah PCI Read Device Configuration DWORD (from biospci.c)
- FreeBSD's import of ficl has functions which wrap the in/out
instructions to allow them to be used from boot FORTH. The actions of
any FORTH programs which use these bindings are not documented here.
- biospnp.c wraps the PnP BIOS. The PnP specification dictates that
there must be a $PnP structure in the BIOS image, which contains a
real mode CS:IP vector to be used for calls into the PnP BIOS. This
vector will vary according to the BIOS in use.
- pxe.c uses v86 to bounce into routines inside the PXE UNDI BIOS which
knows how to get the IP address, etc. These ROMs exist on the network
card, which can reside on an ISA or PCI bus. PXE compliant cards have
$PnP headers in the boot ROM. Again, the PnP BIOS specification details
how the various boot vectors in this header work, when a PnP BIOS is
loading a PnP compliant expansion ROM.
Kernel->BIOS entry points
-------------------------
- Some BIOS extensions can be called from protected mode using the
BIOS32 Service Directory. Others must be called from real mode.
- We're lurking in: /usr/src/sys/i386
- i386/bios.c, i386/bioscall.s and i386/vm86.c define the following:
- bios16() -- Make a 16-bit BIOS call in real mode *no man page*
- bios32() -- Make a 32-bit BIOS call in protected mode (bios(9))
- bios32_SDlookup() -- Attempt to locate a BIOS32 service (bios(9))
- bios_sigsearch() -- Search for a service signature in ROM (bios(9))
- vm86_intcall() -- Make a 16-bit BIOS call in V86 mode *no man page*
- vm86_datacall() -- Make a 16-bit BIOS call in V86 mode which returns
some data *no man page*
- vm86_bioscall() -- Make a 16-bit BIOS call in V86 mode *no man page*
- BIOS_PADDRTOVADDR() wraps a reference to BIOS Data Area memory.
- Grepping for the relevant permutations of the above entry points
will let you see where kernel drivers are entering the BIOS, or
referencing the BIOS Data Area.
Boot-time Kernel->BIOS Communication
------------------------------------
- i386 specific low level code is in: /usr/src/sys/i386/i386
- Early boot initialization is handled in: locore.s
- loader enters kernel at the entry point 'newboot'
- The kernel reloads the GDT whilst bringing up the system. vm86
descriptors are created as part of the system-wide GDT. These are used
to call into the BIOS or other real mode expansion ROMs later on.
- Most of the kernel coupling is to the loader and not the BIOS, which
is a good thing. That is, handling the BIOS directly has been farmed
out to the loader, which passes this information to the kernel using
a boot information structure, _bootinfo, which it fills in after
loading the kernel.
- The kernel does make a limited number of BIOS calls during boot,
these are mainly made within machdep.c to discover the BIOS's
idea of the system memory map:
Int Fn SFn Description
------------------------------------------------------------------
12h 88h n/a Base Memory Size
15h 88h n/a Extended Memory Size
15h E8h 01h Get Extended Memory Info
15h E8h 20h Get System Memory Map
- If you set bootverbose to 1 from the loader, you can see the SMAP
initialization being printed out on the console.
- isa/mca_machdep.c makes these calls via vm86_intcall():
Int Fn SFn Description
------------------------------------------------------------------
15h C0h n/a Return System BIOS Configuration
- This is used to discover a MicroChannel Bus (MCA) machine.
- isa/pci_cfgreg.c makes these calls via bios32():
Int Fn SFn Description
------------------------------------------------------------------
1Ah B1h 01h PCI Test for PCI BIOS Present
1Ah B1h 0Fh PCI Route Device Interrupt
- This is necessary as the board specific knowledge/code to route
interrupts according to the northbridge/southbridge pair is contained
within the BIOS on i386 machines. Note however that configuration
register access is a well defined process on the i386 which doesn't
require assistance from the BIOS.
- The kernel doesn't specifically call into the BIOS after boot, unless
separate initialization is required on behalf of drivers (e.g. APM).
These are considered separately; please see below.
Run-time Kernel->BIOS Communication
-----------------------------------
- apm/apm.c makes these BIOS calls in 16- or 32-bit mode depending
on whether or not the APM BIOS supports 32-bit invocation:
Int Fn SFn Description
------------------------------------------------------------------
15h 53h nnh APM BIOS Calls (PC/AT)
1Fh 9Ah nnh APM BIOS Calls (PC98)
- i386/isa/vesa.c makes the following calls via vm86_[int|data]call():
Int Fn SFn Description
------------------------------------------------------------------
10h 00h n/a Set Video Mode
10h 4Fh 00h VBE Initialize VESA BIOS
10h 4Fh 01h VBE Get Extended Modes
10h 4Fh 02h VBE Set Extended Mode
10h 4Fh 04h VBE Buffer Manipulation
10h 4Fh 05h VBE Window Manipulation
10h 4Fh 06h VBE Scanline Manipulation
10h 4Fh 07h VBE Linear Framebuffer Manipulation
10h 4Fh 08h VBE DAC Manipulation
10h 4Fh 09h VBE Palette Manipulation
- dev/fb/vga.c uses the BIOS Data Area, primarily if there is no VESA
BIOS present.
BIOS Data Area locations referenced:
Address Description
------------------------------------------------------------------
40:4Ah Video Columns (BYTE)
40:4Ch Video Bytes per Page (WORD)
40:4Dh Video Current Page Offset (WORD)
40:63h Video I/O Port Number Base (WORD)
40:84h Video Number of Rows (BYTE)
40:85h Video Pixels per Character (WORD)
40:87h Video Options (BYTE)
40:88h Video Switches (BYTE)
40:A8h Video Parameter Control Block Pointer (DWORD)
- dev/kbd/atkbd.c makes the following calls via vm86_intcall(),
and may reference a BIOS Data Area location as a result of INT 15h:
Int Fn SFn Description
------------------------------------------------------------------
15h C0h n/a Return System BIOS Configuration
16h 03h 06h Get Typematic Rate
16h 09h n/a Get Typematic Capabilities
- XXX: The DMItable is documented in bios(9), but not implemented.
- XXX: The SMBIOStable is documented in bios(9), but not implemented.
- XXX: I haven't documented how ACPI is called yet.
References
----------
The Undocumented PC 2e
van Gilluwe, Frank; Addison-Wesley; ISBN 0-201-47950-8
PC Intern 6e
Tischer & Jennrich; Abacus; ISBN 1-55755-304-1
PCI System Architecture 4e
Shanley & Anderson; Addison-Wesley; ISBN 0-201-30974-2
More information about the freebsd-current
mailing list