Introducción

Buenas, en este post vamos a compilar un kérnel linux a medida de nuestro ordenador. Al ser linux un kérnel libre, es posible descargar el código fuente, configurarlo y comprimirlo. Además, esta tarea a priori compleja, es más sencilla de lo que parece gracias a las herramientas disponibles.

En esta tarea vamos a tratar de compilar un kérnel completamente funcional que reconozca todo el hardware básico de nuestro equipo y que sea a la vez lo más pequeño posible, es decir que incluya un vmlinuz lo más pequeño posible y que incorpore sólo los módulos imprescindibles.

Requisitos necesarios

Necesitaremos saber que versión de kérnel tenemos, para obtener la versión de kérnel de nuestra máquina:

uname -r

Actualizamos el equipo porque vamos a descargar el código fuente de nuestro kérnel de los repositorios y buscamos el paquete:

# apt update && apt upgrade

Y buscamos el paquete correspondiente:

# apt policy linux-source

linux-source:
  Instalados: (ninguno)
  Candidato:  4.19+105+deb10u7
  Tabla de versión:
     5.8.10-1~bpo10+1 100
        100 http://deb.debian.org/debian buster-backports/main amd64 Packages
     4.19+105+deb10u7 500
        500 http://security.debian.org/debian-security buster/updates/main amd64 Packages
        100 /var/lib/dpkg/status
     4.19+105+deb10u6 500
        500 http://deb.debian.org/debian buster/main amd64 Packages

Como podemos comprobar no está instalado ninguno, así que como ya hemos visto cuál es la versión de nuestro kérnel, instalaremos el correspondiente. También instalaremos el paquete sugerido de qtbase5-dev, que nos servirá para poder hacer esa configuración en el ḱérnel gráficamente.

sudo apt install linux-source=4.19+105+deb10u7 qtbase5-dev

Comprobamos que se ha instalado:

dpkg -l | grep linux-source

ii  linux-source                          4.19+105+deb10u7                             all          Linux kernel source (meta-package)
ii  linux-source-4.19                     4.19.152-1                                   all          Linux kernel source for version 4.19 with Debian patches

Y mostramos su contenido para ver dónde se nos ha descargado:

dpkg -L linux-source-4.19
/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/linux-source-4.19
/usr/share/doc/linux-source-4.19/changelog.Debian.gz
/usr/share/doc/linux-source-4.19/copyright
/usr/src
/usr/src/linux-patch-4.19-rt.patch.xz
/usr/src/linux-source-4.19.tar.xz

Como vemos se encuentra en /usr/src/. No es recomendable hacer la compilación del kérnel con el usuario root, así que vamos a crear una carpeta en nuestro directorio de usuario:

mkdir /home/ale/kernel

Y descomprimimos el fichero del kérnel:

tar xf /usr/src/linux-source-4.19.tar.xz /home/ale/kernel

Y ya tendremos el código fuente del kérnel. Podremos obtener las opciones que podemos hacer con make haciendo lo siguiente:

$ make help

Las más usadas son las siguientes:

make clean // Limpiará los archivos que se han obtenido al compilar excepto el archivo de configuración

make mrproper // Elimina también los archivos de configuración.

make config // Decidiremos línea a línea los parámetros que queremos que se incluyan en el kérnel.

make oldconfig // Usa el fichero de configuración de nuestro kérnel actual y nos preguntará si no está seguro, los cambios en la configuración instalada.

make localmodconfig // Comprueba de la lista completa de módulos que tenemos en el kérnel y suprime los que no están en uso.

make xconfig // Asistente gráfico que hemos instalado anteriormente.

Podemos partir del archivo de configuración de nuestra máquina:

# cp /boot/config-4.19.0-12-amd64 .config

Y si hacemos un make oldconfig nos sobreescribirá el fichero .config que acabamos de copiar.

Aunque no es nuestro objetivo, ya podríamos compilar dicho kérnel con el siguiente comando en un paquete .deb para que fácilmente pudiéramos instalarlo en nuestra máquina, vamos a probar:

$ make bindeb-pkg

Nos sale el siguiente error, el cual nos dice que nos faltan dependencias que debemos de instalar

dpkg-checkbuilddeps: fallo: Unmet build dependencies: libelf-dev:native libssl-dev:native

Para solucionar el problema, tendremos que instalar dichas dependencias:

# apt install libelf-dev libssl-dev

Y volvemos a ejecutar:

$ make bindeb-pkg

Si miramos el tamaño del paquete .deb que contiene el kérnel:

~/kernel$ du -hs linux-image-4.19.152_4.19.152-1_amd64.deb 
13M	linux-image-4.19.152_4.19.152-1_amd64.deb

Así ya tendríamos nuestro paquete .deb, pero lo que queremos es hacerlo mucho menos pesado.

Compilación a medida

Para hacerlo menos pesado, usaremos la opción localmodconfig, la cuál nos hace una primera reducción de módulos con los que está usando nuestra máquina en este momento. Primero borramos con clean el rastro antiguo:

$ make clean

Y generamos el .config:

$ make localmodconfig

Mostramos los módulos estáticos y dinámicos que tenemos al comienzo:

grep "=y" .config|wc -l
1438

grep "=m" .config|wc -l
214

Nuestro objetivo será reducirlo lo máximo posible quitándole funcionalidades. Para empezar, sobre el archivo de configuración haremos:

$ make xconfig

Y después de quitar todos los siguientes módulos:

CONFIG_DEBUG_INFO
CONFIG_ENABLE_MUST_CHECK
CONFIG_STRIP_ASM_SYMS
CONFIG_PAGE_POISONING
CONFIG_DEBUG_MEMORY_INIT

CONFIG_HARDLOCKUP_DETECTOR
CONFIG_SOFTLOCKUP_DETECTOR
CONFIG_DETECT_HUNG_TASK

CONFIG_FTRACE

CONFIG_FUNCTION_GRAPH_TRACER
CONFIG_FTRACE_SYSCALLS
CONFIG_TRACER_SNAPSHOT
CONFIG_STACK_TRACER
CONFIG_BLK_DEV_IO_TRACE
CONFIG_KPROBE_EVENTS

RUNTIME_TESTING_MENU

CONFIG_UPROBE_EVENTS
CONFIG_TRACING_EVENTS_GPIO

CONFIG_CRYPTO_FIPS
CONFIG_CRYPTO_CRC32C_INTEL
CONFIG_CRYPTO_CRC32_PCLMUL
CONFIG_CRYPTO_CRCT10DIF_PCLMUL
CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL
CONFIG_CRYPTO_AES_NI_INTEL
CONFIG_CRYPTO_ANSI_CPRNG

CONFIG_CRYPTO_HW
CONFIG_SIGNED_PE_FILE_VERIFICATION
CONFIG_SECONDARY_TRUSTED_KEYRING
CONFIG_SYSTEM_BLACKLIST_KEYRING
CONFIG_EFI_SIGNATURE_LIST_PARSER

XZ_DEC_X86
CONFIG_IRQ_POLL

CONFIG_FIRMWARE_MEMMAP
CONFIG_DMIID
CONFIG_DMI_SYSFS

CONFIG_EFI_VARS
CONFIG_EFI_RUNTIME_MAP
CONFIG_APPLE_PROPERTIES

CONFIG_VIRTUALIZATION

CONFIG_KPROBES
CONFIG_JUMP_LABEL
CONFIG_STACKPROTECTOR--------
	CONFIG_STACKPROTECTOR_STRONG
CONFIG_VMAP_STACK
CONFIG_REFCOUNT_FULL

CONFIG_MODULE_SIG-----
	MODULE_SIG_SHA256

CONFIG_SOUND
CONFIG_USB_SUPPORT

CONFIG_MMC
CONFIG_MEMSTICK
CONFIG_NEW_LEDS
CONFIG_ACCESSIBILITY


CONFIG_VIRT_DRIVERS
VIRTIO_MENU
CONFIG_XEN_BALLOON
CONFIG_XEN_BACKEND
CONFIG_XEN_SYS_HYPERVISOR
CONFIG_XEN_MCE_LOG

CONFIG_STAGING

CONFIG_CHROME_PLATFORMS
CONFIG_PM_DEVFREQ
CONFIG_PWM

CONFIG_POWERCAP

CONFIG_ANDROID

CONFIG_CC_OPTIMIZE_FOR_SIZE
CONFIG_HIGH_RES_TIMERS

CONFIG_NETFILTER
CONFIG_BT

CONFIG_SCHED_MC
CONFIG_HYPERVISOR_GUEST

CONFIG_MACINTOSH_DRIVERS
CONFIG_HWMON

CONFIG_VM_EVENT_COUNTERS

CONFIG_RFKILL
CONFIG_WLAN
CONFIG_WAN

CONFIG_ZONE_DMA
CONFIG_SMP
CONFIG_DMI
CONFIG_CALGARY_IOMMU
CONFIG_X86_16BIT

CONFIG_MEMTEST

MEMORY_HOTPLUG
CONFIG_MEM_SOFT_DIRTY
CONFIG_ARCH_RANDOM
CONFIG_ACPI_AC
CONFIG_ACPI_BATTERY

CONFIG_IPV6
CONFIG_HAMRADIO
WIRELESS

CONFIG_X86_MCE_AMD
CONFIG_X86_SMAP
CONFIG_IP_MROUTE
CONFIG_NETWORK_FILESYSTEMS
CONFIG_SWAP

CONFIG_NAMESPACES
CONFIG_ACPI_EXTLOG
CONFIG_HOTPLUG_PCI_ACPI

CONFIG_FUSION
CONFIG_NET_FC
CONFIG_BSD_PROCESS_ACCT
CONFIG_TASKSTATS
CONFIG_SFI
CONFIG_CPU_FREQ

CONFIG_ISDN
CONFIG_WATCHDOG

CONFIG_AGP

CONFIG_GPIO_SYSFS

CONFIG_NET_SCHED
CONFIG_MSI_WMI
SCSI_LOWLEVEL

CONFIG_INTEL_IDLE
CONFIG_X86_MCE
CONFIG_SYSVIPC
CONFIG_POSIX_MQUEUE
CONFIG_CROSS_MEMORY_ATTACH
CONFIG_PROFILING

CHECKPOINT_RESTORE
CONFIG_FDDI
CONFIG_HIPPI
CONFIG_INPUT_JOYDEV
CONFIG_INPUT_JOYSTICK
CONFIG_INPUT_TABLET
CONFIG_INPUT_TOUCHSCREEN
CONFIG_INPUT_MISC
CONFIG_INPUT_MOUSE
CONFIG_INPUT_MOUSEDEV
DM_UEVENT
CONFIG_ACORN_PARTITION_RISCIX
CONFIG_SECURITY_SELINUX_AVC_STATS
CONFIG_SECURITY_SELINUX_DEVELOP
CONFIG_SERIAL_8250_EXTENDED
CONFIG_EDAC
CONFIG_RTC_CLASS

CONFIG_ACPI_THERMAL
CONFIG_VGA_CONSOLE
CONFIG_CRYPTO_CCM
CONFIG_SECURITY_SELINUX
CONFIG_SECURITY_APPARMOR
CONFIG_SECURITY_TOMOYO
CONFIG_CRYPTO_SHA256 a módulo
CONFIG_CRYPTO_AES_X86_64
CONFIG_CRYPTO_ARC4
CONFIG_PRINTK
CONFIG_PRINT_QUOTA_WARNING
CONFIG_QUOTA
CONFIG_QUOTA_NETLINK_INTERFACE
CONFIG_XFS_QUOTA

CONFIG_HOTPLUG_PCI
CONFIG_IA32_EMULATION
CONFIG_X86_X32

CONFIG_BLK_DEV
CONFIG_SCSI_DH

CONFIG_REGULATOR
CONFIG_DRM_LEGACY
CONFIG_DMADEVICES
CONFIG_IOMMU_SUPPORT

CONFIG_FB_VESA
CONFIG_FB_EFI
CONFIG_FB_MODE_HELPERS

CONFIG_FIRMWARE_EDID

CONFIG_FB_TILEBLITTING

CONFIG_FRAMEBUFFER_CONSOLE
CONFIG_VGA_CONSOLE ACTIVO

CONFIG_FB a modulo

CONFIG_NVMEM
CONFIG_GENERIC_PHY

CONFIG_VGA_SWITCHEROO
CONFIG_VGA_ARB
CONFIG_DRM_DP_CEC

CONFIG_DRM_NOUVEAU
CONFIG_DRM_I915_CAPTURE_ERROR

CONFIG_X86_PLATFORM_DEVICES

CONFIG_BLK_DEV_MD
CONFIG_IPMI_HANDLER
CONFIG_SPI

CONFIG_AUDIT
CONFIG_GART_IOMMU
CONFIG_X86_VSYSCALL_EMULATION

CONFIG_PARTITION_ADVANCED

CONFIG_NET_VENDOR_3COM
CONFIG_NET_VENDOR_ADAPTEC
CONFIG_NET_VENDOR_AGERE
CONFIG_NET_VENDOR_ALACRITECH
CONFIG_NET_VENDOR_ALTEON
CONFIG_NET_VENDOR_AMAZON
CONFIG_NET_VENDOR_AMD
CONFIG_NET_VENDOR_AQUANTIA
CONFIG_NET_VENDOR_BROADCOM
CONFIG_NET_VENDOR_BROCADE
CONFIG_NET_VENDOR_CADENCE
CONFIG_NET_VENDOR_CAVIUM
CONFIG_NET_VENDOR_CHELSIO
CONFIG_NET_VENDOR_CISCO
CONFIG_NET_VENDOR_CORTINA
CONFIG_NET_VENDOR_DEC
CONFIG_NET_VENDOR_DLINK
CONFIG_NET_VENDOR_EMULEX
CONFIG_NET_VENDOR_EZCHIP
CONFIG_NET_VENDOR_HP
CONFIG_NET_VENDOR_HUAWEI
CONFIG_NET_VENDOR_I825XX
CONFIG_NET_VENDOR_INTEL
CONFIG_NET_VENDOR_MARVELL
CONFIG_NET_VENDOR_MELLANOX
CONFIG_NET_VENDOR_MICREL
CONFIG_NET_VENDOR_MICROSEMI
CONFIG_NET_VENDOR_MYRI
CONFIG_NET_VENDOR_NATSEMI
CONFIG_NET_VENDOR_NETERION
CONFIG_NET_VENDOR_NETRONOME
CONFIG_NET_VENDOR_NI
CONFIG_NET_VENDOR_8390
CONFIG_NET_VENDOR_NVIDIA
CONFIG_NET_VENDOR_OKI
CONFIG_NET_VENDOR_PACKET_ENGINES
CONFIG_NET_VENDOR_QLOGIC
CONFIG_NET_VENDOR_RDC
CONFIG_NET_VENDOR_REALTEK
CONFIG_NET_VENDOR_RENESAS
CONFIG_NET_VENDOR_ROCKER
CONFIG_NET_VENDOR_SAMSUNG
CONFIG_NET_VENDOR_SOLARFLARE
CONFIG_NET_VENDOR_SILAN
CONFIG_NET_VENDOR_SIS
CONFIG_NET_VENDOR_SMSC
CONFIG_NET_VENDOR_SOCIONEXT
CONFIG_NET_VENDOR_STMICRO
CONFIG_NET_VENDOR_SUN
CONFIG_NET_VENDOR_SYNOPSYS
CONFIG_NET_VENDOR_TEHUTI
CONFIG_NET_VENDOR_TI
CONFIG_NET_VENDOR_VIA
CONFIG_NET_VENDOR_WIZNET

CONFIG_HFS_FS
CONFIG_HFSPLUS_FS
CONFIG_MINIX_FS
CONFIG_QNX4FS_FS
CONFIG_JFS_FS
CONFIG_XFS_FS
CONFIG_BTRFS_FS

CONFIG_PINCTRL_AMD
CONFIG_PINCTRL_BAYTRAIL
CONFIG_PINCTRL_CHERRYVIEW
CONFIG_PINCTRL_BROXTON
CONFIG_PINCTRL_CANNONLAKE
CONFIG_PINCTRL_CEDARFORK
CONFIG_PINCTRL_DENVERTON
CONFIG_PINCTRL_GEMINILAKE
CONFIG_PINCTRL_ICELAKE
CONFIG_PINCTRL_LEWISBURG
CONFIG_PINCTRL_SUNRISEPOINT
CONFIG_GPIOLIB

Y al compilar con los procesadores de nuestra máquina y con la opción INSTALL_MOD_STRIP=1, la cuál reducirá el tamaño al depurar los módulos:

make -j 4 INSTALL_MOD_STRIP=1 bindeb-pkg

Obtenemos los siguientes:

m=91
y=772

Si comparamos los dos vmlinux(antiguo y nuevo):

5,1M	/boot/vmlinuz-4.19.0-12-amd64
2,6M	/boot/vmlinuz-4.19.152

Vemos que su tamaño ha disminuido considerablemente.