How to set Linux kernel command line on ARM? - command-line

My understanding is that for ARM there are three sources for the kernel boot command line in general:
Those given as CONFIG_CMDLINE in the kernel configuration
Those passed on by the boot loader (typically U-Boot on ARM processors)
Those included in the device tree, under chosen/bootargs
Which one is used depends on kernel configuration parameters. My question is how to choose between these options using kernel configuration?
And can one append to another i.e. can we pass some using CONFIG_CMDLINE and then append hardware specific parameters in device tree?
I'm trying combination 1, 2 AND 3 to begin with but this doesn't compile:
/dts-v1/;
#include "imx6q.dtsi"
#include "imx6q-h.dtsi"
#include "imx6q-m.dtsi"
/ {
model = "A M";
compatible = "a,imx6q-hydra13", "a,imx6q-mercury",
"a,imx6q-hydra", "fsl,imx6q";
};
&ssd_touch {
status = "okay";
};
ERROR AT THIS LINE: chosen {
bootargs = "console=ttymxc1,115200";
};

My understanding is that for ARM there are three sources for the kernel boot command line in general:
That's not accurate for the Linux ARM kernel. The kernel only deals with two "sources", a default kernel command string and a bootloader kernel arguments string.
More details follow.
My question is how to choose between these options using kernel configuration?
You choices may be limited by only "using kernel configuration".
The "additional" command-line configuration choices, i.e. CONFIG_CMDLINE_FROM_BOOTLOADER ("Use bootloader kernel arguments if available"), CONFIG_CMDLINE_EXTEND ("Extend bootloader kernel arguments"), and CONFIG_CMDLINE_FORCE ("Always use the default kernel command string") are only available (since version 3.7) when support for the old ATAGs parameter passing (i.e. CONFIG_ATAGS) is enabled.
However CONFIG_ATAGS does default to y unless explicitly disabled. About a dozen _defconfig files in mainline arch/arm/configs/ do explicitly disable this CONFIG_ATAGS.
But where does the device tree fit in this scheme of things?
The Device Tree is the provider of bootloader kernel arguments.
That is, the bootargs= property in the /chosen node, is the conventional method of providing the command line to the ARM kernel, i.e. when CONFIG_ATAGS is disabled, or either CONFIG_CMDLINE_FROM_BOOTLOADER or CONFIG_CMDLINE_EXTEND are enabled.
The command line is retrieved by the kernel from the Device Tree as a string by early_init_dt_scan_chosen() in drivers/of/fdt.c
Only if CONFIG_CMDLINE_FORCE (with CONFIG_ATAGS) are enabled will the Device Tree bootargs= property be ignored.
You can configure/build the ARM kernel with a default kernel command using CONFIG_CMDLINE in case nothing else managed to set the command line.
A comment in drivers/of/fdt.c documents this.
CONFIG_CMDLINE_EXTEND (with CONFIG_ATAGS) results in a command line that is the concatenation of the Device Tree bootargs= property with the contents of CONFIG_CMDLINE.
However ...
When using U-Boot to boot the Linux kernel, be aware that when the environment variable bootargs is defined, U-Boot will (try to) install that bootargs environment variable (as a property) into the the /chosen node of the loaded Device Tree blob.
If the /chosen node does not exist in the DT, then it is created.
If the bootargs= property does not exist in that DT node, then it is created.
If the bootargs= property already exists in that DT node, then it is overwritten with the U-Boot environment variable.
See fdt_chosen() in common/fdt_support.c.
IOW U-Boot's bootargs environment variable typically becomes the de facto kernel command line.
And can one append to another i.e. can we pass some using CONFIG_CMDLINE and then append hardware specific parameters in device tree?
Only if (a) CONFIG_ATAGS is enabled, and (b) CONFIG_CMDLINE_EXTEND is enabled, and (c) ensure that there is no bootargs variable in U-Boot's environment.
Bottom Line
U-Boot always tries to pass its bootargs variable to the kernel using the Device Tree.
The bootargs= property in the Device Tree is always used by the kernel as the bootloader kernel arguments as mentioned in the arch/arm/Kconfig file.

Related

Where yocto assign default kernel?

There are many kernel *.bb in
~/poky/meta/recipes-kernel/linux
I don't have PREFERRED_PROVIDER_virtual/kernel defined in local.conf
I also include meta-intel layer, I think meta-intel has it's kernel recipe also.
After built the yocto image, boot, and login, type 'uname -a' result is
Linux genericx86-64 5.4.20-yocto-standard xxxxx
I think yocto select it's poky kernel, but I can't find where this default setting located. ( which file setting this kernel )
Usually you can find it in the machine conf in :
meta-yourmeta/conf/machine/yourmachine.conf
The list of supported kernels by your machine is in recipes-kernel of your BSP.
It's set by MACHINE, if I'm not wrong.
If you are unsure of your setting of PREFERRED_PROVIDER_virtual/kernel you can also use bitbake -e <recipe> to see how it is set.
Poky itself has it defined with default value
poky/meta/conf/machine/include/qemu.inc:22:PREFERRED_PROVIDER_virtual/kernel ??= "linux-yocto"
poky/meta/conf/machine/include/x86-base.inc:20:PREFERRED_PROVIDER_virtual/kernel ??= "linux-yocto"

Kernel Configuration Fragment not applying

I am attempting to add a linux kernel configuration fragment file (linux-1024MB-frags.config) into my build. Inside the fragment file I have set, CONFIG_HIGHMEM=y.
In my buildroot .config I have enabled,
BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_MYPATH)/board/common/linux-1024MB-frags.config"
When I do linux-dirclean && linux-configure I see the following output,
Merging /home/labuser/buildroot/trunk/board/common/linux-1024MB-frags.config
#
# merged configuration written to /home/labuser/buildroot/trunk/buildroot/output/build/linux-xilinx-v2017.1/.config (needs make)
#
Inspecting the new .config file shows that CONFIG_HIGHMEM is still not set.
If I set CONFIG_HIGHMEM in the main defconfig that I am using for the kernel (the one defined by BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE) and repeat the make steps I see that the CONFIG_HIGHMEM option IS set.

Yocto find the recipe or class that defines a task

I am a yocto noob, trying to decipher how the device tree is built from a Xilinx hardware definition (.hdf) file. But my question is more general.
Is there a yocto way to find the source of task?
Given a task name is it possible to find where the tasks source code lives? (presumably in a recipe or class)
As an example, where is the source for the Python task do_create_yaml which is called by recipes in the meta-xilinx-bsp layer that compile the device tree blob?
bitbake -e device-tree
Will dump the python source for do_create_yaml (amongst the rest of it prodigious output) but how can I find where that is coming from?
Device tree is part of Linux Kernel. In Yocto, this is compiled from KERNEL_DEVICETREE variable value either defined as part of Linux Kernel recipe or machine configuration.
For example, for cubieboard7 as defined here,
KERNEL_DEVICETREE = "s700_cb7_linux.dtb"
instructs the compilation to use this dts file for compilation. This is done by yocto by using various classes.
In our example, we inherit kernel.bbclass which in turn inherits kernel-devicetree.bbclass, in this class (copied from kernel-devicetree.bbclass),
do_compile_append() {
for dtbf in ${KERNEL_DEVICETREE}; do
dtb=`normalize_dtb "$dtbf"`
oe_runmake $dtb
done
}
do_install_append() {
for dtbf in ${KERNEL_DEVICETREE}; do
dtb=`normalize_dtb "$dtbf"`
dtb_ext=${dtb##*.}
dtb_base_name=`basename $dtb .$dtb_ext`
dtb_path=`get_real_dtb_path_in_kernel "$dtb"`
install -m 0644 $dtb_path ${D}/${KERNEL_IMAGEDEST}/$dtb_base_name.$dtb_ext
done
}
do_deploy_append() {
for dtbf in ${KERNEL_DEVICETREE}; do
dtb=`normalize_dtb "$dtbf"`
this appends tasks to compile, install and deploy tasks. So defining KERNEL_DEVICETREE enables the automatic build of dtb.
I found that the datastore contains the filename for tasks as a VarFlag,
from a devpyshell
pydevshell> d.getVarFlags("do_create_yaml")
gives
{'filename': '.....yocto/sources/core/../meta-xilinx-tools/classes/xsctyaml.bbclass', 'lineno': '61', 'func': 1, 'task': 1, 'python': '1', 'deps': ['do_prepare_recipe_sysroot']}
So for the example in my question the active definition for the do_create_yaml task is in xsctyaml.bbclass.

Passing Bootargs via Chosen node in Device Tree not working for Beaglebone Black

As per my understanding chosen node is used to send boot arguments to the kernel.
The following is the chosen node of the existing device code (am335x-bone-common.dtsi).
chosen {
stdout-path = &uart0;
};
So, I have modified chosen node to pass kernel arguments.
chosen {
bootargs = "console=ttyO0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rw rootwait";
stdout-path = &uart0;
};
While bringing up the board I encountered KERNEL PANIC,
Here is the log {https://pastebin.com/XHyrsmfG}
FYI: These are the u-boot commands issued on serial console(minicom) inorder to port kernel and devicetree using SDcard.
fatload mmc 0:1 0x81000000 zImage
fatload mmc 0:1 0x82000000 am335x-boneblack.dtb
bootz 0x81000000 - 0x82000000
As per my understanding chosen node is used to send boot arguments to the kernel.
Your understanding is incomplete.
As already mentioned in another answer, the kernel command line provided by the bootloader (i.e. U-Boot) is the actual list of parameters currently used when you boot the board.
For ARM Linux the default kernel configuration gives precedence to the bootloader's command line over the default kernel command string and the bootargs in the chosen node in the Device Tree.
The rationale according to U-Boot author/maintainer Wolfgang Denk seems to be that any hardcoded, built-in bootargs are inferior to bootargs that can be easily customized and supplied by a bootloader.
This is exactly what you are seeing.
There are actually three possible ARM kernel boot configuration choices:
Kernel command line type:
(X) Use bootloader kernel arguments if available
( ) Extend bootloader kernel arguments
( ) Always use the default kernel command string
If you want to always ignore the command line in U-Boot's bootargs variable (and the command line from the DT), but exclusively use the default kernel command string as defined in CONFIG_CMDLINE, then the kernel should be configured for the third choice (CONFIG_CMDLINE_FORCE) on that list.
Note that this list of choices is only available when CONFIG_ATAGS is enabled ("Support for the traditional ATAGS boot data passing").
The scheme that selects the DT bootargs is to use the existing kernel configuration, but simply delete that U-Boot environment variable (i.e. setenv bootargs).
If you change U-Boot's bootargs variable to an empty string as mentioned in another answer, the kernel will use its default kernel command string (CONFIG_CMDLINE) rather than the DT.
Also see How to set Linux kernel command line on ARM?
As per my understanding chosen node is used to send boot arguments to
the kernel. The following is the chosen node of the existing device
code (am335x-bone-common.dtsi).
chosen {
bootargs = "console=ttyO0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rw rootwait";
stdout-path = &uart0;
};
Looking at your pastie, the boot log says the command line is the following:
Kernel command line: console=ttyO0,115200
ip=10.0.0.111:10.0.0.4::255.255. 255.0 rw root=/dev/nfs
nfsroot=10.0.0.4:/home/dileep/beaglebone/rootfs,
And since you have also set the bootargs "bootargs = "console=ttyO0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rw rootwait";" in the devicetree wouldnt affect as uboot has already set those parameters, ie if same parameter is set in the device tree and in the tags (uboot), the one from the uboot tags will be chosen.
So you will have to clear up the bootargs set by u-boot.
1] setenv bootargs "";
2] saveenv
3] fatload mmc 0:1 0x81000000 zImage
4] fatload mmc 0:1 0x82000000 am335x-boneblack.dtb
5 bootz 0x81000000 - 0x82000000
For fresh building uboot, where the board is not programmed yet make sure in the u-boot configs you don’t have bootargs variable defined.

Where does dev_dbg writes log to?

In a device driver source in the Linux tree, I saw dev_dbg(...) and dev_err(...), where do I find the logged message?
One reference suggest to add #define DEBUG . The other reference involves dynamic debug and debugfs, and I got lost.
dev_dbg() expands to dynamic_dev_dbg(), dev_printk(), or no-op depending on the compilation flags.
#if defined(CONFIG_DYNAMIC_DEBUG)
#define dev_dbg(dev, format, ...) \
do { \
dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
} while (0)
#elif defined(DEBUG)
#define dev_dbg(dev, format, arg...) \
dev_printk(KERN_DEBUG, dev, format, ##arg)
#else
#define dev_dbg(dev, format, arg...) \
({ \
if (0) \
dev_printk(KERN_DEBUG, dev, format, ##arg); \
})
#endif
dynamic_dev_dbg() and dev_printk() call dev_printk_emit() which calls vprintk_emit().
This very same function is called in a normal mode when you just do a printk(). Just note here, that the rest functions like dev_err() will end up in the same function.
Thus, obviously, the buffer is all the same, i.e. kernel intrenal buffer.
The logged message at the end is printed to
Current console if kernel loglevel value (can be changed via kernel command line or via procfs) is high enough for certain message, here KERN_DEBUG.
Internal buffer which can be read by running dmesg command.
Note, data in 2 is kept as long as there still room in the buffer. Since it's limited and circular, newer data preempts old one.
Additional information how to enable Dynamic Debug.
First of all, be sure you have CONFIG_DYNAMIC_DEBUG=y in the kernel configuration.
Assume we would like to enable all debug prints in the built-in module with name 8250. To achieve that we simple add to the kernel command line the following 8250.dyndbg=+p.
If the same driver is compiled as loadable module we may either add options 8250 dyndbg to the modprobe configuration or to the shell command line when do it manually, like modprobe 8250 dyndbg.
More details are described in the Dynamic Debug documentation.
The "How certain debug prints are automatically enabled in linux kernel?" raises the question why some debug prints are automatically enabled and how DEBUG affects that when CONFIG_DYNAMIC_DEBUG=y. The answer is lying in the dynamic_debug.h and since it's used during compilation the _DPRINTK_FLAGS_DEFAULT defines the certain message appearence.
#if defined DEBUG
#define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
#else
#define _DPRINTK_FLAGS_DEFAULT 0
#endif
you can find dev_err(...) in kernel messages. As the name implies, dev_err(...) messages are error messages, so they will definitely be printed if the execution comes to that point. dev_dbg(...) are debug messages which are more generously used in the kernel driver code and they are not printed by default. So everything you have read about dynamic_debugging comes into play with dev_dbg(...).
There are several pre-conditions to have dynamic debugging working, below 1. and 2. are general preconditions for dynamic debugging. 3. and later are for your particular driver/module/subsystem and can be .
Dynamic debugging support has to be in your kernel config CONFIG_DYNAMIC_DEBUG=y. You may check if it is the case zgrep DYNAMIC_DEBUG /proc/config.gz
debugfs has to be mounted. You can check with sudo mount | grep debugfs and if not existing, you can mount with sudo mount -t debugfs /sys/kernel/debug
refer to dynamic_debugging and enable the particular file/function/line you are interested