OpenWrt 中如何制作sdcard.img镜像文件

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;
}


本文章由作者:佐须之男 整理编辑,原文地址: OpenWrt 中如何制作sdcard.img镜像文件
本站的文章和资源来自互联网或者站长的原创,按照 CC BY -NC -SA 3.0 CN协议发布和共享,转载或引用本站文章应遵循相同协议。如果有侵犯版权的资 源请尽快联系站长,我们会在24h内删除有争议的资源。欢迎大家多多交流,期待共同学习进步。

相关推荐