Home | Projects | Notes > Embedded Linux > Writing uEnv.txt File from Scratch
[!] Note: Instead of booting from eMMC completed from the previous steps (Debian image; where there's only one partition, and boot/ folder does not contain uImage), I've used microSD card (which contains Angstrom image) to boot and follow the lecture.
boot U-boot command will load the Linux kernel and execute it. boot simply runs the environment variable bootcmd. So, if you want to change the behavior of boot, you have to modify the commands stored in the environment variable bootcmd.
U-boot always try to read the uEnv.txt from the boot source. If uEnv.txt is not found, it will use the default values of the enve variables.
If you don't want U-boot to use default values, you need to enforce new values using uEnv.txt.
U-boot's "load from memory device" commands:
fatload - Loads a binary file from FAT based file system into memory.
load - Loads a binary file from any file system.
Examples:
xxxxxxxxxx31fatload usb 0:1 0x82000000 uImage2fatload mmc 0:1 0x88000000 initramfs3load mmc 0:1 0x88000000 uImage
1st arg - Interface (e.g., USB, MMC, etc.)
2nd arg - Device#:Partition# (Device# can be checked by running something like
mmc list.)When the Linux image is properly flashed onto eMMC, eMMC partitions would look like:
Our goal is to write our own uEnv.txt file from scratch and update the bootcmd so that when we run boot command from the U-boot prompt, it will refer to our custom uEnv.txt file while booting.
Let's load the Linux binary image "uImage" from the second partition of the SD card into the DDR memory.
xxxxxxxxxx21=> load mmc 0:2 0x82000000 /boot/uImage24002080 bytes read in 300 ms (12.7 MiB/s)
/boot/uImagesince uImage file is located inside the directoryboot/in the 2nd partition of SD card.
Now, let's boot the Linux kernel image using bootm command (boot application image from memory).
This boot fails because the Linux Bootstrap Loader couldn't find the DTB. (This is why the Bootstrap Loader complains about the "Unrecognized machine ID ...".
xxxxxxxxxx301=> bootm 0x820000002## Booting kernel from Legacy Image at 82000000 ...3 Image Name: Angstrom/3.8.10/beaglebone4 Created: 2013-04-29 19:56:00 UTC5 Image Type: ARM Linux Kernel Image (uncompressed)6 Data Size: 4002016 Bytes = 3.8 MiB7 Load Address: 800080008 Entry Point: 800080009 Verifying Checksum ... OK10 Loading Kernel Image ... OK11
12Starting kernel ...13
14Uncompressing Linux... done, booting the kernel.15
16Error: unrecognized/unsupported machine ID (r1 = 0x00000e05).17
18Available machine support:19
20ID (hex) NAME21ffffffff Generic OMAP4 (Flattened Device Tree)22ffffffff Generic AM33XX (Flattened Device Tree)23ffffffff Generic OMAP3-GP (Flattened Device Tree)24ffffffff Generic OMAP3 (Flattened Device Tree)250000060a OMAP3 Beagle Board2600000a9d IGEP OMAP3 module2700000928 IGEP v2 board2800000ae7 OMAP4 Panda board29
30Please check your kernel config and/or bootloader.L13: The very last message from the U-boot. From this point on, the control is on the Linux Bootstrap Loader.
To boot successfully, we need to first load DTB to somewhere in memory and let the Bootstrap Loader know where the correct DTB file is located.
Boot BBB to U-boot prompt and load uImage (kernel image) and DTB file into DDR memory by running the following commands:
xxxxxxxxxx41=> load mmc 0:2 0x82000000 /boot/uImage24002080 bytes read in 296 ms (12.9 MiB/s)3=> load mmc 0:2 0x88000000 /boot/am335x-boneblack.dtb423334 bytes read in 18 ms (1.2 MiB/s)Now, run bootm by specifying both of those addresses:
xxxxxxxxxx171=> bootm 0x82000000 - 0x880000002## Booting kernel from Legacy Image at 82000000 ...3 Image Name: Angstrom/3.8.10/beaglebone4 Created: 2013-04-29 19:56:00 UTC5 Image Type: ARM Linux Kernel Image (uncompressed)6 Data Size: 4002016 Bytes = 3.8 MiB7 Load Address: 800080008 Entry Point: 800080009 Verifying Checksum ... OK10## Flattened Device Tree blob at 8800000011 Booting using the fdt blob at 0x8800000012 Loading Kernel Image ... OK13 Loading Device Tree to 8fff7000, end 8ffffb25 ... OK14
15Starting kernel ...16
17Uncompressing Linux... done, booting the kernel.Looks like there is no crash, but Linux is not sending any boot logs. So, we can't see the progress.
This is because when the Linux kernel takes over the control, it has no idea which serial port of the board is used for sending the boot logs. The BBB uses UART0 as the serial debug terminal, which is enumerated as /dev/ttyO0 by the serial driver. You need to tell the kernel where to send this information to by using the boot arguments.
Along with this information, many other pieces of information need to be passed to the kernel using the boot arguments.
bootargsNext step is to send bootargs to the Linux kernel from U-boot.
Use the U-boot standard environment variable bootargs to send the boot arguments to the Linux kernel. If not already defined, go ahead and define one.
xxxxxxxxxx51=> printenv bootargs2## Error: "bootargs" not defined3=> setenv bootargs console=ttyO0,1152004=> printenv bootargs5bootargs=console=ttyO0,115200Tell the Linux kernel that our console is
ttyO0.
Run bootm by specifying both of those addresses:
xxxxxxxxxx11=> bootm 0x82000000 - 0x88000000Now, the boot message will show up on our console. But, boot again will fail at some point because the Linux kernel has no idea where it should mount the file system.
So, you have to send the location and type of file system using bootargs.
Let's mount the file system which is present at the partition 2 of the microSD card.
xxxxxxxxxx11=> setenv bootargs console=ttyO0,115200 root=/dev/mmcblk0p2 rw
root=/dev/mmcblk0p2 rwis added to the previously defined environmental variablebootargs.It is basically telling which root file system (RFS) to mount during the booting process and is giving read/write permission.
Now, if you repeat the previous steps all over again, you will be able to boot the Linux kernel successfully.
In summary:
xxxxxxxxxx61=> setenv bootargs 2=> load mmc 0:2 0x82000000 /boot/uImage34002080 bytes read in 296 ms (12.9 MiB/s)4=> load mmc 0:2 0x88000000 /boot/am335x-boneblack.dtb523334 bytes read in 18 ms (1.2 MiB/s)6=> bootm 0x82000000 - 0x88000000xxxxxxxxxx361## Booting kernel from Legacy Image at 82000000 ...2 Image Name: Angstrom/3.8.10/beaglebone3 Created: 2013-04-29 19:56:00 UTC4 Image Type: ARM Linux Kernel Image (uncompressed)5 Data Size: 4002016 Bytes = 3.8 MiB6 Load Address: 800080007 Entry Point: 800080008 Verifying Checksum ... OK9## Flattened Device Tree blob at 8800000010 Booting using the fdt blob at 0x8800000011 Loading Kernel Image ... OK12 Loading Device Tree to 8fff7000, end 8ffffb25 ... OK13
14Starting kernel ...15
16Uncompressing Linux... done, booting the kernel.17[ 0.000000] Booting Linux on physical CPU 0x018
19...20...21...22
23.---O---. 24| | .-. o o 25| | |-----.-----.-----.| | .----..-----.-----.26| | | __ | ---'| '--.| .-'| | |27| | | | | |--- || --'| | | ' | | | |28'---'---'--'--'--. |-----''----''--' '-----'-'-'-'29 -' |30 '---'31
32The Angstrom Distribution beagleboard ttyO033
34Angstrom v2012.12 - Kernel 3.8.1035
36beagleboard login: Booting the Linux kernel using the U-boot commands success!!!
uEnv.txt file helps us to group all these step-by-step processes together in one file so that they can get carried out automatically during the boot process.
Create a simple "uEnv.txt" file.
xxxxxxxxxx21mypcip=setenv serverip 193.168.1.22
You first need to declare a custom environment variable and assign the command to it.
"uEnv.txt" file must contain the very last EMPTY line.
Transfer the "uEnv.txt" file from host to BBB borad using serial port transfer protocols like xmodem or ymodem which are supported by minicom.
U-boot also supports serial port transfer protocol commands:
loadx- Send/receive file using xmodem protocol
loady- Send/receive file using ymodem protocol
loadz- Send/receive file using zmodem protocol
On minicom,
loady command.
Ctrl+A S (this will show the serial port transfer protocols available) ymodem.
Transferring uEnv.txt file to the target does not mean that the environment variable is accessible from the target. You need to IMPORT the file!
xxxxxxxxxx61=> env import -t 0x82000000 382=> printenv mypcip 3mypcip=setenv serverip 192.168.1.24=> run mypcip 5=> printen serverip 6serverip=192.168.1.2L1: The address to pass must be taken from the result of the previous step.
Now, the value 192.168.1.2 is successfully stored in serverip.
Updated uEnv.txt
xxxxxxxxxx51mypcip=setenv serverip 192.168.1.22ipaddr=192.168.27.13bootargs=console=ttyO0,115200 root=/dev/mmcblk0p2 rw4bootcmd=echo"********** Booting from memory **********";load mmc 0:2 0x82000000 /boot/uImage;load mmc 0:2 0x88000000 /boot/am335x-boneblack.dtb;bootm 0x82000000 - 0x880000005
Import
xxxxxxxxxx31=> env import -t 0x82000000 2842=> printenv bootargs3bootargs=console=ttyO0,115200 root=/dev/mmcblk0p2 rwL2: To check if important has been successful.
Now, finally, boot!
xxxxxxxxxx411=> boot2Unknown command 'echo********** Booting from memory **********' - try 'help'34002080 bytes read in 305 ms (12.5 MiB/s)423334 bytes read in 21 ms (1.1 MiB/s)5## Booting kernel from Legacy Image at 82000000 ...6 Image Name: Angstrom/3.8.10/beaglebone7 Created: 2013-04-29 19:56:00 UTC8 Image Type: ARM Linux Kernel Image (uncompressed)9 Data Size: 4002016 Bytes = 3.8 MiB10 Load Address: 8000800011 Entry Point: 8000800012 Verifying Checksum ... OK13## Flattened Device Tree blob at 8800000014 Booting using the fdt blob at 0x8800000015 Loading Kernel Image ... OK16 Loading Device Tree to 8fff7000, end 8ffffb25 ... OK17
18Starting kernel ...19
20Uncompressing Linux... done, booting the kernel.21[ 0.000000] Booting Linux on physical CPU 0x022[ 0.000000] Initializing cgroup subsys cpu23
24...25...26...27
28.---O---. 29| | .-. o o 30| | |-----.-----.-----.| | .----..-----.-----.31| | | __ | ---'| '--.| .-'| | |32| | | | | |--- || --'| | | ' | | | |33'---'---'--'--'--. |-----''----''--' '-----'-'-'-'34 -' |35 '---'36
37The Angstrom Distribution beagleboard ttyO038
39Angstrom v2012.12 - Kernel 3.8.1040
41beagleboard login: L2: This message is what we put in the uEnv.txt file.
What would you need to change in uEnv.txt to be able to boot from the eMMC instead of microSD card?
load mmc command should be adjusted! (microSD card
Also, you must check where the Linux kernel image is located in what format. Arguments of load mmc must reflect this information correctly!
Nayak, K. (2022). Embedded Linux Step by Step Using Beaglebone Black [Video file]. Retrieved from https://www.udemy.com/course/embedded-linux-step-by-step-using-beaglebone/