838b1792ffb049a85e7b1ef535665fb79c38b34e
[openwrt/staging/wigyori.git] / tools / firmware-utils / src / mktplinkfw-lib.c
1 /*
2 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
3 *
4 * This tool was based on:
5 * TP-Link WR941 V2 firmware checksum fixing tool.
6 * Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 *
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdint.h>
17 #include <string.h>
18 #include <unistd.h> /* for unlink() */
19 #include <libgen.h>
20 #include <getopt.h> /* for getopt() */
21 #include <stdarg.h>
22 #include <stdbool.h>
23 #include <endian.h>
24 #include <errno.h>
25 #include <sys/stat.h>
26
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
29
30 #include "mktplinkfw-lib.h"
31 #include "md5.h"
32
33 extern char *progname;
34 static unsigned char jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
35
36 struct flash_layout *find_layout(struct flash_layout *layouts, const char *id)
37 {
38 struct flash_layout *ret;
39 struct flash_layout *l;
40
41 ret = NULL;
42 for (l = layouts; l->id != NULL; l++){
43 if (strcasecmp(id, l->id) == 0) {
44 ret = l;
45 break;
46 }
47 };
48
49 return ret;
50 }
51
52 void get_md5(const char *data, int size, uint8_t *md5)
53 {
54 MD5_CTX ctx;
55
56 MD5_Init(&ctx);
57 MD5_Update(&ctx, data, size);
58 MD5_Final(md5, &ctx);
59 }
60
61 int get_file_stat(struct file_info *fdata)
62 {
63 struct stat st;
64 int res;
65
66 if (fdata->file_name == NULL)
67 return 0;
68
69 res = stat(fdata->file_name, &st);
70 if (res){
71 ERRS("stat failed on %s", fdata->file_name);
72 return res;
73 }
74
75 fdata->file_size = st.st_size;
76 return 0;
77 }
78
79 int read_to_buf(const struct file_info *fdata, char *buf)
80 {
81 FILE *f;
82 int ret = EXIT_FAILURE;
83
84 f = fopen(fdata->file_name, "r");
85 if (f == NULL) {
86 ERRS("could not open \"%s\" for reading", fdata->file_name);
87 goto out;
88 }
89
90 errno = 0;
91 fread(buf, fdata->file_size, 1, f);
92 if (errno != 0) {
93 ERRS("unable to read from file \"%s\"", fdata->file_name);
94 goto out_close;
95 }
96
97 ret = EXIT_SUCCESS;
98
99 out_close:
100 fclose(f);
101 out:
102 return ret;
103 }
104
105 int pad_jffs2(char *buf, int currlen, int maxlen)
106 {
107 int len;
108 uint32_t pad_mask;
109
110 len = currlen;
111 pad_mask = (64 * 1024);
112 while ((len < maxlen) && (pad_mask != 0)) {
113 uint32_t mask;
114 int i;
115
116 for (i = 10; i < 32; i++) {
117 mask = 1 << i;
118 if (pad_mask & mask)
119 break;
120 }
121
122 len = ALIGN(len, mask);
123
124 for (i = 10; i < 32; i++) {
125 mask = 1 << i;
126 if ((len & (mask - 1)) == 0)
127 pad_mask &= ~mask;
128 }
129
130 for (i = 0; i < sizeof(jffs2_eof_mark); i++)
131 buf[len + i] = jffs2_eof_mark[i];
132
133 len += sizeof(jffs2_eof_mark);
134 }
135
136 return len;
137 }
138
139 int write_fw(const char *ofname, const char *data, int len)
140 {
141 FILE *f;
142 int ret = EXIT_FAILURE;
143
144 f = fopen(ofname, "w");
145 if (f == NULL) {
146 ERRS("could not open \"%s\" for writing", ofname);
147 goto out;
148 }
149
150 errno = 0;
151 fwrite(data, len, 1, f);
152 if (errno) {
153 ERRS("unable to write output file");
154 goto out_flush;
155 }
156
157 DBG("firmware file \"%s\" completed", ofname);
158
159 ret = EXIT_SUCCESS;
160
161 out_flush:
162 fflush(f);
163 fclose(f);
164 if (ret != EXIT_SUCCESS) {
165 unlink(ofname);
166 }
167 out:
168 return ret;
169 }
170
171 /* Helper functions to inspect_fw() representing different output formats */
172 inline void inspect_fw_pstr(const char *label, const char *str)
173 {
174 printf("%-23s: %s\n", label, str);
175 }
176
177 inline void inspect_fw_phex(const char *label, uint32_t val)
178 {
179 printf("%-23s: 0x%08x\n", label, val);
180 }
181
182 inline void inspect_fw_phexdec(const char *label, uint32_t val)
183 {
184 printf("%-23s: 0x%08x / %8u bytes\n", label, val, val);
185 }
186
187 inline void inspect_fw_pmd5sum(const char *label, const uint8_t *val, const char *text)
188 {
189 int i;
190
191 printf("%-23s:", label);
192 for (i=0; i<MD5SUM_LEN; i++)
193 printf(" %02x", val[i]);
194 printf(" %s\n", text);
195 }