fcab8562319f12281199a54df87527c96089a62c
[openwrt/openwrt.git] / tools / firmware-utils / src / mkdlinkfw-lib.c
1 /*
2 * mkdlinkfw
3 *
4 * Copyright (C) 2018 PaweĊ‚ Dembicki <paweldembicki@gmail.com>
5 *
6 * This tool is based on mktplinkfw.
7 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
8 * Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
14 */
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <stdint.h>
19 #include <string.h>
20 #include <unistd.h> /* for unlink() */
21 #include <libgen.h>
22 #include <getopt.h> /* for getopt() */
23 #include <stdarg.h>
24 #include <stdbool.h>
25 #include <endian.h>
26 #include <errno.h>
27 #include <time.h>
28 #include <sys/stat.h>
29 #include <zlib.h> /*for crc32 */
30
31 #include "mkdlinkfw-lib.h"
32
33 extern char *progname;
34
35 static unsigned char jffs2_eof_mark[4] = { 0xde, 0xad, 0xc0, 0xde };
36
37 uint32_t jboot_timestamp(void)
38 {
39 time_t rawtime;
40 time(&rawtime);
41 return (((uint32_t) rawtime) - TIMESTAMP_MAGIC) >> 2;
42 }
43
44 uint16_t jboot_checksum(uint16_t start_val, uint16_t *data, int size)
45 {
46 uint32_t counter = start_val;
47 uint16_t *ptr = data;
48
49 while (size > 1) {
50 counter += *ptr;
51 ++ptr;
52 while (counter >> 16)
53 counter = (uint16_t) counter + (counter >> 16);
54 size -= 2;
55 }
56 if (size > 0) {
57 counter += *(uint8_t *) ptr;
58 counter -= 0xFF;
59 }
60 while (counter >> 16)
61 counter = (uint16_t) counter + (counter >> 16);
62 return counter;
63 }
64
65 int get_file_stat(struct file_info *fdata)
66 {
67 struct stat st;
68 int res;
69
70 if (fdata->file_name == NULL)
71 return 0;
72
73 res = stat(fdata->file_name, &st);
74 if (res) {
75 ERRS("stat failed on %s", fdata->file_name);
76 return res;
77 }
78
79 fdata->file_size = st.st_size;
80 return 0;
81 }
82
83 int read_to_buf(const struct file_info *fdata, char *buf)
84 {
85 FILE *f;
86 int ret = EXIT_FAILURE;
87
88 f = fopen(fdata->file_name, "r");
89 if (f == NULL) {
90 ERRS("could not open \"%s\" for reading", fdata->file_name);
91 goto out;
92 }
93
94 errno = 0;
95 fread(buf, fdata->file_size, 1, f);
96 if (errno != 0) {
97 ERRS("unable to read from file \"%s\"", fdata->file_name);
98 goto out_close;
99 }
100
101 ret = EXIT_SUCCESS;
102
103 out_close:
104 fclose(f);
105 out:
106 return ret;
107 }
108
109 int pad_jffs2(char *buf, int currlen, int maxlen)
110 {
111 int len;
112 uint32_t pad_mask;
113
114 len = currlen;
115 pad_mask = (4 * 1024) | (64 * 1024); /* EOF at 4KB and at 64KB */
116 while ((len < maxlen) && (pad_mask != 0)) {
117 uint32_t mask;
118 int i;
119
120 for (i = 10; i < 32; i++) {
121 mask = 1 << i;
122 if (pad_mask & mask)
123 break;
124 }
125
126 len = ALIGN(len, mask);
127
128 for (i = 10; i < 32; i++) {
129 mask = 1 << i;
130 if ((len & (mask - 1)) == 0)
131 pad_mask &= ~mask;
132 }
133
134 for (i = 0; i < sizeof(jffs2_eof_mark); i++)
135 buf[len + i] = jffs2_eof_mark[i];
136
137 len += sizeof(jffs2_eof_mark);
138 }
139
140 return len;
141 }
142
143 int write_fw(const char *ofname, const char *data, int len)
144 {
145 FILE *f;
146 int ret = EXIT_FAILURE;
147
148 f = fopen(ofname, "w");
149 if (f == NULL) {
150 ERRS("could not open \"%s\" for writing", ofname);
151 goto out;
152 }
153
154 errno = 0;
155 fwrite(data, len, 1, f);
156 if (errno) {
157 ERRS("unable to write output file");
158 goto out_flush;
159 }
160
161 DBG("firmware file \"%s\" completed", ofname);
162
163 ret = EXIT_SUCCESS;
164
165 out_flush:
166 fflush(f);
167 fclose(f);
168 if (ret != EXIT_SUCCESS)
169 unlink(ofname);
170 out:
171 return ret;
172 }