| 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); |