Kernel Modification Example Kernel modification involves changing or adding configurations to an existing kernel, or adding recipes to the kernel that are needed to support specific hardware features. The process is similar to creating a Board Support Package (BSP) except that it invloves isolating your work in a kernel layer and the use of menuconfig to help make configuration data easily identifiable. This section presents a simple example that shows how to modify the kernel. The example uses a three-step approach that is convenient for making kernel modifications. Iteratively determine and set kernel configurations and make kernel recipe changes. Apply your configuration changes to your local kernel layer. Push your configuration and recipe changes upstream into the Yocto Project source repositories to make them available to the community.
Modifying a Kernel Example The example changes kernel configurations to support the VFAT filesystem and allow the user to print out a simple text file from the mounted VFAT filesystem. The filesystem used will be an image filesystem rather than a filesystem on some external drive such as a USB stick or external drive. The example uses the linux-yocto-2.6.37 kernel. For a general flow of the example, see Kernel Modification Workflow earlier in this manual.
Setting Up Yocto Project You need to have the Yocto Project files available on your host system. You can get files through tarball extraction or by cloning the poky Git repository. See the bulleted item Yocto Project Release in Getting Setup earlier in this manual for information on how to get these files. Once you have the local poky Git 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: $ git branch -a $ git tag -l For this example we are going to use the Yocto Project 1.1 Release, which maps to the 1.1 branch in the repository. These commands create a local branch named 1.1 that tracks the remote branch of the same name. $ cd poky $ git checkout -b 1.1 origin/1.1 Switched to a new branch '1.1'
Getting a Local Copy of the Kernel Files You need to have a local copy of the Linux Yocto kernel files on your system. Yocto Project files available on your host system. You must create a local Git repository of these files. See the bulleted item Linux Yocto Kernel in Getting Setup earlier in this manual for information on how to get these files.
Create a Layer for Your Kernel Work It is always good to isolate your work using your own layer. Doing so allows you to experiment and easily start over should things go wrong. This example uses a layer named meta-vfatsupport. When you set up a layer for kernel work you should follow general layout guidelines layers. For example, if you were creating a BSP you would want to follow the layout described in the Example Filesystem Layout section of the Board Support Package (BSP) Development Guide. For kernel layers, you can start with a skeleton layer named meta-skeleton found in your local Yocto Project file directory structure (the poky Git repository or the directory structure resulting from unpacking the Yocto Project release tarball). To create your kernel layer simply copy the meta-skeleton layer and rename it meta-vfatsupport. The following command sets up the layer inside the poky Git repository: $ cd ~/poky $ cp -r meta-skeleton meta-vfatsupport In the new layer you will find areas for configuration changes (conf) and recipe changes (recipes-skeleton). You need to modify the structure a bit for your work. These commands add some further structure and names that the Yocto Project build environment expect: $ mkdir meta-vfatsupport/images $ mkdir meta-vfatsupport/recipes-bsp $ mv meta-vfatsupport/recipes-skeleton meta-vfatsupport/recipes-kernel $ mkdir meta-vfatsupport/recipes-kernel/linux $ mkdir meta-vfatsupport/recipes-kernel/linux/linux-yocto The last piece you need for your layer is a linux-yocto_git.bbappend file inside meta-vfatsupport/recipes-kernel/linux. This file needs the following content to make the build process aware of the new layer's location: FILESEXTRAPATHS := "${THISDIR}/${PN}" [WRITER'S NOTE: We need a better meta-skeleton layer that is part of poky. It should have a structure that includes images, recipes-bsp, recipes-kernel, and so forth. For now this step of the example is brute-forcing the structure with shell commands to set up the minimum structure and include the .bbappend file.
Be Sure the Image is Available For the example you need an image that you can use when you run the QEMU emulator. By default, support of VFAT filesystems will not be supported in this image. The example will test that in a subsequent section. In theory, you can get an image suitable for QEMU one of two ways: Download a pre-built kernel image and matching ext3 file system from the Yocto Project Index of downloads. See Index of Downloads earlier in the manual for more information about this source repository. You can also see Using Pre-Build Binaries and QEMU in the Yocto Project Quick Start for information on how to find and choose images ready to run in QEMU. Build an image and matching ext3 filesystem using the poky Git repository on your local development system. This example continues by building the image. If you want to see more on building an image in general, see Building an Image in the Yocto Project Quick Start. The following steps result in a QEMU image and filesystem for an x86 (32-bit) target machine that can run in the emulator. Prepare the Build Environment - Source the script to set up the build environment: $ cd ~/poky $ source oe-init-build-env Change Configurations to Speed Up the Build - If your development system supports multiple cores you can remove the comments in the BB_NUMBER_THREADS and PARALLEL_MAKE statements and adjust the arguments to optimize the build time. For example, a development host that has four cores could use 8 and j 6 to get the best use of your host's multi-core and thread capabilities. Start the Build - Use BitBake to start the build: $ bitbake -k core-image-sato Depending on your host system's load and capabilities the build takes some time. Once it completes you will have the kernel image needed to continue the example. The image and filesystem reside in the build directory at poky/build/tmp/deploy/images.
Is VFAT Supported? I entered runqemu qemux86 and it fires upthis fires up the emulator and uses the image and filesystem in the build area created in the previous section. Then I copied over a pre-created and formated 5.2MB VFAT file named vfat.img. I did this with scp vfat.img root@192.168.7.2: The file is in the root directory. I had to do this because the mkfs.vfat vfat.img command does not work. mkfs is not recognized in the qemu terminal session. when I try mount -o loop -t vfat vfat.img mnt/ I get the error mount: can't set up loop device: No space left on device. This error is because the loop module is not currently in the kernel image. However, this module is available in the build area in the tarball modules-2.6.37.6-yocto-starndard+-20-qemux86.tgz. You can add this to the kernel image by adding the IMAGE_INSTALL += " kernel-module-loop" statement at the top of the local.conf file in the build area and then rebuilding the kernel using bitbake. It should just build whatever is necessary and not go through an entire build again. The menuconfig tool provides an interactive method with which to set kernel configurations. In order to use menuconfig from within the BitBake environment you need to source an environment setup script. This script is located in the local Yocto Project file structure and is called oe-init-build-env. The following command sets up the environment: $ cd ~/poky $ source oe-init-build-env $ runqemu qemux86 Continuing with the following parameters: KERNEL: [/home/scottrif/poky/build/tmp/deploy/images/bzImage-qemux86.bin] ROOTFS: [/home/scottrif/poky/build/tmp/deploy/images/core-image-sato-qemux86.ext3] FSTYPE: [ext3] Setting up tap interface under sudo Acquiring lockfile for tap0... WARNING: distccd not present, no distcc support loaded. Running qemu... /home/scottrif/poky/build/tmp/sysroots/x86_64-linux/usr/bin/qemu -kernel /home/scottrif/poky/build/tmp/deploy/images/bzImage-qemux86.bin -net nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=no,downscript=no -hda /home/scottrif/poky/build/tmp/deploy/images/core-image-sato-qemux86.ext3 -show-cursor -usb -usbdevice wacom-tablet -vga vmware -enable-gl -no-reboot -m 128 --append "vga=0 root=/dev/hda rw mem=128M ip=192.168.7.2::192.168.7.1:255.255.255.0 oprofile.timer=1 " Enabling opengl vmsvga_value_write: guest runs Linux.
Prepare to use <filename>menuconfig</filename> The menuconfig tool provides an interactive method with which to set kernel configurations. In order to use menuconfig from within the BitBake environment you need to source an environment setup script. This script is located in the local Yocto Project file structure and is called oe-init-build-env. The following command sets up the environment: $ cd ~/poky $ source oe-init-build-env
Make Configuration Changes to the Kernel 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-2.6.37 kernel. The Yocto Project build environment recognizes this kernel as linux-yocto. Thus, the following command from the shell in which you previously sourced the environment initialization script launches menuconfig: $ bitbake linux-yocto -c menuconfig [WRITER'S NOTE: Stuff from here down are crib notes] Once menuconfig fires up you see all kinds of categories that you can interactively investigate. If they have an "M" in it then the feature is "modularized". I guess that means that means that it needs to be manually linked in when the kernel is booted??? (Not sure). If they have an "*" then the feature is automatically part of the kernel.] So the tmp/work/ area was created in poky and there is a .config file in there and a .config.old file. The old one must have been created when I exited from menuconfig after poking around a bit. Nope - appears to just be created automatically. A good practice is to first determine what configurations you have for the kernel. You can see the results by looking in the .config file in the build/tmp/work/qemux86-poky-linux area of the local YP files. There is a directory named linux-yocto-2.6.37* in the directory. In that directory is a directory named linux-qemux86-standard-build. In that directory you will find a file named .config that is the configuration file for the kernel that will be used when you build the kernel. You can open that file up and examine it. If you do a search for "VFAT" you will see that that particular configuration is not enabled for the kernel. This means that you cannot print a VFAT text file, or for that matter, even mount one from the image if you were to build it at this point. You can prove the point by actually trying it at this point. Here are the commands: $ mkdir ~/vfat-test $ cd ~/vfat-test $ dd if=/dev/zero of=vfat.img bs=1024 count=5000 [creates a 5MB disk image] 5+0 records in 5+0 records out 5242880 bytes (5.2 MB) copied, 0.00798912 s, 656 MB/s $ ls -lah [lists the contents of the new image. l=long, a=all, h=human readable] total 5.1M drwxr-xr-x 2 srifenbark scottrif 4.0K 2011-08-01 08:18 . drwxr-xr-x 66 srifenbark scottrif 4.0K 2011-08-01 08:14 .. -rw-r--r-- 1 srifenbark scottrif 5.0M 2011-08-01 08:18 vfat.img $ mkfs.vfat vfat.img [formats the disk image] mkfs.vfat 3.0.7 (24 Dec 2009) $ mkdir mnt [mounts the disk image] $ sudo su [gives you root privilege] # mount -o loop vfat.img mnt [mounts it as a loop device] # ls mnt [shows nothing in mnt] # mount [lists the mounted filesystems - note/dev/loop0] /dev/sda1 on / type ext4 (rw,errors=remount-ro) proc on /proc type proc (rw,noexec,nosuid,nodev) none on /sys type sysfs (rw,noexec,nosuid,nodev) none on /sys/fs/fuse/connections type fusectl (rw) none on /sys/kernel/debug type debugfs (rw) none on /sys/kernel/security type securityfs (rw) none on /dev type devtmpfs (rw,mode=0755) none on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620) none on /dev/shm type tmpfs (rw,nosuid,nodev) none on /var/run type tmpfs (rw,nosuid,mode=0755) none on /var/lock type tmpfs (rw,noexec,nosuid,nodev) none on /lib/init/rw type tmpfs (rw,nosuid,mode=0755) binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noexec,nosuid,nodev) gvfs-fuse-daemon on /home/scottrif/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,user=srifenbark) /dev/loop0 on /home/scottrif/vfat-test/mnt type vfat (rw) # echo "hello world" > mnt/hello.txt [creates a text file in the mounted VFAT system] # ls mnt [verifies the file is there] hello.txt # cat mnt/hello.txt [displays the contents of the file created] hello world # umount mnt [unmounts the system and destroys the loop] # exit [gets out of privileged user mode] exit $ lsmod [this stuff Darren did to show me ] Module Size Used by [the status of modules in the regular linux kernel] nls_iso8859_1 4633 0 nls_cp437 6351 0 vfat 10866 0 fat 55350 1 vfat snd_hda_codec_atihdmi 3023 1 binfmt_misc 7960 1 snd_hda_codec_realtek 279008 1 ppdev 6375 0 snd_hda_intel 25805 2 fbcon 39270 71 tileblit 2487 1 fbcon font 8053 1 fbcon bitblit 5811 1 fbcon snd_hda_codec 85759 3 snd_hda_codec_atihdmi,snd_hda_codec_realtek,snd_hda_intel softcursor 1565 1 bitblit snd_seq_dummy 1782 0 snd_hwdep 6924 1 snd_hda_codec vga16fb 12757 0 snd_pcm_oss 41394 0 snd_mixer_oss 16299 1 snd_pcm_oss snd_pcm 87946 3 snd_hda_intel,snd_hda_codec,snd_pcm_oss vgastate 9857 1 vga16fb snd_seq_oss 31191 0 snd_seq_midi 5829 0 snd_rawmidi 23420 1 snd_seq_midi radeon 744506 3 snd_seq_midi_event 7267 2 snd_seq_oss,snd_seq_midi ttm 61007 1 radeon snd_seq 57481 6 snd_seq_dummy,snd_seq_oss,snd_seq_midi,snd_seq_midi_event drm_kms_helper 30742 1 radeon snd_timer 23649 2 snd_pcm,snd_seq snd_seq_device 6888 5 snd_seq_dummy,snd_seq_oss,snd_seq_midi,snd_rawmidi,snd_seq usb_storage 50377 0 snd 71283 16 \ snd_hda_codec_realtek,snd_hda_intel,snd_hda_codec, \ snd_hwdep,snd_pcm_oss,snd_mixer_oss,snd_pcm, \ snd_seq_oss,snd_rawmidi,snd_seq,snd_timer,snd_seq_device soundcore 8052 1 snd psmouse 65040 0 drm 198886 5 radeon,ttm,drm_kms_helper i2c_algo_bit 6024 1 radeon serio_raw 4918 0 snd_page_alloc 8500 2 snd_hda_intel,snd_pcm dell_wmi 2177 0 dcdbas 6886 0 lp 9336 0 parport 37160 2 ppdev,lp usbhid 41116 0 ohci1394 30260 0 hid 83888 1 usbhid ieee1394 94771 1 ohci1394 tg3 122382 0