# Building kernel without devices



## Alain De Vos (Apr 26, 2021)

To build a kernel without some devices I do something like,
in order to remove the lines from GENERIC KERNCONF kernel configuation file.
Maybe there is a nicer solution ?


```
#!/usr/local/bin/zsh -x
#Call with KERNNAME parameter
WORK=$1
gawk -i inplace '{gsub(/GENERIC/,"'"$1"'"); print}' $WORK
gawk -i inplace '! ( $1 == "makeoptions" && $2 == "DEBUG=-g"   )' $WORK
gawk -i inplace '! ( $1 == "makeoptions" && $2 == "WITH_CTF=1" )' $WORK

gawk -i inplace '! ( $1 == "options"     && $2 == "NFSCL" )' $WORK
gawk -i inplace '! ( $1 == "options"     && $2 == "NFSD" )' $WORK
gawk -i inplace '! ( $1 == "options"     && $2 == "NFSLOCKD" )' $WORK
gawk -i inplace '! ( $1 == "options"     && $2 == "NFS_ROOT" )' $WORK

gawk -i inplace '! ( $1 == "device"      && $2 == "fdc" )' $WORK

gawk -i inplace '! ( $1 == "device"      && $2 == "ahc" )' $WORK
gawk -i inplace '! ( $1 == "options"     && $2 == "AHC_REG_PRETTY_PRINT" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ahd" )' $WORK
gawk -i inplace '! ( $1 == "options"     && $2 == "AHD_REG_PRETTY_PRINT" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "esp" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "hptiop" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "isp" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ispfw" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "mpt" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "mps" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "mpr" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "sym" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "trm" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "adv" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "adw" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "aic" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "bt" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "isci" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ocs_fc" )' $WORK

gawk -i inplace '! ( $1 == "device"      && $2 == "amr" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "arcmsr" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ciss" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "dpt" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "hptmv" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "hptnr" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "hptrr" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "hpt27xx" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "iir" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ips" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "mly" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "twa" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "smartpqi" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "tws" )' $WORK

gawk -i inplace '! ( $1 == "device"      && $2 == "aac" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "aacp" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "aacraid" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ida" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "mfi" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "mlx" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "mrsas" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "pmspcv" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "twe" )' $WORK

gawk -i inplace '! ( $1 == "device"      && $2 == "ppc" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ppbus" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "lpt" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ppi" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "puc" )' $WORK

gawk -i inplace '! ( $1 == "device"      && $2 == "bxe" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "de" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "em" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "igb" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ix" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ixv" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ixl" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ixlv" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "le" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ti" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "txp" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "vx" )' $WORK

gawk -i inplace '! ( $1 == "device"      && $2 == "ae" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "age" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "alc" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ale" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "bce" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "bfe" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "bge" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "cas" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "dc" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "et" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "fxp" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "gem" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "hme" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "jme" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "lge" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "msk" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "nfe" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "nge" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "pcn" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "rl" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "sf" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "sge" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "sis" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "sk" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ste" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "stge" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "tl" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "tx" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "vge" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "vr" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "wb" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "xl" )' $WORK

gawk -i inplace '! ( $1 == "device"      && $2 == "snd_cmi" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "snd_csa" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "snd_emu10kx" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "snd_es137x" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "snd_via8233" )' $WORK

gawk -i inplace '! ( $1 == "options"     && $2 == "XENHVM" )' $WORK

gawk -i inplace '! ( $1 == "options"     && $2 == "KDB" )' $WORK
gawk -i inplace '! ( $1 == "options"     && $2 == "KDB_TRACE" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "pvscsi" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "nvme" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "nvd" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "vmd" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "vmd_bus" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "iflib" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "iavf" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "ice" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "vmx" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "axp" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "xenpci" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "mlx5" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "mlxfw" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "mlx5en" )' $WORK
gawk -i inplace '! ( $1 == "device"      && $2 == "hyperv" )' $WORK
```


----------



## Crivens (Apr 26, 2021)

Yes.
You can include GENERIC and 'nodevice XYZ' those you don't need.


----------



## Argentum (Apr 26, 2021)

Alain De Vos said:


> To build a kernel without some devices I do something like,
> in order to remove the lines from GENERIC KERNCONF kernel configuation file.
> Maybe there is a nicer solution ?


Have you tried /usr/src/sys/amd64/conf/MINIMAL?


----------



## Alain De Vos (Apr 26, 2021)

What with options like,
NFSCL,NFSD,NFSLOCKD,NFS_ROOT,XENHVM,KDB,KDB_TRACE ?


----------



## Crivens (Apr 26, 2021)

There is also the 'nooption' option to optionally unoption default options you opt out of.


----------



## SirDice (Apr 27, 2021)

Alain De Vos said:


> NFSCL,NFSD,NFSLOCKD,NFS_ROOT


Respectively, NFS client, NFS server, NFS Lock daemon, ability to use a root filesystem on NFS (diskless systems)



Alain De Vos said:


> XENHVM


xen(4)



Alain De Vos said:


> KDB


Kernel Debugger.



Alain De Vos said:


> KDB_TRACE


Trace information after a panic.

Read GENERIC, much of the information you seek is right there as commentary.


----------



## zirias@ (Apr 27, 2021)

A few remarks:

Don't write scripts using a shell other than /bin/sh and try to avoid "third-party" tools like `gawk` as well, this will make your scripts much more robust (and portable).
For the specific usecase, Crivens is right: the recommended way to have a custom kernel configuration is to `include` an existing one (most likely `GENERIC`) and only add your modifications with `[no]device|options`.
Removing things that are enabled in `GENERIC` is unlikely to improve security (as many seem to assume) *), and the savings in terms of disk space and RAM usage are relatively small, so it only makes sense for "special" target environments – otherwise it's not worth the effort.
—
*) what _does_ improve security is preventing random kernel modules from being able to load at runtime; for that, see the sysctl `kern.securelevel` described in rc.conf(5) and security(7).


----------



## mickey (Apr 27, 2021)

Zirias said:


> and the savings in terms of disk space and RAM usage are relatively small,


That's a matter of perspective.
GENERIC kernel from FreeBSD 13 memstick image:

```
% du -hs /media/SanDisk_Cruzer_Blade_4C531001480801101250_s2_s2a/boot/kernel/kernel
 28M    /media/SanDisk_Cruzer_Blade_4C531001480801101250_s2_s2a/boot/kernel/kernel
```
Custom built kernel from my desktop machine, containing only necessary bits and pieces:

```
% du -hs /boot/kernel/kernel
 10M    /boot/kernel/kernel
```
That's actually less than half the size, YMMV.


----------



## zirias@ (Apr 27, 2021)

Yes, and on a normal-sized server or desktop machine, 18MiB is "nothing". To put it into perspective, an ESP wastes hundreds of MiB, just to host a bootloader.

As I said, for "special" targets (anything embedded and similar), building a "minimal" kernel _might_ make sense.


----------



## mickey (Apr 27, 2021)

A waste of resources cannot be justified, no matter how you put it, it stays what it is: a waste. If having around a gazillion of scsi, hardware raid, network and other drivers that your machine is never gonna use gives you that warm cosy feeling, fine. I still don't like seeing resources wasted that could be put to good use elsewhere.


----------



## zirias@ (Apr 27, 2021)

The key is to believe what you're doing makes any sense (so far for "warm cozy feelings"). Better don't worry about UEFI then  (oh, the horrors)


----------



## Alain De Vos (Apr 27, 2021)

A very very basic question I have , is /etc/src.conf read when you build the kernel or world or both ?

I rebuilded world and was able to remove many things I don't use,


```
WITHOUT_BIND=yes
WITHOUT_BLUETOOTH=yes
WITHOUT_CROSS_COMPILER=yes
WITHOUT_DEBUG_FILES=yes
WITHOUT_FLOPPY=yes
WITHOUT_HYPERV=YES
WITHOUT_INETD=yes
WITHOUT_IPX=yes
WITHOUT_KDUMP=yes
WITHOUT_KVM=yes
WITHOUT_KVM_SUPPORT=yes
WITHOUT_KERNEL_SYMBOLS=yes
WITHOUT_LLVM_TARGET_ALL=yes
WITHOUT_LLVM_TARGET_AARCH64=yes
WITHOUT_LLVM_TARGET_BPF=yes
WITHOUT_LLVM_TARGET_ARM=yes
WITHOUT_LLVM_TARGET_MIPS=yes
WITHOUT_LLVM_TARGET_POWERPC=yes
WITHOUT_LLVM_TARGET_RISCV=yes
WITHOUT_LLVM_TARGET_SPARC=yes
WITHOUT_LOCATE=yes
WITHOUT_LPR=yes
WITHOUT_MAIL=yes
WITHOUT_MAILWRAPPER=yes
WITHOUT_NDIS=yes
WITHOUT_NVME=yes
WITHOUT_OPENSSH=yes
WITHOUT_RPCBIND_WARMSTART_SUPPORT=yes
WITHOUT_SENDMAIL=yes
WITHOUT_TCP_WRAPPERS=yes
WITHOUT_WIRELESS_SUPPORT=yes
WITHOUT_WIRELESS=yes
WITHOUT_WPA_SUPPLICANT_EAPOL=yes
```

I think without IPX make sense in our modern world.


----------



## zirias@ (Apr 27, 2021)

Alain De Vos said:


> A very very basic question I have , is /etc/src.conf read when you build the kernel or world or both ?


/etc/src.conf is included for anything built from /usr/src. So, yes, it's included for building the kernel as well, but I don't know right now if there are any knobs influencing the kernel – I suspect the answer is no.

Anyways, leaving things you don't use out of building "world" will probably save a lot more space than any customization of kernel config can ever do. You could even build a "world" that doesn't include a compiler (which might make sense if your target system doesn't compile anything).


----------



## SirDice (Apr 27, 2021)

Alain De Vos said:


> A very very basic question I have , is /etc/src.conf read when you build the kernel or world or both ?


Answered in the first few lines of src.conf(5):

```
DESCRIPTION
     The src.conf file contains variables that control what components will be
     generated during the build process of the FreeBSD source tree; see
     build(7).
```


----------



## Alain De Vos (Apr 27, 2021)

If you change src.conf, will you will end up with a different compiled kernel ?, does not look answered for me.


----------

