Getting U-boot's Version from Userspace - embedded-linux

Does anyone know of a way to get U-boot version installed from userspace? There is the fw_printenv command that provides access to U-boot's environment variables, but not the version.

If U-boot is located in mtd0, you can get version info as follows:
root#SUPERWIFI:/proc# strings /dev/mtd0 | grep U-Boot
U-Boot 1.1.4-g1c8343c8-dirty (Feb 28 2014 - 13:56:54)
U-Boot
Now running in RAM - U-Boot at: %08lx

Just an update for this.
In our version of U-Boot we changed the code for main_loop() in main.c to this:
#ifdef CONFIG_VERSION_VARIABLE
char *oldver=getenv("ver");
if(oldver==0 ||strcmp(oldver,version_string))
{
setenv("ver", version_string); /* set version variable */
saveenv();
}
#endif /* CONFIG_VERSION_VARIABLE */
So setenv/saveenv is only called, if needed by an update.
In our firmware we added
/sbin/fw_printenv -n ver > /var/config/u-boot.ver
to make the u-boot version public available.

There's no defined way to do this. Once Linux boots, u-boot is no longer running and it's RAM is reclaimed for Linux's use. Linux doesn't even know about u-boot. Nor does it have to have been booted by u-boot.
If you really want to do this, the only way to do it is to add the u-boot version to the kernel's command line, write code to scan the u-boot image in flash for it's version, or something even nastier.

An alternative solution is to read the version directly from the u-boot binary file (can be even embedded in an image file containing other binaries as well like e.g. the first stage bootloader) with e.g. mmcblk0boot0 as partition (of device mmcblk0) the bootloader resides in:
sudo grep -a --null-data U-Boot /dev/mmcblk0boot0
Site note: Does work not only for Arch Linux but e.g. Ubuntu as well.

In my devices UBoot automatically creates a "ver" environment variable containing its version:
U-Boot > printenv
baudrate=115200
ethact=FEC ETHERNET
ethaddr=24-db-ad-00-00-08
bootdelay=3
bootcmd=bootm fc080000 - fc060000
bootargs=console=ttyCPM0,115200n8 rdinit=/sbin/init
stdin=serial
stdout=serial
stderr=serial
ver=U-Boot 2009.03-svn9684 (Mar 08 2010 - 17:08:32)
Environment size: 253/131068 bytes
U-Boot >
I don't use fw_printenv, but I would imagine that this variable gets passed along as well. Maybe you already have something similar in your system?
UPDATE (5/23/2012):
I added fw_printenv to my linux image and can confirm that I do see the "ver" variable:
[root#ST600 /]# fw_printenv
baudrate=115200
ethact=FEC ETHERNET
ethaddr=24-db-ad-00-00-08
stdin=serial
stdout=serial
stderr=serial
ver=U-Boot 2009.03-svn9684 (Mar 11 2010 - 09:43:08)
bootcmd=bootm fc080000 - fc060000
bootdelay=3
bootargs=console=ttyCPM0,115200n8 rdinit=/sbin/init panic=10 mem=32m
[root#ST600 /]#

Try to read uboot version this way:
Find uboot partition, eg. for MTD device:
cat /proc/mtd
For /dev/mtd5:
cat /dev/mtd5 | hexdump -C -n 64

You can't rely on fw_printenv if you want to know u-boot version.
fw_printenv just looks for the printenv partition and dumps its data. So it's OK for normal variables, but it's not OK for the "ver" variable, which is dynamic, and whose value is initialized by u-boot when it boots. The value of this variable doesn't remain after u-boot exit, except if you manually save it to environment.
For example, on my board, if I print the "ver" variable from u-boot prompt:
U-Boot > printenv ver
ver=U-Boot 2009.11-00393-g5ca9497-dirty (Nov 26 2012 - 11:08:44)
This is the real version of u-boot, coming from u-boot itself.
Now, if I boot my board and use fw_printenv:
el#board # fw_printenv | grep ver=
ver=U-Boot 2009.11-00323-gbcc6e0e (Sep 21 2012 - 11:07:19)
As you can see, it's different. Because it happens that I have a "ver" variable defined in my environment. And it doesn't match the real u-boot version.
Of course, I could go back to u-boot, use "saveenv" to update the "ver" value in the environment. Then the two values would match. But then, I should always update the environment after changing u-boot.
So, my conclusion is that using fw_printenv to get u-boot version is definitely not a good idea.

If u-boot is residing in an MTD partition then this will work:
U_BOOT_VER=$(for part in `grep u-boot-[01] /proc/mtd | cut -f 1 -d ':'`; do strings /dev/${part} | grep "^U-Boot.*("; break; done)

Related

Access u-boot env variables set by fw_setenv from boot.scr

I'm experimenting with nanopi board with ubuntu OS and u-boot bootloader.
When booted into system, I set u-boot environment variable with fw_setenv:
$ fw_setenv foo bar
On the following reboot I'd like to access this foo variable from the /boot/boot.scr script:
if [ -z "${foo}" ]; then
echo "Fail"
else
echo "Ok"
fi
I get Fail, so foo is inaccessible.
I've no experience with u-boot but I read that it has two sets of environment variables: one read-only (fixed as a part of U-boot image), and another read/write (user environment). So it looks like user environment is not accessible from boot.scr script? Is it true? How can I make my foo variable visible at the moment when boot.scr is executed?
Upd: My /etc/fw_env.config file:
# Block device
/dev/mmcblk1 0xc0000 0x20000
U-boot version: 2020.01
The problem is found. U-boot constants CONFIG_SYS_MMC_ENV_DEV, CONFIG_ENV_OFFSET, and CONFIG_ENV_SIZE did not match those in /etc/fw_env.config.
Solved the problem by changing these constants to
#define CONFIG_SYS_MMC_ENV_DEV 1
#define CONFIG_ENV_OFFSET 0x3f8000
#define CONFIG_ENV_SIZE 0x20000
recompiling u-boot and updating fw_env.config accordingly:
/dev/mmcblk1 0x3f8000 0x20000

Is the sys_call_table read protected in 4.8 kernel?

I use the simple sys_call_table rewrite to
log all execve calls in a system.
When moving to Ubuntu 16.10 with a 4.8 kernel this
mechanism suddenly stopped to work. In 16.04 with
a 4.6 kernel it was working.
1: write_cr0 (read_cr0 () & (~ 0x10000));
2: original_execve = (void *)syscall_table[__NR_execve];
3: syscall_table[__NR_execve] = (unsigned long)&new_execve;
4: write_cr0 (read_cr0 () | 0x10000);
The page fault already happens when reading the old entry, that is line 2.
To retrive the sys_call_table address I use:
sudo cat /boot/System.map-`uname -r` | grep -e '\ssys_call_table' | awk '{ print $1}' )"
Code is from: https://github.com/eiselekd/shinterposer/tree/master/mod
Does anyone know what happened? Maybe some
protection mechanism has been introduced?
There seem to be Address Space Layout Randomization (kASLR) on the syscall table taking
place by default in the 4.8 kernel. When declaring the sys_call_table symbol as exported and linking against it directly from a module the address for sys_call_table is changing for each boot.
The address from /boot/System.map-xxx is useless.
To disable kaslr in ubuntu 16.10 kernel 4.8 one can add
nokaslr
to the kernel command line.

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

How to insert hwmon module (ARM)

I fear that this is a very specific question.
Hardware: Gumstix Overo Fire (ARM Cortex A8)
Distro: Poky (customized with the Yocto Project)
Kernel: 3.5.7
I tried to write a program to read a HIH6130 i2c sensor, using /dev/i2c-3 and < linux/i2c-dev.h>, but despite it works for every other i2c device, it does not work for this one. Probably this happens because a particularity of the reading protocol, but anyway, that's not the topic.
I found this code that implements a driver for that sensor, and it is inside a so called "hwmon", which seems to be a collection of sensor drivers.
After successfully compiled and inserted this module I was expecting to see the entry humidity1_input somewhere under hwmon but I didn't find it.
root#overo:/sys# find -name hum*
root#overo:/sys# find -name hih*
./bus/i2c/drivers/hih6130
./module/hih6130
root#overo:/sys# ls ./bus/i2c/drivers/hih6130
bind module uevent unbind
root#overo:/sys# ls ./module/hih6130
coresize holders initstate refcnt srcversion uevent
drivers initsize notes sections taint
Do I have to do something else to enable the reading of this sensor? Any ideas?
I ended up using i2cget to read it:
$ i2cget -y 3 0x27 0x00
Later, the author, Iain Paton, kindly showed me how to bind the driver:
$ insmod hih6130.ko
$ echo hih6130 0x27 > /sys/bus/i2c/devices/i2c-3/new_device
In my device it appeared in this directory:
$ find /sys/ -name humidity*
/sys/devices/platform/omap_i2c.3/i2c-3/3-0027/humidity1_input
Also there is a 'temp1_input' in this same directory.

How can I get the builder name of the linux kernel

When the linux kernel booting up,it will print the kernel version and builder, and toolchain infomation. Just like below:
Booting Linux on physical CPU 0
Linux version 3.4.24 (whobuilderthis#cl-builder23)
So how to get the builder whobuilderthis string (using shell)? Where does it store?
Thanks in advance.
You could query /proc/version which should contain the builder string.
shell#android:/ $ cat /proc/version
Linux version 3.0.31-g9f818de (android-build#vpbs1.mtv.corp.google.com) (gcc version 4.6.x-google 20120106 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Nov 28 11:20:29 PST 2012
dmesg gives the kernel log, so you should be able to grep/sed it from there:
dmesg | grep 'Linux version ' | sed 's/[^(]*(\([^)]*\)).*/\1/'
(There are smarter ways of doing this.)
According to Documentation/kbuild/kbuild.rst:
KBUILD_BUILD_USER, KBUILD_BUILD_HOST
These two variables allow to override the user#host string displayed during
boot and in /proc/version. The default value is the output of the commands
whoami and host, respectively.
So "/proc/version" will output the result of current running kernel.
If you want to change the content, you need override the above 2 vars on your kernel build machine.

Resources