官术网_书友最值得收藏!

Compiling

The kernel build system, kbuild, is a set of make scripts that take the configuration information from the .config file, work out the dependencies and compile everything that is necessary to produce a kernel image containing all the statically linked components, possibly a device tree binary and possibly one or more kernel modules. The dependencies are expressed in the makefiles that are in each directory with buildable components. For instance, these two lines are taken from drivers/char/Makefile:

obj-y                    += mem.o random.o
obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o

The obj-y rule unconditionally compiles a file to produce the target, so mem.c and random.c are always part of the kernel. In the second line, ttyprintk.c is dependent on a configuration parameter. If CONFIG_TTY_PRINTK is y it is compiled as a built in, if it is m it is built as a module and, if the parameter is undefined, it is not compiled at all.

For most targets, just typing make (with the appropriate ARCH and CROSS_COMPILE) will do the job, but it is instructive to take it one step at a time.

Compiling the kernel image

To build a kernel image, you need to know what your bootloader expects. This is a rough guide:

  • U-Boot: Traditionally U-Boot has required a uImage, but newer versions can load a zImage file using the bootz command
  • x86 targets: It requires a bzImage file
  • Most other bootloaders: It requires a zImage file

Here is an example of building a zImage file:

$ make -j 4 ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- zImage

Tip

The -j 4 option tells make how many jobs to run in parallel, which reduces the time taken to build. A rough guide is to run as many jobs as you have CPU cores.

It is the same when building bzImage and uImage targets.

There is a small issue with building a uImage file for ARM with multi-platform support, which is the norm for the current generation of ARM SoC kernels. Multi-platform support for ARM was introduced in Linux 3.7. It allows a single kernel binary to run on multiple platforms and is a step on the road toward having a small number of kernels for all ARM devices. The kernel selects the correct platform by reading the machine number or the device tree passed to it by the bootloader. The problem occurs because the location of physical memory might be different for each platform, and so the relocation address for the kernel (usually 0x8000 bytes from the start of physical RAM) might also be different. The relocation address is coded into the uImage header by the mkimage command when the kernel is built, but it will fail if there is more than one relocation address to choose from. To put it another way, the uImage format is not compatible with multi-platform images. You can still create a uImage binary from a multi-platform build so long as you give the LOADADDR of the particular SoC you are hoping to boot this kernel on. You can find the load address by looking in mach-[your SoC]/Makefile.boot and noting the value of zreladdr-y.

In the case of a BeagleBone Black, the full command would look like this:

$ make -j 4 ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- LOADADDR=0x80008000 uImage

A kernel build generates two files in the top level directory: vmlinux and System.map. The first, vmlinux, is the kernel as an ELF binary. If you have compiled your kernel with debug enabled (CONFIG_DEBUG_INFO=y), it will contain debug symbols which can be used with debuggers like kgdb. You can also use other ELF binary tools such as size:

$ arm-cortex_a8-linux-gnueabihf-size vmlinux
 text data bss dec hex filename
8812564 790692 8423536 18026792 1131128 vmlinux

System.map contains the symbol table in human readable form.

Most bootloaders cannot handle ELF code directly. There is a further stage of processing which takes vmlinux and places those binaries in arch/$ARCH/boot that are suitable for the various bootloaders:

  • Image: vmlinux converted to raw binary.
  • zImage: For the PowerPC architecture, this is just a compressed version of Image, which implies that the bootloader must do the decompression. For all other architectures, the compressed Image is piggybacked onto a stub of code that decompresses and relocates it.
  • uImage: zImage plus a 64-byte U-Boot header.

While the build is running, you will see a summary of the commands being executed:

$ make -j 4 ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf-zImage
CC     init/main.o
CHK    include/generated/compile.h
CC     init/version.o
CC     init/do_mounts.o
CC     init/do_mounts_rd.o
CC     init/do_mounts_initrd.o
LD     init/mounts.o
[...]

Sometimes, when the kernel build fails, it is useful to see the actual commands being executed. To do that, add V=1 to the command line:

$ make ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- V=1 zImage
[...]
arm-cortex_a8-linux-gnueabihf-gcc -Wp,-MD,init/.do_mounts_initrd.o.d  -nostdinc -isystem /home/chris/x-tools/arm-cortex_a8-linux-gnueabihf/lib/gcc/arm-cortex_a8-linux-gnueabihf/4.9.1/include -I./arch/arm/include -Iarch/arm/include/generated/uapi -Iarch/arm/include/generated  -Iinclude -I./arch/arm/include/uapi -Iarch/arm/include/generated/uapi -I./include/uapi -Iinclude/generated/uapi -include ./include/linux/kconfig.h -D__KERNEL__ -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -fno-dwarf2-cfi-asm -mabi=aapcs-linux -mno-thumb-interwork -mfpu=vfp -funwind-tables -marm -D__LINUX_ARM_ARCH__=7 -march=armv7-a -msoft-float -Uarm -fno-delete-null-pointer-checks -O2 --param=allow-store-data-races=0 -Wframe-larger-than=1024 -fno-stack-protector -Wno-unused-but-set-variable -fomit-frame-pointer -fno-var-tracking-assignments -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fconserve-stack -Werror=implicit-int -Werror=strict-prototypes -Werror=date-time -DCC_HAVE_ASM_GOTO    -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(do_mounts_initrd)"  -D"KBUILD_MODNAME=KBUILD_STR(mounts)" -c -o init/do_mounts_initrd.o init/do_mounts_initrd.c
[...]

Compiling device trees

The next step is to build the device tree, or trees if you have a multi-platform build. The dtbs target builds device trees according to the rules in arch/$ARCH/boot/dts/Makefile using the device tree source files in that directory:

$ make ARCH=arm dtbs
...
DTC arch/arm/boot/dts/omap2420-h4.dtb
DTC arch/arm/boot/dts/omap2420-n800.dtb
DTC arch/arm/boot/dts/omap2420-n810.dtb
DTC arch/arm/boot/dts/omap2420-n810-wimax.dtb
DTC arch/arm/boot/dts/omap2430-sdp.dtb
...

The .dtb files are generated in the same directory as the sources.

Compiling modules

If you have configured some features to be built as modules, you can build them separately using the modules target:

$ make -j 4 ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- modules

The compiled modules have a .ko suffix and are generated in the same directory as the source code, meaning that they are scattered all around the kernel source tree. Finding them is a little tricky but you can use the modules_install make target to install them in the right place. The default location is /lib/modules in your development system, which is almost certainly not what you want. To install them into the staging area of your root filesystem (we will talk about root filesystems in the next chapter), provide the path using INSTALL_MOD_PATH:

$ make -j4 ARCH=arm CROSS_COMPILE=arm-cortex_a8-linux-gnueabihf- INSTALL_MOD_PATH=$HOME/rootfs modules_install

Kernel modules are put into the directory /lib/modules/[kernel version], relative to the root of the filesystem.

主站蜘蛛池模板: 宜良县| 永吉县| 贞丰县| 类乌齐县| 江安县| 蕉岭县| 含山县| 天水市| 湖南省| 滦南县| 鹿邑县| 碌曲县| 板桥市| 鹤山市| 隆子县| 鹤岗市| 墨玉县| 安国市| 辽阳县| 汝州市| 陆川县| 泸西县| 岳普湖县| 饶阳县| 阳城县| 阿荣旗| 西乌珠穆沁旗| 颍上县| 罗山县| 海宁市| 泰州市| 佛冈县| 元谋县| 佛冈县| 方正县| 庆城县| 北碚区| 孙吴县| 循化| 泾川县| 股票|