• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/lxlfw.c

  1 // SPDX-License-Identifier: GPL-2.0-or-later OR MIT
  2 /*
  3  * Luxul's firmware container format
  4  *
  5  * Copyright 2020 Legrand AV Inc.
  6  */
  7 
  8 #define _GNU_SOURCE
  9 
 10 #include <byteswap.h>
 11 #include <endian.h>
 12 #include <errno.h>
 13 #include <libgen.h>
 14 #include <stddef.h>
 15 #include <stdint.h>
 16 #include <stdio.h>
 17 #include <stdlib.h>
 18 #include <string.h>
 19 #include <unistd.h>
 20 
 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)
 31 #endif
 32 
 33 #define min(a, b)                               \
 34         ({                                      \
 35                 __typeof__ (a) _a = (a);        \
 36                 __typeof__ (b) _b = (b);        \
 37                 _a < _b ? _a : _b;              \
 38         })
 39 
 40 #define max(a, b)                               \
 41         ({                                      \
 42                 __typeof__ (a) _a = (a);        \
 43                 __typeof__ (b) _b = (b);        \
 44                 _a > _b ? _a : _b;              \
 45         })
 46 
 47 #define LXL_FLAGS_VENDOR_LUXUL                  0x00000001
 48 
 49 struct lxl_hdr {
 50         char            magic[4];       /* "LXL#" */
 51         uint32_t        version;
 52         uint32_t        hdr_len;
 53         uint8_t         v0_end[0];
 54         /* Version: 1+ */
 55         uint32_t        flags;
 56         char            board[16];
 57         uint8_t         v1_end[0];
 58         /* Version: 2+ */
 59         uint8_t         release[4];
 60         uint8_t         v2_end[0];
 61 } __packed;
 62 
 63 static uint32_t lxlfw_hdr_len(uint32_t version)
 64 {
 65         switch (version) {
 66         case 0:
 67                 return offsetof(struct lxl_hdr, v0_end);
 68         case 1:
 69                 return offsetof(struct lxl_hdr, v1_end);
 70         case 2:
 71                 return offsetof(struct lxl_hdr, v2_end);
 72         default:
 73                 fprintf(stderr, "Unsupported version %d\n", version);
 74                 return 0;
 75         }
 76 }
 77 
 78 /**************************************************
 79  * Info
 80  **************************************************/
 81 
 82 static int lxlfw_info(int argc, char **argv) {
 83         struct lxl_hdr hdr;
 84         uint32_t version;
 85         uint32_t hdr_len;
 86         char board[17];
 87         size_t bytes;
 88         int err = 0;
 89         FILE *lxl;
 90         int flags;
 91 
 92         if (argc < 3) {
 93                 fprintf(stderr, "Missing <file> argument\n");
 94                 err = -EINVAL;
 95                 goto out;
 96         }
 97 
 98         lxl = fopen(argv[2], "r");
 99         if (!lxl) {
100                 fprintf(stderr, "Could not open \"%s\" file\n", argv[2]);
101                 err = -ENOENT;
102                 goto out;
103         }
104 
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");
108                 err = -ENXIO;
109                 goto err_close;
110         }
111 
112         if (memcmp(hdr.magic, "LXL#", 4)) {
113                 fprintf(stderr, "File <file> does not use Luxul's format\n");
114                 err =  -EINVAL;
115                 goto err_close;
116         }
117 
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);
122                 err = -ENXIO;
123                 goto err_close;
124         }
125 
126         printf("Format version:\t%d\n", version);
127         printf("Header length:\t%d\n", le32_to_cpu(hdr.hdr_len));
128         if (version >= 1) {
129                 printf("Flags:\t\t");
130                 flags = le32_to_cpu(hdr.flags);
131                 if (flags & LXL_FLAGS_VENDOR_LUXUL)
132                         printf("VENDOR_LUXUL ");
133                 printf("\n");
134                 memcpy(board, hdr.board, sizeof(hdr.board));
135                 board[16] = '\0';
136                 printf("Board:\t\t%s\n", board);
137         }
138         if (version >= 2) {
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]);
142                         if (hdr.release[3])
143                                 printf(".%hu", hdr.release[3]);
144                 }
145                 printf("\n");
146         }
147 
148 err_close:
149         fclose(lxl);
150 out:
151         return err;
152 }
153 
154 /**************************************************
155  * Create
156  **************************************************/
157 
158 static int lxlfw_create(int argc, char **argv) {
159         struct lxl_hdr hdr = {
160                 .magic = { 'L', 'X', 'L', '#' },
161         };
162         char *in_path = NULL;
163         uint32_t version = 0;
164         uint32_t hdr_len;
165         ssize_t bytes;
166         char buf[512];
167         int err = 0;
168         FILE *lxl;
169         FILE *in;
170         int c;
171 
172         if (argc < 3) {
173                 fprintf(stderr, "Missing <file> argument\n");
174                 err = -EINVAL;
175                 goto out;
176         }
177 
178         optind = 3;
179         while ((c = getopt(argc, argv, "i:lb:r:")) != -1) {
180                 switch (c) {
181                 case 'i':
182                         in_path = optarg;
183                         break;
184                 case 'l':
185                         hdr.flags |= cpu_to_le32(LXL_FLAGS_VENDOR_LUXUL);
186                         version = max(version, 1);
187                         break;
188                 case 'b':
189                         memcpy(hdr.board, optarg, strlen(optarg) > 16 ? 16 : strlen(optarg));
190                         version = max(version, 1);
191                         break;
192                 case 'r':
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);
195                                 err = -EINVAL;
196                                 goto out;
197                         }
198                         version = max(version, 2);
199                         break;
200                 }
201         }
202 
203         hdr.version = cpu_to_le32(version);
204         hdr_len = lxlfw_hdr_len(version);
205         if (!hdr_len) {
206                 err = -EINVAL;
207                 goto out;
208         }
209         hdr.hdr_len = cpu_to_le32(hdr_len);
210 
211         if (!in_path) {
212                 fprintf(stderr, "Missing input file argument\n");
213                 err = -EINVAL;
214                 goto out;
215         }
216 
217         in = fopen(in_path, "r");
218         if (!in) {
219                 fprintf(stderr, "Could not open input file %s\n", in_path);
220                 err = -EIO;
221                 goto out;
222         }
223 
224         lxl = fopen(argv[2], "w+");
225         if (!lxl) {
226                 fprintf(stderr, "Could not open \"%s\" file\n", argv[2]);
227                 err = -EIO;
228                 goto err_close_in;
229         }
230 
231         bytes = fwrite(&hdr, 1, hdr_len, lxl);
232         if (bytes != hdr_len) {
233                 fprintf(stderr, "Could not write Luxul's header\n");
234                 err = -EIO;
235                 goto err_close_lxl;
236         }
237 
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);
241                         err = -EIO;
242                         goto err_close_lxl;
243                 }
244         }
245 
246 err_close_lxl:
247         fclose(lxl);
248 err_close_in:
249         fclose(in);
250 out:
251         return err;
252 }
253 
254 /**************************************************
255  * Start
256  **************************************************/
257 
258 static void usage() {
259         printf("Usage:\n");
260         printf("\n");
261         printf("Get info about Luxul firmware:\n");
262         printf("\tlxlfw info <file>\n");
263         printf("\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");
270 }
271 
272 int main(int argc, char **argv) {
273         if (argc > 1) {
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);
278         }
279 
280         usage();
281         return 0;
282 }
283 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt