a661c0bc821fc132d847098ddba504a21aa05bbb
[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 uint32_t jboot_timestamp(void)
36 {
37 time_t rawtime;
38 time(&rawtime);
39 return (((uint32_t) rawtime) - TIMESTAMP_MAGIC) >> 2;
40 }
41
42 uint16_t jboot_checksum(uint16_t start_val, uint16_t *data, int size)
43 {
44 uint32_t counter = start_val;
45 uint16_t *ptr = data;
46
47 while (size > 1) {
48 counter += *ptr;
49 ++ptr;
50 while (counter >> 16)
51 counter = (uint16_t) counter + (counter >> 16);
52 size -= 2;
53 }
54 if (size > 0) {
55 counter += *(uint8_t *) ptr;
56 counter -= 0xFF;
57 }
58 while (counter >> 16)
59 counter = (uint16_t) counter + (counter >> 16);
60 return counter;
61 }
62
63 int get_file_stat(struct file_info *fdata)
64 {
65 struct stat st;
66 int res;
67
68 if (fdata->file_name == NULL)
69 return 0;
70
71 res = stat(fdata->file_name, &st);
72 if (res) {
73 ERRS("stat failed on %s", fdata->file_name);
74 return res;
75 }
76
77 fdata->file_size = st.st_size;
78 return 0;
79 }
80
81 int read_to_buf(const struct file_info *fdata, char *buf)
82 {
83 FILE *f;
84 int ret = EXIT_FAILURE;
85
86 f = fopen(fdata->file_name, "r");
87 if (f == NULL) {
88 ERRS("could not open \"%s\" for reading", fdata->file_name);
89 goto out;
90 }
91
92 errno = 0;
93 fread(buf, fdata->file_size, 1, f);
94 if (errno != 0) {
95 ERRS("unable to read from file \"%s\"", fdata->file_name);
96 goto out_close;
97 }
98
99 ret = EXIT_SUCCESS;
100
101 out_close:
102 fclose(f);
103 out:
104 return ret;
105 }
106
107 int write_fw(const char *ofname, const char *data, int len)
108 {
109 FILE *f;
110 int ret = EXIT_FAILURE;
111
112 f = fopen(ofname, "w");
113 if (f == NULL) {
114 ERRS("could not open \"%s\" for writing", ofname);
115 goto out;
116 }
117
118 errno = 0;
119 fwrite(data, len, 1, f);
120 if (errno) {
121 ERRS("unable to write output file");
122 goto out_flush;
123 }
124
125 DBG("firmware file \"%s\" completed", ofname);
126
127 ret = EXIT_SUCCESS;
128
129 out_flush:
130 fflush(f);
131 fclose(f);
132 if (ret != EXIT_SUCCESS)
133 unlink(ofname);
134 out:
135 return ret;
136 }