ramips: add support for TP-Link RE305 v3
[project/firmware-utils.git] / src / uimage_sgehdr.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * uimage_sgehdr.c : add 96 bytes of extra header information after the normal tail of uimage header
4 * this is an edited version of uimage_padhdr.c
5 *
6 * Copyright (C) 2019 NOGUCHI Hiroshi <drvlabo@gmail.com>
7 */
8
9 #include <stdio.h>
10 #include <errno.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #include <sys/stat.h>
16 #include <arpa/inet.h>
17 #include <zlib.h>
18
19
20 /* from u-boot/include/image.h */
21 #define IH_NMLEN 32 /* Image Name Length */
22 #define SGE_PRODUCTLEN 64 /* sge_Product Length */
23 #define SGE_VERSIONLEN 16 /* sge Version Length */
24 #define OrignalHL 64 /* Original Header Length */
25
26 /*
27 * SGE format image header,
28 * all data in network byte order (aka natural aka bigendian).
29 */
30 struct image_header {
31 uint32_t ih_magic; /* Image Header Magic Number */
32 uint32_t ih_hcrc; /* Image Header CRC Checksum */
33 uint32_t ih_time; /* Image Creation Timestamp */
34 uint32_t ih_size; /* Image Data Size */
35 uint32_t ih_load; /* Data Load Address */
36 uint32_t ih_ep; /* Entry Point Address */
37 uint32_t ih_dcrc; /* Image Data CRC Checksum */
38 uint8_t ih_os; /* Operating System */
39 uint8_t ih_arch; /* CPU architecture */
40 uint8_t ih_type; /* Image Type */
41 uint8_t ih_comp; /* Compression Type */
42 uint8_t ih_name[IH_NMLEN]; /* Image Name */
43 uint8_t sgeih_p[SGE_PRODUCTLEN]; /* sge_Product */
44 uint8_t sgeih_sv[SGE_VERSIONLEN]; /* sge Software Version */
45 uint8_t sgeih_hv[SGE_VERSIONLEN]; /* sge Hardware Version */
46 };
47
48
49 /* default padding size */
50 #define IH_PAD_BYTES (96)
51
52
53 static void usage(char *prog)
54 {
55 fprintf(stderr,
56 "%s -i <input_uimage_file> -o <output_file> -m <model> -h <hardware version> -s <software version>\n",
57 prog);
58 }
59
60 int main(int argc, char *argv[])
61 {
62 struct stat statbuf;
63 u_int8_t *filebuf;
64 int ifd;
65 int ofd;
66 ssize_t rsz;
67 u_int32_t crc_recalc;
68 struct image_header *imgh;
69 int opt;
70 char *infname = NULL;
71 char *outfname = NULL;
72 char *model = NULL;
73 char *hversion = NULL;
74 char *sversion = NULL;
75 int padsz = IH_PAD_BYTES;
76 int ltmp;
77
78 while ((opt = getopt(argc, argv, "i:o:m:h:s:")) != -1) {
79 switch (opt) {
80 case 'i':
81 infname = optarg;
82 break;
83 case 'o':
84 outfname = optarg;
85 break;
86 case 'm':
87 model = optarg;
88 break;
89 case 'h':
90 hversion = optarg;
91 break;
92 case 's':
93 sversion = optarg;
94 break;
95 default:
96 break;
97 }
98 }
99
100 if (!infname || !outfname) {
101 usage(argv[0]);
102 exit(1);
103 }
104
105 ifd = open(infname, O_RDONLY);
106 if (ifd < 0) {
107 fprintf(stderr,
108 "could not open input file. (errno = %d)\n", errno);
109 exit(1);
110 }
111
112 ofd = open(outfname, O_WRONLY | O_CREAT, 0644);
113 if (ofd < 0) {
114 fprintf(stderr,
115 "could not open output file. (errno = %d)\n", errno);
116 exit(1);
117 }
118
119 if (fstat(ifd, &statbuf) < 0) {
120 fprintf(stderr,
121 "could not fstat input file. (errno = %d)\n", errno);
122 exit(1);
123 }
124
125 filebuf = malloc(statbuf.st_size + padsz);
126 if (!filebuf) {
127 fprintf(stderr, "buffer allocation failed\n");
128 exit(1);
129 }
130
131 rsz = read(ifd, filebuf, OrignalHL);
132 if (rsz != OrignalHL) {
133 fprintf(stderr,
134 "could not read input file (errno = %d).\n", errno);
135 exit(1);
136 }
137
138 memset(&(filebuf[OrignalHL]), 0, padsz);
139
140 rsz = read(ifd, &(filebuf[sizeof(*imgh)]),
141 statbuf.st_size - OrignalHL);
142 if (rsz != (int32_t)(statbuf.st_size - OrignalHL)) {
143 fprintf(stderr,
144 "could not read input file (errno = %d).\n", errno);
145 exit(1);
146 }
147
148 imgh = (struct image_header *)filebuf;
149
150 imgh->ih_hcrc = 0;
151
152 strncpy(imgh->sgeih_p, model, sizeof(imgh->sgeih_p));
153 strncpy(imgh->sgeih_sv, sversion, sizeof(imgh->sgeih_sv));
154 strncpy(imgh->sgeih_hv, hversion, sizeof(imgh->sgeih_hv));
155
156 crc_recalc = crc32(0, filebuf, sizeof(*imgh));
157 imgh->ih_hcrc = htonl(crc_recalc);
158
159 rsz = write(ofd, filebuf, statbuf.st_size + padsz);
160 if (rsz != (int32_t)statbuf.st_size + padsz) {
161 fprintf(stderr,
162 "could not write output file (errnor = %d).\n", errno);
163 exit(1);
164 }
165
166 return 0;
167 }