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

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.

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?

Where on disk is the BIOS file used by Simics?

(I saw one of my previous posts didn't actually answer the "where's the BIOS file used by simics?" question, so I renamed the previous one and am pulling that question out and making it standalone here.)
I can see the BIOS code for a default "targets\qsp-x86\firststeps.simics" invocation by just stepping through the debugger from the start. But if I want to see the full binary, is there a specific file somewhere I can look at?
you can check "bios" attribute on motherboard image:
simics> board.mb->bios
"%simics%/targets/qsp-x86/images/SIMICSX58IA32X64_1_0_0_bp_r.fd"
You can specify what BIOS image to use by bios_image script parameter to qsp-clear-linux.simics scripts.
Help info for the script:
$ ./simics -h targets/qsp-x86/qsp-clear-linux.simics
System:
bios_image - existing file or NIL
BIOS file.
Default value:
"%simics%/targets/qsp-x86/images/SIMICSX58IA32X64_1_0_0_bp_r.fd"
you can run with your own BIOS like this:
$ ./simics -e '$bios_image=my-bios.bin' targets/qsp-x86/qsp-clear-linux.simics
Now the BIOS is not quite handled consistently with some other things. Typically in Simics, disks and similar things are images. You can list them using list-persistent-images and resolve locations using lookup-file:
simics> list-persistent-images
┌─────────────────────┬────────────┬───────────────────────────────────────────────────────┐
│Image │Unsaved data│File(s) (read-only/read-write) │
├─────────────────────┼────────────┼───────────────────────────────────────────────────────┤
│board.disk0.hd_image │ no│%simics%/targets/qsp-x86/images/cl-b28910-v2.craff (ro)│
│board.disk1.hd_image │ no│ │
│board.mb.sb.spi_image│ yes│%simics%/targets/qsp-x86/images/spi-flash.bin (ro) │
└─────────────────────┴────────────┴───────────────────────────────────────────────────────┘
simics> lookup-file "%simics%/targets/qsp-x86/images/spi-flash.bin"
"/disk1/simics-6/simics-qsp-x86-6.0.47/targets/qsp-x86/images/spi-flash.bin"
The BIOS in the QSP is just loaded straight into target memory for execution. Which is a bit of a cheat for convenience.
Upon searching around, I found the following folder:
C:\Users\yourusername\AppData\Local\Programs\Simics\simics-qsp-x86-6.0.44\targets\qsp-x86\images
Inside that folder are the following 3 files:
SIMICSX58IA32X64_1_0_0_bp_r.fd
SIMICSX58IA32X64-ahci.fd
spi-flash. bin
Both SIMICSX58IA32X64_1_0_0_bp_r. fd and SIMICSX58IA32X64-ahci.fd have UEFI filevolume headers at the start, and a seeming BIOS entry point at the end. The spi-flash. bin seems to have a placeholder of the flash descriptor which would go at the start of the flash, but is mostly empty. So I believe Intel basically either stitches these together in memory, or possibly just uses the spi-flash. bin to allow for "soft strap" configuration or somesuch (since it's a virtual MCH/ICH anyway.)

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.

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