| @@ -1,608 +1,612 @@ | | | @@ -1,608 +1,612 @@ |
1 | /* $NetBSD: mkubootimage.c,v 1.27 2019/12/07 12:34:17 wiz Exp $ */ | | 1 | /* $NetBSD: mkubootimage.c,v 1.28 2020/01/01 10:35:10 skrll Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2010 Jared D. McNeill <jmcneill@invisible.ca> | | 4 | * Copyright (c) 2010 Jared D. McNeill <jmcneill@invisible.ca> |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. The name of the author may not be used to endorse or promote products | | 12 | * 2. The name of the author may not be used to endorse or promote products |
13 | * derived from this software without specific prior written permission. | | 13 | * derived from this software without specific prior written permission. |
14 | * | | 14 | * |
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | | 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
20 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | | 20 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | | 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
22 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | | 22 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 | * SUCH DAMAGE. | | 25 | * SUCH DAMAGE. |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | #if HAVE_NBTOOL_CONFIG_H | | 28 | #if HAVE_NBTOOL_CONFIG_H |
29 | #include "nbtool_config.h" | | 29 | #include "nbtool_config.h" |
30 | #endif | | 30 | #endif |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __RCSID("$NetBSD: mkubootimage.c,v 1.27 2019/12/07 12:34:17 wiz Exp $"); | | 33 | __RCSID("$NetBSD: mkubootimage.c,v 1.28 2020/01/01 10:35:10 skrll Exp $"); |
34 | | | 34 | |
35 | #include <sys/mman.h> | | 35 | #include <sys/mman.h> |
36 | #include <sys/stat.h> | | 36 | #include <sys/stat.h> |
37 | #include <sys/endian.h> | | 37 | #include <sys/endian.h> |
38 | #include <sys/param.h> | | 38 | #include <sys/param.h> |
39 | #include <sys/uio.h> | | 39 | #include <sys/uio.h> |
40 | #include <err.h> | | 40 | #include <err.h> |
41 | #include <errno.h> | | 41 | #include <errno.h> |
42 | #include <fcntl.h> | | 42 | #include <fcntl.h> |
43 | #include <inttypes.h> | | 43 | #include <inttypes.h> |
44 | #include <limits.h> | | 44 | #include <limits.h> |
45 | #include <stdint.h> | | 45 | #include <stdint.h> |
46 | #include <stdio.h> | | 46 | #include <stdio.h> |
47 | #include <stdlib.h> | | 47 | #include <stdlib.h> |
48 | #include <string.h> | | 48 | #include <string.h> |
49 | #include <time.h> | | 49 | #include <time.h> |
50 | #include <unistd.h> | | 50 | #include <unistd.h> |
51 | | | 51 | |
52 | #include "uboot.h" | | 52 | #include "uboot.h" |
53 | #include "arm64.h" | | 53 | #include "arm64.h" |
54 | | | 54 | |
55 | #ifndef __arraycount | | 55 | #ifndef __arraycount |
56 | #define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) | | 56 | #define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) |
57 | #endif | | 57 | #endif |
58 | | | 58 | |
59 | enum image_format { | | 59 | enum image_format { |
60 | FMT_UNKNOWN, | | 60 | FMT_UNKNOWN, |
61 | FMT_UIMG, /* Legacy U-Boot image */ | | 61 | FMT_UIMG, /* Legacy U-Boot image */ |
62 | FMT_ARM64, /* Linux ARM64 image (booti) */ | | 62 | FMT_ARM64, /* Linux ARM64 image (booti) */ |
63 | }; | | 63 | }; |
64 | | | 64 | |
65 | extern uint32_t crc32(const void *, size_t); | | 65 | extern uint32_t crc32(const void *, size_t); |
66 | extern uint32_t crc32v(const struct iovec *, int); | | 66 | extern uint32_t crc32v(const struct iovec *, int); |
67 | | | 67 | |
68 | static enum uboot_image_os image_os = IH_OS_NETBSD; | | 68 | static enum uboot_image_os image_os = IH_OS_NETBSD; |
69 | static enum uboot_image_arch image_arch = IH_ARCH_UNKNOWN; | | 69 | static enum uboot_image_arch image_arch = IH_ARCH_UNKNOWN; |
70 | static enum uboot_image_type image_type = IH_TYPE_UNKNOWN; | | 70 | static enum uboot_image_type image_type = IH_TYPE_UNKNOWN; |
71 | static enum uboot_image_comp image_comp = IH_COMP_NONE; | | 71 | static enum uboot_image_comp image_comp = IH_COMP_NONE; |
72 | static uint32_t image_loadaddr = 0; | | 72 | static uint32_t image_loadaddr = 0; |
73 | static uint32_t image_entrypoint = 0; | | 73 | static uint32_t image_entrypoint = 0; |
74 | static char *image_name; | | 74 | static char *image_name; |
75 | static uint32_t image_magic = IH_MAGIC; | | 75 | static uint32_t image_magic = IH_MAGIC; |
76 | static enum image_format image_format = FMT_UIMG; | | 76 | static enum image_format image_format = FMT_UIMG; |
77 | static int update_image = 0; | | 77 | static int update_image = 0; |
78 | | | 78 | |
79 | static const struct uboot_image_format { | | 79 | static const struct uboot_image_format { |
80 | enum image_format format; | | 80 | enum image_format format; |
81 | const char *name; | | 81 | const char *name; |
82 | } uboot_image_format[] = { | | 82 | } uboot_image_format[] = { |
83 | { FMT_UIMG, "uimg" }, | | 83 | { FMT_UIMG, "uimg" }, |
84 | { FMT_ARM64, "arm64" }, | | 84 | { FMT_ARM64, "arm64" }, |
85 | }; | | 85 | }; |
86 | | | 86 | |
87 | static enum image_format | | 87 | static enum image_format |
88 | get_image_format(const char *name) | | 88 | get_image_format(const char *name) |
89 | { | | 89 | { |
90 | unsigned int i; | | 90 | unsigned int i; |
91 | | | 91 | |
92 | for (i = 0; i < __arraycount(uboot_image_format); i++) { | | 92 | for (i = 0; i < __arraycount(uboot_image_format); i++) { |
93 | if (strcmp(uboot_image_format[i].name, name) == 0) | | 93 | if (strcmp(uboot_image_format[i].name, name) == 0) |
94 | return uboot_image_format[i].format; | | 94 | return uboot_image_format[i].format; |
95 | } | | 95 | } |
96 | | | 96 | |
97 | return FMT_UNKNOWN; | | 97 | return FMT_UNKNOWN; |
98 | } | | 98 | } |
99 | | | 99 | |
100 | static const char * | | 100 | static const char * |
101 | get_image_format_name(enum image_format format) | | 101 | get_image_format_name(enum image_format format) |
102 | { | | 102 | { |
103 | unsigned int i; | | 103 | unsigned int i; |
104 | | | 104 | |
105 | for (i = 0; i < __arraycount(uboot_image_format); i++) { | | 105 | for (i = 0; i < __arraycount(uboot_image_format); i++) { |
106 | if (uboot_image_format[i].format == format) | | 106 | if (uboot_image_format[i].format == format) |
107 | return uboot_image_format[i].name; | | 107 | return uboot_image_format[i].name; |
108 | } | | 108 | } |
109 | | | 109 | |
110 | return "Unknown"; | | 110 | return "Unknown"; |
111 | } | | 111 | } |
112 | | | 112 | |
113 | static const struct uboot_os { | | 113 | static const struct uboot_os { |
114 | enum uboot_image_os os; | | 114 | enum uboot_image_os os; |
115 | const char *name; | | 115 | const char *name; |
116 | } uboot_os[] = { | | 116 | } uboot_os[] = { |
117 | { IH_OS_OPENBSD, "openbsd" }, | | 117 | { IH_OS_OPENBSD, "openbsd" }, |
118 | { IH_OS_NETBSD, "netbsd" }, | | 118 | { IH_OS_NETBSD, "netbsd" }, |
119 | { IH_OS_FREEBSD, "freebsd" }, | | 119 | { IH_OS_FREEBSD, "freebsd" }, |
120 | { IH_OS_LINUX, "linux" }, | | 120 | { IH_OS_LINUX, "linux" }, |
121 | }; | | 121 | }; |
122 | | | 122 | |
123 | static enum uboot_image_os | | 123 | static enum uboot_image_os |
124 | get_os(const char *name) | | 124 | get_os(const char *name) |
125 | { | | 125 | { |
126 | unsigned int i; | | 126 | unsigned int i; |
127 | | | 127 | |
128 | for (i = 0; i < __arraycount(uboot_os); i++) { | | 128 | for (i = 0; i < __arraycount(uboot_os); i++) { |
129 | if (strcmp(uboot_os[i].name, name) == 0) | | 129 | if (strcmp(uboot_os[i].name, name) == 0) |
130 | return uboot_os[i].os; | | 130 | return uboot_os[i].os; |
131 | } | | 131 | } |
132 | | | 132 | |
133 | return IH_OS_UNKNOWN; | | 133 | return IH_OS_UNKNOWN; |
134 | } | | 134 | } |
135 | | | 135 | |
136 | static const char * | | 136 | static const char * |
137 | get_os_name(enum uboot_image_os os) | | 137 | get_os_name(enum uboot_image_os os) |
138 | { | | 138 | { |
139 | unsigned int i; | | 139 | unsigned int i; |
140 | | | 140 | |
141 | for (i = 0; i < __arraycount(uboot_os); i++) { | | 141 | for (i = 0; i < __arraycount(uboot_os); i++) { |
142 | if (uboot_os[i].os == os) | | 142 | if (uboot_os[i].os == os) |
143 | return uboot_os[i].name; | | 143 | return uboot_os[i].name; |
144 | } | | 144 | } |
145 | | | 145 | |
146 | return "Unknown"; | | 146 | return "Unknown"; |
147 | } | | 147 | } |
148 | | | 148 | |
149 | static const struct uboot_arch { | | 149 | static const struct uboot_arch { |
150 | enum uboot_image_arch arch; | | 150 | enum uboot_image_arch arch; |
151 | const char *name; | | 151 | const char *name; |
152 | } uboot_arch[] = { | | 152 | } uboot_arch[] = { |
153 | { IH_ARCH_ARM, "arm" }, | | 153 | { IH_ARCH_ARM, "arm" }, |
154 | { IH_ARCH_ARM64, "arm64" }, | | 154 | { IH_ARCH_ARM64, "arm64" }, |
155 | { IH_ARCH_I386, "i386" }, | | 155 | { IH_ARCH_I386, "i386" }, |
156 | { IH_ARCH_MIPS, "mips" }, | | 156 | { IH_ARCH_MIPS, "mips" }, |
157 | { IH_ARCH_MIPS64, "mips64" }, | | 157 | { IH_ARCH_MIPS64, "mips64" }, |
158 | { IH_ARCH_PPC, "powerpc" }, | | 158 | { IH_ARCH_PPC, "powerpc" }, |
159 | { IH_ARCH_OPENRISC, "or1k" }, | | 159 | { IH_ARCH_OPENRISC, "or1k" }, |
160 | { IH_ARCH_SH, "sh" }, | | 160 | { IH_ARCH_SH, "sh" }, |
161 | }; | | 161 | }; |
162 | | | 162 | |
163 | static enum uboot_image_arch | | 163 | static enum uboot_image_arch |
164 | get_arch(const char *name) | | 164 | get_arch(const char *name) |
165 | { | | 165 | { |
166 | unsigned int i; | | 166 | unsigned int i; |
167 | | | 167 | |
168 | for (i = 0; i < __arraycount(uboot_arch); i++) { | | 168 | for (i = 0; i < __arraycount(uboot_arch); i++) { |
169 | if (strcmp(uboot_arch[i].name, name) == 0) | | 169 | if (strcmp(uboot_arch[i].name, name) == 0) |
170 | return uboot_arch[i].arch; | | 170 | return uboot_arch[i].arch; |
171 | } | | 171 | } |
172 | | | 172 | |
173 | return IH_ARCH_UNKNOWN; | | 173 | return IH_ARCH_UNKNOWN; |
174 | } | | 174 | } |
175 | | | 175 | |
176 | static const char * | | 176 | static const char * |
177 | get_arch_name(enum uboot_image_arch arch) | | 177 | get_arch_name(enum uboot_image_arch arch) |
178 | { | | 178 | { |
179 | unsigned int i; | | 179 | unsigned int i; |
180 | | | 180 | |
181 | for (i = 0; i < __arraycount(uboot_arch); i++) { | | 181 | for (i = 0; i < __arraycount(uboot_arch); i++) { |
182 | if (uboot_arch[i].arch == arch) | | 182 | if (uboot_arch[i].arch == arch) |
183 | return uboot_arch[i].name; | | 183 | return uboot_arch[i].name; |
184 | } | | 184 | } |
185 | | | 185 | |
186 | return "Unknown"; | | 186 | return "Unknown"; |
187 | } | | 187 | } |
188 | | | 188 | |
189 | static const struct uboot_type { | | 189 | static const struct uboot_type { |
190 | enum uboot_image_type type; | | 190 | enum uboot_image_type type; |
191 | const char *name; | | 191 | const char *name; |
192 | } uboot_type[] = { | | 192 | } uboot_type[] = { |
193 | { IH_TYPE_STANDALONE, "standalone" }, | | 193 | { IH_TYPE_STANDALONE, "standalone" }, |
194 | { IH_TYPE_KERNEL, "kernel" }, | | 194 | { IH_TYPE_KERNEL, "kernel" }, |
195 | { IH_TYPE_KERNEL_NOLOAD, "kernel_noload" }, | | 195 | { IH_TYPE_KERNEL_NOLOAD, "kernel_noload" }, |
196 | { IH_TYPE_RAMDISK, "ramdisk" }, | | 196 | { IH_TYPE_RAMDISK, "ramdisk" }, |
197 | { IH_TYPE_FILESYSTEM, "fs" }, | | 197 | { IH_TYPE_FILESYSTEM, "fs" }, |
198 | { IH_TYPE_SCRIPT, "script" }, | | 198 | { IH_TYPE_SCRIPT, "script" }, |
199 | }; | | 199 | }; |
200 | | | 200 | |
201 | static enum uboot_image_type | | 201 | static enum uboot_image_type |
202 | get_type(const char *name) | | 202 | get_type(const char *name) |
203 | { | | 203 | { |
204 | unsigned int i; | | 204 | unsigned int i; |
205 | | | 205 | |
206 | for (i = 0; i < __arraycount(uboot_type); i++) { | | 206 | for (i = 0; i < __arraycount(uboot_type); i++) { |
207 | if (strcmp(uboot_type[i].name, name) == 0) | | 207 | if (strcmp(uboot_type[i].name, name) == 0) |
208 | return uboot_type[i].type; | | 208 | return uboot_type[i].type; |
209 | } | | 209 | } |
210 | | | 210 | |
211 | return IH_TYPE_UNKNOWN; | | 211 | return IH_TYPE_UNKNOWN; |
212 | } | | 212 | } |
213 | | | 213 | |
214 | static const char * | | 214 | static const char * |
215 | get_type_name(enum uboot_image_type type) | | 215 | get_type_name(enum uboot_image_type type) |
216 | { | | 216 | { |
217 | unsigned int i; | | 217 | unsigned int i; |
218 | | | 218 | |
219 | for (i = 0; i < __arraycount(uboot_type); i++) { | | 219 | for (i = 0; i < __arraycount(uboot_type); i++) { |
220 | if (uboot_type[i].type == type) | | 220 | if (uboot_type[i].type == type) |
221 | return uboot_type[i].name; | | 221 | return uboot_type[i].name; |
222 | } | | 222 | } |
223 | | | 223 | |
224 | return "Unknown"; | | 224 | return "Unknown"; |
225 | } | | 225 | } |
226 | | | 226 | |
227 | static const struct uboot_comp { | | 227 | static const struct uboot_comp { |
228 | enum uboot_image_comp comp; | | 228 | enum uboot_image_comp comp; |
229 | const char *name; | | 229 | const char *name; |
230 | } uboot_comp[] = { | | 230 | } uboot_comp[] = { |
231 | { IH_COMP_NONE, "none" }, | | 231 | { IH_COMP_NONE, "none" }, |
232 | { IH_COMP_GZIP, "gz" }, | | 232 | { IH_COMP_GZIP, "gz" }, |
233 | { IH_COMP_BZIP2, "bz2" }, | | 233 | { IH_COMP_BZIP2, "bz2" }, |
234 | { IH_COMP_LZMA, "lzma" }, | | 234 | { IH_COMP_LZMA, "lzma" }, |
235 | { IH_COMP_LZO, "lzo" }, | | 235 | { IH_COMP_LZO, "lzo" }, |
236 | }; | | 236 | }; |
237 | | | 237 | |
238 | static enum uboot_image_comp | | 238 | static enum uboot_image_comp |
239 | get_comp(const char *name) | | 239 | get_comp(const char *name) |
240 | { | | 240 | { |
241 | unsigned int i; | | 241 | unsigned int i; |
242 | | | 242 | |
243 | for (i = 0; i < __arraycount(uboot_comp); i++) { | | 243 | for (i = 0; i < __arraycount(uboot_comp); i++) { |
244 | if (strcmp(uboot_comp[i].name, name) == 0) | | 244 | if (strcmp(uboot_comp[i].name, name) == 0) |
245 | return uboot_comp[i].comp; | | 245 | return uboot_comp[i].comp; |
246 | } | | 246 | } |
247 | | | 247 | |
248 | return IH_COMP_NONE; | | 248 | return IH_COMP_NONE; |
249 | } | | 249 | } |
250 | | | 250 | |
251 | static const char * | | 251 | static const char * |
252 | get_comp_name(enum uboot_image_comp comp) | | 252 | get_comp_name(enum uboot_image_comp comp) |
253 | { | | 253 | { |
254 | unsigned int i; | | 254 | unsigned int i; |
255 | | | 255 | |
256 | for (i = 0; i < __arraycount(uboot_comp); i++) { | | 256 | for (i = 0; i < __arraycount(uboot_comp); i++) { |
257 | if (uboot_comp[i].comp == comp) | | 257 | if (uboot_comp[i].comp == comp) |
258 | return uboot_comp[i].name; | | 258 | return uboot_comp[i].name; |
259 | } | | 259 | } |
260 | | | 260 | |
261 | return "Unknown"; | | 261 | return "Unknown"; |
262 | } | | 262 | } |
263 | | | 263 | |
264 | __dead static void | | 264 | __dead static void |
265 | usage(void) | | 265 | usage(void) |
266 | { | | 266 | { |
267 | fprintf(stderr, "usage: mkubootimage [-hu] -A " | | 267 | fprintf(stderr, "usage: mkubootimage [-hu] -A " |
268 | "<arm|arm64|i386|mips|mips64|or1k|powerpc|sh> -a address\n"); | | 268 | "<arm|arm64|i386|mips|mips64|or1k|powerpc|sh> -a address\n"); |
269 | fprintf(stderr, "\t-C <bz2|gz|lzma|lzo|none> [-E address] [-e address]\n"); | | 269 | fprintf(stderr, "\t-C <bz2|gz|lzma|lzo|none> [-E address] [-e address]\n"); |
270 | fprintf(stderr, "\t[-f <arm64|uimg>] [-m magic] -n image -O <freebsd|linux|netbsd|openbsd>\n"); | | 270 | fprintf(stderr, "\t[-f <arm64|uimg>] [-m magic] -n image -O <freebsd|linux|netbsd|openbsd>\n"); |
271 | fprintf(stderr, "\t-T <fs|kernel|kernel_noload|ramdisk|script|standalone>\n"); | | 271 | fprintf(stderr, "\t-T <fs|kernel|kernel_noload|ramdisk|script|standalone>\n"); |
272 | fprintf(stderr, "\tsource destination\n"); | | 272 | fprintf(stderr, "\tsource destination\n"); |
273 | | | 273 | |
274 | exit(EXIT_FAILURE); | | 274 | exit(EXIT_FAILURE); |
275 | } | | 275 | } |
276 | | | 276 | |
277 | static void | | 277 | static void |
278 | dump_header_uimg(struct uboot_image_header *hdr) | | 278 | dump_header_uimg(struct uboot_image_header *hdr) |
279 | { | | 279 | { |
280 | time_t tm = ntohl(hdr->ih_time); | | 280 | time_t tm = ntohl(hdr->ih_time); |
281 | | | 281 | |
282 | printf(" magic: 0x%08x\n", ntohl(hdr->ih_magic)); | | 282 | printf(" magic: 0x%08x\n", ntohl(hdr->ih_magic)); |
283 | printf(" time: %s", ctime(&tm)); | | 283 | printf(" time: %s", ctime(&tm)); |
284 | printf(" size: %u\n", ntohl(hdr->ih_size)); | | 284 | printf(" size: %u\n", ntohl(hdr->ih_size)); |
285 | printf(" load addr: 0x%08x\n", ntohl(hdr->ih_load)); | | 285 | printf(" load addr: 0x%08x\n", ntohl(hdr->ih_load)); |
286 | printf(" entry point: 0x%08x\n", ntohl(hdr->ih_ep)); | | 286 | printf(" entry point: 0x%08x\n", ntohl(hdr->ih_ep)); |
287 | printf(" data crc: 0x%08x\n", ntohl(hdr->ih_dcrc)); | | 287 | printf(" data crc: 0x%08x\n", ntohl(hdr->ih_dcrc)); |
288 | printf(" os: %d (%s)\n", hdr->ih_os, | | 288 | printf(" os: %d (%s)\n", hdr->ih_os, |
289 | get_os_name(hdr->ih_os)); | | 289 | get_os_name(hdr->ih_os)); |
290 | printf(" arch: %d (%s)\n", hdr->ih_arch, | | 290 | printf(" arch: %d (%s)\n", hdr->ih_arch, |
291 | get_arch_name(hdr->ih_arch)); | | 291 | get_arch_name(hdr->ih_arch)); |
292 | printf(" type: %d (%s)\n", hdr->ih_type, | | 292 | printf(" type: %d (%s)\n", hdr->ih_type, |
293 | get_type_name(hdr->ih_type)); | | 293 | get_type_name(hdr->ih_type)); |
294 | printf(" comp: %d (%s)\n", hdr->ih_comp, | | 294 | printf(" comp: %d (%s)\n", hdr->ih_comp, |
295 | get_comp_name(hdr->ih_comp)); | | 295 | get_comp_name(hdr->ih_comp)); |
296 | printf(" name: %s\n", hdr->ih_name); | | 296 | printf(" name: %s\n", hdr->ih_name); |
297 | printf(" header crc: 0x%08x\n", hdr->ih_hcrc); | | 297 | printf(" header crc: 0x%08x\n", hdr->ih_hcrc); |
298 | } | | 298 | } |
299 | | | 299 | |
300 | static int | | 300 | static int |
301 | generate_header_uimg(struct uboot_image_header *hdr, int kernel_fd) | | 301 | generate_header_uimg(struct uboot_image_header *hdr, int kernel_fd) |
302 | { | | 302 | { |
303 | uint8_t *p; | | 303 | uint8_t *p; |
304 | struct stat st; | | 304 | struct stat st; |
305 | uint32_t crc, dsize, size_buf[2]; | | 305 | uint32_t crc, dsize, size_buf[2]; |
306 | int error; | | 306 | int error; |
307 | | | 307 | |
308 | error = fstat(kernel_fd, &st); | | 308 | error = fstat(kernel_fd, &st); |
309 | if (error == -1) { | | 309 | if (error == -1) { |
310 | perror("stat"); | | 310 | perror("stat"); |
311 | return errno; | | 311 | return errno; |
312 | } | | 312 | } |
313 | | | 313 | |
314 | if (st.st_size + sizeof(*hdr) > UINT32_MAX) { | | 314 | if (st.st_size + sizeof(*hdr) > UINT32_MAX) { |
315 | fprintf(stderr, "fatal: kernel too big\n"); | | 315 | fprintf(stderr, "fatal: kernel too big\n"); |
316 | return EINVAL; | | 316 | return EINVAL; |
317 | } | | 317 | } |
318 | | | 318 | |
319 | p = mmap(0, st.st_size, PROT_READ, MAP_FILE|MAP_SHARED, kernel_fd, 0); | | 319 | p = mmap(0, st.st_size, PROT_READ, MAP_FILE|MAP_SHARED, kernel_fd, 0); |
320 | if (p == MAP_FAILED) { | | 320 | if (p == MAP_FAILED) { |
321 | perror("mmap kernel"); | | 321 | perror("mmap kernel"); |
322 | return EINVAL; | | 322 | return EINVAL; |
323 | } | | 323 | } |
324 | if (image_type == IH_TYPE_SCRIPT) { | | 324 | if (image_type == IH_TYPE_SCRIPT) { |
325 | struct iovec iov[3]; | | 325 | struct iovec iov[3]; |
326 | dsize = st.st_size + (sizeof(uint32_t) * 2); | | 326 | dsize = st.st_size + (sizeof(uint32_t) * 2); |
327 | size_buf[0] = htonl(st.st_size); | | 327 | size_buf[0] = htonl(st.st_size); |
328 | size_buf[1] = htonl(0); | | 328 | size_buf[1] = htonl(0); |
329 | iov[0].iov_base = &size_buf[0]; | | 329 | iov[0].iov_base = &size_buf[0]; |
330 | iov[0].iov_len = sizeof(size_buf[0]); | | 330 | iov[0].iov_len = sizeof(size_buf[0]); |
331 | iov[1].iov_base = &size_buf[1]; | | 331 | iov[1].iov_base = &size_buf[1]; |
332 | iov[1].iov_len = sizeof(size_buf[1]); | | 332 | iov[1].iov_len = sizeof(size_buf[1]); |
333 | iov[2].iov_base = p; | | 333 | iov[2].iov_base = p; |
334 | iov[2].iov_len = st.st_size; | | 334 | iov[2].iov_len = st.st_size; |
335 | crc = crc32v(iov, 3); | | 335 | crc = crc32v(iov, 3); |
336 | } else { | | 336 | } else { |
337 | dsize = st.st_size; | | 337 | dsize = update_image ? |
| | | 338 | st.st_size - sizeof(*hdr) : st.st_size; |
338 | crc = crc32(p, st.st_size); | | 339 | crc = crc32(p, st.st_size); |
339 | } | | 340 | } |
340 | munmap(p, st.st_size); | | 341 | munmap(p, st.st_size); |
341 | | | 342 | |
342 | memset(hdr, 0, sizeof(*hdr)); | | 343 | memset(hdr, 0, sizeof(*hdr)); |
343 | hdr->ih_magic = htonl(image_magic); | | 344 | hdr->ih_magic = htonl(image_magic); |
344 | hdr->ih_time = htonl(st.st_mtime); | | 345 | hdr->ih_time = htonl(st.st_mtime); |
345 | hdr->ih_size = htonl(dsize); | | 346 | hdr->ih_size = htonl(dsize); |
346 | hdr->ih_load = htonl(image_loadaddr); | | 347 | hdr->ih_load = htonl(image_loadaddr); |
347 | hdr->ih_ep = htonl(image_entrypoint); | | 348 | hdr->ih_ep = htonl(image_entrypoint); |
348 | hdr->ih_dcrc = htonl(crc); | | 349 | hdr->ih_dcrc = htonl(crc); |
349 | hdr->ih_os = image_os; | | 350 | hdr->ih_os = image_os; |
350 | hdr->ih_arch = image_arch; | | 351 | hdr->ih_arch = image_arch; |
351 | hdr->ih_type = image_type; | | 352 | hdr->ih_type = image_type; |
352 | hdr->ih_comp = image_comp; | | 353 | hdr->ih_comp = image_comp; |
353 | strlcpy((char *)hdr->ih_name, image_name, sizeof(hdr->ih_name)); | | 354 | strlcpy((char *)hdr->ih_name, image_name, sizeof(hdr->ih_name)); |
354 | crc = crc32((void *)hdr, sizeof(*hdr)); | | 355 | crc = crc32((void *)hdr, sizeof(*hdr)); |
355 | hdr->ih_hcrc = htonl(crc); | | 356 | hdr->ih_hcrc = htonl(crc); |
356 | | | 357 | |
357 | dump_header_uimg(hdr); | | 358 | dump_header_uimg(hdr); |
358 | | | 359 | |
359 | return 0; | | 360 | return 0; |
360 | } | | 361 | } |
361 | | | 362 | |
362 | static void | | 363 | static void |
363 | dump_header_arm64(struct arm64_image_header *hdr) | | 364 | dump_header_arm64(struct arm64_image_header *hdr) |
364 | { | | 365 | { |
365 | printf(" magic: 0x%" PRIx32 "\n", le32toh(hdr->magic)); | | 366 | printf(" magic: 0x%" PRIx32 "\n", le32toh(hdr->magic)); |
366 | printf(" text offset: 0x%" PRIx64 "\n", le64toh(hdr->text_offset)); | | 367 | printf(" text offset: 0x%" PRIx64 "\n", le64toh(hdr->text_offset)); |
367 | printf(" image size: %" PRIu64 "\n", le64toh(hdr->image_size)); | | 368 | printf(" image size: %" PRIu64 "\n", le64toh(hdr->image_size)); |
368 | printf(" flags: 0x%" PRIx64 "\n", le64toh(hdr->flags)); | | 369 | printf(" flags: 0x%" PRIx64 "\n", le64toh(hdr->flags)); |
369 | } | | 370 | } |
370 | | | 371 | |
371 | static int | | 372 | static int |
372 | generate_header_arm64(struct arm64_image_header *hdr, int kernel_fd) | | 373 | generate_header_arm64(struct arm64_image_header *hdr, int kernel_fd) |
373 | { | | 374 | { |
374 | struct stat st; | | 375 | struct stat st; |
375 | uint32_t flags; | | 376 | uint32_t flags; |
376 | int error; | | 377 | int error; |
377 | | | 378 | |
378 | error = fstat(kernel_fd, &st); | | 379 | error = fstat(kernel_fd, &st); |
379 | if (error == -1) { | | 380 | if (error == -1) { |
380 | perror("stat"); | | 381 | perror("stat"); |
381 | return errno; | | 382 | return errno; |
382 | } | | 383 | } |
383 | | | 384 | |
384 | flags = 0; | | 385 | flags = 0; |
385 | flags |= ARM64_FLAGS_PAGE_SIZE_4K; | | 386 | flags |= ARM64_FLAGS_PAGE_SIZE_4K; |
386 | #if 0 | | 387 | #if 0 |
387 | flags |= ARM64_FLAGS_PHYS_PLACEMENT_ANY; | | 388 | flags |= ARM64_FLAGS_PHYS_PLACEMENT_ANY; |
388 | #endif | | 389 | #endif |
389 | | | 390 | |
| | | 391 | const uint64_t dsize = update_image ? |
| | | 392 | st.st_size - sizeof(*hdr) : st.st_size; |
| | | 393 | |
390 | memset(hdr, 0, sizeof(*hdr)); | | 394 | memset(hdr, 0, sizeof(*hdr)); |
391 | hdr->code0 = htole32(ARM64_CODE0); | | 395 | hdr->code0 = htole32(ARM64_CODE0); |
392 | hdr->text_offset = htole64(image_entrypoint); | | 396 | hdr->text_offset = htole64(image_entrypoint); |
393 | hdr->image_size = htole64(st.st_size + sizeof(*hdr)); | | 397 | hdr->image_size = htole64(dsize); |
394 | hdr->flags = htole32(flags); | | 398 | hdr->flags = htole32(flags); |
395 | hdr->magic = htole32(ARM64_MAGIC); | | 399 | hdr->magic = htole32(ARM64_MAGIC); |
396 | | | 400 | |
397 | dump_header_arm64(hdr); | | 401 | dump_header_arm64(hdr); |
398 | | | 402 | |
399 | return 0; | | 403 | return 0; |
400 | } | | 404 | } |
401 | | | 405 | |
402 | static int | | 406 | static int |
403 | write_image(void *hdr, size_t hdrlen, int kernel_fd, int image_fd) | | 407 | write_image(void *hdr, size_t hdrlen, int kernel_fd, int image_fd) |
404 | { | | 408 | { |
405 | uint8_t buf[4096]; | | 409 | uint8_t buf[4096]; |
406 | ssize_t rlen, wlen; | | 410 | ssize_t rlen, wlen; |
407 | struct stat st; | | 411 | struct stat st; |
408 | uint32_t size_buf[2]; | | 412 | uint32_t size_buf[2]; |
409 | int error; | | 413 | int error; |
410 | | | 414 | |
411 | error = fstat(kernel_fd, &st); | | 415 | error = fstat(kernel_fd, &st); |
412 | if (error == -1) { | | 416 | if (error == -1) { |
413 | perror("stat"); | | 417 | perror("stat"); |
414 | return errno; | | 418 | return errno; |
415 | } | | 419 | } |
416 | | | 420 | |
417 | wlen = write(image_fd, hdr, hdrlen); | | 421 | wlen = write(image_fd, hdr, hdrlen); |
418 | if (wlen != (ssize_t)hdrlen) { | | 422 | if (wlen != (ssize_t)hdrlen) { |
419 | perror("short write"); | | 423 | perror("short write"); |
420 | return errno; | | 424 | return errno; |
421 | } | | 425 | } |
422 | | | 426 | |
423 | if (image_type == IH_TYPE_SCRIPT) { | | 427 | if (image_type == IH_TYPE_SCRIPT) { |
424 | size_buf[0] = htonl(st.st_size); | | 428 | size_buf[0] = htonl(st.st_size); |
425 | size_buf[1] = htonl(0); | | 429 | size_buf[1] = htonl(0); |
426 | wlen = write(image_fd, &size_buf, sizeof(size_buf)); | | 430 | wlen = write(image_fd, &size_buf, sizeof(size_buf)); |
427 | if (wlen != sizeof(size_buf)) { | | 431 | if (wlen != sizeof(size_buf)) { |
428 | perror("short write"); | | 432 | perror("short write"); |
429 | return errno; | | 433 | return errno; |
430 | } | | 434 | } |
431 | } | | 435 | } |
432 | | | 436 | |
433 | if (update_image) { | | 437 | if (update_image) { |
434 | if (lseek(kernel_fd, hdrlen, SEEK_SET) != (off_t)hdrlen) { | | 438 | if (lseek(kernel_fd, hdrlen, SEEK_SET) != (off_t)hdrlen) { |
435 | perror("seek failed"); | | 439 | perror("seek failed"); |
436 | return errno; | | 440 | return errno; |
437 | } | | 441 | } |
438 | } | | 442 | } |
439 | | | 443 | |
440 | while ((rlen = read(kernel_fd, buf, sizeof(buf))) > 0) { | | 444 | while ((rlen = read(kernel_fd, buf, sizeof(buf))) > 0) { |
441 | wlen = write(image_fd, buf, rlen); | | 445 | wlen = write(image_fd, buf, rlen); |
442 | if (wlen != rlen) { | | 446 | if (wlen != rlen) { |
443 | perror("short write"); | | 447 | perror("short write"); |
444 | return errno; | | 448 | return errno; |
445 | } | | 449 | } |
446 | } | | 450 | } |
447 | | | 451 | |
448 | return 0; | | 452 | return 0; |
449 | } | | 453 | } |
450 | | | 454 | |
451 | int | | 455 | int |
452 | main(int argc, char *argv[]) | | 456 | main(int argc, char *argv[]) |
453 | { | | 457 | { |
454 | struct uboot_image_header hdr_uimg; | | 458 | struct uboot_image_header hdr_uimg; |
455 | struct arm64_image_header hdr_arm64; | | 459 | struct arm64_image_header hdr_arm64; |
456 | const char *src, *dest; | | 460 | const char *src, *dest; |
457 | char *ep; | | 461 | char *ep; |
458 | int kernel_fd, image_fd; | | 462 | int kernel_fd, image_fd; |
459 | int ch; | | 463 | int ch; |
460 | unsigned long long num; | | 464 | unsigned long long num; |
461 | | | 465 | |
462 | while ((ch = getopt(argc, argv, "A:C:E:O:T:a:e:f:hm:n:u")) != -1) { | | 466 | while ((ch = getopt(argc, argv, "A:C:E:O:T:a:e:f:hm:n:u")) != -1) { |
463 | switch (ch) { | | 467 | switch (ch) { |
464 | case 'A': /* arch */ | | 468 | case 'A': /* arch */ |
465 | image_arch = get_arch(optarg); | | 469 | image_arch = get_arch(optarg); |
466 | break; | | 470 | break; |
467 | case 'C': /* comp */ | | 471 | case 'C': /* comp */ |
468 | image_comp = get_comp(optarg); | | 472 | image_comp = get_comp(optarg); |
469 | break; | | 473 | break; |
470 | case 'O': /* os */ | | 474 | case 'O': /* os */ |
471 | image_os = get_os(optarg); | | 475 | image_os = get_os(optarg); |
472 | break; | | 476 | break; |
473 | case 'T': /* type */ | | 477 | case 'T': /* type */ |
474 | image_type = get_type(optarg); | | 478 | image_type = get_type(optarg); |
475 | break; | | 479 | break; |
476 | case 'a': /* addr */ | | 480 | case 'a': /* addr */ |
477 | errno = 0; | | 481 | errno = 0; |
478 | num = strtoull(optarg, &ep, 0); | | 482 | num = strtoull(optarg, &ep, 0); |
479 | if (*ep != '\0' || (errno == ERANGE && | | 483 | if (*ep != '\0' || (errno == ERANGE && |
480 | (num == ULLONG_MAX || num == 0)) || | | 484 | (num == ULLONG_MAX || num == 0)) || |
481 | ((signed long long)num != (int32_t)num && | | 485 | ((signed long long)num != (int32_t)num && |
482 | num != (uint32_t)num)) | | 486 | num != (uint32_t)num)) |
483 | errx(1, "illegal number -- %s", optarg); | | 487 | errx(1, "illegal number -- %s", optarg); |
484 | image_loadaddr = (uint32_t)num; | | 488 | image_loadaddr = (uint32_t)num; |
485 | break; | | 489 | break; |
486 | case 'E': /* ep (byte swapped) */ | | 490 | case 'E': /* ep (byte swapped) */ |
487 | case 'e': /* ep */ | | 491 | case 'e': /* ep */ |
488 | errno = 0; | | 492 | errno = 0; |
489 | num = strtoull(optarg, &ep, 0); | | 493 | num = strtoull(optarg, &ep, 0); |
490 | if (*ep != '\0' || (errno == ERANGE && | | 494 | if (*ep != '\0' || (errno == ERANGE && |
491 | (num == ULLONG_MAX || num == 0)) || | | 495 | (num == ULLONG_MAX || num == 0)) || |
492 | ((signed long long)num != (int32_t)num && | | 496 | ((signed long long)num != (int32_t)num && |
493 | num != (uint32_t)num)) | | 497 | num != (uint32_t)num)) |
494 | errx(1, "illegal number -- %s", optarg); | | 498 | errx(1, "illegal number -- %s", optarg); |
495 | image_entrypoint = (uint32_t)num; | | 499 | image_entrypoint = (uint32_t)num; |
496 | if (ch == 'E') | | 500 | if (ch == 'E') |
497 | image_entrypoint = bswap32(image_entrypoint); | | 501 | image_entrypoint = bswap32(image_entrypoint); |
498 | break; | | 502 | break; |
499 | case 'f': /* image format */ | | 503 | case 'f': /* image format */ |
500 | image_format = get_image_format(optarg); | | 504 | image_format = get_image_format(optarg); |
501 | break; | | 505 | break; |
502 | case 'm': /* magic */ | | 506 | case 'm': /* magic */ |
503 | errno = 0; | | 507 | errno = 0; |
504 | num = strtoul(optarg, &ep, 0); | | 508 | num = strtoul(optarg, &ep, 0); |
505 | if (*ep != '\0' || (errno == ERANGE && | | 509 | if (*ep != '\0' || (errno == ERANGE && |
506 | (num == ULONG_MAX || num == 0))) | | 510 | (num == ULONG_MAX || num == 0))) |
507 | errx(1, "illegal number -- %s", optarg); | | 511 | errx(1, "illegal number -- %s", optarg); |
508 | image_magic = (uint32_t)num; | | 512 | image_magic = (uint32_t)num; |
509 | break; | | 513 | break; |
510 | case 'n': /* name */ | | 514 | case 'n': /* name */ |
511 | image_name = strdup(optarg); | | 515 | image_name = strdup(optarg); |
512 | break; | | 516 | break; |
513 | case 'u': /* update image */ | | 517 | case 'u': /* update image */ |
514 | update_image = 1; | | 518 | update_image = 1; |
515 | break; | | 519 | break; |
516 | case 'h': | | 520 | case 'h': |
517 | default: | | 521 | default: |
518 | usage(); | | 522 | usage(); |
519 | /* NOTREACHED */ | | 523 | /* NOTREACHED */ |
520 | } | | 524 | } |
521 | } | | 525 | } |
522 | argc -= optind; | | 526 | argc -= optind; |
523 | argv += optind; | | 527 | argv += optind; |
524 | | | 528 | |
525 | if (argc != 2) | | 529 | if (argc != 2) |
526 | usage(); | | 530 | usage(); |
527 | | | 531 | |
528 | if (image_entrypoint == 0) | | 532 | if (image_entrypoint == 0) |
529 | image_entrypoint = image_loadaddr; | | 533 | image_entrypoint = image_loadaddr; |
530 | | | 534 | |
531 | switch (image_format) { | | 535 | switch (image_format) { |
532 | case FMT_UIMG: | | 536 | case FMT_UIMG: |
533 | if (image_arch == IH_ARCH_UNKNOWN || | | 537 | if (image_arch == IH_ARCH_UNKNOWN || |
534 | image_type == IH_TYPE_UNKNOWN || | | 538 | image_type == IH_TYPE_UNKNOWN || |
535 | image_name == NULL) | | 539 | image_name == NULL) |
536 | usage(); | | 540 | usage(); |
537 | /* NOTREACHED */ | | 541 | /* NOTREACHED */ |
538 | | | 542 | |
539 | switch (image_type) { | | 543 | switch (image_type) { |
540 | case IH_TYPE_SCRIPT: | | 544 | case IH_TYPE_SCRIPT: |
541 | case IH_TYPE_RAMDISK: | | 545 | case IH_TYPE_RAMDISK: |
542 | case IH_TYPE_KERNEL_NOLOAD: | | 546 | case IH_TYPE_KERNEL_NOLOAD: |
543 | break; | | 547 | break; |
544 | default: | | 548 | default: |
545 | if (image_loadaddr == 0) | | 549 | if (image_loadaddr == 0) |
546 | usage(); | | 550 | usage(); |
547 | /* NOTREACHED */ | | 551 | /* NOTREACHED */ |
548 | break; | | 552 | break; |
549 | } | | 553 | } |
550 | break; | | 554 | break; |
551 | | | 555 | |
552 | case FMT_ARM64: | | 556 | case FMT_ARM64: |
553 | if (image_arch != IH_ARCH_UNKNOWN && | | 557 | if (image_arch != IH_ARCH_UNKNOWN && |
554 | image_arch != IH_ARCH_ARM64) | | 558 | image_arch != IH_ARCH_ARM64) |
555 | usage(); | | 559 | usage(); |
556 | /* NOTREACHED */ | | 560 | /* NOTREACHED */ |
557 | | | 561 | |
558 | break; | | 562 | break; |
559 | | | 563 | |
560 | default: | | 564 | default: |
561 | usage(); | | 565 | usage(); |
562 | /* NOTREACHED */ | | 566 | /* NOTREACHED */ |
563 | } | | 567 | } |
564 | | | 568 | |
565 | src = argv[0]; | | 569 | src = argv[0]; |
566 | dest = argv[1]; | | 570 | dest = argv[1]; |
567 | | | 571 | |
568 | kernel_fd = open(src, O_RDONLY); | | 572 | kernel_fd = open(src, O_RDONLY); |
569 | if (kernel_fd == -1) { | | 573 | if (kernel_fd == -1) { |
570 | perror("open kernel"); | | 574 | perror("open kernel"); |
571 | return EXIT_FAILURE; | | 575 | return EXIT_FAILURE; |
572 | } | | 576 | } |
573 | image_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0666); | | 577 | image_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0666); |
574 | if (image_fd == -1) { | | 578 | if (image_fd == -1) { |
575 | perror("open image"); | | 579 | perror("open image"); |
576 | return EXIT_FAILURE; | | 580 | return EXIT_FAILURE; |
577 | } | | 581 | } |
578 | | | 582 | |
579 | printf(" image type: %s\n", get_image_format_name(image_format)); | | 583 | printf(" image type: %s\n", get_image_format_name(image_format)); |
580 | | | 584 | |
581 | switch (image_format) { | | 585 | switch (image_format) { |
582 | case FMT_UIMG: | | 586 | case FMT_UIMG: |
583 | if (generate_header_uimg(&hdr_uimg, kernel_fd) != 0) | | 587 | if (generate_header_uimg(&hdr_uimg, kernel_fd) != 0) |
584 | return EXIT_FAILURE; | | 588 | return EXIT_FAILURE; |
585 | | | 589 | |
586 | if (write_image(&hdr_uimg, sizeof(hdr_uimg), | | 590 | if (write_image(&hdr_uimg, sizeof(hdr_uimg), |
587 | kernel_fd, image_fd) != 0) | | 591 | kernel_fd, image_fd) != 0) |
588 | return EXIT_FAILURE; | | 592 | return EXIT_FAILURE; |
589 | | | 593 | |
590 | break; | | 594 | break; |
591 | case FMT_ARM64: | | 595 | case FMT_ARM64: |
592 | if (generate_header_arm64(&hdr_arm64, kernel_fd) != 0) | | 596 | if (generate_header_arm64(&hdr_arm64, kernel_fd) != 0) |
593 | return EXIT_FAILURE; | | 597 | return EXIT_FAILURE; |
594 | | | 598 | |
595 | if (write_image(&hdr_arm64, sizeof(hdr_arm64), | | 599 | if (write_image(&hdr_arm64, sizeof(hdr_arm64), |
596 | kernel_fd, image_fd) != 0) | | 600 | kernel_fd, image_fd) != 0) |
597 | return EXIT_FAILURE; | | 601 | return EXIT_FAILURE; |
598 | | | 602 | |
599 | break; | | 603 | break; |
600 | default: | | 604 | default: |
601 | break; | | 605 | break; |
602 | } | | 606 | } |
603 | | | 607 | |
604 | close(image_fd); | | 608 | close(image_fd); |
605 | close(kernel_fd); | | 609 | close(kernel_fd); |
606 | | | 610 | |
607 | return EXIT_SUCCESS; | | 611 | return EXIT_SUCCESS; |
608 | } | | 612 | } |