Adding and compiling new code in the linux kernel - compilation

This may sound like a very noob question.
I'm trying to implement a UDP-based protocol in the linux kernel. I was following the UDPLite protocol implementation as a reference.
Step 1
I created a new_protocol.c in net/ipv4/
This file has a function
void _init protocol_init(void){*Code here*}
I also used
#include "udp_impl.h"
in this file as I was using some functions from the UDP protocol
Step 2
I modified the file net/ipv4/udp_impl.h to include net/new_protocol.h
Step 3
I created the file include/net/new_protocol.h where I defined the function
void protocol_init(void);
Step 4
Finally, I called the function in net/ipv4/af_inet.c. Also, I gave an include statement in this file for net/new_protocol.h
Now when I try to build the kernel, I get an error saying
undefined reference to `protocol_init()'
What am I missing here? Is my way of including header files incorrect? Do I need to include some info in the makefile to pick up the new net/ipv4/protocol.c?

Do I need to include some info in the makefile to pick up the new net/ipv4/protocol.c?
Yes, you need. Kernel build system doesn't autodetect source files, all of them should be listed explicitely in appropriate Makefile. In you case you need to modify net/ipv4/Makefile.
Makefiles used for kernel build are described in file Documentation/kbuild/makefiles.txt.

I just needed to add protocol.o in the makefile in net/ipv4/

Related

Error(s) in building Veins-LTE: OperationalBase.h not found

I am trying to build Veins-LTE 1.3, which includes inet, simulte and veins for LTE-based vehicular networks simulations.
By following the README, I get into the root package and write:
make makefiles //this creates the required Makefile in inet, veins and simulte
make
This last command, however, results into a fatal error in building inet:
In file included from applications/common/ApplicationBase.h:21:10:
fatal error: 'OperationalBase.h': file not found
By opening the file 'inet/src/applications/common/ApplicationBase.h', I immediately realize that the problem lies in the inclusion of the 'OperationalBase.h', which, as a matter of fact, is not present in the same directory. Instead, it can be found in the 'inet/src/base/' directory.
Omnet++ : 5.2.
Veins-LTE: inet 2.3.0, veins 2.1bis, simulte 0.9.1
SUMO: 0.30.0 (if this could be relevant)
Environment: Ubuntu 16.04.1 - amd64
I am perfectly conscious that a similar question already exists here, but it has not received answers nor comments since last August, so..
WHAT I TRIED TO DO:
My first action was simply to change the path in the include statement so that to point to the right folder: #include "../../base/OperationalBase.h"; this actually shifts the problem elsewhere, since all the other source files in the 'inet' framework inside the veins-lte package do not include the full paths of the required header files (i.e., they seem to assume all the .h files are inside the same directory). Moreover, the omnetpp methods are not recognized, since no using namespace omnetpp is present.
I had a look at 'inet/Makefile' file; in particular, after changing to the 'src/' folder, the opp_makemake command comes with the following options:
opp_makemake -f --deep --make-so -o inet -O out -pINET -
Xapplications/voipstream -Xtransport/tcp_lwip -Xtransport/tcp_nsc -
DWITH_TCP_COMMON .... and other stuff sounding like -DWITH_
As per the opp_makemake documentation (opp_makemake), the --deep option should cater for deep includes. Does it mean that the full (or relative to src/) path of the .h file to be included is not required? The only source folders that are excluded seem to be transport/tcp_lwip, applications/voipstream, transport/tcp_nsc.
So, should I modify all source files by writing the full/relative path of the included files?
Is there a better, smarter, more centralized way to achieve this goal, maybe by modifying something in the inet/Makefile file?
Am I missing something very obvious?
Thank You
WHAT I AM ABLE TO DO:
Successfully run the Omnet++ TicToc examples;
Successfully run the veins RSU Example (by using the stand-alone veins
release)
Successfully run basic SUMO examples.

How to write a BitBake driver recipe which requires kernel source header files?

Introduction
I have a do_install task in a BitBake recipe which I've written for a driver where I execute a custom install script. The task fails because the installation script cannot find kernel source header files within <the image rootfs>/usr/src/kernel. This script runs fine on the generated OS.
What's Happening
Here's the relevant part of my recipe:
SRC_URI += "file://${TOPDIR}/example"
DEPENDS += " virtual/kernel linux-libc-headers "
do_install () {
( cd ${TOPDIR}/example/Install ; ./install )
}
Here's a relevant portion of the install script:
if [ ! -d "/usr/src/kernel/include" ]; then
echo ERROR: Linux kernel source include directory not found.
exit 1
fi
cd /usr/src/kernel
make scripts
...
./install_drv pci ${DRV_ARGS}
I checked changing to if [ ! -d "/usr/src/kernel" ], which also failed. install passes different options to install_drv, which I have a relevant portion of below:
cd ${DRV_PATH}/pci
make NO_SYSFS=${ARG_NO_SYSFS} NO_INSTALL=${ARG_NO_INSTALL} ${ARGS_HWINT}
if [ ${ARG_NO_INSTALL} == 0 ]; then
if [ `/sbin/lsmod | grep -ci "uceipci"` -eq 1 ]; then
./unload_pci
fi
./load_pci DEBUG=${ARG_DEBUG}
fi
The make target build: within ${DRV_PATH}/pci is essentially this:
make -C /usr/src/kernel SUBDIRS=${PWD} modules
My Research
I found these comments within linux-libc-headers.inc relevant:
# You're probably looking here thinking you need to create some new copy
# of linux-libc-headers since you have your own custom kernel. To put
# this simply, you DO NOT.
#
# Why? These headers are used to build the libc. If you customise the
# headers you are customising the libc and the libc becomes machine
# specific. Most people do not add custom libc extensions to the kernel
# and have a machine specific libc.
#
# But you have some kernel headers you need for some driver? That is fine
# but get them from STAGING_KERNEL_DIR where the kernel installs itself.
# This will make the package using them machine specific but this is much
# better than having a machine specific C library. This does mean your
# recipe needs a DEPENDS += "virtual/kernel" but again, that is fine and
# makes total sense.
#
# There can also be a case where your kernel extremely old and you want
# an older libc ABI for that old kernel. The headers installed by this
# recipe should still be a standard mainline kernel, not your own custom
# one.
I'm a bit unclear if I can 'get' the headers from the STAGING_KERNEL_DIR properly since I'm not using make.
Within kernel.bbclass provided in the meta/classes directory, there is this variable assigment:
# Define where the kernel headers are installed on the target as well as where
# they are staged.
KERNEL_SRC_PATH = "/usr/src/kernel"
This path is then packaged later within that .bbclass file here:
PACKAGES = "kernel kernel-base kernel-vmlinux kernel-image kernel-dev kernel-modules"
...
FILES_kernel-dev = "/boot/System.map* /boot/Module.symvers* /boot/config* ${KERNEL_SRC_PATH} /lib/modules/${KERNEL_VERSION}/build"
Update (1/21):
A suggestion on the yocto IRC channel was to use the following line:
do_configure[depends] += "virtual/kernel:do_shared_workdir"
which is corroborated by the Yocto Project Reference Manual, which states that in version 1.8, there was the following change:
The kernel build process was changed to place the source in a common shared work area and to place build artifacts separately in the source code tree. In theory, migration paths have been provided for most common usages in kernel recipes but this might not work in all cases. In particular, users need to ensure that ${S} (source files) and ${B} (build artifacts) are used correctly in functions such as do_configure and do_install. For kernel recipes that do not inherit from kernel-yocto or include linux-yocto.inc, you might wish to refer to the linux.inc file in the meta-oe layer for the kinds of changes you need to make. For reference, here is the commit where the linux.inc file in meta-oewas updated.
Recipes that rely on the kernel source code and do not inherit the module classes might need to add explicit dependencies on the do_shared_workdir kernel task, for example:
do_configure[depends] += "virtual/kernel:do_shared_workdir"
But I'm having difficulties applying this to my recipe. From what I understand, I should be able to change the above line to:
do_install[depends] += "virtual/kernel:do_shared_workdir"
Which would mean that the do_install task now must be run after do_shared_workdir task of the virtual/kernel recipe, which means that I should be able to work with the shared workdir (see Question 3 below), but I still have the same missing kernel header issue.
My Questions
I'm using a custom linux kernel (v3.14) from git.kernel.org. which inherits the kernel class. Here are some of my questions:
Shouldn't the package kernel-dev be a part of any recipe which inherits the kernel class? (this section of the variables glossary)
If I add the virtual/kernel to the DEPENDS variable, wouldn't that mean that the kernel-dev would be brought in?
If kernel-dev is part of the dependencies of my recipe, wouldn't I be able to point to the /usr/src/kernel directory from my recipe? According to this reply on the Yocto mailing list, I think I should.
How can I properly reference the kernel source header files, preferably without changing the installation script?
Consider your Environment
Remember that there are different environments within the the build time environment, consisting of:
sysroots
in the case of kernels, a shared work directory
target packages
kernel-dev is a target package, which you'd install into the rootfs of the target system for certain things like kernel symbol maps which are needed by profiling tools like perf/oprofile. It is not present at build time although some of its contents are available in the sysroots or shared workdir.
Point to the Correct Directories
Your do_install runs at build time so this is within the build directory structures of the build system, not the target one. In particular, /usr/src/ won't be correct, it would need to be some path within your build directory. The virtual/kernel do_shared_workdir task populates ${STAGING_DIR_KERNEL} so you would want to change to that directory in your script.
Adding a Task Dependency
The:
do_install[depends] += "virtual/kernel:do_shared_workdir
dependency like looks correct for your use case, assuming nothing in do_configure or do_compile accesses the data there.
Reconsider the module BitBake class
The other answers are correct in the recommendation to look at module.bbclass, since this illustrates how common kernel modules can be built. If you want to use custom functions or make commands, this is fine, you can just override them. If you really don't want to use that class, I would suggest taking inspiration from it though.
Task Dependencies
Adding virtual/kernel to DEPENDS means virtual/kernel:do_populate_sysroot must run before our do_configure task. Since you need a dependency for do_shared_workdir here, a DEPENDS on virtual/kernel is not enough.
Answer to Question 3
The kernel-dev package would be built, however it would then need to be installed into your target image and used at runtime on a real target. You need this at build time so kernel-dev is not appropriate.
Other Suggestions
You'd likely want the kernel-devsrc package for what you're doing, not the kernel-dev package.
I don't think anyone can properly answer that last question here. You are using a non-standard install method: we can't know how to interact with it...
That said, take a look at what meta/classes/module.bbclass does. It sets several related variables for make: KERNEL_SRC=${STAGING_KERNEL_DIR}, KERNEL_PATH=${STAGING_KERNEL_DIR}, O=${STAGING_KERNEL_BUILDDIR}. Maybe your installer supports some of these environment variables and you could set them in your recipe?

How do I generate loadable modules during Linux kernel build?

I seem to successfully build a kernel image, but I can not generate all the modules I expect. I expect more modules since I see them enabled in the gconfig window. Here is a copy of my make session. Seems like make goes into the devices directories. I can not figure out why it is not create the .ko files. I expect to see .ko files. I have checked the Makefile in /drivers directory, and I can see that it is configured with a number of lines like
obj-$(CONFIG_PCI) += pci/
Which directs make to build the pci module for instance. I think this implies that I should see a number .ko files. But I do not. I have seen just one .ko file for scsi module. I like to be able to build all of modules selected.
I also verified that a number of mudules are enabled when I issued:
make VARIANT_DEFCONFIG=msm8974_sec_hlte_spr_defconfig msm8974_sec_defconfig SELINUX_DEFCONFIG=selinux_defconfig gconfig
But as I said, I do not see any of them. What am I missing please?
#Subin - Thanks. I just tried make modules_install. I have to mention that I am cross compiling this for an arm target. I believe modules_install is for the purpose of installing the driver for the machine you are on? I got a message about needing to be in root, and I did not proceed. I have been wondering when I need to run it. What does it do exactly please?
Re: the make modules; I have run it before. I'll run it again and post the result. Since I got one .ko file I figured the issue is something different between that one module, and every other one enabled in my config. Here is what I got when I ran make modules:
sansari#ubuntu:~/WORKING_DIRECTORY$ make modules
CHK include/linux/version.h
CHK include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h' is up to date.
CALL scripts/checksyscalls.sh
Building modules, stage 2.
MODPOST 1 modules
Re: your comment on the location of .ko files, I am doing a find to see if perhaps I am not looking at the right place, it only finds the one which was built. Not the other ones. Here is the output:
sansari#ubuntu:~/WORKING_DIRECTORY$ find . -type f -name "*.ko"
./drivers/scsi/scsi_wait_scan.ko
sansari#ubuntu:~/WORKING_DIRECTORY$
Should I perhaps run make v=1, in verbose mode that is? Would that provide more information on why the other modules are not built?
#Gil Hamilton - Thanks. You are right. Here is an excerpt of the .config file:
#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
# CONFIG_BLK_DEV_SR is not set
CONFIG_CHR_DEV_SG=y
CONFIG_CHR_DEV_SCH=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_WAIT_SCAN=m
This entry is the only one set to 'm'.
Most device driver modules in the linux kernel build system use a tristate (3-valued) configuration setting. The options are
'n' (don't build at all),
'y' (build and link statically into the main kernel object), and
'm' (build as module for dynamic loading).
The values are determined by the content of .config. The values in .config are usually generated from an existing config file (look in arch/<ARCH>/configs for your <ARCH>). Also check the output of 'make help' for interesting configuration targets.
If you're not seeing the .ko files being created, that indicates the corresponding configuration variable is either set to 'y' or 'n'.

Need help in enable configuration when compile Kernel module

I am using 3.10.x kernel tree. My kernel module needs config VIDEOBUF2.
That is defined in drivers/media/v4l2-core/Kconfig:
# Used by drivers that need Videobuf2 modules
config VIDEOBUF2_CORE
select DMA_SHARED_BUFFER
tristate
So I put 'CONFIG_VIDEOBUF2_CORE=y' in my Kernel config file and
compile. From the Kconfig it has CONFIG_VIDEOBUF2_CORE has no
dependency and I think adding CONFIG_VIDEOBUF2_CORE=y to my kernel
config should work. I am modify the right kernel config file since I
set other flags like CONFIG_VIDEO_DEV=y and that works.
The generated .config does not contain 'CONFIG_VIDEOBUF2_CORE=y'
and the compilation fails with a bunch of
undefined reference to `vb2_buffer_done'
undefined reference to `vb2_buffer_done'
undefined reference to `vb2_buffer_done'
undefined reference to `vb2_buffer_done'
I really appreciate if someone can help me with this.
Thank you.
I cant directly comment on the subject as it requires 50 reputations to have this privilege. You can do : make ARCH = target_architecture CROSS_COMPILE = toolchain defconfig_file. This command execution will create a .config file in home directory of your kernel source. This file would contain default configuration for the peripherals on your target SOC ( I assume you have knowledge pertaining to defconfig files). Now if you wish to manipulate it and want to add your device support to it do : make menuconfig and you could add your device support by selecting configuration say like VIDEOBUF2_CORE in your case and then your kernel soure is ready to be compiled/cross-compiled. PS: Avoid editing .config file manually.

How to "make" existing Linux kernel module driver after modifying the driver source code

I have made some trivial modifications to a Linux USB Wi-Fi card driver to insert some logging (printk statements). I am loosely following a guide on how to recompile/load the module, which states that I need to execute make in order to build the .ko file. There is an existing Makefile in the working directory (/usr/src/linux/drivers/net/wireless/rtl818x/rtl8187/), which reads:
rtl8187-objs := dev.o rtl8225.o leds.o rfkill.o
obj-$(CONFIG_RTL8187) += rtl8187.o
ccflags-y += -Idrivers/net/wireless/rtl818x
When I execute make inside this directory, I get:
make: *** No targets. Stop.
According to this, this means "that some makefile was found, but it didn't contain any default goal and none was given on the command line. GNU make has nothing to do in these situations."
So my question is, what does this mean in the context of what I am trying to do, and how do I go about generating the .ko file which I am purported to need for the next step?
You must run make from the top directory of the Linux source (/usr/src/linux/). Be sure that your driver is included in your /usr/src/linux/.config file. So, build the kernel with your driver.
If you don't want to rebuild the entire kernel, read more :)
If you want to re-build all modules inside the directory:
make M=drivers/net/wireless/rtl818x/rtl8187/
If you want to re-build a single module inside the directory:
make M=drivers/net/wireless/rtl818x/ CONFIG_RTL8187=m
The *CONFIG_RTL8187* name can be found in drivers/net/wireless/rtl818x/Kconfig (CONFIG_ + RTL8187)
It should works also this:
make drivers/net/wireless/rtl818x/rtl8187/rtl8187.ko

Resources