1 // SPDX-License-Identifier: GPL-2.0-or-later OR MIT
3 * Luxul's firmware container format
5 * Copyright 2020 Legrand AV Inc.
21 #if __BYTE_ORDER == __BIG_ENDIAN
22 #define cpu_to_le32(x) bswap_32(x)
23 #define cpu_to_le16(x) bswap_16(x)
24 #define le32_to_cpu(x) bswap_32(x)
25 #define le16_to_cpu(x) bswap_16(x)
26 #elif __BYTE_ORDER == __LITTLE_ENDIAN
27 #define cpu_to_le32(x) (x)
28 #define cpu_to_le16(x) (x)
29 #define le32_to_cpu(x) (x)
30 #define le16_to_cpu(x) (x)
35 __typeof__ (a) _a = (a); \
36 __typeof__ (b) _b = (b); \
42 __typeof__ (a) _a = (a); \
43 __typeof__ (b) _b = (b); \
47 #define LXL_FLAGS_VENDOR_LUXUL 0x00000001
50 char magic
[4]; /* "LXL#" */
63 static uint32_t lxlfw_hdr_len(uint32_t version
)
67 return offsetof(struct lxl_hdr
, v0_end
);
69 return offsetof(struct lxl_hdr
, v1_end
);
71 return offsetof(struct lxl_hdr
, v2_end
);
73 fprintf(stderr
, "Unsupported version %d\n", version
);
78 /**************************************************
80 **************************************************/
82 static int lxlfw_info(int argc
, char **argv
) {
93 fprintf(stderr
, "Missing <file> argument\n");
98 lxl
= fopen(argv
[2], "r");
100 fprintf(stderr
, "Could not open \"%s\" file\n", argv
[2]);
105 bytes
= fread(&hdr
, 1, sizeof(hdr
), lxl
);
106 if (bytes
< offsetof(struct lxl_hdr
, v0_end
)) {
107 fprintf(stderr
, "Input file too small to use Luxul format\n");
112 if (memcmp(hdr
.magic
, "LXL#", 4)) {
113 fprintf(stderr
, "File <file> does not use Luxul's format\n");
118 version
= le32_to_cpu(hdr
.version
);
119 hdr_len
= lxlfw_hdr_len(version
);
120 if (bytes
< hdr_len
) {
121 fprintf(stderr
, "Input file too small for header version %d\n", version
);
126 printf("Format version:\t%d\n", version
);
127 printf("Header length:\t%d\n", le32_to_cpu(hdr
.hdr_len
));
129 printf("Flags:\t\t");
130 flags
= le32_to_cpu(hdr
.flags
);
131 if (flags
& LXL_FLAGS_VENDOR_LUXUL
)
132 printf("VENDOR_LUXUL ");
134 memcpy(board
, hdr
.board
, sizeof(hdr
.board
));
136 printf("Board:\t\t%s\n", board
);
139 printf("Release:\t");
140 if (hdr
.release
[0] || hdr
.release
[1] || hdr
.release
[2] || hdr
.release
[3]) {
141 printf("%hu.%hu.%hu", hdr
.release
[0], hdr
.release
[1], hdr
.release
[2]);
143 printf(".%hu", hdr
.release
[3]);
154 /**************************************************
156 **************************************************/
158 static int lxlfw_create(int argc
, char **argv
) {
159 struct lxl_hdr hdr
= {
160 .magic
= { 'L', 'X', 'L', '#' },
162 char *in_path
= NULL
;
163 uint32_t version
= 0;
173 fprintf(stderr
, "Missing <file> argument\n");
179 while ((c
= getopt(argc
, argv
, "i:lb:r:")) != -1) {
185 hdr
.flags
|= cpu_to_le32(LXL_FLAGS_VENDOR_LUXUL
);
186 version
= max(version
, 1);
189 memcpy(hdr
.board
, optarg
, strlen(optarg
) > 16 ? 16 : strlen(optarg
));
190 version
= max(version
, 1);
193 if (sscanf(optarg
, "%hhu.%hhu.%hhu.%hhu", &hdr
.release
[0], &hdr
.release
[1], &hdr
.release
[2], &hdr
.release
[3]) < 1) {
194 fprintf(stderr
, "Failed to parse release number \"%s\"\n", optarg
);
198 version
= max(version
, 2);
203 hdr
.version
= cpu_to_le32(version
);
204 hdr_len
= lxlfw_hdr_len(version
);
209 hdr
.hdr_len
= cpu_to_le32(hdr_len
);
212 fprintf(stderr
, "Missing input file argument\n");
217 in
= fopen(in_path
, "r");
219 fprintf(stderr
, "Could not open input file %s\n", in_path
);
224 lxl
= fopen(argv
[2], "w+");
226 fprintf(stderr
, "Could not open \"%s\" file\n", argv
[2]);
231 bytes
= fwrite(&hdr
, 1, hdr_len
, lxl
);
232 if (bytes
!= hdr_len
) {
233 fprintf(stderr
, "Could not write Luxul's header\n");
238 while ((bytes
= fread(buf
, 1, sizeof(buf
), in
)) > 0) {
239 if (fwrite(buf
, 1, bytes
, lxl
) != bytes
) {
240 fprintf(stderr
, "Could not copy %zu bytes from input file\n", bytes
);
254 /**************************************************
256 **************************************************/
258 static void usage() {
261 printf("Get info about Luxul firmware:\n");
262 printf("\tlxlfw info <file>\n");
264 printf("Create new Luxul firmware:\n");
265 printf("\tlxlfw create <file> [options]\n");
266 printf("\t-i file\t\t\t\tinput file for Luxul's firmware container\n");
267 printf("\t-l\t\t\t\tmark firmware as created by Luxul company (DON'T USE)\n");
268 printf("\t-b board\t\t\tboard (device) name\n");
269 printf("\t-r release\t\t\trelease number (e.g. 5.1.0, 7.1.0.2)\n");
272 int main(int argc
, char **argv
) {
274 if (!strcmp(argv
[1], "info"))
275 return lxlfw_info(argc
, argv
);
276 else if (!strcmp(argv
[1], "create"))
277 return lxlfw_create(argc
, argv
);