How can uboot
pass command line argument to kernel? I did some googling and got to know that it uses the bootargs
environment variable. There it was mentioned that setenv bootargs key=value
. Since I am using bash
and don't have setenv
I did this using export bootargs="value"
. But it's not affecting anything. I checked in /proc/cmdline
the arguments remain the same.
Any idea what I am doing wrong?
Linux – Uboot passes arguments to kernel!
bootboot-loaderkernellinux-kernelu-boot
Related Solutions
The short answer to burning u-boot to the mmc is probably
tftp ${loadaddr} u-boot.bin
mmc partconf 0 ${emmc_boot_ack} ${emmc_boot_part} 1
mmc write ${fileaddr} 0 800
mmc partconf 0 ${emmc_boot_ack} ${emmc_boot_part} 0
but it depends on how you've setup the mmc. This command will write 1048576 (0x800 * 512) bytes from ${fileaddr} to the mmc starting at address 0.
For a longer and more complete answer on writing the mmc. Let's say you are going to setup the mmc the way the manufacturer suggests.
| u-boot[0] | DT[0x680] | Kernel[0x800] | FS[0x8000] |
Let's assume you already have the files you need, if not you can build these with Yocto. I can provide details on that if you like.
u-boot.bin, imx6ul-txul-0011.dtb, uImage, rootfs.tar.bz2, modules.tgz
Let's also assume you already at least sideloaded u-boot, it looks like you have it running somehow.
First thing you'll need to partition the mmc. You can't do this from u-boot, so you'll need to setup a network boot. It seems you already have a tftp server with your files in it, you'll also need to setup an nfs server and extract rootfs to there. Let's say you setup your nfs server file system at /nfsroot. Set the following variables to enable net boot.
env default -a
env set bootdelay 3
env set serverip 192.168.1.99
env set nfs_server 192.168.1.99
env set ipaddr 192.168.1.90
env set netmask 255.255.255.0
env set bootfile uImage
env set nfsroot /nfsroot
env set boot_mode net
env set default_bootargs setenv bootargs init=/bin/sh console=ttymxc0,115200 ro debug panic=1 ${append_bootargs}
save
Boot to the Linux prompt and from there run
fdisk /dev/mmcblk0
and setup partitions as follows
Partition Start Cyl End Cyl Start Sector End Sector Type
1 33 512 2048 32767 0x0c
2 513 - 32768 - 0x83
Switch back to u-boot and you should now be able to see your partitions
> mmc part
Partition Map for MMC device 0 -- Partition Type: DOS
Part Start Sector Num Sectors UUID Type
1 2048 30720 00ee66ee-01 0c
2 32768 7700480 00ee66ee-02 83
Note that partition 1 starts at sector 2048 which is 0x800. Partition 2 starts at 32768 which is 0x8000. You should now see where these numbers come from.
We updated u-boot.bin with the commands above, but notice that it also overwrites the Device Table (DT). So to update the DT, use
tftp ${fdtaddr} imx6ul-txul-0011.dtb
mmc partconf 0 ${emmc_boot_ack} ${emmc_boot_part} 1
mmc write ${fdtaddr} 0x680 80
mmc partconf 0 ${emmc_boot_ack} ${emmc_boot_part} 0
There also may be an environment variable set with these commands, ${fdtsave}, if so, you can just use
run fdtsave
To update the partitions, you will need to create the disk images on your linux box, then tftp them to the TX6UL and burn them with the mmc write command. To make the image for the first partition, you could use these commands on your linux box.
dd if=/dev/zero of=part1.image bs=15728640 count=0 seek=1
/sbin/mkfs -t vfat part1.image
sudo mkdir /mnt/mkpart
sudo mount -o loop part1.image /mnt/mkpart
cp uImage /mnt/mkpart/uImage
sudo umount /mnt/mkpart
Then in u-boot
tftp ${loadaddr} part1.image
mmc write ${fileaddr} 800 7800
You can see the contents of the partition from u-boot using
> fatls mmc 0:1
3676512 uimage
1 file(s), 0 dir(s)
Similarly for the second partition, from your linux box use something like
dd if=/dev/zero of=part2.image bs=64M count=0 seek=1
/sbin/mkfs -t ext3 part2.image
sudo mkdir /mnt/mkpart
sudo mount -o loop part2.image /mnt/mkpart
sudo tar -C /mnt/mkpart -xjf rootfs.tar.bz2
sudo tar -C /mnt/mkpart -xzf modules.tgz
ln -s sbin/init /mnt/mkpart/linuxrc
sudo umount /mnt/mkpart
And then from u-boot
tftp ${loadaddr} part2.image
setexpr fs ${filesize} + 1ff
setexpr fs ${fs} / 200
mmc write ${fileaddr} 8000 ${fs}
If you want to see the contents of the second partition from u-boot
> ext2ls mmc 0:2
To boot from the new partitions, set init back to normal in the boot arguments
env set default_bootargs setenv bootargs init=/linuxrc console=ttymxc0,115200 ro debug panic=1 ${append_bootargs}
save
And don't forget to either change the partition id or the env variable to point to the new file system. In this case
env set rootpart_uuid 00ee66ee-02
save
Hope this helps.
Yes, this is how you traditionally tell a regular init system what state to boot into. If you're running sysv-init (or pretty much any widely used init system other than systemd), you can put a number between 1 and 5 at the end of the kernel arguments and it will boot into that run level (1 is always single-user mode, the others are system defined, 3 or 4 is what most Linux distros have conventionally used as the default). If you're using systemd, you can pass single
or emergency
at the end of the kernel arguments to boot into those modes respectively.
Using this mechanism for passing arbitrary arguments however is somewhat difficult because the kernel does the absolute minimum of parsing, which means in particular that:
- Arguments with whitespace in them can't be passed at all, because the kernel doesn't parse quoted strings (that is,
'some string'
gets parsed as two arguments'some
andstring'
). - You can't reference any environment variables at all, because the kernel doesn't do variable substitution (which is normally done by the shell you're running the command from before it even starts the command).
- In general, the arguments have to be correctly interpretable under the POSIX C locale (essentially US ASCII), which throws internationalization out the window unless you want to use something like base64 or punycode.
- There is an upper limit on how much data can be passed in kernel arguments, but I forget what it is.
These limitations combined are why you can't find anything on Google about doing this type of thing, no systems integration engineer in their right mind does it, because it's far more effort to work around the above limitations than it is to just write a script containing all the required arguments and call that instead.
Best Answer
There are two ways to pass arguments to kernel: 1. Compile them inside. 2. Use bootloader
So first check if your arguments are not compiled into kernel. Second setenv command you've found in not a bash command but boot loader command. It depends on how particular device made, but usually there is a partition in some internal storage (flash memory of your device, not on host) where bootloader reads parameters or file on filesystem and u-boot takes configuration from there.
Other way is to connect your device via cable and use device-specific way to get bootloader prompt and interactively change your settings.
It's not really trivial if you not familiar with your particular device boot scheme. Name your device, it may help to answer your question.