OpenWrt 中sdcard.img 制作过程
sdcard.img 的文件组成
分区表
u-boot
boot.img
rootfs.img
制作脚本分析
openwrt/target/linux/sunxi/image/gen_sunxi_sdcard_img.sh
#!/usr/bin/env bash # # Copyright (C) 2013 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # set -ex [ $# -eq 6 ] || { echo "SYNTAX: $0 <file> <bootfs image> <rootfs image> <bootfs size> <rootfs size> <u-boot image>" exit 1 } OUTPUT="$1" BOOTFS="$2" ROOTFS="$3" BOOTFSSIZE="$4" ROOTFSSIZE="$5" UBOOT="$6" head=4 sect=63 # 1.这里写分区表 set `ptgen -o $OUTPUT -h $head -s $sect -l 1024 -t c -p ${BOOTFSSIZE}M -t 83 -p ${ROOTFSSIZE}M` BOOTOFFSET="$(($1 / 512))" BOOTSIZE="$(($2 / 512))" ROOTFSOFFSET="$(($3 / 512))" ROOTFSSIZE="$(($4 / 512))" # 2.接下来写 u-boot + boot.img + rootfs.mg dd bs=1024 if="$UBOOT" of="$OUTPUT" seek=8 conv=notrunc dd bs=512 if="$BOOTFS" of="$OUTPUT" seek="$BOOTOFFSET" conv=notrunc dd bs=512 if="$ROOTFS" of="$OUTPUT" seek="$ROOTFSOFFSET" conv=notrunc
重要的工具:ptgen
ptgen 用于生成分区表,分区表占用 512 字节
Usage: ./ptgen [-v] -h <heads> -s <sectors> -o <outputfile> [-a 0..4] [-l <align kB>] [[-t <type>] -p <size>...] lql@debian:~/work/openwrt/staging_dir/host/bin$ ./ptgen -o /tmp/test.img -h 4 -s 63 -l 1024 -t c -p 5M -t 83 -p 32M 1048576 5242880 7340032 33554432 lql@debian:~/work/openwrt/staging_dir/host/bin$ ls -lh /tmp/test.img -rw-r--r-- 1 lql lql 512 May 19 15:11 /tmp/test.img lql@debian:~/work/openwrt/staging_dir/host/bin$ ls -lh /tmp/test.img -rw-r--r-- 1 lql lql 512 May 19 15:11 /tmp/test.img lql@debian:~/work/openwrt/staging_dir/host/bin$ lql@debian:~/work/openwrt/staging_dir/host/bin$ hexdump -C /tmp/test.img 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000001b0 00 00 00 00 00 00 00 00 4f 57 52 54 00 00 80 00 |........OWRT....| 000001c0 21 08 0c 03 03 30 00 08 00 00 00 28 00 00 00 03 |!....0.....(....| 000001d0 24 38 83 03 73 3c 00 38 00 00 00 00 01 00 00 00 |$8..s<.8........| 000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.| 00000200
上面 ls -lh /tmp/test.img 可以看出分区表大小是 512 字节。
ptgen 最多生成4个分区
已知的问题:ptgen 生成的分区中间会有1M的空隙,不知道是有意为之还是 bug ?
+-------+ | | +-------+ 1M | | boot.img(5M) +-------+ 6M | | <-------- 1M 的空隙 +-------+ 7M | | rootfs.img(32M) +-------+
源码:位于 openwrt/tools/firmware-utils/src/ptgen.c
代码摘要:
/* Partition table entry */ struct pte { uint8_t active; uint8_t chs_start[3]; uint8_t type; uint8_t chs_end[3]; uint32_t start; uint32_t length; }; static int gen_ptable(uint32_t signature, int nr) { struct pte pte[4]; unsigned long sect = 0; int i, fd, ret = -1, start, len; memset(pte, 0, sizeof(struct pte) * 4); for (i = 0; i < nr; i++) { if (!parts[i].size) { fprintf(stderr, "Invalid size in partition %d!\n", i); return -1; } pte[i].active = ((i + 1) == active) ? 0x80 : 0; pte[i].type = parts[i].type; start = sect + sectors; if (kb_align != 0) start = round_to_kb(start); pte[i].start = cpu_to_le32(start); sect = start + parts[i].size * 2; if (kb_align == 0) sect = round_to_cyl(sect); pte[i].length = cpu_to_le32(len = sect - start); to_chs(start, pte[i].chs_start); to_chs(start + len - 1, pte[i].chs_end); if (verbose) fprintf(stderr, "Partition %d: start=%ld, end=%ld, size=%ld\n", i, (long)start * 512, ((long)start + (long)len) * 512, (long)len * 512); printf("%ld\n", (long)start * 512); printf("%ld\n", (long)len * 512); } if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) { fprintf(stderr, "Can't open output file '%s'\n",filename); return -1; } lseek(fd, 440, SEEK_SET); if (write(fd, &signature, sizeof(signature)) != sizeof(signature)) { fprintf(stderr, "write failed.\n"); goto fail; } lseek(fd, 446, SEEK_SET); if (write(fd, pte, sizeof(struct pte) * 4) != sizeof(struct pte) * 4) { fprintf(stderr, "write failed.\n"); goto fail; } lseek(fd, 446, SEEK_SET); if (write(fd, pte, sizeof(struct pte) * 4) != sizeof(struct pte) * 4) { fprintf(stderr, "write failed.\n"); goto fail; } lseek(fd, 510, SEEK_SET); if (write(fd, "\x55\xaa", 2) != 2) { fprintf(stderr, "write failed.\n"); goto fail; } ret = 0; fail: close(fd); return ret; }
本站的文章和资源来自互联网或者站长的原创,按照 CC BY -NC -SA 3.0 CN协议发布和共享,转载或引用本站文章应遵循相同协议。如果有侵犯版权的资 源请尽快联系站长,我们会在24h内删除有争议的资源。欢迎大家多多交流,期待共同学习进步。