Implement a subset of the multiboot specification in order to boot Xen
and a FreeBSD Dom0 from the FreeBSD bootloader. This multiboot
implementation is tailored to boot Xen and FreeBSD Dom0, and it will
most surely fail to boot any other multiboot compilant kernel.
In order to detect and boot the Xen microkernel, two new file formats
are added to the bootloader, multiboot and multiboot_obj. Multiboot
support must be tested before regular ELF support, since Xen is a
multiboot kernel that also uses ELF. After a multiboot kernel is
detected, all the other loaded kernels/modules are parsed by the
multiboot_obj format.
The layout of the loaded objects in memory is the following; first the
Xen kernel is loaded as a 32bit ELF into memory (Xen will switch to
long mode by itself), after that the FreeBSD kernel is loaded as a RAW
file (Xen will parse and load it using it's internal ELF loader), and
finally the metadata and the modules are loaded using the native
FreeBSD way. After everything is loaded we jump into Xen's entry point
using a small trampoline. The order of the multiboot modules passed to
Xen is the following, the first module is the RAW FreeBSD kernel, and
the second module is the metadata and the FreeBSD modules.
Since Xen will relocate the memory position of the second
multiboot module (the one that contains the metadata and native
FreeBSD modules), we need to stash the original modulep address inside
of the metadata itself in order to recalculate its position once
booted. This also means the metadata must come before the loaded
modules, so after loading the FreeBSD kernel a portion of memory is
reserved in order to place the metadata before booting.
In order to tell the loader to boot Xen and then the FreeBSD kernel the
following has to be added to the /boot/loader.conf file:
xen_cmdline="dom0_mem=1024M dom0_max_vcpus=2 dom0pvh=1 console=com1,vga"
xen_kernel="/boot/xen"
The first argument contains the command line that will be passed to the Xen
kernel, while the second argument is the path to the Xen kernel itself. This
can also be done manually from the loader command line, by for example
typing the following set of commands:
OK unload
OK load /boot/xen dom0_mem=1024M dom0_max_vcpus=2 dom0pvh=1 console=com1,vga
OK load kernel
OK load zfs
OK load if_tap
OK load ...
OK boot
Sponsored by: Citrix Systems R&D
Reviewed by: jhb
Differential Revision: https://reviews.freebsd.org/D517
For the Forth bits:
Submitted by: Julien Grall <julien.grall AT citrix.com>
bootloader. Implement the following routines:
pcibios-device-count count the number of instances of a devid
pcibios-read-config read pci config space
pcibios-write-config write pci config space
pcibios-find-devclass find the nth device with a given devclass
pcibios-find-device find the nth device with a given devid
pcibios-locator convert bus device function ti pcibios locator
These commands are thin wrappers over their PCI BIOS 2.1 counterparts. More
informaiton, such as it is, can be found in the standard.
Export a nunmber of pcibios.X variables into the environment to report
what the PCI IDENTIFY command returned.
Also implmenet a new command line primitive (pci-device-count), but don't
include it by default just yet, since it depends on the recently added
words and any errors here can render a system unbootable.
This is intended to allow the boot loader to do special things based
on the hardware it finds. This could be have special settings that are
optimized for the specific cards, or even loading special drivers. It
goes without saying that writing to pci config space should not be
done without a just cause and a sound mind.
Sponsored by: Netflix
particular, allow loaders to define the name of the RC script the
interpreter needs to use. Use this new-found control to have the
PXE loader (when compiled with TFTP support and not NFS support)
read from ${bootfile}.4th, where ${bootfile} is the name of the
file fetched by the PXE firmware.
The normal startup process involves reading the following files:
1. /boot/boot.4th
2. /boot/loader.rc or alternatively /boot/boot.conf
When these come from a FreeBSD-defined file system, this is all
good. But when we boot over the network, subdirectories and fixed
file names are often painful to administrators and there's really
no way for them to change the behaviour of the loader.
Obtained from: Juniper Networks, Inc.
In zfs loader zfs device name format now is "zfs:pool/fs",
fully qualified file path is "zfs:pool/fs:/path/to/file"
loader allows accessing files from various pools and filesystems as well
as changing currdev to a different pool/filesystem.
zfsboot accepts kernel/loader name in a format pool:fs:path/to/file or,
as before, pool:path/to/file; in the latter case a default filesystem
is used (pool root or bootfs). zfsboot passes guids of the selected
pool and dataset to zfsloader to be used as its defaults.
zfs support should be architecture independent and is provided
in a separate library, but architectures wishing to use this zfs support
still have to provide some glue code and their devdesc should be
compatible with zfs_devdesc.
arch_zfs_probe method is used to discover all disk devices that may
be part of ZFS pool(s).
libi386 unconditionally includes zfs support, but some zfs-specific
functions are stubbed out as weak symbols. The strong definitions
are provided in libzfsboot.
This change mean that the size of i386_devspec becomes larger
to match zfs_devspec.
Backward-compatibility shims are provided for recently added sparc64
zfs boot support. Currently that architecture still works the old
way and does not support the new features.
TODO:
- clear up pool root filesystem vs pool bootfs filesystem distinction
- update sparc64 support
- set vfs.root.mountfrom based on currdev (for zfs)
Mid-future TODO:
- loader sub-menu for selecting alternative boot environment
Distant future TODO:
- support accessing snapshots, using a snapshot as readonly root
Reviewed by: marius (sparc64),
Gavin Mu <gavin.mu@gmail.com> (sparc64)
Tested by: Florian Wagner <florian@wagner-flo.net> (x86),
marius (sparc64)
No objections: fs@, hackers@
MFC after: 1 month
'comconsole_pcidev'. The former allows to set the base address of the
serial console i/o port. The later takes the string of the format
'bus:device:function:[bar]' as a value and uses the serial port attached
as PCI device at the specified location for console.
Both variants pass 'hw.uart.console' variable to the uart driver to
properly hand-over the kernel console.
Change allows to use ISA serial ports other than COM1 for the
loader/kernel console without loader recompilation. Also, you can use
PCI-attached port as the console, e.g. Intel AMT serial pseudo-port on
some motherboards based on Q67 chipset.
Reviewed by: jhb
MFC after: 2 weeks
and constants related to the BIOS Enhanced Disk Drive Specification.
- Use this header instead of magic numbers and various duplicate structure
definitions for doing I/O.
- Use an actual structure for the request to fetch drive parameters in
drvsize() rather than a gross hack of a char array with some magic
size. While here, change drvsize() to only pass the 1.1 version of
the structure and not request device path information. If we want
device path information you have to set the length of the device
path information as an input (along with probably checking the actual
EDD version to see which size one should use as the device path
information is variable-length). This fixes data smashing problems
from passing an EDD 3 structure to BIOSes supporting EDD 4.
Reviewed by: avg
Tested by: Dennis Koegel dk neveragain.de
MFC after: 1 week
heap when using a range above 1MB.
Previously the loader would always use the last 3MB in the first memory
range above 1MB for the heap. However, this memory range is also where the
kernel and any modules are loaded. If this memory range is "small", then
using the high 3MB for the heap may not leave enough room for the kernel
and modules.
Now the loader will use any range below 4GB for the heap, and the logic to
choose the "high" heap region has moved into biosmem.c. It sets two
variables that the loader can use for a high heap if it desires. When a
high heap is enabled (BZIP2, FireWire, GPT, or ZFS), then the following
memory ranges are preferred for the heap in order from best to worst:
- The largest memory region in the SMAP with a start address greater than
1MB. The memory region must be at least 3MB in length. This leaves the
region starting at 1MB purely for use by the kernel and modules.
- The last 3MB of the memory region starting at 1MB if it is at least 3MB
in size. This matches the current behavior except that the current loader
would break horribly if the first region was not at least 3MB in size.
- The memory range from the end of the loader up to the 640k window. This
is the range the loader uses when none of the high-heap-requesting options
are enabled.
Tested by: hrs
MFC after: 1 week
booting because the CD driver did not use bounce buffers to ensure
request buffers sent to the BIOS were always in the first 1MB. Copy over
the bounce buffer logic from the BIOS disk driver (minus the 64k boundary
code for floppies) to fix this.
Reported by: kensmith
device (kind) specific unit field to the common field. This change
allows a future version of libefi to work without requiring anything
more than what is defined in struct devdesc and as such makes it
possible to compile said version of libefi for different platforms
without requiring that those platforms have identical derivatives
of struct devdesc.
Use 'BOOT_SENSITIVE_INFO=YES' variable to turn them on.
- Use 'uint*_t' instead of 'u_int*_t', correct compilation warnings, and
update copyright while I am here.
3MB of physical memory for heap instead of range between 1MB and 4MB.
This makes this feature working with PAE and amd64 kernels, which are
loaded at 2MB. Teach i386_copyin() to avoid using range allocated by
heap in such case, so that it won't trash heap in the low memory
conditions.
This should make loading bzip2-compressed kernels/modules/mfs images
generally useable, so that re@ team is welcome to evaluate merits
of using this feature in the installation CDs.
Valuable suggestions by: jhb
variables to loader:
hint.smbios.0.enabled "YES" when SMBIOS is detected
hint.smbios.0.bios.vendor BIOS vendor
hint.smbios.0.bios.version BIOS version
hint.smbios.0.bios.reldate BIOS release date
hint.smbios.0.system.maker System manufacturer
hint.smbios.0.system.product System product name
hint.smbios.0.system.version System version number
hint.smbios.0.planar.maker Base board manufacturer
hint.smbios.0.planar.product Base board product name
hint.smbios.0.planar.version Base board version number
hint.smbios.0.chassis.maker Enclosure manufacturer
hint.smbios.0.chassis.version Enclosure version
These strings can be used to detect hardware quirks and to set appropriate
flags. For example, Compaq R3000 series and some HP laptops require
hint.atkbd.0.flags="0x9"
to boot. See amd64/67745 for more detail.
Note: Please do not abuse this feature to resolve general problem when it
can be fixed programmatically. This must be used as a last resort.
PR: kern/81449
Approved by: anholt (mentor)
things over floppy size limits, I can exclude it for release builds or
something like that. Most of the changes are to get the load_elf.c file
into a seperate elf32_ or elf64_ namespace so that you can have two
ELF loaders present at once. Note that for 64 bit kernels, it actually
starts up the kernel already in 64 bit mode with paging enabled. This
is really easy because we have a known minimum feature set.
Of note is that for amd64, we have to pass in the bios int 15 0xe821
memory map because once in long mode, you absolutely cannot make VM86
calls. amd64 does not use 'struct bootinfo' at all. It is a pure loader
metadata startup, just like sparc64 and powerpc. Much of the
infrastructure to support this was adapted from sparc64.
no emulation mode. Unlike other BIOS devices, this device uses 2048 byte
sectors. Also, the bioscd driver does not have to worry about slices
or partitions.
the ACPI module if the system apperars to be ACPI compliant.
This is an initial cut; the load should really be done by Forth support
code, and we should check both the BIOS build date and a blacklist.
- Don't hard code 0x10000 as the entry point for the loader. Instead add
src/sys/boot/i386/Makefile.inc which defines a make variable with the
entry point for the loader. Move the loader's entry point up to
0x20000, which makes PXE happy.
- Don't try to use cpp to parse btxldr for the optional BTXLDR_VERBOSE,
instead use m4 to achieve this. Also, add a BTXLDR_VERBOSE knob in the
btxldr Makefile to turn this option on.
- Redo parts of cdldr's Makefile so that it now builds and installs cdboot
instead of having i386/loader/Makefile do that. Also, add in some more
variables to make the pxeldr Makefile almost identical and thus to ease
maintainability.
- Teach cdldr about the a.out format. Cdldr now parsers the a.out header
of the loader binary and relocates it based on that. The entry point of
the loader no longer has to be hardcoded into cdldr. Also, the boot
info table from mkisofs is no longer required to get a useful cdboot.
- Update the lsdev function for BIOS disks to parse other file systems
(such as DOS FAT) that we currently support. This is still buggy as
it assumes that a floppy with a DOS boot sector actually has a MBR and
parses it as such. I'll be fixing this in the future.
- The biggie: Add in support for booting off of PXE-enabled network
adapters. Currently, we use the TFTP API provided by the PXE BIOS.
Eventually we will switch to using the low-level NIC driver thus
allowing both TFTP and NFS to be used, but for now it's just TFTP.
Submitted by: ps, alfred
Testing by: Benno Rice <benno@netizen.com.au>
for our use. Use the same search order for BIOS memory size functions
as the kernel will later use.
Allow the loader to use all of the detected physical memory (this will
greatly help people trying to load enormous memory disk images).
More correctly handle running out of memory when loading an object.
Use the end of base memory for the top of the heap, rather than
blindly hoping that there is 384k left.
Add copyrights to a couple of files I forgot.
This should resolve the problem raised in PR 12315, and incidentally
makes it easier to determine what geometry the BIOS is actually using
(by way of boot -v and dmesg).
Use bd_getdev() to work out a dev_t for the root device.
Allow $rootdev to override $currdev as the root device.
biosdisk.c
Save the slice table and disklabel when opening a disk.
Add bd_getdev(), which attempts to return a dev_t corresponding
to a given device. Cases which it still doesn't get right:
- The inevitable da-when-wd-also-exists
- Disks with no slice table (the slice number is not set correctly)
The first is difficult to get right, the second will be
fixed in an upcoming commit.
comconsole.c
vidconsole.c
getchar() should return an 8-bit value; some BIOSsen pack extra
information in %eax.
libi386.h
Remove some stale prototypes, add new ones.
* Fix a raft of warnings, printf and otherwise.
* Allocate the correct amount in mod_searchmodule to prevent an overflow.
* Fix the makefiles so they work outside my home directory (oops).
- Discard large amounts of BIOS-related code in favour of the more compact
BTX vm86 interface.
- Build the loader module as ELF, although the resulting object is a.out,
make gensetdefs 32/64-bit sensitive and use a single copy of it.
- Throw away installboot, as it's no longer required.
- Use direct bcopy operations in the i386_copy module, as BTX
maps the first 16M of memory. Check operations against the
detected size of actual memory.
- Use format-independant module allocator.
- Conditionalise ISA PnP support.
- Simplify PnP enumerator interface.
- Improve module/object searching.
- Add missing depend/install targets in BTX makefiles.
- Pass the kernel environment and module data in extended bootinfo fields.
- Add a pointer to the end of the kernel + modules in bootinfo.
- Fix parsing of old-style kernel arguments.
- Move some startup code from MD to MI sections
- Add a 'copyout' and some copyout-related functions. These will be
obsoleted when BTX is available for the 386 and the kernel load
area becomes directly addressable.
- Add the ability load an arbitrary file as a module, associating
and arbitrary type string with it. This can be used eg. for loading
splash-screen images etc.
- Add KLD module dependancy infrastructure. We know how to look for
dependancies inside KLD modules, how to resolve these dependancies
and what to do if things go wrong. Only works for a.out at the
moment, due to lack of an MI ELF loader. Attach KLD module information
to loaded modules as metadata, but don't pass it to the kernel (it
can find it itself).
- Load a.out KLD modules on a page boundary. Only pad the a.out BSS
for the kernel, as it may want to throw symbols away. (We might want
to do this for KLD modules too.)
- Allow commands to be hidden from the '?' display, to avoid cluttering
it with things like 'echo'. Add 'echo'.
- Bring the 'prompt' command into line with the parser syntax.
- Fix the verbose 'ls'; it was using an uninitialised stack variable.
- Add a '-v' flag to 'lsmod' to have it display module metadata as well
(not terribly useful for the average user)
- Support a 'module searchpath' for required modules.
- The bootstrap file on i386 is now called 'loader' to permit the
/boot directory to use that name.
- Discard the old i386 pread() function, as it's replaced by
arch_readin()
- Implement a new copyin/readin interface for loading modules.
This allows the module loaders to become MI, reducing code duplication.
- Simplify the search for an image activator for the loaded kernel.
- Use the common module management code for all module metadata.
- Add an 'unload' command that throws everything away.
- Move the a.out module loader to MI code, add support for a.out
kld modules.
Submitted by: Alpha changes fixed by Doug Rabson <dfr@freebsd.org>
'three-stage' bootstrap.
There are a number of caveats with the code in its current state:
- The i386 bootstrap only supports booting from a floppy.
- The kernel and kld do not yet know how to deal with the extended
information and module summary passed in.
- PnP-based autodetection and demand loading of modules is not implemented.
- i386 ELF kernel loading is not ready yet.
- The i386 bootstrap is loaded via an ugly blockmap.
On the alpha, both net- and disk-booting (SRM console machines only) is
supported. No blockmaps are used by this code.
Obtained from: Parts from the NetBSD/i386 standalone bootstrap.