CentOS 7: Rebuild kernel with src.rpm

This article will changing kernel configuration and source code, and rebuilding kernel with using src.rpm package.

 

1 Install packages for building kernel

Install packages for building kernel with yum.

$ sudo yum-builddep -y kernel
$ sudo yum install -y pesign

2 Download kernel src.rpm

Download kernel src.rpm.

$ yumdownloader --source kernel
$ rpm -i kernel-*.src.rpm
$ cd rpmbuild

3 Change kernel version

Define buildid variable in spec file. The buildid variable change not only rpm file name but also kernel file name.

$ diff -uprN SPECS/kernel.spec{.org,}
--- SPECS/kernel.spec.org       2016-05-28 05:09:48.825520275 +0900
+++ SPECS/kernel.spec   2016-05-28 05:10:13.376316809 +0900
@@ -3,7 +3,7 @@

 Summary: The Linux kernel

-# % define buildid .local
+%define buildid .local

 # For a kernel released for public testing, released_kernel should be 1.
 # For internal testing builds during development, it should be 0.

4 Change kernel configuration

Run "rpmbuild -bp" for extracting source tree and applying patches. Configuration file needs CPU architecture at the top of file.

$ rpmbuild -bp SPECS/kernel.spec
$ cd BUILD/kernel-*
$ make menuconfig # Change config
$ echo "# x86_64" > ~/kernel-*-x86_64.config
$ cat .config >> ~/rpmbuild/SOURCES/kernel-*-x86_64.config

This article will disable CONFIG_RELOCATABLE.

$ diff -uprN SOURCES/kernel-3.10.0-x86_64.config{.org,}
--- SOURCES/kernel-3.10.0-x86_64.config.org     2016-05-29 04:27:16.779380876 +0900
+++ SOURCES/kernel-3.10.0-x86_64.config 2016-05-29 05:10:24.144476432 +0900
@@ -1,7 +1,7 @@
 # x86_64
 #
 # Automatically generated file; DO NOT EDIT.
-# Linux/x86_64 3.10.0 Kernel Configuration
+# Linux/x86 3.10.0 Kernel Configuration
 #
 CONFIG_64BIT=y
 CONFIG_X86_64=y
@@ -527,7 +527,7 @@ CONFIG_KEXEC_BZIMAGE_VERIFY_SIG=y
 CONFIG_CRASH_DUMP=y
 CONFIG_KEXEC_JUMP=y
 CONFIG_PHYSICAL_START=0x1000000
-CONFIG_RELOCATABLE=y
+# CONFIG_RELOCATABLE is not set
 CONFIG_PHYSICAL_ALIGN=0x1000000
 CONFIG_HOTPLUG_CPU=y
 CONFIG_BOOTPARAM_HOTPLUG_CPU0=y

5 Change kernel source code

Run "rpmbuild -bp" for extracting source tree and applying patches. Copy kernel tree for creating a patch file.

$ rpmbuild -bp SPECS/kernel.spec
$ cd BUILD/kernel-*
$ cp -a linux-3.10.0-327.22.2.el7.local.x86_64{,.org}
# Change linux-3.10.0-327.22.2.el7.local.x86_64
# diff -uprN linux-3.10.0-327.22.2.el7.local.x86_64{.org,}

This article will change kernel code which prints "Hello, World" before mounting RAM disk.

$ cat SOURCES/hello.patch
diff -uprN linux-3.10.0-327.18.2.el7.local.x86_64.org/init/main.c linux-3.10.0-327.18.2.el7.local.x86_64/init/main.c
--- linux-3.10.0-327.18.2.el7.local.x86_64.org/init/main.c    2016-04-08 17:33:21.000000000 +0900
+++ linux-3.10.0-327.18.2.el7.local.x86_64/init/main.c        2016-05-27 15:46:43.271577474 +0900
@@ -892,6 +892,8 @@ static int __ref kernel_init(void *unuse

        flush_delayed_fput();

+       printk("Hello, World\n");
+
        if (ramdisk_execute_command) {
                if (!run_init_process(ramdisk_execute_command))
                        return 0;

Add entry of the patch file which named "hello.patch" to spec file.

$ diff -uprN SPECS/kernel.spec{.org,}
--- SPECS/kernel.spec.org       2016-05-28 06:11:02.452648537 +0900
+++ SPECS/kernel.spec   2016-05-28 06:09:39.284293579 +0900
@@ -380,6 +380,7 @@ Patch999999: linux-kernel-test.patch
 Patch1000: debrand-single-cpu.patch
 Patch1001: debrand-rh_taint.patch
 Patch1002: debrand-rh-i686-cpu.patch
+Patch2000: hello.patch

 BuildRoot: %{_tmppath}/kernel-%{KVRA}-root

@@ -691,6 +692,7 @@ ApplyOptionalPatch linux-kernel-test.pat
 ApplyOptionalPatch debrand-single-cpu.patch
 ApplyOptionalPatch debrand-rh_taint.patch
 ApplyOptionalPatch debrand-rh-i686-cpu.patch
+ApplyOptionalPatch hello.patch

 # Any further pre-build tree manipulations happen here.

6 Build kernel

Reduce build time with using –without option. It takes 3 hours without –without option and 1 hour without –with option.

$ rpmbuild -ba --without debug --without doc --without perf \
--without tools --without debuginfo --without kdump \
--without bootwrapper SPECS/kernel.spec
$ ls RPMS/x86_64/
kernel-3.10.0-327.18.2.el7.local.x86_64.rpm
kernel-devel-3.10.0-327.18.2.el7.local.x86_64.rpm
kernel-headers-3.10.0-327.18.2.el7.local.x86_64.rpm

7 Execution result

Kernel prints "Hello, World".

[    0.719104] rtc_cmos 00:00: setting system clock to 2016-05-28
14:58:30 UTC (1464447510)
[    0.719567] Freeing unused kernel memory: 1620k freed
[    0.719722] Hello, World
[    0.721348] systemd[1]: systemd 219 running in system mode. (+PAM
+AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP
+GCRYPT +GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
[    0.721362] systemd[1]: Detected virtualization kvm.

Kernel version has a prefix fo ".local".

$ uname -r
3.10.0-327.18.2.el7.local.x86_64

CONFIG_RELOCATABLE is disabled in configration file.

$ grep -nr "CONFIG_RELOCATABLE" /boot/config-3.10.0-327.18.2.el7.local.x86_64
529:# CONFIG_RELOCATABLE is not set