1 // SPDX-License-Identifier: GPL-2.0-only
3 * (C) Nicolò Veronese <nicveronese@gmail.com>
16 #include <netinet/in.h> // htonl
18 // Usage: mkdapimg2 -s signature [-v version] [-r region]
19 // [-k uImage block size] -i <input> -o <output>
21 // NOTE: The kernel block size is used to know the offset of the rootfs
24 // The system writes in the uImage partition until the end of uImage
25 // is reached, after that, the system jumps to the offset specified with the -k
26 // parameter and begin writing at the beginning of the rootfs MTD partition.
28 // If the -k parameter is the size of the original uImage partition, the system
29 // continue writing in the rootfs partition starting from the last block
30 // that has been wrote. (This is useful if the new kernel size is
31 // different from the original one)
34 // ------------------------------------------
35 // Creating 7 MTD partitions on "ath-nor0":
36 // 0x000000000000-0x000000010000 : "u-boot"
37 // 0x000000010000-0x000000020000 : "ART"
38 // 0x000000020000-0x000000030000 : "MP"
39 // 0x000000030000-0x000000040000 : "config"
40 // 0x000000040000-0x000000120000 : "uImage"
41 // 0x000000120000-0x000000800000 : "rootfs"
42 // 0x000000040000-0x000000800000 : "firmware"
43 // ------------------------------------------
45 // 0x000000120000-0x000000040000 = 0xE0000 -> 917504
47 // e.g.: mkdapimg2 -s HONEYBEE-FIRMWARE-DAP-1330 -v 1.00.21 -r Default
48 // -k 917504 -i sysupgrade.bin -o factory.bin
51 // The img_hdr_struct was taken from the D-Link SDK:
52 // DAP-1330_OSS-firmware_1.00b21/DAP-1330_OSS-firmware_1.00b21/uboot/uboot.patch
54 #define MAX_SIGN_LEN 32
55 #define MAX_FW_VER_LEN 16
58 struct img_hdr_struct
{
63 char signature
[MAX_SIGN_LEN
];
64 char fw_ver
[MAX_FW_VER_LEN
];
65 char fw_reg
[MAX_REG_LEN
];
71 perrexit(int code
, char *msg
)
73 fprintf(stderr
, "%s: %s: %s\n", progname
, msg
, strerror(errno
));
80 fprintf(stderr
, "usage: %s -s signature [-v version] [-r region] [-k uImage part size] -i <input> -o <output>\n", progname
);
85 main(int ac
, char *av
[])
87 char signature
[MAX_SIGN_LEN
];
88 char version
[MAX_FW_VER_LEN
];
89 char region
[MAX_REG_LEN
];
99 progname
= basename(av
[0]);
101 memset(signature
, 0, sizeof(signature
));
102 memset(version
, 0, sizeof(version
));
103 memset(region
, 0, sizeof(region
));
109 c
= getopt(ac
, av
, "s:v:r:k:i:o:");
115 if (strlen(optarg
) > MAX_SIGN_LEN
+ 1) {
116 fprintf(stderr
, "%s: signature exceeds %d chars\n",
117 progname
, MAX_SIGN_LEN
);
120 strcpy(signature
, optarg
);
123 if (strlen(optarg
) > MAX_FW_VER_LEN
+ 1) {
124 fprintf(stderr
, "%s: version exceeds %d chars\n",
125 progname
, MAX_FW_VER_LEN
);
128 strcpy(version
, optarg
);
131 if (strlen(optarg
) > MAX_REG_LEN
+ 1) {
132 fprintf(stderr
, "%s: region exceeds %d chars\n",
133 progname
, MAX_REG_LEN
);
136 strcpy(region
, optarg
);
139 kernel
= strtoul(optarg
, &ptr
, 0);
145 if ((ifile
= fopen(optarg
, "r")) == NULL
)
149 if ((ofile
= fopen(optarg
, "w")) == NULL
)
157 if (signature
[0] == 0 || ifile
== NULL
|| ofile
== NULL
) {
162 for (bcnt
= 0, cksum
= 0 ; (c
= fgetc(ifile
)) != EOF
; bcnt
++)
165 if (fseek(ifile
, 0, SEEK_SET
) < 0)
166 perrexit(2, "fseek on input");
168 // Fill in the header
169 memset(&imghdr
, 0, sizeof(imghdr
));
170 imghdr
.hdr_len
= sizeof(imghdr
);
171 imghdr
.checksum
= htonl(cksum
);
172 imghdr
.total_size
= htonl(bcnt
);
173 imghdr
.kernel_size
= htonl(kernel
);
175 strncpy(imghdr
.signature
, signature
, MAX_SIGN_LEN
);
176 strncpy(imghdr
.fw_ver
, version
, MAX_FW_VER_LEN
);
177 strncpy(imghdr
.fw_reg
, region
, MAX_REG_LEN
);
179 if (fwrite(&imghdr
, sizeof(imghdr
), 1, ofile
) < 0)
180 perrexit(2, "fwrite header on output");
182 while ((c
= fgetc(ifile
)) != EOF
) {
183 if (fputc(c
, ofile
) == EOF
)
184 perrexit(2, "fputc on output");
188 perrexit(2, "fgetc on input");
193 fprintf(stderr
, "imgHdr.hdr_len = %lu\n", sizeof(imghdr
));
194 fprintf(stderr
, "imgHdr.checksum = 0x%08x\n", cksum
);
195 fprintf(stderr
, "imgHdr.total_size = 0x%08x\n", bcnt
);
196 fprintf(stderr
, "imgHdr.kernel_size = 0x%08x\n", kernel
);
197 fprintf(stderr
, "imgHdr.header = %s\n", signature
);
198 fprintf(stderr
, "imgHdr.fw_ver = %s\n", version
);
199 fprintf(stderr
, "imgHdr.fw_reg = %s\n", region
);