OpenWrt – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * This program is free software; you can redistribute it and/or |
||
3 | * modify it under the terms of the GNU General Public License, |
||
4 | * version 2 as published by the Free Software Foundation. |
||
5 | * |
||
6 | * (C) Nicolò Veronese <nicveronese@gmail.com> |
||
7 | */ |
||
8 | |||
9 | #include <stdio.h> |
||
10 | #include <stdint.h> |
||
11 | #include <stdlib.h> |
||
12 | #include <unistd.h> |
||
13 | #include <libgen.h> |
||
14 | #include <stdarg.h> |
||
15 | #include <getopt.h> |
||
16 | #include <string.h> |
||
17 | #include <errno.h> |
||
18 | |||
19 | #include <netinet/in.h> // htonl |
||
20 | |||
21 | // Usage: mkdapimg2 -s signature [-v version] [-r region] |
||
22 | // [-k uImage block size] -i <input> -o <output> |
||
23 | // |
||
24 | // NOTE: The kernel block size is used to know the offset of the rootfs |
||
25 | // in the image file. |
||
26 | // |
||
27 | // The system writes in the uImage partition until the end of uImage |
||
28 | // is reached, after that, the system jumps to the offset specified with the -k |
||
29 | // parameter and begin writing at the beginning of the rootfs MTD partition. |
||
30 | // |
||
31 | // If the -k parameter is the size of the original uImage partition, the system |
||
32 | // continue writing in the rootfs partition starting from the last block |
||
33 | // that has been wrote. (This is useful if the new kernel size is |
||
34 | // different from the original one) |
||
35 | // |
||
36 | // Example: |
||
37 | // ------------------------------------------ |
||
38 | // Creating 7 MTD partitions on "ath-nor0": |
||
39 | // 0x000000000000-0x000000010000 : "u-boot" |
||
40 | // 0x000000010000-0x000000020000 : "ART" |
||
41 | // 0x000000020000-0x000000030000 : "MP" |
||
42 | // 0x000000030000-0x000000040000 : "config" |
||
43 | // 0x000000040000-0x000000120000 : "uImage" |
||
44 | // 0x000000120000-0x000000800000 : "rootfs" |
||
45 | // 0x000000040000-0x000000800000 : "firmware" |
||
46 | // ------------------------------------------ |
||
47 | // |
||
48 | // 0x000000120000-0x000000040000 = 0xE0000 -> 917504 |
||
49 | // |
||
50 | // e.g.: mkdapimg2 -s HONEYBEE-FIRMWARE-DAP-1330 -v 1.00.21 -r Default |
||
3 | office | 51 | // -k 917504 -i sysupgarde.bin -o factory.bin |
1 | office | 52 | // |
53 | // |
||
54 | // The img_hdr_struct was taken from the D-Link SDK: |
||
55 | // DAP-1330_OSS-firmware_1.00b21/DAP-1330_OSS-firmware_1.00b21/uboot/uboot.patch |
||
56 | |||
57 | #define MAX_SIGN_LEN 32 |
||
58 | #define MAX_FW_VER_LEN 16 |
||
59 | #define MAX_REG_LEN 8 |
||
60 | |||
61 | struct img_hdr_struct { |
||
62 | uint32_t hdr_len; |
||
63 | uint32_t checksum; |
||
64 | uint32_t total_size; |
||
65 | uint32_t kernel_size; |
||
66 | char signature[MAX_SIGN_LEN]; |
||
67 | char fw_ver[MAX_FW_VER_LEN]; |
||
68 | char fw_reg[MAX_REG_LEN]; |
||
69 | } imghdr ; |
||
70 | |||
71 | char *progname; |
||
72 | |||
73 | void |
||
74 | perrexit(int code, char *msg) |
||
75 | { |
||
76 | fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno)); |
||
77 | exit(code); |
||
78 | } |
||
79 | |||
80 | void |
||
81 | usage() |
||
82 | { |
||
83 | fprintf(stderr, "usage: %s -s signature [-v version] [-r region] [-k uImage part size] -i <input> -o <output>\n", progname); |
||
84 | exit(1); |
||
85 | } |
||
86 | |||
87 | int |
||
88 | main(int ac, char *av[]) |
||
89 | { |
||
90 | char signature[MAX_SIGN_LEN]; |
||
91 | char version[MAX_FW_VER_LEN]; |
||
92 | char region[MAX_REG_LEN]; |
||
93 | int kernel = 0; |
||
94 | |||
95 | FILE *ifile, *ofile; |
||
96 | int c; |
||
97 | |||
98 | uint32_t cksum; |
||
99 | uint32_t bcnt; |
||
100 | |||
101 | progname = basename(av[0]); |
||
102 | |||
103 | memset(signature, 0, sizeof(signature)); |
||
104 | memset(version, 0, sizeof(version)); |
||
105 | memset(region, 0, sizeof(region)); |
||
106 | |||
107 | while ( 1 ) { |
||
108 | char *ptr; |
||
109 | int c; |
||
110 | |||
111 | c = getopt(ac, av, "s:v:r:k:i:o:"); |
||
112 | if (c == -1) |
||
113 | break; |
||
114 | |||
115 | switch (c) { |
||
116 | case 's': |
||
117 | if (strlen(optarg) > MAX_SIGN_LEN + 1) { |
||
118 | fprintf(stderr, "%s: signature exceeds %d chars\n", |
||
119 | progname, MAX_SIGN_LEN); |
||
120 | exit(1); |
||
121 | } |
||
122 | strcpy(signature, optarg); |
||
123 | break; |
||
124 | case 'v': |
||
125 | if (strlen(optarg) > MAX_FW_VER_LEN + 1) { |
||
126 | fprintf(stderr, "%s: version exceeds %d chars\n", |
||
127 | progname, MAX_FW_VER_LEN); |
||
128 | exit(1); |
||
129 | } |
||
130 | strcpy(version, optarg); |
||
131 | break; |
||
132 | case 'r': |
||
133 | if (strlen(optarg) > MAX_REG_LEN + 1) { |
||
134 | fprintf(stderr, "%s: region exceeds %d chars\n", |
||
135 | progname, MAX_REG_LEN); |
||
136 | exit(1); |
||
137 | } |
||
138 | strcpy(region, optarg); |
||
139 | break; |
||
140 | case 'k': |
||
141 | kernel = strtoul(optarg, &ptr, 0); |
||
142 | if(ptr[0] == 'k'){ |
||
143 | kernel *= 1000; |
||
144 | } |
||
145 | break; |
||
146 | case 'i': |
||
147 | if ((ifile = fopen(optarg, "r")) == NULL) |
||
148 | perrexit(1, optarg); |
||
149 | break; |
||
150 | case 'o': |
||
151 | if ((ofile = fopen(optarg, "w")) == NULL) |
||
152 | perrexit(1, optarg); |
||
153 | break; |
||
154 | default: |
||
155 | usage(); |
||
156 | } |
||
157 | } |
||
158 | |||
159 | if (signature[0] == 0 || ifile == NULL || ofile == NULL) { |
||
160 | usage(); |
||
161 | exit(1); |
||
162 | } |
||
163 | |||
164 | for (bcnt = 0, cksum = 0 ; (c = fgetc(ifile)) != EOF ; bcnt++) |
||
165 | cksum += c & 0xff; |
||
166 | |||
167 | if (fseek(ifile, 0, SEEK_SET) < 0) |
||
168 | perrexit(2, "fseek on input"); |
||
169 | |||
170 | // Fill in the header |
||
171 | memset(&imghdr, 0, sizeof(imghdr)); |
||
172 | imghdr.hdr_len = sizeof(imghdr); |
||
173 | imghdr.checksum = htonl(cksum); |
||
174 | imghdr.total_size = htonl(bcnt); |
||
175 | imghdr.kernel_size = htonl(kernel); |
||
176 | |||
177 | strncpy(imghdr.signature, signature, MAX_SIGN_LEN); |
||
178 | strncpy(imghdr.fw_ver, version, MAX_FW_VER_LEN); |
||
179 | strncpy(imghdr.fw_reg, region, MAX_REG_LEN); |
||
180 | |||
181 | if (fwrite(&imghdr, sizeof(imghdr), 1, ofile) < 0) |
||
182 | perrexit(2, "fwrite header on output"); |
||
183 | |||
184 | while ((c = fgetc(ifile)) != EOF) { |
||
185 | if (fputc(c, ofile) == EOF) |
||
186 | perrexit(2, "fputc on output"); |
||
187 | } |
||
188 | |||
189 | if (ferror(ifile)) |
||
190 | perrexit(2, "fgetc on input"); |
||
191 | |||
192 | fclose(ofile); |
||
193 | fclose(ifile); |
||
194 | |||
195 | fprintf(stderr, "imgHdr.hdr_len = %lu\n", sizeof(imghdr)); |
||
196 | fprintf(stderr, "imgHdr.checksum = 0x%08x\n", cksum); |
||
197 | fprintf(stderr, "imgHdr.total_size = 0x%08x\n", bcnt); |
||
198 | fprintf(stderr, "imgHdr.kernel_size = 0x%08x\n", kernel); |
||
199 | fprintf(stderr, "imgHdr.header = %s\n", signature); |
||
200 | fprintf(stderr, "imgHdr.fw_ver = %s\n", version); |
||
201 | fprintf(stderr, "imgHdr.fw_reg = %s\n", region); |
||
202 | |||
203 | return 0; |
||
204 | } |