Linux – uboot write kernel into mmc partition

embeddedlinuxu-boot

I want to write a Linux kernel with U-Boot into a mmc hwpartition of an eMMC storage on an i.MX6 board:

TX6UL U-Boot > mmc info
Device: FSL_SDHC
Manufacturer ID: 11
OEM: 100
Name: 004G6 
Tran Speed: 52000000
Rd Block Len: 512
MMC version 5.0
High Capacity: Yes
Capacity: 8 MiB
Bus Width: 4-bit
Erase Group Size: 4 MiB
HC WP Group Size: 4 MiB
User Capacity: 8 MiB WRREL
Boot Capacity: 2 MiB ENH
RPMB Capacity: 512 KiB ENH
GP1 Capacity: 8 MiB WRREL
GP2 Capacity: 1.8 GiB ENH WRREL

The general-purpose hwpartition GP1 was intended to be used for the kernel. Usually the following commands are used to write the image (assuming a tftp-server is running and hosting the image as file uImage_txul):

TX6UL U-Boot > tftp ${loadaddr} uImage_txul
TX6UL U-Boot > mmc write ${loadaddr} 0xXXXX 0xYYYY

How to find out the needed adresses 0xXXXX 0xYYYY to write the image into the hwpartition GP1?

Best Answer

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.

Related Question