Passing Bootargs via Chosen node in Device Tree not working for Beaglebone Black - linux-device-driver

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.

Related

U-Boot won't take keyboard input from serial Raspberry Pi Model 3 B

I already have a working config for a compute module 3+. As I need the same setup on a raspberry Pi Model 3 B I tried bringing the config over.
Everything is compiled in a buildroot environment. U-Boot v2020.10 is used.
After some small changes regarding the device tree and dtoverlays I managed to get U-Boot to print on the serial console(as expected), but it ignores all keyboard input.
The following output is produced by U-Boot on serial console.
EDIT
I used the term serial very loosely here. I'm connected to the serial console with a serial-USB adapter and picocom. I applied the miniuart-bt overlay to restore /dev/ttyAMA0 respectively UART0 on gpio pins 14/15.
Lastely I configured U-Boot with PL011.
I left out support for mini-uart as this would break the output too.
This configuration works just fine on the compute module, but doen't register input on the model 3B.
EDIT
I moved the working u-boot.bin from the cm 3 to the model B to see what happens. It seemingly works as both are close enough. But the same problem occurs. The other way around though it does not work. So it is potential not a problem with U-Boot but with the Model B configuration.
1 Isa-Boot>·
2
3 U-Boot 2020.10 (Mar 24 2022 - 12:18:38 +0000)
4
5 DRAM: 924 MiB
6 RPI 3 Model B (0xa02082)
7 MMC: mmc#7e202000: 0, sdhci#7e300000: 1
8 In: serial
9 Out: vidconsole
10 Err: vidconsole
11 Hit any key to stop autoboot: 0·
Neither can I stop autoboot nor can I use the shell to complete the boot script.
I tried what feels like a million configurations and I'm out of ideas what could be the reason for this behavior. I also never experienced this with the cm module.
RPi setup config.txt:
enable_uart=1
start_file=start.elf
fixup_file=fixup.dat
kernel=u-boot.bin
gpu_mem=100
dtoverlay=miniuart-bt
dtparam=spi=on
device_tree=bcm2710-rpi-3-b.dtb
dtoverlay=sc16is750-spi0-ce0
U-Boot defconfig:
CONFIG_ARM=y
CONFIG_ARCH_CPU_INIT=y
CONFIG_ARCH_BCM283X=y
CONFIG_SYS_TEXT_BASE=0x00008000
CONFIG_TARGET_RPI_3_32B=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_NR_DRAM_BANKS=1
CONFIG_ENV_SIZE=0x4000
CONFIG_DEFAULT_DEVICE_TREE="bcm2837-rpi-3-b"
CONFIG_DISTRO_DEFAULTS=y
CONFIG_OF_BOARD_SETUP=y
CONFIG_SYS_STDIO_DEREGISTER=y
CONFIG_MISC_INIT_R=y
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SYS_PROMPT="Isa-Boot> "
CONFIG_CMD_GPIO=y
CONFIG_CMD_MMC=y
CONFIG_CMD_USB=y
CONFIG_CMD_FS_UUID=y
CONFIG_OF_EMBED=y
# CONFIG_ENV_IS_IN_FAT is not set
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
# CONFIG_NET is not set
CONFIG_DM_MMC=y
# CONFIG_MMC_HW_PARTITIONING is not set
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_BCM2835=y
CONFIG_DM_ETH=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_GENERIC is not set
# CONFIG_REQUIRE_SERIAL_CONSOLE is not set
# CONFIG_BCM283X_MU_SERIAL is not set
CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_DM_VIDEO=y
# CONFIG_VIDEO_BPP8 is not set
# CONFIG_VIDEO_BPP16 is not set
CONFIG_SYS_WHITE_ON_BLACK=y
CONFIG_CONSOLE_SCROLL_LINES=10
CONFIG_PHYS_TO_BUS=y
CONFIG_OF_LIBFDT_OVERLAY=y
From U-boot documentation, "U-boot Environment Variables":
bootdelay: After reset, U-Boot will wait this number of seconds before it executes the contents of the bootcmd variable. During this time a countdown is printed, which can be interrupted by pressing any key.
Set this variable to 0 boot without delay. Be careful: depending on the contents of your bootcmd variable, this can prevent you from entering interactive commands again forever!
Is this value 0 in your case?

Yocto Space Profiling Using KSize

I have a Yocto build that I am trying to shrink. I have removed a lot of unnecessary code by building core-image-full-cmdline. The Yocto mega manual mentions that to strip the size of your kernel you can use the ksize.py script in the project build directory. When I run this script I get an output of all 0s. This cannot be correct as I have a working SD card image with a booting kernel.
As I remember, you need to execute the script in the kernel folder. The script scan the current folder.
cd /path/to/kernel
python /path/to/ksize.py
(use python2 or 3 depending the current Yocto branch)
#PierreOlivier is right, you need to run this specifically from the kernel build directory (not the kernel source directory), in my case it is:
$ cd tmp/work/qemuarm64-poky-linux/linux-yocto/5.15.14+gitAUTOINC+72e4eafb6b_f77b2ba7d5-r0/linux-qemuarm64-standard-build
$ ../../../../../../../scripts/tiny/ksize.py
Linux Kernel total | text data bss
--------------------------------------------------------------------------------
vmlinux 20936031 | 15461191 4784912 689928
--------------------------------------------------------------------------------
fs/built-in.a 4548119 | 3862922 640608 44589
drivers/built-in.a 3991696 | 3591409 339384 60903
kernel/built-in.a 3104792 | 2078218 834883 191691
net/built-in.a 3083322 | 2731018 305491 46813
Additionally I recommend you try setting either:
DISTRO="poky-tiny"
or
PREFERRED_PROVIDER_linux-yocto = "linux-yocto-tiny"
Which would build a smaller kernel and/or rootfs as reference (assuming you are using linux-yocto and poky), you may set this on your local.conf

How to set Linux kernel command line on ARM?

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.

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"

U-boot environment is not the same as Linux "fw_printenv"

I've build an image for my Jetson Nano with yocto using the meta-tegra layer.
This build is using u-boot as bootloader which is set to save the environment on an MMC partition (mmcblk0p14).
gdisk -l /dev/mmcblk0 shows the following:
Number Start (sector) End (sector) Size Code Name
...
14 20996096 20998143 1024.0 KiB 8300 UBOOTENV
...
And the sector size is 512.
I've then configured u-boot-tegra/include/configs/p3450-porg.h with:
...
/* Env is located in it's own partition */
#define CONFIG_ENV_IS_IN_MMC
#define CONFIG_SYS_MMC_ENV_DEV 1
#define CONFIG_ENV_OFFSET (20996096 * 512)
...
Where CONFIG_ENV_OFFSET = Start_Sector * Block_Size
This works fine (as far as I can see) as the environment is saved successfully to MMC when i use saveenv.
However, the environment i get when i print it in u-boot shell is NOT the same as when i print the environment with fw_printenv u-boot tool. I have set the /etc/fw_env.config to:
# Device name Device offset Env size
/dev/mmcblk0p14 0 0x2000
So what I've gathered is that, either the fw_env.config is set wrong or the u-boot environment is saved somewhere else on the MMC and no the partition 14.
Does anyone have suggestions to what i could try?
*****************************************************EDIT:*****************************************************
Doing dd if=/dev/mmcblk0p14 of=tmp.txt and reading the tmp.txt file shows the environment that the fw_printenv shows and not the environment I'm seeing in u-boot shell.
So something must be wrong in the u-boot-tegra/include/configs/p3450-porg.h configuration. I just wonder where it actually writes the environment to when i do a saveenv...
Any Idea what I can try to change?
As stated in the comments to the question, the offset is a 32-bit integer so attempting to give it the value of more than 4,294,967,295 (which 20996096 * 512 is) is not gonna work.
To fix it, I've rearranged my partition scheme to have my uboot environment partition as partition 1 instead of 14 and changed the fw_env.config and p3450-porg.h patch accordingly.