Linux kernel
Kernel drivers
- Kernel platform drivers: http://lwn.net/Articles/448499/
- Device trees: http://lwn.net/Articles/448502/
Building the kernel
Configure
config using defconfig
To configure using a specified defconfig for a specified architecture
make ARCH=x86 i386_defconfig
To menuconfig starting from a specified defconfig for a specified architecture
make menuconfig ARCH=x86 i386_defconfig
Be sure to explicitly save the configuration.
To menuconfig starting from a .config for a specified architecture
make menuconfig ARCH=x86
When inside menuconfig, choose "Load" and specify path to your .config Then edit the configuration as you see fit, then choose "Save" and save it as ".config" only. Then you can exit menuconfig and do:
make savedefconfig ARCH=x86
to save your updated, minimal defconfig. Be sure to specify your architecture at all times (if it is not the default x86).
Build
make -j4 ARCH=x86 CROSS_COMPILE=/bin/i686-linux- all
Various kernel information
New Linux network names
https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/
Tips for booting the kernel on a new ARM board
Step 1 - Uncompressing
Do you get the "Uncompressing Linux... done, booting the kernel." print? If not and you are on an ARM architecture, you can enable:
CONFIG_EARLY_PRINTK=y CONFIG_DEBUG_LL=y CONFIG_DEBUG_LL_UART_PL01X=y CONFIG_DEBUG_UART_PHYS=0xF7800000 CONFIG_DEBUG_UART_VIRT=0xF7800000
If you are working on a arm64 architecture, DEBUG_LL is no longer available. The new way to do the same thing is to append something like the following to your kernel cmdline:
earlycon=pl011,mmio32,0xF7800000
More info on earlycon and other kernel cmdline options: https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html
In both cases you have to adjust the UART config according to your platform! Now you should get the Uncompressing Linux... print, otherwise your bootloader has either:
- Not uploaded the kernel to RAM.
- Not jumped to the correct place in RAM to execute it.
Good places to check out:
arch/arm/boot/compressed/head.S arch/arm/boot/compressed/misc.c
Step 2 - First assembly files
The kernel will boot in two different ways:
- Without device tree support (old style). Your bootloader should have set up register r1 to contain the machine ID and register r2 to contain a pointer to the ATAGS area.
- With device tree support (new style). Your bootloader should have set up register r2 to contain a pointer to the DTB (device tree blob).
Do you get "Error: unrecognized/unsupported processor variant (0x414fc091)."? Then you have set your defconfig flags in your kernel to the wrong CPU type. Make sure to check if your CPU is an ARMv5, ARMv7 or whatever and set the correct defconfig flags (such as CONFIG_ARCH_ and CONFIG_CPU_).
Good places to check out:
arch/arm/kernel/head-common.S
Step 3 - early c code
You should now be able to reach the function start_kernel() in file init/main.c. This is great place to start off. prints are working differently here, the CONFIG_DEBUG_LL and EARLY_PRINTK is not working here, but once you reach the setup_arch() function in arch/arm/kernel/setup.c, you can use the early_print() function to print stuff using the CONFIG_DEBUG_LL stuff again!
Hack to get something on the serial line
If you have trouble getting the regular pr_xxxx-prints going, then you can replace them all in this file with early_print() instead.
Another good hack is to copy the function early_print() from file arch/arm/kernel/setup.c, and replace the function printk() in file kernel/prink/printk.c with the implementation from early_print(). Now all printk:s will be redirected to be output by the early assembler routines enabled by CONFIG_DEBUG_LL.
Good places to start with are:
init/main.c arch/arm/kernel/setup.c arch/arm/kernel/devtree.c
Step 4 - interrupts and timers
If the board hangs at calibrate_delay() (you may see "Calibrating delay loop..." in the console), then your interrupts are not working. Check that the correct driver for your IRQ block has been enabled by defconfigs and that you have added correct configuration in your devicetree.
Step 5 - getting the serial running the proper way
Make sure you have enabled the correct drivers for your serial HW block and added configuration for them in the devicetree if applicable.
Then make sure you have set up the kernel command line to contain a console keyword with a suitable UART configuration, either in your device tree file (*.dts) or in your defconfig (CONFIG_CMDLINE="console=ttyAMA0,115200 earlyprintk init=/linuxrc") or that it is given from your bootloader. Make sure it is set up to the correct UART and speed.
Other logging tips
If you want to dump out a buffer or a bunch of registers, then you can use the excellent:
print_hex_dump_bytes("HEX: ", DUMP_PREFIX_OFFSET, buf, size);