tplink-safeloader: support Archer C6v3.0 (BR)
[project/firmware-utils.git] / src / mkdlinkfw-lib.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * mkdlinkfw
4 *
5 * Copyright (C) 2018 Paweł Dembicki <paweldembicki@gmail.com>
6 *
7 * This tool is based on mktplinkfw.
8 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
9 * Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
10 */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stdint.h>
15 #include <string.h>
16 #include <unistd.h> /* for unlink() */
17 #include <libgen.h>
18 #include <getopt.h> /* for getopt() */
19 #include <stdarg.h>
20 #include <stdbool.h>
21 #include <endian.h>
22 #include <errno.h>
23 #include <time.h>
24 #include <sys/stat.h>
25 #include <zlib.h> /*for crc32 */
26
27 #include "mkdlinkfw-lib.h"
28
29 extern char *progname;
30
31 uint32_t jboot_timestamp(void)
32 {
33 char *env = getenv("SOURCE_DATE_EPOCH");
34 char *endptr = env;
35 time_t fixed_timestamp = -1;
36 errno = 0;
37
38 if (env && *env) {
39 fixed_timestamp = strtoull(env, &endptr, 10);
40
41 if (errno || (endptr && *endptr != '\0')) {
42 fprintf(stderr, "Invalid SOURCE_DATE_EPOCH");
43 fixed_timestamp = -1;
44 }
45 }
46
47 if (fixed_timestamp == -1)
48 time(&fixed_timestamp);
49
50 return (((uint32_t) fixed_timestamp) - TIMESTAMP_MAGIC) >> 2;
51 }
52
53 uint16_t jboot_checksum(uint16_t start_val, uint16_t *data, int size)
54 {
55 uint32_t counter = start_val;
56 uint16_t *ptr = data;
57
58 while (size > 1) {
59 counter += *ptr;
60 ++ptr;
61 while (counter >> 16)
62 counter = (uint16_t) counter + (counter >> 16);
63 size -= 2;
64 }
65 if (size > 0) {
66 counter += *(uint8_t *) ptr;
67 counter -= 0xFF;
68 }
69 while (counter >> 16)
70 counter = (uint16_t) counter + (counter >> 16);
71 return counter;
72 }
73
74 int get_file_stat(struct file_info *fdata)
75 {
76 struct stat st;
77 int res;
78
79 if (fdata->file_name == NULL)
80 return 0;
81
82 res = stat(fdata->file_name, &st);
83 if (res) {
84 ERRS("stat failed on %s", fdata->file_name);
85 return res;
86 }
87
88 fdata->file_size = st.st_size;
89 return 0;
90 }
91
92 int read_to_buf(const struct file_info *fdata, char *buf)
93 {
94 FILE *f;
95 int ret = EXIT_FAILURE;
96 size_t read;
97
98 f = fopen(fdata->file_name, "r");
99 if (f == NULL) {
100 ERRS("could not open \"%s\" for reading", fdata->file_name);
101 goto out;
102 }
103
104 read = fread(buf, fdata->file_size, 1, f);
105 if (ferror(f) || read != 1) {
106 ERRS("unable to read from file \"%s\"", fdata->file_name);
107 goto out_close;
108 }
109
110 ret = EXIT_SUCCESS;
111
112 out_close:
113 fclose(f);
114 out:
115 return ret;
116 }
117
118 int write_fw(const char *ofname, const char *data, int len)
119 {
120 FILE *f;
121 int ret = EXIT_FAILURE;
122
123 f = fopen(ofname, "w");
124 if (f == NULL) {
125 ERRS("could not open \"%s\" for writing", ofname);
126 goto out;
127 }
128
129 errno = 0;
130 fwrite(data, len, 1, f);
131 if (errno) {
132 ERRS("unable to write output file");
133 goto out_flush;
134 }
135
136 DBG("firmware file \"%s\" completed", ofname);
137
138 ret = EXIT_SUCCESS;
139
140 out_flush:
141 fflush(f);
142 fclose(f);
143 if (ret != EXIT_SUCCESS)
144 unlink(ofname);
145 out:
146 return ret;
147 }