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