• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/mktplinkfw-lib.c

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
  4  *
  5  * This tool was based on:
  6  *   TP-Link WR941 V2 firmware checksum fixing tool.
  7  *   Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
  8  */
  9 
 10 #include <stdio.h>
 11 #include <stdlib.h>
 12 #include <stdint.h>
 13 #include <string.h>
 14 #include <unistd.h>     /* for unlink() */
 15 #include <libgen.h>
 16 #include <getopt.h>     /* for getopt() */
 17 #include <stdarg.h>
 18 #include <stdbool.h>
 19 #include <endian.h>
 20 #include <errno.h>
 21 #include <sys/stat.h>
 22 
 23 #include <arpa/inet.h>
 24 #include <netinet/in.h>
 25 
 26 #include "mktplinkfw-lib.h"
 27 #include "md5.h"
 28 
 29 extern char *ofname;
 30 extern char *progname;
 31 extern uint32_t kernel_len;
 32 extern struct file_info kernel_info;
 33 extern struct file_info rootfs_info;
 34 extern struct flash_layout *layout;
 35 extern uint32_t rootfs_ofs;
 36 extern uint32_t rootfs_align;
 37 extern int combined;
 38 extern int strip_padding;
 39 extern int add_jffs2_eof;
 40 
 41 static unsigned char jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
 42 
 43 void fill_header(char *buf, int len);
 44 
 45 struct flash_layout *find_layout(struct flash_layout *layouts, const char *id)
 46 {
 47         struct flash_layout *ret;
 48         struct flash_layout *l;
 49 
 50         ret = NULL;
 51         for (l = layouts; l->id != NULL; l++){
 52                 if (strcasecmp(id, l->id) == 0) {
 53                         ret = l;
 54                         break;
 55                 }
 56         };
 57 
 58         return ret;
 59 }
 60 
 61 void get_md5(const char *data, int size, uint8_t *md5)
 62 {
 63         MD5_CTX ctx;
 64 
 65         MD5_Init(&ctx);
 66         MD5_Update(&ctx, data, size);
 67         MD5_Final(md5, &ctx);
 68 }
 69 
 70 int get_file_stat(struct file_info *fdata)
 71 {
 72         struct stat st;
 73         int res;
 74 
 75         if (fdata->file_name == NULL)
 76                 return 0;
 77 
 78         res = stat(fdata->file_name, &st);
 79         if (res){
 80                 ERRS("stat failed on %s", fdata->file_name);
 81                 return res;
 82         }
 83 
 84         fdata->file_size = st.st_size;
 85         return 0;
 86 }
 87 
 88 int read_to_buf(const struct file_info *fdata, char *buf)
 89 {
 90         FILE *f;
 91         int ret = EXIT_FAILURE;
 92 
 93         f = fopen(fdata->file_name, "r");
 94         if (f == NULL) {
 95                 ERRS("could not open \"%s\" for reading", fdata->file_name);
 96                 goto out;
 97         }
 98 
 99         errno = 0;
100         fread(buf, fdata->file_size, 1, f);
101         if (errno != 0) {
102                 ERRS("unable to read from file \"%s\"", fdata->file_name);
103                 goto out_close;
104         }
105 
106         ret = EXIT_SUCCESS;
107 
108 out_close:
109         fclose(f);
110 out:
111         return ret;
112 }
113 
114 static int pad_jffs2(char *buf, int currlen, int maxlen)
115 {
116         int len;
117         uint32_t pad_mask;
118 
119         len = currlen;
120         pad_mask = (4 * 1024) | (64 * 1024);    /* EOF at 4KB and at 64KB */
121         while ((len < maxlen) && (pad_mask != 0)) {
122                 uint32_t mask;
123                 int i;
124 
125                 for (i = 10; i < 32; i++) {
126                         mask = 1 << i;
127                         if (pad_mask & mask)
128                                 break;
129                 }
130 
131                 len = ALIGN(len, mask);
132 
133                 for (i = 10; i < 32; i++) {
134                         mask = 1 << i;
135                         if ((len & (mask - 1)) == 0)
136                                 pad_mask &= ~mask;
137                 }
138 
139                 for (i = 0; i < sizeof(jffs2_eof_mark); i++)
140                         buf[len + i] = jffs2_eof_mark[i];
141 
142                 len += sizeof(jffs2_eof_mark);
143         }
144 
145         return len;
146 }
147 
148 int write_fw(const char *ofname, const char *data, int len)
149 {
150         FILE *f;
151         int ret = EXIT_FAILURE;
152 
153         f = fopen(ofname, "w");
154         if (f == NULL) {
155                 ERRS("could not open \"%s\" for writing", ofname);
156                 goto out;
157         }
158 
159         errno = 0;
160         fwrite(data, len, 1, f);
161         if (errno) {
162                 ERRS("unable to write output file");
163                 goto out_flush;
164         }
165 
166         DBG("firmware file \"%s\" completed", ofname);
167 
168         ret = EXIT_SUCCESS;
169 
170 out_flush:
171         fflush(f);
172         fclose(f);
173         if (ret != EXIT_SUCCESS) {
174                 unlink(ofname);
175         }
176 out:
177         return ret;
178 }
179 
180 /* Helper functions to inspect_fw() representing different output formats */
181 inline void inspect_fw_pstr(const char *label, const char *str)
182 {
183         printf("%-23s: %s\n", label, str);
184 }
185 
186 inline void inspect_fw_phex(const char *label, uint32_t val)
187 {
188         printf("%-23s: 0x%08x\n", label, val);
189 }
190 
191 inline void inspect_fw_phexdec(const char *label, uint32_t val)
192 {
193         printf("%-23s: 0x%08x / %8u bytes\n", label, val, val);
194 }
195 
196 inline void inspect_fw_pmd5sum(const char *label, const uint8_t *val, const char *text)
197 {
198         int i;
199 
200         printf("%-23s:", label);
201         for (i=0; i<MD5SUM_LEN; i++)
202                 printf(" %02x", val[i]);
203         printf(" %s\n", text);
204 }
205 
206 // header_size = sizeof(struct fw_header)
207 int build_fw(size_t header_size)
208 {
209         int buflen;
210         char *buf;
211         char *p;
212         int ret = EXIT_FAILURE;
213         int writelen = 0;
214 
215         writelen = header_size + kernel_len;
216 
217         if (combined)
218                 buflen = writelen;
219         else
220                 buflen = layout->fw_max_len;
221 
222         buf = malloc(buflen);
223         if (!buf) {
224                 ERR("no memory for buffer\n");
225                 goto out;
226         }
227 
228         memset(buf, 0xff, buflen);
229         p = buf + header_size;
230         ret = read_to_buf(&kernel_info, p);
231         if (ret)
232                 goto out_free_buf;
233 
234         if (!combined) {
235                 p = buf + rootfs_ofs;
236 
237                 ret = read_to_buf(&rootfs_info, p);
238                 if (ret)
239                         goto out_free_buf;
240 
241                 writelen = rootfs_ofs + rootfs_info.file_size;
242 
243                 if (add_jffs2_eof)
244                         writelen = pad_jffs2(buf, writelen, layout->fw_max_len);
245         }
246 
247         if (!strip_padding)
248                 writelen = buflen;
249 
250         fill_header(buf, writelen);
251         ret = write_fw(ofname, buf, writelen);
252         if (ret)
253                 goto out_free_buf;
254 
255         ret = EXIT_SUCCESS;
256 
257 out_free_buf:
258         free(buf);
259 out:
260         return ret;
261 }
262 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt