Flexible firmware upgrade

This post has been moved to codelectron.blogspot.com/2014/03/flexible-firmware-upgrade-for-linux.html

Any comments or feedback please do it there.

 

This hack talks about an alternative solution using dfu-util and u-boot for flashing firmwares , Linux or other operating systems etc. To proceed further its important to know what is currently implemented and how it works. USB Device Firmware Upgrade (DFU) is an official USB device class specification of the USB Implementers Forum. You can find the document here. http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf .
How the present solution works?.
The below example is using the dfu-util flashing open-moko phone,

Listing the number of partition that are supported:
# ./dfu-util –list
dfu-util – (C) 2007 by Openmoko Inc.
This program is Free Software and has ABSOLUTELY NO WARRANTY

Found DFU: [0x1457:0x5119] devnum=16, cfg=0, intf=0, alt=0, name=”RAM 0x32000000″
Found DFU: [0x1457:0x5119] devnum=16, cfg=0, intf=0, alt=1, name=”u-boot”
Found DFU: [0x1457:0x5119] devnum=16, cfg=0, intf=0, alt=2, name=”u-boot_env”
Found DFU: [0x1457:0x5119] devnum=16, cfg=0, intf=0, alt=3, name=”kernel”
Found DFU: [0x1457:0x5119] devnum=16, cfg=0, intf=0, alt=4, name=”splash”
Found DFU: [0x1457:0x5119] devnum=16, cfg=0, intf=0, alt=5, name=”rootfs”
Flashing a particular partition with a new firmware

./dfu-util -a u-boot -R -D u-boot-gta01bv3-latest.bin
dfu-util – (C) 2007 by Openmoko Inc. This program is Free Software and has ABSOLUTELY NO WARRANTY
Opening USB Device 0×0000:0×0000…
Claiming USB DFU Runtime Interface…
Determining device status: state = appIDLE, status = 0
Device really in Runtime Mode, send DFU detach request…
Resetting USB… Opening USB Device…
Found Runtime: [0x1d50:0x5119] devnum=9, cfg=0, intf=0, alt=1, name=”u-boot”
Claiming USB DFU Interface…
Setting Alternate Setting …
Determining device status: state = dfuIDLE, status = 0 dfuIDLE, continuing Transfer Size = 0×1000 bytes_per_hash=4316
Starting download: [##################################################] finished! state(2) = dfuIDLE, status(0) = No error condition is present Done!
Resetting USB to switch back to runtime mode

Making it faster

So these are the normal operation, to make it faster you need to tweak the dfu protocol a little bit in both U-boot and dfu-util project. You can find the dfu-util source here http://dfu-util.gnumonks.org/releases/

In the latest snapshop release open the file dfu_load.c

In the function dfuload_do_dnload, watch carefully this lines.

ret = dfu_download(dif->dev_handle, dif->interface, ret, ret ? buf : NULL);

if (ret < 0) {

fprintf(stderr, “Error during download\n”);

goto out_free;

}

bytes_sent += ret;

do {

ret = dfu_get_status(dif->dev_handle, dif->interface, &dst);

if (ret < 0) {

fprintf(stderr, “Error during download get_status\n”);

goto out_free;

}

if (dst.bState == DFU_STATE_dfuDNLOAD_IDLE ||

dst.bState == DFU_STATE_dfuERROR)

break;

/* Wait while device executes flashing */

if (quirks & QUIRK_POLLTIMEOUT)

milli_sleep(DEFAULT_POLLTIMEOUT);

else

milli_sleep(dst.bwPollTimeout);

} while (1);

The whole lines which are in bold can be simply removed, for a reason. And back in your u-boot you need to remove the corresponding states in the DFU state machine depending on your implementation of it. Recompile both uboot and dfu-util and you are done. You will see a drastic change in the speed.

The reason why this piece of code is not required is because, in U-boot its uni-tasking, and one doesn’t have to wait till the flashing of that block is complete as it will not respond unless it has flashed it. Secondly the only error which can happen is that Flash being corrupted , and for that reason you have an error handler for each dfu_download, and further this ack does not either retransmit the block and to avoid badblock you can use nand_write_skip_bad or any equivalent based on your flash. For all this tweak it also depending on the dfu implementation that is done in the u-boot side, I did using Atmel usb gadget driver combined with open moko DFU state machine, and NOT the standard DFU implementation of U-boot.

Making it flexible:

This is bit more a variation of DFU protocol as suggested by the USB forum. The current limitation is that you have fixed partitions say for example u-boot, kernel, filesystem. Lets take an arbitrary address for them, such as

u-boot   0×1000000
kernel   0×2000000
root-fs   0×5000000

and when you run the command dfu-util –list it will list down these three partitions. So the limitation here is you can only flash these partitions, and you cant change the address of the partitions at all. The only solution is to touch the u-boot environment variable either by booting Linux and running some command or re-flashing the u-boot-env partition which will erase some values which might be very sensitive to change, and might affect the existing configuration of the system.

 Here is the solution for that problem,

Instead of having so many partitions listed, it will list only one.

And instead of the device deciding where the firmware should be flashed, it can be decided in PC by the user and the u-boot will do that for you. But how to pass the information run-time to u-boot about what firmware and where to flash?. This can be achieved using a header based solution.

The code to create a header for your flash images can be found here

https://github.com/codelectron/DFU-Tweak/

After you make the header you can concatenate them to the binary images of kernel, rootfs, u-boot etc.

With the example image address given above the steps to make image with header will look like this

$./makehdr -a  0×1000000 -o  ubootheader -t 1  -b sam  -s 0x40000  -c

$cat ubootheader.bin uboot.bin>uboot.dfu

$./makehdr -a  0×2000000 -o  kernelheader -t 2  -b sam  -s 0×3000000 -c

$cat kernelheader .bin kernel.bin>kernel.dfu

$./makehdr -a  0×5000000 -o  rootfsheader-t 1  -b sam  -s 0x9000000  -c

$cat rootfsheader.bin rootfs.bin>rootfs.dfu

Now they can be flashed like how it is normally done without have to mention what you are flash as the header will contain all the information about which address to flash and what size it is and also other information that can be used for future purpose.

Tagged with: , , , , ,
Posted in Linux

Leave a comment

Archives