%poky; ] > Kernel Modification Example Kernel modification involves changing or adding configurations to an existing kernel, changing or adding recipes to the kernel that are needed to support specific hardware features, or even altering the source code itself. This appendix presents simple examples that modify the kernel source code, change the kernel configuration, and add a kernel source recipe.
Modifying the Kernel Source Code This example adds some simple QEMU emulator console output at boot time by adding printk statements to the kernel's calibrate.c source code file. Booting the modified image causes the added messages to appear on the emulator's console.
Understanding the Files You Need Before you modify the kernel, you need to know what Git repositories and file structures you need. Briefly, you need the following: A local Yocto Project Files Git repository The poky-extras Git repository placed within the local Yocto Project files Git repository A bare clone of the Linux Yocto Kernel upstream Git repository to which you want to push your modifications. A copy of that bare clone in which you make your source modifcations The following figure summarizes these four areas. Within each rectangular that represents a data structure, a host development directory pathname appears at the lower left-hand corner of the box. These pathnames are the locations used in this example. The figure also provides key statements and commands used during the kernel modification process: Here is a brief description of the four areas: Local Yocto Project Files Git Repository: This area contains all the metadata that supports building images in the Yocto Project build environment - the local Yocto Project files. In this example, the local Yocto Project files Git repository also contains the build directory, which contains the configuration directory that lets you control the build. In this example, the repository also contains the poky-extras Git repository. See the bulleted item "Yocto Project Release" for information on how to get these files. poky-extras Git Repository: This area contains the meta-kernel-dev layer, which is where you make changes that append the kernel build recipes. You edit .bbappend files to locate your local kernel source files and to identify the kernel being built. This Git repository is a gathering place for extensions to the Linux Yocto (or really any) kernel recipes that faciliate the creation and development of kernel features, BSPs or configurations. See the bulleted item "The poky-extras Git Repository" for information on how to get these files. Bare Clone of the Linux Yocto kernel: This bare Git repository tracks the upstream Git repository of the Linux Yocto kernel source code you are changing. When you modify the kernel you must work through a bare clone. All source code changes you make to the kernel must be committed and pushed to the bare clone using Git commands. As mentioned, the .bbappend file in the poky-extras repository points to the bare clone so that the build process can locate the locally changed source files. See the bulleted item "Linux Yocto Kernel" for information on how to set up the bare clone. Copy of the Linux Yocto Kernel Bare Clone: This Git repository contains the actual source files that you modify. Any changes you make to files in this location need to ultimately be pushed to the bare clone using the git push command. See the bulleted item "Linux Yocto Kernel" for information on how to set up the bare clone. Typically, Git workflows follow a scheme where changes made to a local area are pulled into a Git repository. However, because the git pull command does not work with bare clones, this workflow pushes changes to the repository even though you could use other more complicated methods to get changes into the bare clone.
Setting Up the Local Yocto Project Files Git Repository You can get the local Yocto Project files through tarball extraction or by cloning the poky Git repository. This example uses poky as the root directory of the local Yocto Project files Git repository. See the bulleted item "Yocto Project Release" for information on how to get these files. Once you have the repository set up, you have many development branches from which you can work. From inside the repository you can see the branch names and the tag names used in the Git repository using either of the following two commands: $ cd poky $ git branch -a $ git tag -l This example uses the Yocto Project &DISTRO; Release code named "&DISTRO_NAME;", which maps to the &DISTRO_NAME; branch in the repository. The following commands create and checkout the local &DISTRO_NAME; branch: $ git checkout -b &DISTRO_NAME; origin/&DISTRO_NAME; Branch &DISTRO_NAME; set up to track remote branch &DISTRO_NAME; from origin. Switched to a new branch '&DISTRO_NAME;'
Setting Up the poky-extras Git Repository This example places the poky-extras Git repository inside of poky. See the bulleted item "The poky-extras Git Repository" for information on how to get the poky-extras repository. Because this example uses the Yocto Project &DISTRO; Release code named "&DISTRO_NAME;", which maps to the &DISTRO_NAME; branch in the repository, you need to be sure you are using that branch for poky-extra. The following commands create and checkout the local branch you are using for the &DISTRO_NAME; branch: $ git checkout -b &DISTRO_NAME; origin/&DISTRO_NAME; Branch &DISTRO_NAME; set up to track remote branch &DISTRO_NAME; from origin. Switched to a new branch '&DISTRO_NAME;'
Setting Up the Bare Clone and its Copy This example modifies the linux-yocto-3.2 kernel. Thus, you need to create a bare clone of that kernel and then make a copy of the bare clone. See the bulleted item "Linux Yocto Kernel" for information on how to do that. The bare clone exists for the kernel build tools and simply as the receiving end of git push commands after you make edits and commits inside the copy of the clone. The copy (my-linux-yocto-3.2-work in this example) has to have a local branch created and checked out for your work. This example uses common-pc-base as the local branch. The following commands create and checkout the branch: $ cd ~/my-linux-yocto-3.2-work $ git checkout -b common-pc-base origin/standard/default/common-pc/base Checking out files: 100% (532/532), done. Branch common-pc-base set up to track remote branch standard/default/common-pc/base from origin. Switched to a new branch 'common-pc-base'
Building and Booting the Default QEMU Kernel Image Before we make changes to the kernel source files, this example first builds the default image and then boots it inside the QEMU emulator. Because a full build can take hours, you should check two variables in the build directory that is created after you source the oe-init-build-env script. You can find these variables BB_NUMBER_THREADS and PARALLEL_MAKE in the build/conf directory in the local.conf configuration file. By default, these variables are commented out. If your host development system supports multi-core and multi-thread capabilities, you can uncomment these statements and set the variables to significantly shorten the full build time. As a guideline, set both BB_NUMBER_THREADS and PARALLEL_MAKE to twice the number of cores your machine supports. The following two commands source the build environment setup script and build the default qemux86 image. If necessary, the script creates the build directory: $ cd ~/poky $ source oe-init-build-env ### Shell environment set up for builds. ### You can now run 'bitbake <target>' Common targets are: core-image-minimal core-image-sato meta-toolchain meta-toolchain-sdk adt-installer meta-ide-support You can also run generated qemu images with a command like 'runqemu qemux86' The following bitbake command starts the build: $ bitbake -k core-image-minimal Be sure to check the settings in the local.conf before starting the build. After the build completes, you can start the QEMU emulator using the resulting image qemux86 as follows: $ runqemu qemux86 As the image boots in the emulator, console message and status output appears across the terminal window. Because the output scrolls by quickly, it is difficult to read. To examine the output, you log into the system using the login root with no password. Once you are logged in, issue the following command to scroll through the console output: # dmesg | less Take note of the output as you will want to look for your inserted print command output later in the example.
Changing the Source Code and Pushing it to the Bare Clone The file you change in this example is named calibrate.c and is located in the my-linux-yocto-3.2-work Git repository (the copy of the bare clone) in init. This example simply inserts several printk statements at the beginning of the calibrate_delay function. Here is the unaltered code at the start of this function: void __cpuinit calibrate_delay(void) { unsigned long lpj; static bool printed; int this_cpu = smp_processor_id(); if (per_cpu(cpu_loops_per_jiffy, this_cpu)) { . . . Here is the altered code showing five new printk statements near the top of the function: void __cpuinit calibrate_delay(void) { unsigned long lpj; static bool printed; int this_cpu = smp_processor_id(); printk("*************************************\n"); printk("* *\n"); printk("* HELLO YOCTO KERNEL *\n"); printk("* *\n"); printk("*************************************\n"); if (per_cpu(cpu_loops_per_jiffy, this_cpu)) { . . . After making and saving your changes, you need to stage them for the push. The following Git commands are one method of staging and committing your changes: $ git add calibrate.c $ git commit --signoff Once the source code has been modified, you need to use Git to push the changes to the bare clone. If you do not push the changes, then the Yocto Project build system will not pick up the changed source files. The following command pushes the changes to the bare clone: $ git push origin common-pc-base:standard/default/common-pc/base
Changing Build Parameters for Your Build At this point, the source has been changed and pushed. The example now defines some variables used by the Yocto Project build system to locate your kernel source. You essentially need to identify where to find the kernel recipe and the changed source code. You also need to be sure some basic configurations are in place that identify the type of machine you are building and to help speed up the build should your host support multiple-core and thread capabilities. Do the following to make sure the build parameters are set up for the example. Once you set up these build parameters, they do not have to change unless you change the target architecture of the machine you are building or you move the bare clone, copy of the clone, or the poky-extras repository: Build for the Correct Target Architecture: The local.conf file in the build directory defines the build's target architecture. By default, MACHINE is set to qemux86, which specifies a 32-bit Intel Architecture target machine suitable for the QEMU emulator. In this example, MACHINE is correctly configured. Optimize Build Time: Also in the local.conf file are two variables that can speed your build time if your host supports multi-core and multi-thread capabilities: BB_NUMBER_THREADS and PARALLEL_MAKE. If the host system has multiple cores then you can optimize build time by setting both these variables to twice the number of cores. Identify Your meta-kernel-dev Layer: The BBLAYERS variable in the bblayers.conf file found in the poky/build/conf directory needs to have the path to your local meta-kernel-dev layer. By default, the BBLAYERS variable contains paths to meta and meta-yocto in the poky Git repository. Add the path to your meta-kernel-dev location. Be sure to substitute your user information in the statement. Here is an example: BBLAYERS = " \ /home/scottrif/poky/meta \ /home/scottrif/poky/meta-yocto \ /home/scottrif/poky/poky-extras/meta-kernel-dev \ " Identify Your Source Files: In the linux-yocto_3.2.bbappend file located in the poky-extras/meta-kernel-dev/recipes-kernel/linux directory, you need to identify the location of the local source code, which in this example is the bare clone named linux-yocto-3.2.git. To do this, set the KSRC_linux_yocto variable to point to your local linux-yocto-3.2.git Git repository by adding the following statement. Be sure to substitute your user information in the statement: KSRC_linux_yocto_3_2 ?= "/home/scottrif/linux-yocto-3.2.git" Before attempting to build the modified kernel, there is one more set of changes you need to make in the meta-kernel-dev layer. Because all the kernel .bbappend files are parsed during the build process regardless of whether you are using them or not, you should either comment out the COMPATIBLE_MACHINE statements in all unused .bbappend files. Alternatively, you can simply remove all the files except the one your are using for the build (i.e. linux-yocto_3.2.bbappend in this example).
Building and Booting the Modified QEMU Kernel Image Next, you need to build the modified image. Do the following: Your environment should be set up since you previously sourced the oe-init-build-env script. If it isn't, source the script again from poky. $ cd ~/poky $ source oe-init-build-env Be sure old images are cleaned out by running the cleanall BitBake task as follows from your build directory: $ bitbake -c cleanall linux-yocto Never remove any files by hand from the tmp/deploy directory insided the local Yocto Project files build directory. Always use the BitBake cleanall task to clear out previous builds. Next, build the kernel image using this command: $ bitbake -k core-image-minimal Finally, boot the modified image in the QEMU emulator using this command: $ runqemu qemux86 Log into the machine using root with no password and then use the following shell command to scroll through the console's boot output. # dmesg | less You should see the results of your printk statements as part of the output.
Changing the Kernel Configuration This example changes the default behavior, which is "on", of the Symmetric Multi-processing Support (CONFIG_SMP) to "off". It is a simple example that demonstrates how to reconfigure the kernel.
Getting Set Up to Run this Example If you took the time to work through the example that modifies the kernel source code in "Modifying the Kernel Source Code" you should already have the Yocto Project files set up on your host machine. If this is the case, go to the next section, which is titled "Examining the Default CONFIG_SMP Behavior", and continue with the example. If you don't have the Yocto Project files established on your system, you can get them through tarball extraction or by cloning the poky Git repository. This example uses poky as the root directory of the local Yocto Project Files Git repository. See the bulleted item "Yocto Project Release" for information on how to get these files. Once you have the repository set up, you have many development branches from which you can work. From inside the repository you can see the branch names and the tag names used in the Git repository using either of the following two commands: $ cd poky $ git branch -a $ git tag -l This example uses the Yocto Project &DISTRO; Release code named "&DISTRO_NAME;", which maps to the &DISTRO_NAME; branch in the repository. The following commands create and checkout the local &DISTRO_NAME; branch: $ git checkout -b &DISTRO_NAME; origin/&DISTRO_NAME; Branch &DISTRO_NAME; set up to track remote branch &DISTRO_NAME; from origin. Switched to a new branch '&DISTRO_NAME;' Next, you need to build the default qemux86 image that you can boot using QEMU. Because a full build can take hours, you should check two variables in the build directory that is created after you source the oe-init-build-env script. You can find these variables BB_NUMBER_THREADS and PARALLEL_MAKE in the build/conf directory in the local.conf configuration file. By default, these variables are commented out. If your host development system supports multi-core and multi-thread capabilities, you can uncomment these statements and set the variables to significantly shorten the full build time. As a guideline, set BB_NUMBER_THREADS to twice the number of cores your machine supports and set PARALLEL_MAKE to one and a half times the number of cores your machine supports. The following two commands source the build environment setup script and build the default qemux86 image. If necessary, the script creates the build directory: $ cd ~/poky $ source oe-init-build-env ### Shell environment set up for builds. ### You can now run 'bitbake <target>' Common targets are: core-image-minimal core-image-sato meta-toolchain meta-toolchain-sdk adt-installer meta-ide-support You can also run generated qemu images with a command like 'runqemu qemux86' The following bitbake command starts the build: $ bitbake -k core-image-minimal Be sure to check the settings in the local.conf before starting the build.
Examining the Default  <filename>CONFIG_SMP</filename> Behavior By default, CONFIG_SMP supports multiple processor machines. To see this default setting from within the QEMU emulator, boot your image using the emulator as follows: $ runqemu qemux86 qemuparams="-smp 4" Login to the machine using root with no password. After logging in, enter the following command to see how many processors are being supported in the emulator. The emulator reports support for the number of processors you specified using the -smp option, four in this case: # cat /proc/cpuinfo | grep processor processor : 0 processor : 1 processor : 2 processor : 3 # To check the setting for CONFIG_SMP, you can use the following command: zcat /proc/config.gz | grep CONFIG_SMP The console returns the following showing that multi-processor machine support is set: CONFIG_SMP=y Logout of the emulator using the exit command and then close it down.
Changing the  <filename>CONFIG_SMP</filename> Configuration Using  <filename>menuconfig</filename> The menuconfig tool provides an interactive method with which to set kernel configurations. You need to run menuconfig inside the Yocto BitBake environment. Thus, the environment must be set up using the oe-init-build-env script found in the Yocto Project files Git repository build directory. If you have not sourced this script do so with the following commands: $ cd ~/poky $ source oe-init-build-env After setting up the environment to run menuconfig, you are ready to use the tool to interactively change the kernel configuration. In this example, we are basing our changes on the linux-yocto-3.2 kernel. The Yocto Project build environment recognizes this kernel as linux-yocto. Thus, the following commands from the shell in which you previously sourced the environment initialization script cleans the shared state memory and the WORKDIR directory and then builds and launches menuconfig: $ bitbake linux-yocto -c cleansstate $ bitbake linux-yocto -c menuconfig Due to a bug in the release, it is necessary to clean the shared state memory in order for configurations made using menuconfig to take effect. For information on the bug, see Once menuconfig launches, navigate through the user interface to find the CONFIG_SMP configuration setting. You can find it at Processor Type and Features. The configuration selection is Symmetric Multi-processing Support. After using the arrow keys to highlight this selection, press "n" to turn it off. Then, exit out and save your selections. Once you save the selection, the .config configuration file is updated. This is the file that the build system uses to configure the Linux Yocto kernel when it is built. You can find and examine this file in the Yocto Project Files Git repository in the build directory. This example uses the following: ~/poky/build/tmp/work/qemux86-poky-linux/linux-yocto-3.2.11+git1+84f... ...656ed30-r1/linux-qemux86-standard-build The previous example directory is artificially split and many of the characters in the actual filename are omitted in order to make it more readable. Also, depending on the kernel you are using, the exact pathname might differ slightly. Within the .config file, you can see the following setting: # CONFIG_SMP is not set A good method to isolate changed configurations is to use a combination of the menuconfig tool and simple shell commands. Before changing configurations with menuconfig, copy the existing .config and rename it to something else, use menuconfig to make as many changes an you want and save them, then compare the renamed configuration file against the newly created file. You can use the resulting differences as your base to create configuration fragments to permanently save in your kernel layer. Be sure to make a copy of the .config and don't just rename it. The Yocto Project build system needs an existing .config from which to work.
Recompiling the Kernel and Testing the New Configuration At this point, you are ready to recompile your kernel image with the new setting in effect using the BitBake commands below: $ bitbake linux-yocto -c compile -f $ bitbake linux-yocto Manually turning off a kernel configuration setting such as CONFIG_SMP can cause the kernel configuration audit to issue warnings during the build. In this example, warnings appear telling you that the expected value CONFIG_SMP does not appear in the .config file. Because in this example you specifically turned off CONFIG_SMP, you can safely ignore the apparent conflict. Now run the QEMU emulator and pass it the same multi-processor option as before: $ runqemu qemux86 qemuparams="-smp 4" Login to the machine using root with no password and test for the number of processors the kernel supports: # cat /proc/cpuinfo | grep processor processor : 0 # From the output, you can see that the kernel no longer supports multi-processor systems. The output indicates support for a single processor. You can verify the CONFIG_SMP setting by using this command: zcat /proc/config.gz | grep CONFIG_SMP The console returns the following output: # CONFIG_SMP is not set You have successfully reconfigured the kernel.
Adding Kernel Recipes A future release of this manual will present an example that adds kernel recipes, which provide new functionality to the kernel.