blob: d5f09ecc706c2a58c4da7620ff0d07b8c5dda8d5 [file] [log] [blame] [raw]
An experiment to make a Multiboot-compliant kFreeBSD i386 image.
Copyright 2019 Rivoreo
Added code are released under the FreeBSD license (2-clause).
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
--- a/sys/boot/common/load_elf.c 2016-03-25 09:09:27.000000000 +0800
+++ b/sys/boot/common/load_elf.c 2019-05-15 18:46:30.670084560 +0800
@@ -161,6 +161,9 @@
Elf_Ehdr *ehdr;
int err;
+#ifndef LOADER_USE_MULTIBOOT
+ if(multiboot) panic("%s: multiboot requested but LOADER_USE_MULTIBOOT was not set in build time", __func__);
+#endif
fp = NULL;
bzero(&ef, sizeof(struct elf_file));
ef.fd = -1;
@@ -210,12 +213,14 @@
ef.kernel = 1;
} else if (ehdr->e_type == ET_DYN) {
+#ifdef LOADER_USE_MULTIBOOT
/* Looks like a kld module */
if (multiboot != 0) {
printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n");
err = EPERM;
goto oerr;
}
+#endif
if (kfp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n");
err = EPERM;
@@ -248,14 +253,20 @@
err = EPERM;
goto out;
}
+#ifdef LOADER_USE_MULTIBOOT
if (ef.kernel == 1 && multiboot == 0)
+#endif
setenv("kernelname", filename, 1);
fp->f_name = strdup(filename);
+#ifdef LOADER_USE_MULTIBOOT
if (multiboot == 0)
+#endif
fp->f_type = strdup(ef.kernel ?
__elfN(kerneltype) : __elfN(moduletype));
+#ifdef LOADER_USE_MULTIBOOT
else
fp->f_type = strdup("elf multiboot kernel");
+#endif
#ifdef ELF_VERBOSE
if (ef.kernel)
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/boot/i386/libi386/multiboot.c b/sys/boot/i386/libi386/multiboot.c
--- a/sys/boot/i386/libi386/multiboot.c 2016-03-25 09:09:27.000000000 +0800
+++ b/sys/boot/i386/libi386/multiboot.c 2019-05-15 18:41:48.203156332 +0800
@@ -34,6 +34,8 @@
* http://www.gnu.org/software/grub/manual/multiboot/multiboot.html
*/
+#ifdef LOADER_USE_MULTIBOOT
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: releng/10.3/sys/boot/i386/libi386/multiboot.c 294417 2016-01-20 13:23:02Z royger $");
@@ -423,3 +425,5 @@
return (EFTYPE);
}
+
+#endif
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/boot/i386/libi386/multiboot_tramp.S b/sys/boot/i386/libi386/multiboot_tramp.S
--- a/sys/boot/i386/libi386/multiboot_tramp.S 2016-03-25 09:09:27.000000000 +0800
+++ b/sys/boot/i386/libi386/multiboot_tramp.S 2019-05-15 18:12:21.049222631 +0800
@@ -26,6 +26,8 @@
* $FreeBSD: releng/10.3/sys/boot/i386/libi386/multiboot_tramp.S 294417 2016-01-20 13:23:02Z royger $
*/
+#ifdef LOADER_USE_MULTIBOOT
+
#define ASM_FILE
#include "multiboot.h"
@@ -49,3 +51,5 @@
movl 4(%esp), %ecx
call *%ecx
+
+#endif
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/boot/i386/loader/conf.c b/sys/boot/i386/loader/conf.c
--- a/sys/boot/i386/loader/conf.c 2016-03-25 09:09:27.000000000 +0800
+++ b/sys/boot/i386/loader/conf.c 2019-05-15 18:41:37.218103623 +0800
@@ -107,12 +107,12 @@
extern struct file_format i386_elf_obj;
extern struct file_format amd64_elf;
extern struct file_format amd64_elf_obj;
+#ifdef LOADER_USE_MULTIBOOT
extern struct file_format multiboot;
extern struct file_format multiboot_obj;
+#endif
struct file_format *file_formats[] = {
- &multiboot,
- &multiboot_obj,
#ifdef LOADER_PREFER_AMD64
&amd64_elf,
&amd64_elf_obj,
@@ -123,6 +123,10 @@
&amd64_elf,
&amd64_elf_obj,
#endif
+#ifdef LOADER_USE_MULTIBOOT
+ &multiboot,
+ &multiboot_obj,
+#endif
NULL
};
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
--- a/sys/conf/kern.pre.mk 2016-03-25 09:09:25.000000000 +0800
+++ b/sys/conf/kern.pre.mk 2019-05-22 12:22:13.634155265 +0800
@@ -170,8 +170,8 @@
SYSTEM_OBJS= locore.o ${MDOBJS} ${OBJS}
SYSTEM_OBJS+= ${SYSTEM_CFILES:.c=.o}
SYSTEM_OBJS+= hack.So
-SYSTEM_LD= @${LD} -Bdynamic -T ${LDSCRIPT} ${LDFLAGS} --no-warn-mismatch \
- -warn-common -export-dynamic -dynamic-linker /red/herring \
+SYSTEM_LD= @${LD} --call_shared -T ${LDSCRIPT} ${LDFLAGS} --no-warn-mismatch \
+ --warn-common --export-dynamic --dynamic-linker "" \
-o ${.TARGET} -X ${SYSTEM_OBJS} vers.o
SYSTEM_LD_TAIL= @${OBJCOPY} --strip-symbol gcc2_compiled. ${.TARGET} ; \
${SIZE} ${.TARGET} ; chmod 755 ${.TARGET}
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/conf/ldscript.i386 b/sys/conf/ldscript.i386
--- a/sys/conf/ldscript.i386 2016-03-25 09:09:25.000000000 +0800
+++ b/sys/conf/ldscript.i386 2019-05-21 15:02:11.235524344 +0800
@@ -7,7 +7,7 @@
{
/* Read-only sections, merged into text segment: */
. = kernbase + kernload + SIZEOF_HEADERS;
- .interp : { *(.interp) }
+ .mbheader : AT (ADDR(.mbheader) - kernbase) { *(.mbheader) *(.interp) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/conf/options b/sys/conf/options
--- a/sys/conf/options 2016-03-25 09:09:25.000000000 +0800
+++ b/sys/conf/options 2019-05-24 12:58:42.461252499 +0800
@@ -941,3 +941,6 @@
# Intel em(4) driver
EM_MULTIQUEUE opt_em.h
+
+# Multiboot support, for i386 only
+MULTIBOOT opt_multiboot.h
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/i386/conf/Rivoreo b/sys/i386/conf/Rivoreo
--- a/sys/i386/conf/Rivoreo 1970-01-01 08:00:00.000000000 +0800
+++ b/sys/i386/conf/Rivoreo 2019-05-24 14:15:22.331939846 +0800
@@ -0,0 +1,379 @@
+#
+# GENERIC -- Generic kernel configuration file for FreeBSD/i386
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD: releng/10.3/sys/i386/conf/GENERIC 286132 2015-07-31 15:25:07Z gjb $
+
+ident Rivoreo
+
+cpu I486_CPU
+cpu I586_CPU
+cpu I686_CPU
+
+#makeoptions CC=gcc
+makeoptions COPTFLAGS="-Os --pipe"
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support
+makeoptions WITHOUT_SOURCELESS_HOST=1
+
+options SCHED_ULE # ULE scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options TCP_OFFLOAD # TCP offload
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_EXTATTR
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options MD_ROOT # MD is a potential root device
+options NFSCL # New Network Filesystem Client
+options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+#options MSDOSFS # MSDOS Filesystem
+#options CD9660 # ISO 9660 Filesystem
+#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options GEOM_PART_GPT # GUID Partition Tables.
+options GEOM_PART_MBR
+options GEOM_PART_BSD
+options GEOM_RAID # Soft RAID functionality.
+options GEOM_LABEL # Provides labelization
+options COMPAT_FREEBSD4 # Compatible with FreeBSD4
+options COMPAT_FREEBSD5 # Compatible with FreeBSD5
+options COMPAT_FREEBSD6 # Compatible with FreeBSD6
+options COMPAT_FREEBSD7 # Compatible with FreeBSD7
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+options STACK # stack(9) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed.
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4)
+options AUDIT # Security event auditing
+options CAPABILITY_MODE # Capsicum capability mode
+options CAPABILITIES # Capsicum capabilities
+options PROCDESC # Support for process descriptors
+options MAC # TrustedBSD MAC Framework
+options KDTRACE_HOOKS # Kernel DTrace hooks
+options DDB_CTF # Kernel ELF linker loads CTF data
+options INCLUDE_CONFIG_FILE # Include this file in kernel
+options RACCT # Resource accounting framework
+options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
+options RCTL # Resource limits
+options MULTIBOOT
+
+# Debugging support. Always need this:
+options KDB # Enable kernel debugger support.
+options KDB_TRACE # Print a stack trace for a panic.
+
+# To make an SMP kernel, the next two lines are needed
+options SMP # Symmetric MultiProcessor Kernel
+device apic # I/O APIC
+
+# CPU frequency control
+device cpufreq
+
+device mem
+
+# Bus support.
+device acpi
+device eisa
+device pci
+device isa
+device io
+
+# Floppy drives
+device fdc
+
+# ATA controllers
+device ahci # AHCI-compatible SATA controllers
+device ata # Legacy ATA/SATA controllers
+options ATA_STATIC_ID # Static device numbering
+device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
+device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA
+
+# SCSI Controllers
+device ahb # EISA AHA1742 family
+device ahc # AHA2940 and onboard AIC7xxx devices
+options AHC_REG_PRETTY_PRINT # Print register bitfields in debug
+ # output. Adds ~128k to driver.
+device ahd # AHA39320/29320 and onboard AIC79xx devices
+options AHD_REG_PRETTY_PRINT # Print register bitfields in debug
+ # output. Adds ~215k to driver.
+device esp # AMD Am53C974 (Tekram DC-390(T))
+device hptiop # Highpoint RocketRaid 3xxx series
+device isp # Qlogic family
+#device ispfw # Firmware for QLogic HBAs- normally a module
+device mpt # LSI-Logic MPT-Fusion
+device mps # LSI-Logic MPT-Fusion 2
+device mpr # LSI-Logic MPT-Fusion 3
+#device ncr # NCR/Symbios Logic
+device sym # NCR/Symbios Logic (newer chipsets + those of `ncr')
+device trm # Tekram DC395U/UW/F DC315U adapters
+
+device adv # Advansys SCSI adapters
+device adw # Advansys wide SCSI adapters
+device aha # Adaptec 154x SCSI adapters
+device aic # Adaptec 15[012]x SCSI adapters, AIC-6[23]60.
+device bt # Buslogic/Mylex MultiMaster SCSI adapters
+
+device ncv # NCR 53C500
+device nsp # Workbit Ninja SCSI-3
+device stg # TMC 18C30/18C50
+device isci # Intel C600 SAS controller
+
+# ATA/SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device ch # SCSI media changers
+device da # Direct Access (disks)
+device sa # Sequential Access (tape etc)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+device ses # Enclosure Services (SES and SAF-TE)
+#device ctl # CAM Target Layer
+
+# RAID controllers interfaced to the SCSI subsystem
+device amr # AMI MegaRAID
+device arcmsr # Areca SATA II RAID
+device asr # DPT SmartRAID V, VI and Adaptec SCSI RAID
+device ciss # Compaq Smart RAID 5*
+device dpt # DPT Smartcache III, IV - See NOTES for options
+device iir # Intel Integrated RAID
+device ips # IBM (Adaptec) ServeRAID
+device mly # Mylex AcceleRAID/eXtremeRAID
+device twa # 3ware 9000 series PATA/SATA RAID
+device tws # LSI 3ware 9750 SATA+SAS 6Gb/s RAID controller
+
+# RAID controllers
+device aac # Adaptec FSA RAID
+device aacp # SCSI passthrough for aac (requires CAM)
+device aacraid # Adaptec by PMC RAID
+device ida # Compaq Smart RAID
+device mfi # LSI MegaRAID SAS
+device mlx # Mylex DAC960 family
+device mrsas # LSI/Avago MegaRAID SAS/SATA, 6Gb/s and 12Gb/s
+#XXX PCI ID conflicts with ahd(4) and mvs(4)
+#device pmspcv # PMC-Sierra SAS/SATA Controller driver
+device pst # Promise Supertrak SX6000
+device twe # 3ware ATA RAID
+
+# NVM Express (NVMe) support
+device nvme # base NVMe driver
+device nvd # expose NVMe namespace as disks, depends on nvme
+
+# atkbdc0 controls both the keyboard and the PS/2 mouse
+device atkbdc # AT keyboard controller
+device atkbd # AT keyboard
+device psm # PS/2 mouse
+
+device kbdmux # keyboard multiplexer
+
+device vga # VGA video card driver
+options VESA # Add support for VESA BIOS Extensions (VBE)
+
+device splash # Splash screen and screen saver support
+
+# syscons is the default console driver, resembling an SCO console
+device sc
+options SC_PIXEL_MODE # add support for the raster text mode
+
+# vt is the new video console driver
+device vt
+device vt_vga
+
+device agp # support several AGP chipsets
+
+# Power management support (see NOTES for more options)
+#device apm
+# Add suspend/resume support for the i8254.
+device pmtimer
+
+# PCCARD (PCMCIA) support
+# PCMCIA and cardbus bridge support
+device cbb # cardbus (yenta) bridge
+device pccard # PC Card (16-bit) bus
+device cardbus # CardBus (32-bit) bus
+
+# Serial (COM) ports
+device uart # Generic UART driver
+
+# Parallel port
+device ppc
+device ppbus # Parallel port bus (required)
+device lpt # Printer
+device ppi # Parallel port interface device
+#device vpo # Requires scbus and da
+
+device puc # Multi I/O cards and multi-channel UARTs
+
+# PCI Ethernet NICs.
+device bxe # Broadcom NetXtreme II BCM5771X/BCM578XX 10GbE
+device de # DEC/Intel DC21x4x (``Tulip'')
+device em # Intel PRO/1000 Gigabit Ethernet Family
+device igb # Intel PRO/1000 PCIE Server Gigabit Family
+device ixgb # Intel PRO/10GbE Ethernet Card
+device le # AMD Am7900 LANCE and Am79C9xx PCnet
+device ti # Alteon Networks Tigon I/II gigabit Ethernet
+device txp # 3Com 3cR990 (``Typhoon'')
+device vx # 3Com 3c590, 3c595 (``Vortex'')
+
+# PCI Ethernet NICs that use the common MII bus controller code.
+# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
+device miibus # MII bus support
+device ae # Attansic/Atheros L2 FastEthernet
+device age # Attansic/Atheros L1 Gigabit Ethernet
+device alc # Atheros AR8131/AR8132 Ethernet
+device ale # Atheros AR8121/AR8113/AR8114 Ethernet
+device bce # Broadcom BCM5706/BCM5708 Gigabit Ethernet
+device bfe # Broadcom BCM440x 10/100 Ethernet
+device bge # Broadcom BCM570xx Gigabit Ethernet
+device cas # Sun Cassini/Cassini+ and NS DP83065 Saturn
+device dc # DEC/Intel 21143 and various workalikes
+device et # Agere ET1310 10/100/Gigabit Ethernet
+device fxp # Intel EtherExpress PRO/100B (82557, 82558)
+device gem # Sun GEM/Sun ERI/Apple GMAC
+device hme # Sun HME (Happy Meal Ethernet)
+device jme # JMicron JMC250 Gigabit/JMC260 Fast Ethernet
+device lge # Level 1 LXT1001 gigabit Ethernet
+device msk # Marvell/SysKonnect Yukon II Gigabit Ethernet
+device nfe # nVidia nForce MCP on-board Ethernet
+device nge # NatSemi DP83820 gigabit Ethernet
+device pcn # AMD Am79C97x PCI 10/100 (precedence over 'le')
+device re # RealTek 8139C+/8169/8169S/8110S
+device rl # RealTek 8129/8139
+device sf # Adaptec AIC-6915 (``Starfire'')
+device sge # Silicon Integrated Systems SiS190/191
+device sis # Silicon Integrated Systems SiS 900/SiS 7016
+device sk # SysKonnect SK-984x & SK-982x gigabit Ethernet
+device ste # Sundance ST201 (D-Link DFE-550TX)
+device stge # Sundance/Tamarack TC9021 gigabit Ethernet
+device tl # Texas Instruments ThunderLAN
+device tx # SMC EtherPower II (83c170 ``EPIC'')
+device vge # VIA VT612x gigabit Ethernet
+device vr # VIA Rhine, Rhine II
+device vte # DM&P Vortex86 RDC R6040 Fast Ethernet
+device wb # Winbond W89C840F
+device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'')
+
+# ISA Ethernet NICs. pccard NICs included.
+device cs # Crystal Semiconductor CS89x0 NIC
+# 'device ed' requires 'device miibus'
+device ed # NE[12]000, SMC Ultra, 3c503, DS8390 cards
+device ex # Intel EtherExpress Pro/10 and Pro/10+
+device ep # Etherlink III based cards
+device fe # Fujitsu MB8696x based cards
+device ie # EtherExpress 8/16, 3C507, StarLAN 10 etc.
+device sn # SMC's 9000 series of Ethernet chips
+device xe # Xircom pccard Ethernet
+
+# Wireless NIC cards
+device wlan # 802.11 support
+options IEEE80211_DEBUG # enable debug msgs
+options IEEE80211_AMPDU_AGE # age frames in AMPDU reorder q's
+options IEEE80211_SUPPORT_MESH # enable 802.11s draft support
+device wlan_wep # 802.11 WEP support
+device wlan_ccmp # 802.11 CCMP support
+device wlan_tkip # 802.11 TKIP support
+device wlan_amrr # AMRR transmit rate control algorithm
+device an # Aironet 4500/4800 802.11 wireless NICs.
+device ath # Atheros NICs
+device ath_pci # Atheros pci/cardbus glue
+device ath_hal # pci/cardbus chip support
+options AH_SUPPORT_AR5416 # enable AR5416 tx/rx descriptors
+options AH_AR5416_INTERRUPT_MITIGATION # AR5416 interrupt mitigation
+options ATH_ENABLE_11N # Enable 802.11n support for AR5416 and later
+device ath_rate_sample # SampleRate tx rate control for ath
+#device bwi # Broadcom BCM430x/BCM431x wireless NICs.
+#device bwn # Broadcom BCM43xx wireless NICs.
+device ipw # Intel 2100 wireless NICs.
+device iwi # Intel 2200BG/2225BG/2915ABG wireless NICs.
+device iwn # Intel 4965/1000/5000/6000 wireless NICs.
+device malo # Marvell Libertas wireless NICs.
+device mwl # Marvell 88W8363 802.11n wireless NICs.
+device ral # Ralink Technology RT2500 wireless NICs.
+device wi # WaveLAN/Intersil/Symbol 802.11 wireless NICs.
+#device wl # Older non 802.11 Wavelan wireless NIC.
+device wpi # Intel 3945ABG wireless NICs.
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device padlock_rng # VIA Padlock RNG
+device rdrand_rng # Intel Bull Mountain RNG
+device ether # Ethernet support
+device vlan # 802.1Q VLAN support
+device md # Memory "disks"
+device firmware # firmware assist module
+
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device bpf # Berkeley packet filter
+
+# USB support
+options USB_DEBUG # enable debug msgs
+device uhci # UHCI PCI->USB interface
+device ohci # OHCI PCI->USB interface
+device ehci # EHCI PCI->USB interface (USB 2.0)
+device xhci # XHCI PCI->USB interface (USB 3.0)
+device usb # USB Bus (required)
+device ukbd # Keyboard
+device umass # Disks/Mass storage - Requires scbus and da
+
+# Sound support
+device sound # Generic sound driver (required)
+device snd_cmi # CMedia CMI8338/CMI8738
+device snd_csa # Crystal Semiconductor CS461x/428x
+device snd_emu10kx # Creative SoundBlaster Live! and Audigy
+device snd_es137x # Ensoniq AudioPCI ES137x
+device snd_hda # Intel High Definition Audio
+device snd_ich # Intel, NVidia and other ICH AC'97 Audio
+device snd_via8233 # VIA VT8233x Audio
+
+# MMC/SD
+device mmc # MMC/SD bus
+device mmcsd # MMC/SD memory card
+device sdhci # Generic PCI SD Host Controller
+
+# VirtIO support
+device virtio # Generic VirtIO bus (required)
+device virtio_pci # VirtIO PCI device
+device vtnet # VirtIO Ethernet device
+device virtio_blk # VirtIO Block device
+device virtio_scsi # VirtIO SCSI device
+device virtio_balloon # VirtIO Memory Balloon device
+
+# HyperV drivers and enchancement support
+# NOTE: HYPERV depends on hyperv. They must be added or removed together.
+options HYPERV # Hyper-V kernel infrastructure
+device hyperv # HyperV drivers
+
+# Xen HVM Guest Optimizations
+# NOTE: XENHVM depends on xenpci. They must be added or removed together.
+#options XENHVM # Xen HVM kernel infrastructure
+#device xenpci # Xen HVM Hypervisor services driver
+
+# VMware support
+#device vmx # VMware VMXNET3 Ethernet
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s
--- a/sys/i386/i386/locore.s 2016-03-25 09:09:25.000000000 +0800
+++ b/sys/i386/i386/locore.s 2019-05-24 13:10:42.989381512 +0800
@@ -43,10 +43,11 @@
#include "opt_compat.h"
#include "opt_nfsroot.h"
#include "opt_pmap.h"
+#include "opt_multiboot.h"
#include <sys/syscall.h>
#include <sys/reboot.h>
-
+#include <sys/multiboot.h>
#include <machine/asmacros.h>
#include <machine/cputypes.h>
#include <machine/psl.h>
@@ -126,6 +127,22 @@
.space 0x240
#endif
+#ifdef MULTIBOOT
+ .globl multiboot_env
+multiboot_env: .long 0
+ .globl multiboot_mem_lower, multiboot_mem_upper, multiboot_cmdline, multiboot_mods
+multiboot_mem_lower:
+ .long 0
+multiboot_mem_upper:
+ .long 0
+multiboot_cmdline:
+ .space MI_CMDLINE_MAX, 0
+ .byte 0
+multiboot_mods:
+ .long 0
+ .long 0
+#endif
+
/**********************************************************************
*
* Some handy macros
@@ -175,6 +192,16 @@
shrl $PAGE_SHIFT, %ebx ; \
fillkpt(R(KPTphys), prot)
+ .section .mbheader
+ .align 4
+#ifdef MULTIBOOT
+#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_PAGE_ALIGN|MULTIBOOT_MEMORY_INFO)
+multiboot_header:
+ .long MULTIBOOT_HEADER_MAGIC
+ .long MULTIBOOT_HEADER_FLAGS
+ .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
+#endif
+
.text
/**********************************************************************
*
@@ -196,6 +223,17 @@
movw $0x1234,0x472
#endif /* PC98 */
+#ifdef MULTIBOOT
+ /* Are we booted up by a multiboot bootloader? */
+ cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
+ jne 1f
+ movl $0, R(bootinfo+BI_KERNEND)
+ movl %ebx, R(multiboot_env)
+ jmp 2f
+
+1:
+#endif
+
/* Set up a real frame in case the double return in newboot is executed. */
pushl %ebp
movl %esp, %ebp
@@ -232,6 +270,8 @@
call recover_bootinfo
+2:
+
/* Get onto a stack that we can trust. */
/*
* XXX this step is delayed in case recover_bootinfo needs to return via
@@ -239,6 +279,12 @@
* returns via the old frame.
*/
movl $R(tmpstk),%esp
+#ifdef MULTIBOOT
+ cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax /* %eax remains same if we jumped here by label 2 */
+ jne 3f
+ call recover_multiboot_env
+3:
+#endif
#ifdef PC98
/* pc98_machine_type & M_EPSON_PC98 */
@@ -552,6 +598,69 @@
ret
+#ifdef MULTIBOOT
+/* https://www.gnu.org/software/grub/manual/multiboot/html_node/Boot-information-format.html */
+recover_multiboot_env:
+ movl R(multiboot_env), %eax
+ testl $MI_FLAG_MEMORY, (%eax)
+ jz 1f
+ /* Recover memory information */
+ movl MI_MEM_LOWER(%eax), %ecx
+ movl %ecx, R(multiboot_mem_lower)
+ movl MI_MEM_UPPER(%eax), %ecx
+ movl %ecx, R(multiboot_mem_upper)
+1:
+ testl $MI_FLAG_CMDLINE, (%eax)
+ jz 6f
+ /* Recover cmdline. */
+ movl MI_CMDLINE(%eax), %esi
+ movl $R(multiboot_cmdline), %edi
+ movl $MI_CMDLINE_MAX, %ecx
+ cld
+2:
+ cmpl $0, (%esi)
+ jz 3f
+ movsb
+ testl %ecx, %ecx
+ jnz 2b
+3:
+ /* Copy first arguament to kernelname if it starts with '/' */
+ movl MI_CMDLINE(%eax), %esi
+ cmpb $'/', (%esi)
+ jne 6f
+ movl $MAXPATHLEN-1, %ecx
+ movl $R(kernelname), %edi
+ cld
+4:
+ cmpb $' ', (%esi)
+ je 5f
+ cmpb $0, (%esi)
+ je 5f
+ movsb
+ testl %ecx, %ecx
+ jnz 4b
+5:
+ movb $0, (%edi)
+6:
+ testl $MI_FLAG_MODS, (%eax)
+ jz 7f
+ movl MI_MODS_ADDR(%eax), %ecx
+ movl %ecx, R(multiboot_mods+4)
+ movl MI_MODS_COUNT(%eax), %ecx
+ movl %ecx, R(multiboot_mods)
+ /* Set bootinfo.bi_kernend from multiboot modules if any */
+ testl %ecx, %ecx
+ jz 7f
+// pushl %eax
+ pushl %ecx
+ pushl R(multiboot_mods+4)
+ call get_kernend_from_multiboot_mods
+ addl $8, %esp
+// popl %eax
+7:
+ ret
+#endif
+
/**********************************************************************
*
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
--- a/sys/i386/i386/machdep.c 2016-03-25 09:09:25.000000000 +0800
+++ b/sys/i386/i386/machdep.c 2019-05-24 14:08:17.171974098 +0800
@@ -57,6 +57,7 @@
#include "opt_platform.h"
#include "opt_xbox.h"
#include "opt_kdtrace.h"
+#include "opt_multiboot.h"
#include <sys/param.h>
#include <sys/proc.h>
@@ -121,6 +122,10 @@
#include <net/netisr.h>
#include <machine/bootinfo.h>
+#ifdef MULTIBOOT
+#include <machine/multiboot.h>
+#include <machine/elf.h>
+#endif
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cputypes.h>
@@ -2206,6 +2211,10 @@
}
#endif /* !XEN */
+#ifdef MULTIBOOT
+int ignore_multiboot_memory_size = 0;
+#endif
+
/*
* Populate the (physmap) array with base/bound pairs describing the
* available physical memory in the system, then test this memory and
@@ -2556,6 +2565,15 @@
goto have_smap;
}
+#ifdef MULTIBOOT
+ if(!ignore_multiboot_memory_size && multiboot_env && multiboot_mem_lower && multiboot_mem_upper) {
+ basemem = multiboot_mem_lower;
+ basemem_setup();
+ extmem = multiboot_mem_upper;
+ goto skip_bios_calls;
+ }
+#endif
+
/*
* Some newer BIOSes have a broken INT 12H implementation
* which causes a kernel panic immediately. In this case, we
@@ -2644,6 +2662,9 @@
#endif
}
+#ifdef MULTIBOOT
+skip_bios_calls:
+#endif
/*
* Special hack for chipsets that still remap the 384k hole when
* there's 16MB of memory - this really confuses people that
@@ -2894,6 +2915,276 @@
}
#endif /* PC98 */
+#ifdef MULTIBOOT
+extern int _end;
+
+static size_t fill_module_info_from_multiboot(caddr_t addr) {
+ size_t r = 0;
+ unsigned int i = 0;
+ // Note the first module in bootinfo.bi_modulep should be the kernel image itself.
+ size_t kernel_name_len = strlen(kernelname) + 1;
+ r += sizeof(uint32_t) * 2 + roundup(kernel_name_len, sizeof(uint32_t));
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_NAME;
+ ((uint32_t *)addr)[1] = kernel_name_len;
+ memcpy(addr + sizeof(uint32_t) * 2, kernelname, kernel_name_len);
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ r += sizeof(uint32_t) * 2 + roundup(sizeof "elf kernel", sizeof(uint32_t));
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_TYPE;
+ ((uint32_t *)addr)[1] = sizeof "elf kernel";
+ strcpy(addr + sizeof(uint32_t) * 2, "elf kernel");
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ if(*multiboot_cmdline) {
+ const char *space = strchr(multiboot_cmdline, ' ');
+ if(space) {
+ size_t len = strlen(space + 1) + 1;
+ r += sizeof(uint32_t) * 2 + roundup(len, sizeof(uint32_t));
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_ARGS;
+ ((uint32_t *)addr)[1] = len;
+ memcpy(addr + sizeof(uint32_t) * 2, space + 1, len);
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ }
+ }
+ r += sizeof(uint32_t) * 2 + sizeof(caddr_t);
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_ADDR;
+ ((uint32_t *)addr)[1] = sizeof(uint32_t);
+ *(caddr_t *)(addr + sizeof(uint32_t) * 2) = (caddr_t)KERNLOAD;
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ r += sizeof(uint32_t) * 2 + sizeof(size_t);
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_SIZE;
+ ((uint32_t *)addr)[1] = sizeof(uint32_t);
+ *(size_t *)(addr + sizeof(uint32_t) * 2) = (size_t)((caddr_t)&_end - (caddr_t)(KERNLOAD + KERNBASE));
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ while(i < multiboot_mods.count) {
+ struct multiboot_module *mbmod = (struct multiboot_module *)((caddr_t)(multiboot_mods.address + i) + KERNBASE);
+ const char *name = (const char *)mbmod->cmdline;
+ const char *space = strchr(name, ' ');
+ size_t name_len = space ? (space - name) : strlen(name);
+ r += sizeof(uint32_t) * 2 + roundup(name_len + 1, sizeof(uint32_t));
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_NAME;
+ ((uint32_t *)addr)[1] = name_len + 1;
+ memcpy(addr + sizeof(uint32_t) * 2, name, name_len);
+ addr[sizeof(uint32_t) * 2 + name_len] = 0;
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+
+ // XXX: Assuming other module types are 'md_image' (initrd).
+ const char *module_type = "md_image";
+ size_t module_type_len = sizeof "md_image";
+ size_t multiboot_module_size = mbmod->mod_end - mbmod->mod_start;
+ Elf_Ehdr *elfhdr = NULL;
+ caddr_t *start_address;
+ size_t *module_size;
+ if(multiboot_module_size > sizeof(Elf_Ehdr)) {
+ elfhdr = (Elf_Ehdr *)mbmod->mod_start;
+ if(IS_ELF(*elfhdr) && elfhdr->e_ident[EI_CLASS] == ELFCLASS32 &&
+ elfhdr->e_ident[EI_DATA] == ELFDATA2LSB &&
+ elfhdr->e_ident[EI_VERSION] == EV_CURRENT &&
+ elfhdr->e_version == EV_CURRENT && elfhdr->e_machine == EM_386) {
+ //switch(elfhdr->e_type)
+ // i386 kernel didn't use relocatable object
+ module_type = "elf module";
+ module_type_len = sizeof "elf module";
+ } else {
+ elfhdr = NULL;
+ }
+ }
+ r += sizeof(uint32_t) * 2 + roundup(module_type_len, sizeof(uint32_t));
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_TYPE;
+ ((uint32_t *)addr)[1] = module_type_len;
+ memcpy(addr + sizeof(uint32_t) * 2, module_type, module_type_len);
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ if(space) {
+ size_t len = strlen(space + 1) + 1;
+ r += sizeof(uint32_t) * 2 + roundup(len, sizeof(uint32_t));
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_ARGS;
+ ((uint32_t *)addr)[1] = len;
+ memcpy(addr + sizeof(uint32_t) * 2, space + 1, len);
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ }
+ r += sizeof(uint32_t) * 2 + sizeof(caddr_t);
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_ADDR;
+ ((uint32_t *)addr)[1] = sizeof(caddr_t);
+ start_address = (caddr_t *)(addr + sizeof(uint32_t) * 2);
+ *start_address = (caddr_t)mbmod->mod_start;
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ r += sizeof(uint32_t) * 2 + sizeof(size_t);
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_SIZE;
+ ((uint32_t *)addr)[1] = sizeof(size_t);
+ module_size = (size_t *)(addr + sizeof(uint32_t) * 2);
+ *module_size = multiboot_module_size;
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ if(elfhdr) {
+ r += sizeof(uint32_t) * 2 + roundup(sizeof(Elf_Ehdr), sizeof(uint32_t));
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_METADATA | MODINFOMD_ELFHDR;
+ ((uint32_t *)addr)[1] = sizeof(Elf_Ehdr);
+ memcpy(addr + sizeof(uint32_t) * 2, elfhdr, sizeof(Elf_Ehdr));
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ Elf_Phdr *phdr = (Elf_Phdr *)(mbmod->mod_start + elfhdr->e_phoff);
+ if((uint32_t)phdr < mbmod->mod_end) {
+ uint32_t segment_offset = (uint32_t)-1;
+ uint32_t segment_end_offset = 0;
+ unsigned int j = 0;
+ while(j < elfhdr->e_phnum) {
+ if(phdr->p_filesz < phdr->p_memsz) {
+ // This gap was the BSS
+ if(mbmod->mod_start + phdr->p_offset + phdr->p_memsz > mbmod->mod_end) {
+ // No room to fill BSS, sorry...
+ break;
+ }
+ memset((caddr_t)(mbmod->mod_start + phdr->p_offset + phdr->p_filesz),
+ 0, phdr->p_memsz - phdr->p_filesz);
+ }/* else if(phdr->p_filesz > phdr->p_memsz) {
+ // What?
+ break;
+ }*/
+ if(phdr->p_offset < phdr->p_vaddr) {
+ // Relocate segment
+ if(mbmod->mod_start + phdr->p_vaddr + phdr->p_memsz > mbmod->mod_end) {
+ // No room to relocate, sorry...
+ break;
+ }
+ memmove((caddr_t)(mbmod->mod_start + phdr->p_vaddr),
+ (caddr_t)(mbmod->mod_start + phdr->p_offset), phdr->p_memsz);
+ } else if(phdr->p_offset > phdr->p_vaddr) {
+ // Hm?
+ memmove((caddr_t)(mbmod->mod_start + phdr->p_vaddr),
+ (caddr_t)(mbmod->mod_start + phdr->p_offset), phdr->p_memsz);
+ }
+ switch(phdr->p_type) {
+ case PT_LOAD:
+ //if(!addr) break;
+ if(segment_offset > phdr->p_vaddr) {
+ segment_offset = phdr->p_vaddr;
+ }
+ if(segment_end_offset < phdr->p_vaddr + phdr->p_memsz) {
+ segment_end_offset = phdr->p_vaddr + phdr->p_memsz;
+ }
+ break;
+ case PT_DYNAMIC:
+ r += sizeof phdr->p_vaddr;
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_METADATA | MODINFOMD_DYNAMIC;
+ ((uint32_t *)addr)[1] = sizeof phdr->p_vaddr;
+ *(Elf_Addr *)(addr + sizeof(uint32_t) * 2) = phdr->p_vaddr;
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ break;
+ }
+ phdr++;
+ j++;
+ }
+ if(addr && segment_offset != (uint32_t)-1 && segment_end_offset) {
+ *start_address += segment_offset;
+ *module_size = roundup(segment_end_offset - segment_offset, sizeof(uint32_t));
+ }
+ size_t shdr_size = elfhdr->e_shnum * elfhdr->e_shentsize;
+ if(shdr_size && shdr_size <= multiboot_module_size - elfhdr->e_shoff &&
+ segment_offset != (uint32_t)-1 && segment_end_offset) {
+ unsigned int k;
+ Elf_Shdr *shdr = (Elf_Shdr *)(mbmod->mod_start + elfhdr->e_shoff);
+/* // Skip MODINFOMD_SHDR, i386 kernel doesn't use it
+ r += sizeof(uint32_t) * 2 + roundup(shdr_size, sizeof(uint32_t));
+ if(addr) {
+ ((uint32_t *)addr)[0] = MODINFO_METADATA | MODINFOMD_SHDR;
+ ((uint32_t *)addr)[1] = shdr_size;
+ memcpy(addr + sizeof(uint32_t) * 2, shdr, shdr_size);
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+*/
+ // XXX: Assuming MODINFOMD_SSYM and MODINFOMD_ESYM will be written
+ r += (sizeof(uint32_t) * 2 + sizeof(Elf_Addr)) * 2;
+ if(addr) {
+ Elf_Addr ssym = 0, esym = 0;
+ int symtabi = -1, symstri = -1;
+ phdr = (Elf_Phdr *)(mbmod->mod_start + elfhdr->e_phoff);
+ for(j = 0; j < elfhdr->e_shnum; j++) {
+ if(shdr[j].sh_type != SHT_SYMTAB) continue;
+ for(k = 0; k < elfhdr->e_phnum; k++) {
+ if(phdr[k].p_type != PT_LOAD) continue;
+ if(shdr[j].sh_offset >= phdr[k].p_offset &&
+ (shdr[j].sh_offset + shdr[j].sh_size <=
+ phdr[k].p_offset + phdr[k].p_filesz)) {
+ shdr[j].sh_offset = 0;
+ shdr[j].sh_size = 0;
+ }
+ if(!shdr[j].sh_offset || !shdr[j].sh_size) continue;
+ symtabi = j;
+ symstri = shdr[j].sh_link;
+ }
+ }
+ if(symtabi >= 0 && symstri >= 0) {
+ caddr_t rewrite = (caddr_t)(mbmod->mod_start + segment_end_offset);
+ ssym = (Elf_Addr)rewrite;
+ for(j = symtabi; j >= 0; j = symstri) {
+ if(mbmod->mod_start + shdr[j].sh_offset + shdr[j].sh_size > mbmod->mod_end) {
+ ssym = 0;
+ break;
+ }
+ *(Elf_Size *)rewrite = shdr[j].sh_size;
+ rewrite += sizeof(Elf_Size);
+ memmove(rewrite, (caddr_t)(mbmod->mod_start + shdr[j].sh_offset), shdr[j].sh_size);
+ rewrite += roundup(shdr[j].sh_size, sizeof(Elf_Size));
+ if(j == symstri) break;
+ }
+ if(ssym) {
+ esym = (Elf_Addr)rewrite;
+ *module_size = roundup(rewrite - *start_address, sizeof(uint32_t));
+ }
+ }
+ ((uint32_t *)addr)[0] = MODINFO_METADATA | MODINFOMD_SSYM;
+ ((uint32_t *)addr)[1] = sizeof ssym;
+ *(Elf_Addr *)(addr + sizeof(uint32_t) * 2) = ssym;
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ ((uint32_t *)addr)[0] = MODINFO_METADATA | MODINFOMD_ESYM;
+ ((uint32_t *)addr)[1] = sizeof esym;
+ *(Elf_Addr *)(addr + sizeof(uint32_t) * 2) = esym;
+ addr += roundup(sizeof(uint32_t) * 2 + ((uint32_t *)addr)[1], sizeof(uint32_t));
+ }
+ }
+ }
+ }
+ i++;
+ }
+ r += sizeof(uint32_t) * 2;
+ if(addr) memset(addr, 0, sizeof(uint32_t) * 2);
+ return r;
+}
+
+// Prepare bootinfo.bi_modulep from the current image and multiboot modules if any
+static int init_multiboot_modules(int addr) {
+ size_t module_len = fill_module_info_from_multiboot(NULL);
+ int page = addr;
+ do {
+ pmap_kenter(page + KERNBASE, page);
+ page += PAGE_SIZE;
+ } while(page < addr + module_len);
+ bootinfo.bi_modulep = addr;
+ fill_module_info_from_multiboot((caddr_t)(addr + KERNBASE));
+ return page - addr;
+}
+#endif /* MULTIBOOT */
+
#ifdef XEN
#define MTOPSIZE (1<<(14 + PAGE_SHIFT))
@@ -3183,6 +3474,15 @@
pc98_init_dmac();
#endif
+#ifdef MULTIBOOT
+ if(multiboot_env) {
+ pmap_kenter(first + KERNBASE, first);
+ parse_kernel_command_line(multiboot_cmdline,
+ (char *)(first + KERNBASE), PAGE_SIZE);
+ first += PAGE_SIZE;
+ first += init_multiboot_modules(first);
+ }
+#endif
metadata_missing = 0;
if (bootinfo.bi_modulep) {
preload_metadata = (caddr_t)bootinfo.bi_modulep + KERNBASE;
@@ -3191,10 +3491,18 @@
metadata_missing = 1;
}
- if (bootinfo.bi_envp)
- init_static_kenv((caddr_t)bootinfo.bi_envp + KERNBASE, 0);
- else
- init_static_kenv(NULL, 0);
+ /* Static environment is already initialized in
+ * parse_kernel_command_line if the kernel is loaded by a muiltboot
+ * boot loader. */
+#ifdef MULTIBOOT
+ if(!multiboot_env) {
+#endif
+ init_static_kenv(bootinfo.bi_envp ?
+ (caddr_t)bootinfo.bi_envp + KERNBASE : NULL,
+ 0);
+#ifdef MULTIBOOT
+ }
+#endif
/* Init basic tunables, hz etc */
init_param1();
@@ -4184,3 +4492,17 @@
}
#endif /* KDB */
+
+#ifdef MULTIBOOT
+/* Called from locore.s, before paging */
+void get_kernend_from_multiboot_mods(const struct multiboot_module *mbmod, size_t count) {
+ struct bootinfo *bi = (struct bootinfo *)((char *)&bootinfo - KERNBASE);
+ while(count > 0) {
+ if(bi->bi_kernend < mbmod->mod_end) {
+ bi->bi_kernend = roundup(mbmod->mod_end, PAGE_SIZE);
+ }
+ mbmod++;
+ count--;
+ }
+}
+#endif
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h
--- a/sys/i386/include/md_var.h 2016-03-25 09:09:25.000000000 +0800
+++ b/sys/i386/include/md_var.h 2019-05-24 13:37:33.548092674 +0800
@@ -85,6 +85,9 @@
extern int _ucodesel;
extern int use_xsave;
extern uint64_t xsave_mask;
+#ifdef MULTIBOOT
+extern int ignore_multiboot_memory_size;
+#endif
typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss);
struct pcb;
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/i386/include/multiboot.h b/sys/i386/include/multiboot.h
--- a/sys/i386/include/multiboot.h 1970-01-01 08:00:00.000000000 +0800
+++ b/sys/i386/include/multiboot.h 2019-05-22 12:45:32.956511998 +0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019 Rivoreo
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_MULTIBOOT_H_
+#define _MACHINE_MULTIBOOT_H_
+
+struct multiboot_module {
+ uint32_t mod_start;
+ uint32_t mod_end;
+ uint32_t cmdline;
+ uint32_t pad;
+};
+
+#ifdef _KERNEL
+extern uint32_t multiboot_mem_lower;
+extern uint32_t multiboot_mem_upper;
+extern void *multiboot_env;
+extern char multiboot_cmdline[];
+extern struct {
+ uint32_t count;
+ struct multiboot_module *address;
+} multiboot_mods;
+#endif
+
+#endif
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/kern/init_main.c b/sys/kern/init_main.c
--- a/sys/kern/init_main.c 2018-11-05 19:30:33.000000000 +0800
+++ b/sys/kern/init_main.c 2019-05-24 14:14:05.952006276 +0800
@@ -46,6 +46,7 @@
#include "opt_ddb.h"
#include "opt_init_path.h"
+#include "opt_multiboot.h"
#include <sys/param.h>
#include <sys/kernel.h>
@@ -76,7 +77,10 @@
#include <sys/malloc.h>
#include <sys/conf.h>
#include <sys/cpuset.h>
-
+#ifdef MULTIBOOT
+#include <sys/multiboot.h>
+#endif
+#include <machine/md_var.h>
#include <machine/cpu.h>
#include <security/audit/audit.h>
@@ -120,6 +124,158 @@
#endif
/*
+ * List of paths to try when searching for "init".
+ */
+static char init_path[MAXPATHLEN] =
+#ifdef INIT_PATH
+ __XSTRING(INIT_PATH);
+#else
+ "/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init";
+#endif
+SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0,
+ "Path used to search the init process");
+
+#ifdef MULTIBOOT
+// Prase kernel command line to fill boothowto and static kernel environment
+// Usage: kernel [-acCdDghmprsv] [-i <init-path>] [-e <env>] [<env>] [...]
+void parse_kernel_command_line(const char *command_line, char *buffer, size_t buffer_size) {
+ int argc = 0;
+ char *argv[64];
+ char *p = buffer;
+ unsigned int i = 0, j = 0;
+ int qm = 0;
+ while(j < buffer_size - 1) {
+ char c = command_line[i];
+ switch(c) {
+ case '\\':
+ c = buffer[j++] = command_line[++i];
+ break;
+ case '\'':
+ case '"':
+ if(qm == c) qm = 0;
+ else if(!qm) qm = c;
+ else buffer[j++] = c;
+ break;
+ case ' ':
+ case ' ':
+ case '\n':
+ if(qm) {
+ buffer[j++] = c;
+ } else {
+ buffer[j++] = 0;
+ if(argc >= sizeof argv / sizeof *argv - 2) {
+ // Stop parsing!
+ c = 0;
+ break;
+ }
+ argv[argc++] = p;
+ p = buffer + i + 1;
+ }
+ break;
+ default:
+ buffer[j++] = c;
+ break;
+ }
+ if(!c) {
+ argv[argc++] = p;
+ break;
+ }
+ i++;
+ }
+ argv[argc] = NULL;
+
+ if(*argv[0] == '-' || strchr(argv[0], '=')) {
+ i = strchr(argv[0], '/') ? 1 : 0;
+ } else {
+ strcpy(kernelname, argv[0]);
+ i = 1;
+ }
+ p = buffer;
+ while(i < argc) {
+ if(argv[i][0] == '-') {
+ const char *o = argv[i];
+ while(*++o) switch(*o) {
+ case 'a':
+ boothowto |= RB_ASKNAME;
+ break;
+ case 'c':
+#ifdef RB_CONFIG
+ boothowto |= RB_CONFIG;
+#endif
+ break;
+ case 'C':
+ boothowto |= RB_CDROM;
+ break;
+ case 'd':
+ boothowto |= RB_KDB;
+ break;
+ case 'D':
+ boothowto |= RB_MULTIPLE;
+ break;
+ case 'e':
+ if(!argv[++i]) goto next_outer_loop;
+ try_putenv:
+ {
+ const char *e = strchr(argv[i], '=');
+ if(e && (!(boothowto & RB_INITNAME) || e - argv[i] != 9 || strncmp(argv[i], "init_path", 9))) {
+ size_t len = strlen(argv[i]) + 1;
+ memmove(p, argv[i], len);
+ p += len;
+ }
+ }
+ goto next_outer_loop;
+ case 'g':
+ boothowto |= RB_GDB;
+ break;
+ case 'h':
+ boothowto |= RB_SERIAL;
+ break;
+ case 'i':
+ if(!argv[++i]) goto next_outer_loop;
+ strlcpy(init_path, argv[i], sizeof init_path);
+ boothowto |= RB_INITNAME;
+ goto next_outer_loop;
+ case 'm':
+ boothowto |= RB_MUTE;
+ break;
+#if defined __i386__ && defined MULTIBOOT
+ case 'M':
+ ignore_multiboot_memory_size = 1;
+ break;
+#endif
+ case 'p':
+ boothowto |= RB_PAUSE;
+ break;
+ case 'r':
+ boothowto |= RB_DFLTROOT;
+ break;
+ case 's':
+ boothowto |= RB_SINGLE;
+ break;
+#if 0
+ case 'S':
+ goto next_outer_loop;
+#endif
+ case 'v':
+ boothowto |= RB_VERBOSE;
+ break;
+ }
+ } else {
+ goto try_putenv;
+ }
+next_outer_loop:
+ i++;
+ }
+ *p = 0;
+//#ifdef __i386__
+// bootinfo.bi_envp = (uint32_t)(buffer - KERNBASE);
+//#else
+ init_static_kenv(buffer, 0);
+//#endif
+}
+#endif /* MULTIBOOT */
+
+/*
* This ensures that there is at least one entry so that the sysinit_set
* symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never
* executed.
@@ -666,18 +822,6 @@
*/
/*
- * List of paths to try when searching for "init".
- */
-static char init_path[MAXPATHLEN] =
-#ifdef INIT_PATH
- __XSTRING(INIT_PATH);
-#else
- "/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init";
-#endif
-SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0,
- "Path used to search the init process");
-
-/*
* Shutdown timeout of init(8).
* Unused within kernel, but used to control init(8), hence do not remove.
*/
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/sys/multiboot.h b/sys/sys/multiboot.h
--- a/sys/sys/multiboot.h 1970-01-01 08:00:00.000000000 +0800
+++ b/sys/sys/multiboot.h 2019-05-18 11:43:14.881904599 +0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2019 Rivoreo
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS_MULTIBOOT_H_
+#define _SYS_MULTIBOOT_H_
+
+#define MULTIBOOT_HEADER_MAGIC 0x1badb002
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2badb002
+#define MULTIBOOT_PAGE_ALIGN (1)
+#define MULTIBOOT_MEMORY_INFO (1 << 1)
+#define MULTIBOOT_VIDEO_MODE (1 << 2)
+#define MI_FLAG_MEMORY (1)
+#define MI_FLAG_BOOTDEV (1 << 1)
+#define MI_FLAG_CMDLINE (1 << 2)
+#define MI_FLAG_MODS (1 << 3)
+#define MI_FLAG_AOUT_SYMS (1 << 4)
+#define MI_FLAG_ELF_SHDR (1 << 5)
+#define MI_FLAG_MMAP (1 << 6)
+#define MI_FLAG_DRIVES (1 << 7)
+#define MI_FLAG_CONFIG_TABLE (1 << 8)
+#define MI_FLAG_BOOT_LOADER_NAME (1 << 9)
+#define MI_FLAG_APM_TABLE (1 << 10)
+#define MI_FLAG_VBE (1 << 11)
+#define MI_FLAG_FRAMEBUFFER (1 << 12)
+#define MI_MEM_LOWER 0x4
+#define MI_MEM_UPPER 0x8
+#define MI_CMDLINE 0x10
+#define MI_MODS_COUNT 0x14
+#define MI_MODS_ADDR 0x18
+#define MI_MMAP_LENGTH 0x2c
+#define MI_MMAP_ADDR 0x2e
+#define MI_BOOT_LOADER_NAME 0x40
+#define MI_CMDLINE_MAX 0x1000
+
+#endif
diff -ru --exclude-from freebsd-src-diff-exclude-names --new-file a/sys/sys/systm.h b/sys/sys/systm.h
--- a/sys/sys/systm.h 2016-03-25 09:09:26.000000000 +0800
+++ b/sys/sys/systm.h 2019-05-22 11:28:57.038384000 +0800
@@ -235,6 +235,8 @@
#define HD_OMIT_HEX (1 << 17)
#define HD_OMIT_CHARS (1 << 18)
+void parse_kernel_command_line(const char *, char *, size_t) __nonnull(1) __nonnull(2);
+
#define ovbcopy(f, t, l) bcopy((f), (t), (l))
void bcopy(const void *from, void *to, size_t len) __nonnull(1) __nonnull(2);
void bzero(void *buf, size_t len) __nonnull(1);