I have a series of questions on how U-boot works on the BeagleBone Black. Everything started with this tutorial on how to use a micro SD card(uSD) as extra storage.
uSD as extra storage on BBB.
Currently my setup looks like this.
$ fdisk -l
Disk /dev/mmcblk0: 7948 MB, 7948206080 bytes #uSD
Device Boot Start End Blocks Id System
/dev/mmcblk0p1 2048 198655 98304 e W95 FAT16 (LBA)
/dev/mmcblk0p2 198656 15523839 7662592 83 Linux
Disk /dev/mmcbk1: 3867 MB, 3867148288 bytes #eMMC
Device Boot Start End Blocks Id System
/dev/mmcblk1p1 * 2048 198655 98304 e W95 FAT16 (LBA)
/dev/mmcblk1p2 198656 7553023 3677184 83 Linux
So if I havent had it wrong this is what happends.
Boot sequence.
1.The BBB is powered.
2.The U-boot is loaded from the eMMC(/dev/mmcblk1p1)
3.The U-boot searches for uEnv.txt file within the uSD(/dev/mmcblk0p1) and loads it.
...... We will retake from here.
In /dev/mmcblk0p1 i have a uEnv.txt file that looks like this.
mmcdev=1
bootpart=1:2
mmcroot=/dev/mmcblk1p2 ro
optargs=quiet
In /dev/mmcblk1p1 i have the default uEnv.txt file that at some point have this lines.
loadkernel=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${kernel_file}
loadinitrd=load mmc ${mmcdev}:${mmcpart} ${initrd_addr} ${initrd_file}; setenv initrd_size ${filesize}
.......
mmcargs=setenv bootargs console=tty0 console=${console} ${optargs} ${kms_force_mode} root=${mmcroot} rootfstype=${mmcrootfstype} ${systemd}
We can see how ${mmcdev}, ${mmcroot}, ${optargs} are used although they arent defined in the file, they are defined uSD uEnv.txt.
Question 1.
¿Does this mean that both uEnv.txt files are loaded?
Retaking the boot sequence.
Boot sequence.
4.The U-boot searches for uEnv.txt file within the eMMC(/dev/mmcblk1p1) and loads it.
5.The Linux kernel is loaded.
When there is no uSD the ${mmcdev}, ${mmcroot}, ${optargs} arguments aren't defined, not in the uEnv.txt at least.
Question 2.
¿Where do the default values come?
Now the part that really bothers me. On another board a have a eMMC uEnv.txt file that looks like this.
optargs=quiet drm.debug=7 capemgr.enable_partno=BB-UART2,BB-UART1
The board boots fine without uSD.
Question 3.
How is that even posible?
The answer to the question should be in your board configuration file. Specifically the definition of 'CONFIG_EXTRA_ENV_SETTINGS'- "Define this to contain any number of null terminated strings (variable = value pairs) that will be part of the default environment compiled into the boot image." (from u-boot README file)
Related
Hi I'm a newbie of embeded linux. I'm following this tutorial (https://e2e.ti.com/support/embedded/linux/f/354/t/398780?Script-to-Erase-Emmc-independently-Beagle-Bone-Black) for flashing my linux system to beaglebone eMMC.
But I have an error: umount: can't umount /dev/mmcblk1p1: Invalid argument
This is my cmd :
Disk /dev/mmcblk1: 3825 MB, 3825205248 bytes
4 heads, 16 sectors/track, 116736 cylinders
Units = cylinders of 64 * 512 = 32768 bytes
Device Boot Start End Blocks Id System
/dev/mmcblk1p1 * 2048 2536 15648 e Win95 FAT16 (LBA)
/dev/mmcblk1p2 1 2047 65496 83 Linux
Partition table entries are not in disk order
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table
[ 235.274729] mmcblk1: p1 p2
root#beaglebone:/# umount /dev/mmcblk1p1
umount: can't umount /dev/mmcblk1p1: Invalid argument
Sorry my English is not good. Does anybody have any idea of what did I do wrong or did I miss something?
This is an error in the script you are following. If you have created new partitions without a file system you would not expect them to be mounted.
Creating the 2nd partition in sectors 1 - 2047 is probably not what you want to do. You should use all the space after partition 1.
I am compiling my own kernel and bootloader (U-boot). I added a bunch of new environmental variables, but U-boot doesn't load anymore (it just doesn't load anything from the memory). I am using pocketbeagle and booting from an SD card. Thus I am editing the file "am335x_evm.h" found in /include/configs/.
I am trying to allocate U-boot in a way that it has more space for the environmental variables and that it can load succesfully from the memory, but I have been unable to do so. As far as I understand, by default it allocates 128kb of memory to U-boot env variables. Since I added a bunch of them, I am trying to increase its size from 128kb to 512kb.
I have changed the following line (from 128kb to 512kb):
#define CONFIG_ENV_SIZE (512 << 10)
(By the way, anyone knows why it is shifted to the left 10 bits?)
I have also changed CONFIG_ENV_OFFSET and CONFIG_ENV_OFFSET_REDUND to:
#define CONFIG_ENV_OFFSET (1152 << 10) /* Originally 768 KiB in */
#define CONFIG_ENV_OFFSET_REDUND (1664 << 10) /* Originally 896 KiB in */
Then after compiling the new U-boot, I format the SD card and insert the new kernel and U-boot.
I start by erasing partitions:
export DISK=/dev/mmcblk0
sudo dd if=/dev/zero of=${DISK} bs=1M count=10
Then I transfer U-boot by doing:
sudo dd if=./u-boot/MLO of=${DISK} count=1 seek=1 bs=512k
sudo dd if=./u-boot/u-boot.img of=${DISK} count=2 seek=1 bs=576k
I then create the partition layout by doing:
sudo sfdisk ${DISK} <<-__EOF__
4M,,L,*
__EOF__
Then I add the kernel, binary trees, kernel modules, etc... When trying to boot and reading the serial port, I get nothing at all. U-boot is not able to load anything from the SD card. What am I doing wrong? I'd appreciate if you could point me what my problem is and exactly what I should be doing to increase the size and allocate everything correctly.
I know we can use NFS, but I just don't want to use it.
(don't want to keep network connection to NFS server all the time).
I know we can use tftp in u-boot to load kernel and device-tree!
But can we use tftp in u-boot to download root-filesystem, put it in the right partition of SD card, and boot?
If yes, how to do it? (I googled, but found no answers)
Thanks,
Jerry
I use TFTP in uboot to flash my rootfs (for debug purposes) on my internal eMMC. It's nearly the same case as you.
First download in you RAM the filesystem:
tftpboot ${rootfs_addr} ${tftppath}/${rootfs_file}
rootfs_addr will be the RAM address, I use 0x10800000.
tftppath is the TFTP path (depends on your configuration)
rootfs_file is the ext4 or ext3 file
Then update the mmc device (you can run mmc listto show SD u-boot number)
mmc dev 2
Here I set the device to the number 2, you need to set it corresponding to the mmc list command.
Then write the content of the RAM to the SD:
setexpr rootfsblksz ${filesize} / 200
setexpr rootfsblksz ${rootfsblksz} + 1
mmc write ${rootfs_addr} 6000 ${rootfsblksz}
Description:
I create a rootfsblksz variable, it converts the number of bytes downloaded to a number of blocks. filesizeis set automatically when we use TFTP, it represents the size of the last downloaded file (in Bytes).
Here my block is 512Bytes (0x200)
I add +1 to the blocksize (to be shure to have all the data)
I write it on the eMMC (or SD) at the address 0x6000 (in blocks) -> 24 576 blocks -> 12 582 912 (in Bytes) -> 12MB because my ext partition is at 12MB offset
Hope it helps!
Depending on a few configurations I tried in /etc/fw_env.config such as one or two entries, I got the following errors when trying to read the U-boot environment variables:
root#varsomam33:~# fw_printenv serverip
Warning: Bad CRC, using default environment
or
root#varsomam33:~# fw_printenv serverip
Cannot read bad block mark: Invalid argument
According to this tutorial (https://developer.ridgerun.com/wiki/index.php/Setting_up_fw_printenv_to_modify_u-boot_environment_variables), I constructed my /etc/fw_env.config to look like this:
# MTD device name Device offset Env. size Flash sector size Number of sectors
/dev/mtd6 0x1C0000 0x20000 0x20000 1
/dev/mtd7 0x1E0000 0x20000 0x20000 1
FYI I'm using a TI Omap ARM chip (var-som-am33) with Yocto Fido default out-of-box from Variscite with these software versions:
U-boot version: u-boot-var-som-am33 2014-+gitrAUTOINC+adf9a14020
U-boot-fw-utils version: u-boot-fw-utils v2014.07+gitAUTOINC+524123a707-r0-arago0-var
The main problem is that "Device offset" is incorrectly described in the RidgeRun tutorial. It is not the absolute offset in NAND flash, but rather the offset from the partition which should be "0x0" in my case.
Here is my working /etc/fw_env.config
root#varsomam33:~# cat /etc/fw_env.config
# MTD device name Device offset Env. size Flash sector size Number of sectors
/dev/mtd6 0x0 0x20000 0x20000 1
/dev/mtd7 0x0 0x20000 0x20000 1
Further, the CRC error I was getting is thrown when there is not a U-boot backup (redundant) environment described in the /etc/fw_env.config file. The fw_printenv utility works by copying the "selected" environment, modifying the variable you have changed, and writing it out to the "new" environment. Then it swaps "selected" and "new".
So if you only have one environment in /etc/fw_env.config, it uses default values for the "selected" environment.
Here is the code tools/env/fw_env.c
1230 crc0_ok = (crc0 == *environment.crc);
1231 if (!HaveRedundEnv) {
1232 if (!crc0_ok) {
1233 fprintf (stderr,
1234 "Warning: Bad CRC, using default environment\n");
1235 memcpy(environment.data, default_environment, sizeof default_environment);
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)