OpenWrt 中sdcard.img 制作过程
OpenWrt 中sdcard.img 制作过程sdcard.img 的文件组成分区表u-bootboot.imgrootfs.img制作脚本分析openwrt/target/linux/sunxi/image/gen_sunxi_sdcard_img.sh#!/usr/bin/env bash## Copyright (C) 2013 OpenWrt.org## This is free sof
·
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;
}
更多推荐
已为社区贡献1条内容
所有评论(0)