分享一个使用sunxi-fel直接启动u-boot的fastboot的方法.
sunxi-fel使用uboot命令下载u-boot-sunxi-with-spl.bin之后可以直接运行u-boot, 如果需要配置uboot工作在其他模式, 比如ums或者fastboot等, 需要手动在u-boot的控制台上输入指令, 麻烦的很, 不利于自动化运行. 下面介绍一个简单的方法.
$ cat fastboot.env
#=uEnv
bootdelay=0
bootcmd=fastboot usb 0
$ sudo sunxi-fel uboot u-boot-sunxi-with-spl.bin write 0x44000000 fastboot.env
$ fastboot version
version: 0.4
finished. total time: 0.001s
----------------------------------------
从代码上分析下该方式的实现:
1. sunxi-tools
使用sunxi-fel write固件的时候, 函数内部会对固件类型进行判断, 目前支持两种特殊的固件, 一是u-boot env, 以字符串"#=uEnv"开头. 另一个是u-boot scripts, 由mkimage生成的. 如果是这两种格式之一, 会将write的地址存放在spl header的fel_script_address中, 长度存放在fel_uEnv_length. u-boot scripts脚本的话, fel_uEnv_length为0.
/* private helper function, gets used for "write*" and "multi*" transfers */
static unsigned int file_upload(feldev_handle *dev, size_t count,
size_t argc, char **argv, progress_cb_t callback)
{
if (argc < count * 2)
pr_fatal("error: too few arguments for uploading %zu files\n",
count);
/* get all file sizes, keeping track of total bytes */
size_t size = 0;
unsigned int i;
for (i = 0; i < count; i++)
size += file_size(argv[i * 2 + 1]);
progress_start(callback, size); /* set total size and progress callback */
/* now transfer each file in turn */
for (i = 0; i < count; i++) {
void *buf = load_file(argv[i * 2 + 1], &size);
if (size > 0) {
uint32_t offset = strtoul(argv[i * 2], NULL, 0);
aw_write_buffer(dev, buf, offset, size, callback != NULL);
/* If we transferred a script, try to inform U-Boot about its address. */
if (get_image_type(buf, size) == IH_TYPE_SCRIPT)
pass_fel_information(dev, offset, 0);
if (is_uEnv(buf, size)) /* uEnv-style data */
pass_fel_information(dev, offset, size);
}
free(buf);
}
return i; /* return number of files that were processed */
}
2. u-boot的实现
u-boot relocated之后, 在初始化的后半部分调用misc_init_r, 其中执行parse_spl_header, 会对spl_header中sunxi-tools传递的信息进行处理.
/*
* Check the SPL header for the "sunxi" variant. If found: parse values
* that might have been passed by the loader ("fel" utility), and update
* the environment accordingly.
*/
static void parse_spl_header(const uint32_t spl_addr)
{
struct boot_file_head *spl = get_spl_header(SPL_ENV_HEADER_VERSION);
if (spl == INVALID_SPL_HEADER)
return;
if (!spl->fel_script_address)
return;
if (spl->fel_uEnv_length != 0) {
/*
* data is expected in uEnv.txt compatible format, so "env
* import -t" the string(s) at fel_script_address right away.
*/
himport_r(&env_htab, (char *)(uintptr_t)spl->fel_script_address,
spl->fel_uEnv_length, '\n', H_NOCLEAR, 0, 0, NULL);
return;
}
/* otherwise assume .scr format (mkimage-type script) */
env_set_hex("fel_scriptaddr", spl->fel_script_address);
}
这种实现方式真是因吹斯汀.
离线
有点意思,这个 0x44000000 地址是怎么算出来的?
离线
有点意思,这个 0x44000000 地址是怎么算出来的?
随便填个有效地址就行了
离线
memory 说:有点意思,这个 0x44000000 地址是怎么算出来的?
随便填个有效地址就行了
随便填怎么关联呢?
离线
qianfan 说:memory 说:有点意思,这个 0x44000000 地址是怎么算出来的?
随便填个有效地址就行了
随便填怎么关联呢?
看上面贴出的sunxi-tools的代码, sunxi-tools会将这个地址, 也就是44000000放到spl的header中(fel_scripts_address), 等开机之后从spl header里面取到的.
离线
这个操作不得不说有点骚!
离线