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