uClinux下,一种合并uzImage.bin和cramfs.bin的方法
来源:互联网 发布:smali文件批量转java 编辑:程序博客网 时间:2024/06/04 01:21
以下这种方法最后合并出的文件不是通常uClinux“认为”的标准镜像文件,而且一定要修改bootload代码。请慎用此方法。
(一)、为什么要合并uzImage.bin和cramfs.bin?
一、为了升级时安全、方便
安全。当系统升级程序拿到升级文件时,它必然要判断该文件合法性。uzImage.bin有crc检查,判断起来很容易,cramfs.bin是不带的,有难度。如果两个合为一个,然后使用加在uzImage.bin上的crc机制,那合法性检查上就简单了。
方便。两个合为一个,升级时只须一个文件。
二、节省flash占用空间
分为uzImage.bin和cramfs.bin,则意味着必须给flash人为地分出两个空间,而且这两个空间大小被事先固定。像4M字节flash,uzImage.bin占用从0x040000开始的1M字节,cramfs.bin占用从0x140000开始的2,752K字节。
既分在两个区就使得分配时不得不存在一个权衡问题,代码不可能写得“恰好”占用。像对于uzImage.bin,这个版本可能是恰好占用,但代码写多了都知道,功能上的删、加、修改是不确定的,下个版块可能就要因一个意外修改而导致不得不修改uzImage.bin。为解决这个问题,可以使用在bootload环境变量中写上两区边界方法,但这种方法怎么说也没只是一个文件时方便,而且再“恰好”也肯定是有一定字节“空隙”。
(二)、如何合并
合并采用的方法分为宿主机链接时和uClinux的bootload加载时两个部分。
注:image.0000.img表示最终形成的单个镜像文件。
宿主机链接时
当拿到uzImage.bin.gz(这里多了个gz,这个文件不是最后mkimage后的,而是在mkimage之前gzip之后)和cramfs.bin,链接时执行:
cat $(cramfs.bin) $(uzImage.bin.gz) > $(uzImage.gz)
./mkimage -A arm -O linux -T kernel -C gzip -a <加载地址> -e <执行地址> -n "uClinux Kernel for xxxx" -d $(uzImage.gz) $(IMAGEDIR)/image.0000.img
简单来说,就是在mkimage uzImage.bin.gz之前,先用cat命令合并uzImage.bin.gz和cramfs.bin,合并时cramfs.bin必须放在前头。
cramfs.bin为何要放在前头?
cramfs.bin文件的[4h---7h]四字节存储了该cramfs.bin的文件长度。gzip之后的uzImage.bin.gz无法自识别长度。
至此形成的image.0000.img文件结构
image_header_t:mkImage添加的文件头,固定64字节
cramfs.bin:cramfs.bin部分,它的长度可由偏移68--71字节处得到,假设是cramfs_len。
uzImage.bin:uzImage.bin部分。它在image.0000.img开始址址是64+cramfs_len,它的长度则可以由image_head_t中的有效数据长度字段值减去cramfs_len得到。
uClinux的bootload加载时
加载还是要分两次进行,分别加载uzImage.bin和cramfs.bin。
当运行到要加载uzImage.bin时。开始地址:image.0000.img开始地址加上64+cramfs_len;长度:image_head_t中的有效数据长度字段值减去cramfs_len。
当运行到要加载cramfs.bin时。开始地址:image.0000.img开始地址加上64。长度:image.0000.img偏移处68--71字节处得到的值。
(三)、几点补充
一、检查镜像文件合法性上沿用原先给uzImage.bin的crc机制,可以说不增加较验上开销。
二、在flash向ram加载效率上,只是多了几个判断,和原先分两个文件加载方法上可说一样的执行效率。
一个实例:对bootload改动
1):把uzImage.bin从flash加载到sdram;
2):把cramfs.bin从flash加载到sdram;
3):把矢量表加载到sdram零处
4):运行uClinux内核
bootcmd环境变量表示以上四个过程:
- bootcmd=cp.l fc040000 01800000 40000; cp.l fc140000 02000000 AC000; cp.l fc3f8000 0 e;bootm 01800000
注:以下的flash地址像fc040000,完全大于了4M/8M,那时因为flash被map后它的起始地址就是0xfc000000,所以fc040000对应的其实是flash上的0x40000地址。
- flash-2-mem(0xfc040000, 0x01800000, 0x40000 << 2);
- flash-2-mem(0xfc140000, 0x02000000, 0xac000 << 2);
- flash-2-mem(0xfc3f8000, 0x00000000, 0xe << 2);
- bootm(0x1800000)
- int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
- {
- ulong addr, dest, count;
- int size;
- image_header_t* hdr;
- if (argc != 4) {
- printf ("Usage:\n%s\n", cmdtp->usage);
- return 1;
- }
- /* Check for size specification.
- */
- if ((size = cmd_get_data_size(argv[0], 4)) < 0)
- return 1;
- addr = simple_strtoul(argv[1], NULL, 16);
- addr += base_address;
- dest = simple_strtoul(argv[2], NULL, 16);
- dest += base_address;
- count = simple_strtoul(argv[3], NULL, 16);
- if (count == 0) {
- puts ("Zero length ???\n");
- return 1;
- }
- //
- // 由于使用了把uzImage.bin和cramfs.bin合并到一个文件,而在命令行上又保持不变,就须要修正一些变量意义。
- //
- if (addr == 0xfc040000) {
- // fc040000, flash(uzImage.bin)-->ram
- // dest = 0x01008000;
- // 读出cramfs.bin文件长度
- cramfs_len = *(ulong *)(0xfc040000 + sizeof(image_header_t) + 4);
- printf("addr == 0xfc040000, this is uzImage.bin, base_address: %lu, cramfs_len: %lu\n", base_address, cramfs_len);
- hdr = (image_header_t*)addr;
- count = sizeof(image_header_t) / size; // sizeo = 4, sizeof(image_header_t)一般0x40字节,可以被4整除
- // 复制头
- while (count-- > 0) {
- if (size == 4)
- *((ulong *)dest) = *((ulong *)addr);
- else if (size == 2)
- *((ushort *)dest) = *((ushort *)addr);
- else
- *((u_char *)dest) = *((u_char *)addr);
- addr += size;
- dest += size;
- }
- // 从image_header_t中取出数据长度(count = cramfs.bin + uzImage.bin.gz)
- count = SWAP_LONG(hdr->ih_size); // ntohl(ih_size)
-
- // 注意,此时的addr已经变成, 函数参数中的addr + sizeof(image_header_t)
- addr = addr + cramfs_len;
- count = (count - cramfs_len) / size + 1; // cp.l时,size是4, uzImage.bin有效长度会由gzip压缩机制保证(4M flash)或只要至少比有效多就行(8M flash),这里多复制四个字节总不会出错
- #ifndef USE_4M_FLASH
- // 对于uzImage.bin来说,为减少字节占用一般使用gzip压缩(大概可以达到2:1压缩率),使整个软件能约束在4M字节以内。
- // 因为使用gzip压缩,bootload必须对uzImage.bin进行解压,这个过程有时较耗时间,为减少启动时间宁愿采用不压缩而使用8M字节flash
- // 这里就是8M情况
- // 对于8M, uzImage.bin没经过压缩, 这里就直接复制到解压后的uzImage.bin应该放到的地址, 省掉do_bootm()中的memcpy
- dest = SWAP_LONG(hdr->ih_load);
- #endif
-
- } else if ((addr == 0xfc140000) && cramfs_len) {
- // fc140000, flash(cramfs.bin)-->ram
- // 总是假定uzImage.bin已被下载
- printf("addr == 0xfc140000, this is cramfs.bin, base_address: %lu, cramfs_len: %lu\n", base_address, cramfs_len);
- addr = 0xfc040000 + sizeof(image_header_t); // addr要回到flash开始内核开始处: 0xfc040000
- count = cramfs_len / size;
- } else if (addr == 0xfc3f8000) {
- // 矢量表。这个才60字节,直接是以内存数组表示
- printf("addr == 0xfc3f8000, this is vector, count: %lu\n", count);
- addr = vectordata;
- }
- while (count-- > 0) {
- if (size == 4)
- *((ulong *)dest) = *((ulong *)addr);
- else if (size == 2)
- *((ushort *)dest) = *((ushort *)addr);
- else
- *((u_char *)dest) = *((u_char *)addr);
- addr += size;
- dest += size;
- }
- return 0;
- }
来自:http://www.freeors.com/bbs/forum.php?mod=viewthread&tid=11149
- uClinux下,一种合并uzImage.bin和cramfs.bin的方法
- 合并BIN文件的两种方法
- 合并BIN文件的两种方法
- 合并BIN文件的两种方法
- 合并BIN文件的两种方法
- 合并bootloader和app的bin文件
- ubuntu下安装*.sh和*.bin包的方法
- 在Ubuntu下安装*.sh和*.bin的简单方法。
- MAC 下如何合并.cue 和 .bin 文件成为 .ISO
- linux下JDK的bin安装方法
- 合并烧写程序BIN文件的两种方法
- 合并BIN文件的两种方法 ---转载
- 合并烧写程序BIN文件的两种方法
- linux下 bin和sbin的区别
- linux下 bin和sbin的区别
- Linux下/bin和/sbin的区别
- /bin和/usr/bin的区别
- #!/bin/bash和#!/bin/sh的区别
- EditPlus正则表达式替换字符串
- Java 加密解密
- yum使用总结
- Unicore xuudb启动报错:java.security.InvalidKeyException: Illegal key size 解决方案
- Single Number I & II
- uClinux下,一种合并uzImage.bin和cramfs.bin的方法
- Extjs在火狐浏览器下提示ext-all.js 中出现TypeError: b is null的错误
- 一道百度校招笔试题
- 什么是JavaBean
- UVa 592 Island of Logic (有趣的枚举题)
- MFC的图片按钮
- VB遇报表
- 一些技术问题
- RSA hdu 1211 数论的水题(数据较弱)