fdt_addr not setup by U-Boot/first stage bootloader - raspberry-pi3

I'm working on setting up U-Boot for our systems using raspberry pi 3B plus and cm3. (Though atm I'm working just with cm3. I'm confident the same applies to the 3B plus)
I got rid of the default bootcmd run distro_bootcmd and load a first stage boot script first_boot.scr which then loads and sources the respected boot.scr.
%EDIT%
In my answer I mentioned already that the failure description is wrong. I just checked the fdt_addr variable at the wrong time, thus leading me on the wrong path.
%EDIT%
As we already have machines out in the field I'm working on updating them. Here lies the problem. If I setup a fresh device with the new architecture everything works just fine. If I update and older system though, fdt_addr is not setup, thus the boot failes.
I can of course manually setup fdt_addt, but I want to understand what could be the reason for fdt_addr not being setup. As far as I could find, the first stage bootloader is responsible. So I imagine something is not beeing triggered.
Updating in our case describes simply copying the new images to the device, moving u-boot.bin and first_boot.scr to the boot partition and then changing the config.txt to start U-Boot not the kernel directly.
While setting up a fresh machine is pretty much the same just with formatting the device and placing the files in the exact same places.
bootcmd: load mmc 0:1 ${scriptaddr} /first_boot.scr; source ${scriptaddr}
env load #<- %EDIT%
if test "${boot_count}" > 4; then
echo "###Loading factory kernel bootscript###"
setenv boot_kernel 2;
load mmc 0:2 ${scriptaddr} images/factory/boot.scr;
source ${scriptaddr}
elif test "${boot_count}" > 2; then
echo "###Loading factory kernel bootscript###"
setenv boot_kernel 1;
load mmc 0:2 ${scriptaddr} images/previous/boot.scr;
source ${scriptaddr}
else
echo "###Loading current kernel bootscript###"
setenv boot_kernel 0;
load mmc 0:2 ${scriptaddr} images/latest/boot.scr;
source ${scriptaddr}
fi
if test "${boot_kernel}" = 2; then
echo "###Loading factory kernel###"
load mmc 0:2 ${kernel_addr_r} images/factory/Image;
load mmc 0:2 ${fdt_addr} images/factory/device_tree.dtb;
elif test "${boot_kernel}" = 1; then
echo "###Loading previous kernel###"
load mmc 0:2 ${kernel_addr_r} images/previous/Image;
load mmc 0:2 ${fdt_addr} images/previous/device_tree.dtb;
else
echo "###Loading current kernel###"
load mmc 0:2 ${kernel_addr_r} images/latest/Image;
load mmc 0:2 ${fdt_addr} images/latest/device_tree.dtb;
fi
setenv bootargs console=ttyAMA0,115200 printk.devkmsg=on usbcore.autosuspend=-1 fsck.mode=force fsck.repair=yes
env save
booti ${kernel_addr_r} - ${fdt_addr}

The culprit was a line I sadly left out in my example as I deemed it unimportant...
I work with the boot_count variable also in user land, for that reason I save my environment to the drive so I can interact with it via fw_saveenv.
Because of that I need to load the environment at the beginning of first_boot.scr.
But if you try to load with env load when there is no uboot.env file alot of the environment information is lost. So now I do a check for uboot.env and save if it is not present and load if so.
I described the problem wrong in my question though. I check the presence of fdt_addr before sourching first_boot.scr at times, thus getting lead on the wrong track.
if test -e mmc 0:1 uboot.env; then
echo "Loading env"
env load
else
echo "Saving default environment to file"
env save
fi
if test "${boot_count}" > 4; then
echo "###Loading factory kernel bootscript###"
setenv boot_kernel 2;
load mmc 0:2 ${scriptaddr} images/factory/boot.scr;
source ${scriptaddr}
elif test "${boot_count}" > 2; then
echo "###Loading factory kernel bootscript###"
setenv boot_kernel 1;
load mmc 0:2 ${scriptaddr} images/previous/boot.scr;
source ${scriptaddr}
else
echo "###Loading current kernel bootscript###"
setenv boot_kernel 0;
load mmc 0:2 ${scriptaddr} images/latest/boot.scr;
source ${scriptaddr}
fi

Related

Yocto linux loading wrong dtb

I have my custom image for beaglebone created with linux-yocto-tiny. In order to make my cape work, i've created a custom .dts file. Everything compiles successfully, .dtb is created and placed inside boot directory. However, upon boot linux is trying to load am335x-boneblack.dtb. I am certain that my custom device-tree is working, because when i re-name it to am335x*** everything is working as intended.
Now, i've made few patches that i thought will make linux load my device tree:
1) In my machine configuration file my-yocto.conf i have the following lines (pasting relevant, in my opinion lines):
KERNEL_DEVICETREE = "my-cape.dtb"
IMAGE_BOOT_FILES ?= "u-boot.${UBOOT_SUFFIX} MLO zImage my-cape.dtb"
UBOOT_MACHINE = "am335x_evm_defconfig"
2) I've patched makefile:
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index dab2914fa..6f9892643 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
## -730,6 +730,7 ## dtb-$(CONFIG_SOC_AM33XX) += \
am335x-base0033.dtb \
am335x-bone.dtb \
am335x-boneblack.dtb \
+ my-cape.dtb \
am335x-boneblack-wireless.dtb \
am335x-boneblue.dtb \
am335x-bonegreen.dtb \
3) Made patches in u-boot:
Here i wasn't sure what to place in CONFIG_OF_LIST, a name of machine or device-tree, so i placed both:
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index 3457c1fc34..cc260ccedf 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
## -32,7 +32,7 ## CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:128k(NAND.SPL),128k(NAND.SPL.backup1),1
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_OF_CONTROL=y
CONFIG_DEFAULT_DEVICE_TREE="am335x-evm"
-CONFIG_OF_LIST="am335x-evm am335x-bone am335x-boneblack am335x-evmsk am335x-bonegreen am335x-icev2 am335x-pocketbeagle"
+CONFIG_OF_LIST="am335x-evm am335x-bone am335x-boneblack am335x-evmsk am335x-bonegreen am335x-icev2 am335x-pocketbeagle my-cape my-yocto"
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_SPL_ENV_IS_NOWHERE=y
CONFIG_BOOTCOUNT_LIMIT=y
--
2.17.1
Changes in am335x_evm.h:
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index c2b2d8dc..e0c1a160 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
## -139,7 +139,7 ##
"if test $board_name = A335BONE; then " \
"setenv fdtfile my-cape.dtb; fi; " \
"if test $board_name = A335BNLT; then " \
- "setenv fdtfile am335x-boneblack.dtb; fi; " \
+ "setenv fdtfile my-cape.dtb; fi; " \
"if test $board_name = A335PBGL; then " \
"setenv fdtfile am335x-pocketbeagle.dtb; fi; " \
"if test $board_name = BBBW; then " \
--
2.17.1
and
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index b5fba0a8b0..c2b2d8dc90 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
## -103,7 +103,7 ##
"bootpart=0:2\0" \
"bootdir=/boot\0" \
"bootfile=zImage\0" \
- "fdtfile=undefined\0" \
+ "fdtfile=my-cape.dtb\0" \
"console=ttyO0,115200n8\0" \
"partitions=" \
Did i miss something? I can load my dtb with a uEnv file (which i did, and it's working). But i would like my device-tree to be loaded without it. Upon loading the system i see this:
witch to partitions #0, OK
mmc0 is current device
SD/MMC found on device 0
switch to partitions #0, OK
mmc1(part 0) is current device
SD/MMC found on device 1
** Unrecognized filesystem type **
** Unrecognized filesystem type **
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found /extlinux/extlinux.conf
Retrieving file: /extlinux/extlinux.conf
119 bytes read in 5 ms (22.5 KiB/s)
1: Yocto
Retrieving file: /zImage
8905216 bytes read in 574 ms (14.8 MiB/s)
append: root=PARTUUID=0b6a9c67-02 rootwait console=ttyS0,115200
Retrieving file: /am335x-boneblack.dtb
Skipping Yocto for failure retrieving fdt
How do i make u-boot to look for my-cape.dtb instead of am335x-boneblack.dtb ?
EDIT
I found this when doing printenv:
findfdt=if test $board_name = A335BONE; then setenv fdtfile am335x-bone.dtb; fi
Why is it still looking for am335x-bone.dtb ? I think something is overwriting my patches.
Well, this depends on the uboot configuration. From what I can tell, the latest uboot recipe in the meta-beagleboard layer (specifially this patch) configures the default boot command to load am335x-boneblack.dtb.
Most uboot configs allow you to specify your own boot command in your uEnv.txt (maybe just try to set the fdtfile variable there fdtfile=mydevicetree.dtb).
Otherwise you could provide your own uboot configuration or patch the existing one to load your dtb file.

bitbake not producing a zImage file

I've been running a Yocto build in bitbake for a few days, but I've noticed it sometimes stops producing the zImage file of my kernel. Most of the changes I'm making are to the kernel config, and the machine.conf file. when this happens, I still get updated tar.gz files with each build, but the zImage stops being updated. Running the do_clean, do_cleanall and do_cleansstate tasks do not help, and neither does deleting the old zImage file from build/tmp/deploy. The only thing that helps is deleting the entire pocky/build/tmp directory and rebuilding the entire project from scratch. Here is my current machine.conf file:
##TYPE: Machine
##Name: EMAC, Inc. SoM-9G45M Module
##DESCRIPTION: Machine.inc configuration for the SoM-9G45M board with a at91sam9g45 processor
TARGET_ARCH = "arm"
PREFERRED_PROVIDER_virtual/kernel = "linux-2.6.30-at91-emac"
PREFERRED_PROVIDER_xserver = "xserver-kdrive"
KERNEL_IMAGETYPE = "zImage"
KERNEL_EXTRA_ARGS = "LOADADDR=0x74000000"
#don't try to access tty1
USE_VT = "0"
MACHINE_FEATURES = "kernel26 apm alsa ext2 usbhost usbgadget"
KERNEL_DEVICETREE = "at91som9g45.dtb"
# used by sysvinit_2
#SERIAL_CONSOLE = "115200 ttyS1"
SERIAL_CONSOLE = "115200 ttyS0"
#SERIAL_CONSOLES = "115200;ttyS0 115200;ttyS1"
#SYSLINUX_DEFAULT_CONSOLE = "console=ttyS0"
#SYSLINUX_SERIAL = "0 115200"
#SYSLINUX_SERIAL_TTY = "console=ttyS0,115200"
#EXTRA_IMAGECMD_jffs2 = "--pad=0xA00000 --little-endian --eraseblock=0x20000"
# NAND
MKUBIFS_ARGS = " -e 129024 -c 2047 -m 2048 -x lzo"
UBINIZE_ARGS = " -m 2048 -p 128KiB -s 512"
UBI_VOLNAME = "rootfs"
UBOOT_MACHINE = "${MACHINE}_nandflash_config"
UBOOT_ENTRYPOINT = "0x74000000"
UBOOT_LOADADDRESS = "0x74000000"
require include/at91sam9.inc
What can cause a bitbake build to stop producing the specified kernel image, and how do I fix it?
The answer ended up having two parts.
First, running bitbake -c do_cleansstate linux-at91 and then bitbake core-image-sato successfully regenerated the zImage file.
Second, linux-2.6.30-at91-emac was incorrect since my kerenl was just called linux-at91. So my kernel build was likely only being run when I ran builds for other machines.
So my full image build wasn't rebuilding the kernel because I had referenced a different kernel. Once I fixed that, the kernel build would start running again. I'm not sure how I got a zImage in the first place, or why bitbake never threw an error after being told to build a kernel that didn't exist.

Accessing initramfs-tools features in Yocto generated initramfs image

I would like to load a few kernel modules, and activate framebuffer access prior to Plymouth launch. This is normally done using /etc/initramfs-tools directory provided with the initramfs-tools. However, when building an initramfs image with Yocto, no such directory is available. This means that whatever initramfs-tools does for loading modules and initializing framebuffer, has to be done manually in the initramfs image as far as I could understand.
The tasks I want to accomplish is very delicately explained by notro in https://github.com/notro/fbtft/wiki/Bootsplash
. I'd like to do the equivalent of what's done below:
Access to /etc/initramfs-tools/scripts/init-top/spi and modprobe a module.
Access to /etc/initramfs-tools/modules and list further modules to be launched by modules daemon
Enable framebuffer which is done via echo "export FRAMEBUFFER=/dev/fb1" | sudo tee /etc/initramfs-tools/conf.d/fb1
With my research, I could find initramfs-framework-base package which features some scripts that initramfs boot uses. I think this might be a good starting point. However, I do not know how to explicitly tell initramfs to do what I want to accomplish (tasks above).
Note: Currently, my initramfs image is generated by the following recipe:
include recipes-core/images/rpi-basic-image.bb
BASEPACKS = " \
base-passwd \
busybox \
initramfs-live-boot \
initramfs-framework-base \
udev \
${ROOTFS_BOOTSTRAP_INSTALL} \
"
IMAGE_INSTALL = " ${BASEPACKS} \
plymouth plymouth-set-default-theme \
"
# Do not pollute the initrd image with rootfs features
IMAGE_FEATURES = "splash"
SPLASH = "plymouth"
IMAGE_LINGUAS = ""
LICENSE = "MIT"
IMAGE_FSTYPES = "${INITRAMFS_FSTYPES}"
IMAGE_ROOTFS_SIZE = "8192"
IMAGE_OVERHEAD_FACTOR = "1.0"
IMAGE_ROOTFS_EXTRA_SPACE = "0"
IMAGE_ROOTFS_MAXSIZE = "12288"
CMDLINE_append = " quiet splash nomodeset plymouth.ignore-serial-consoles consoleblank=0"
BAD_RECOMMENDATIONS += "busybox-syslog"
Also Note: I'm using an ARMv6-based machine with U-boot bootloader. Compiling the original initramfs-tools (that is originally developed for Debian) generates 0 byte images. I'm guessing this is an issue with its compatibility. So I'll have to resort to generating initramfs with yocto's internal tools.
Any help is appreciated. Thanks in advance.

uenvcmd in uEnv.txt can not be executed automatically

I am using an arm board using TFTP and NFS but it got stuck at kernel loading as shown in the screenshot and I have to input the run uenvcmd then the process will keep going and everything is OK.
Below is my uEnv.txt:
# This uEnv.txt file can contain additional environment settings that you
# want to set in U-Boot at boot time. This can be simple variables such
# as the serverip or custom variables. The format of this file is:
# variable=value
# NOTE: This file will be evaluated after the bootcmd is run and the
# bootcmd must be set to load this file if it exists (this is the
# default on all newer U-Boot images. This also means that some
# variables such as bootdelay cannot be changed by this file since
# it is not evaluated until the bootcmd is run.
autoload=no
ipaddr=192.168.1.100
serverip=192.168.1.13
gatewayip=192.168.1.1
staticip=${ipaddr}:${serverip}:${gatewayip}:255.255.255.0:::off
bootpath=/tftpboot
rootfspath=/opt/ti-processor-sdk-linux-rt-am57xx-evm-03.00.00.04/targetNFS
#setting for kernel loading
kernel_addr=0x82000000
fdt_addr=0x88000000
nfs_args=setenv bootargs console=ttyO0,115200n8 root=/dev/nfs rw nfsroot=${serverip}:${rootfspath} ip=${staticip}
load_zimage=tftp ${kernel_addr} ${bootpath}/zImage
loadfdt=tftp ${fdt_addr} ${bootpath}/am572x-idk.dtb
boot_zimage=bootz ${kernel_addr} - ${fdt_addr}
uenvcmd=run load_zimage; run loadfdt; run nfs_args; run boot_zimage
these is a strange file called uboot.env beside the uEnv.txt, too long to paste here, uboot.env
Problem solved: Just delete the file uboot.env
This should be a bug of SDK. I will report this to TI. Thanks #Notlikethat

NFS rootfs for Wandboard

My first time working on the Uboot and Serial Port. I am trying to mount my /nfsroot from my ubuntu host to the wandboard target so that I can boot up the board with TFTP in Kernel and NFS as rootfs.
Been getting error here and there and do not know what they mean.
Please advice.
This is the complete Error Log with root=/dev/nfs
This is the error I have when I try to mount the nfs to one of my SDCard's partition (mmcblk2p2). root=/dev/mmcblk2p2
It mounted but then devtmpfs return error mounting -2.
EXT3-fs (mmcblk2p2): error: couldn't mount because of unsupported optional features (240)
EXT2-fs (mmcblk2p2): error: couldn't mount because of unsupported optional features (244)
EXT4-fs (mmcblk2p2): recovery complete
EXT4-fs (mmcblk2p2): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext4 filesystem) on device 179:2.
devtmpfs: error mounting -2
Freeing unused kernel memory: 328K (80d22000 - 80d74000)
Failed to execute /sbin/init (error -2). Attempting defaults...
Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
CPU1: stopping
And this is my printenv
=> printenv
baudrate=115200
boot_fdt=try
bootargs=console=ttymxc0,115200 root=/dev/mmcblk0p2 rw nfsroot=192.168.0.227:/nfsroot,v3,tcp
bootcmd=mmc dev ${mmcdev}; if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; else run netboot; fi
bootdelay=5
bootfile=zImage-wandboard-quad.bin
bootscript=echo Running bootscript from mmc ...; source
console=ttymxc0
ethact=FEC
ethaddr=00:1f:7b:b4:14:ce
ethprime=FEC
fdt_addr=0x18000000
fdt_file=zImage-imx6q-wandboard.dtb
fdt_high=0xffffffff
get_cmd=dhcp
image=zImage-wandboard-quad.bin
initrd_high=0xffffffff
ip_dyn=yes
loadaddr=0x12000000
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}; run videoargs
mmcboot=echo Booting from mmc ...; run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; e;
mmcdev=0
mmcpart=1
mmcroot=/dev/mmcblk2p2 rootwait rw
netargs=setenv bootargs console=${console},${baudrate} ${smp} root=/dev/mmcblk2p2 rw ip={ipaddr} nfsroot=${serverip}:${nfsroot},v3,tcp init=/sbin/init
netboot=echo Booting from net ...; run netargs; if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${image}; if test ${boot_fdt} = yes || test ${boot_fdt} = try; th;
nfsroot=/nfsroot
script=boot.scr
serverip=192.168.0.227
splashpos=m,m
update_sd_firmware=if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; if mmc dev ${mmcdev}; then if ${get_cmd} ${update_sd_firmware_filename}; then setexpr fw_sz ${filesize} /i
update_sd_firmware_filename=u-boot.imx
videoargs=setenv nextcon 0; if hdmidet; then setenv bootargs ${bootargs} video=mxcfb${nextcon}:dev=hdmi,1280x720M#60,if=RGB24; setenv fbmen fbmem=28M; setexpr nextcon ${nextcon} + 1; else echo - no HDMI mo}
Environment size: 2810/8188 bytes
On the host (Ubuntu):
sudo apt-get install nfs-kernel-server
sudo mkdir /nfsroot
Add the /nfsroot directory to the /etc/exports file:
/nfsroot *(rw,sync,no_root_squash)
sudo /etc/init.d/nfs-common start or sudo /etc/init.d/nfs-kernel-server start
On the target (Wandboard):
Root filesystem on NFS must have been enabled when compiling the kernel (hopefully, it was, otherwise you'll need to recompile the Linux kernel)
Add root=/dev/nfs rw ip=target_IP nfsroot=NFS_server_IP>:/nfsroot/ to U-Boot's bootargs variable, where target_IP is the static IP address for the target and NFS_server_IP is the host IP address.
It turns out that I need to set the client IP parameter after I got the IP from DHCP. I thought that DHCP will handle all the IP configuration for the netboot arguments but I was wrong;
setenv ip 192.168.0.172:192.168.0.227::::eth0:on
setenv ipaddr 192.168.0.172
setenv netargs 'setenv bootargs console=${console},${baudrate} ${smp} root=/dev/nfs ip=${ipaddr} nfsroot=${serverip}:${nfsroot},v3,tcp'

Resources