1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * mkhsfls - build the .FLS firmware container accepted by the web 4 * interface of Herospeed and Longse RV1126 IP cameras 5 */ 6 #include <errno.h> 7 #include <getopt.h> 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 13 #define MAX_ENTRIES 32 14 #define HDR_SIZE 0x18 15 #define HDR_STR_LEN 8 16 #define HDR_OFF_SENSOR 8 17 #define HDR_OFF_DATA_LEN 16 18 #define HDR_OFF_FILE_NUM 20 19 #define ENTRY_SIZE 0x100 20 #define ENTRY_NAME_LEN 128 21 #define ENTRY_OFF_LEN 128 22 #define ENTRY_OFF_OFFSET 132 23 #define ENTRY_OFF_MAGIC 140 24 #define ENTRY_MAGIC 0x12345 25 26 struct entry { 27 char *name; 28 uint8_t *data; 29 size_t len; 30 }; 31 32 static void put_le32(uint8_t *buf, uint32_t val) 33 { 34 buf[0] = val & 0xff; 35 buf[1] = (val >> 8) & 0xff; 36 buf[2] = (val >> 16) & 0xff; 37 buf[3] = val >> 24; 38 } 39 40 static int entry_read(struct entry *entry, char *spec) 41 { 42 char *sep; 43 FILE *fp; 44 long len; 45 46 sep = strchr(spec, '='); 47 if (!sep || sep == spec || (size_t)(sep - spec) >= ENTRY_NAME_LEN) { 48 fprintf(stderr, "%s: expected <name>=<file>\n", spec); 49 return -1; 50 } 51 *sep = '\0'; 52 entry->name = spec; 53 54 fp = fopen(sep + 1, "rb"); 55 if (!fp) { 56 fprintf(stderr, "%s: %s\n", sep + 1, strerror(errno)); 57 return -1; 58 } 59 if (fseek(fp, 0, SEEK_END) || (len = ftell(fp)) < 0 || 60 fseek(fp, 0, SEEK_SET)) { 61 fprintf(stderr, "%s: cannot determine size\n", sep + 1); 62 fclose(fp); 63 return -1; 64 } 65 entry->len = len; 66 entry->data = malloc(len ? len : 1); 67 if (!entry->data || fread(entry->data, 1, len, fp) != (size_t)len) { 68 fprintf(stderr, "%s: read failed\n", sep + 1); 69 fclose(fp); 70 return -1; 71 } 72 fclose(fp); 73 return 0; 74 } 75 76 static int fls_write(const char *path, const char *ic, const char *sensor, 77 const struct entry *entries, int count) 78 { 79 size_t offset = HDR_SIZE + (size_t)count * ENTRY_SIZE; 80 size_t total; 81 uint8_t *buf; 82 uint8_t *ent; 83 FILE *fp; 84 int i; 85 86 total = offset; 87 for (i = 0; i < count; i++) 88 total += entries[i].len; 89 90 buf = calloc(1, total); 91 if (!buf) 92 return -1; 93 94 strncpy((char *)buf, ic, HDR_STR_LEN - 1); 95 strncpy((char *)buf + HDR_OFF_SENSOR, sensor, HDR_STR_LEN - 1); 96 put_le32(buf + HDR_OFF_DATA_LEN, total); 97 put_le32(buf + HDR_OFF_FILE_NUM, count); 98 99 for (i = 0; i < count; i++) { 100 ent = buf + HDR_SIZE + (size_t)i * ENTRY_SIZE; 101 strcpy((char *)ent, entries[i].name); 102 put_le32(ent + ENTRY_OFF_LEN, entries[i].len); 103 put_le32(ent + ENTRY_OFF_OFFSET, offset); 104 put_le32(ent + ENTRY_OFF_MAGIC, ENTRY_MAGIC); 105 memcpy(buf + offset, entries[i].data, entries[i].len); 106 offset += entries[i].len; 107 } 108 109 fp = fopen(path, "wb"); 110 if (!fp) { 111 fprintf(stderr, "%s: %s\n", path, strerror(errno)); 112 free(buf); 113 return -1; 114 } 115 if (fwrite(buf, 1, total, fp) != total || fclose(fp)) { 116 fprintf(stderr, "%s: write failed\n", path); 117 free(buf); 118 return -1; 119 } 120 free(buf); 121 return 0; 122 } 123 124 static void usage(const char *progname) 125 { 126 fprintf(stderr, 127 "Usage: %s -i <ic> -s <sensor> -o <output> " 128 "-e <name=file> [-e ...]\n" 129 "\n" 130 "Options:\n" 131 " -i <string> SoC name checked by the device, e.g. RV1126\n" 132 " -s <string> sensor name checked by the device, e.g. IMX415\n" 133 " -e <name=file> entry: boot, system, uboot, param, var, update,\n" 134 " userdata or an absolute path of a file to write\n" 135 " -o <file> output file\n" 136 " -h show this help\n", 137 progname); 138 } 139 140 int main(int argc, char *argv[]) 141 { 142 struct entry entries[MAX_ENTRIES]; 143 const char *out_path = NULL; 144 const char *sensor = NULL; 145 const char *ic = NULL; 146 int count = 0; 147 int opt; 148 149 while ((opt = getopt(argc, argv, "i:s:e:o:h")) != -1) { 150 switch (opt) { 151 case 'i': 152 ic = optarg; 153 break; 154 case 's': 155 sensor = optarg; 156 break; 157 case 'e': 158 if (count >= MAX_ENTRIES || 159 entry_read(&entries[count], optarg)) 160 return EXIT_FAILURE; 161 count++; 162 break; 163 case 'o': 164 out_path = optarg; 165 break; 166 default: 167 usage(argv[0]); 168 return opt == 'h' ? EXIT_SUCCESS : EXIT_FAILURE; 169 } 170 } 171 172 if (!ic || !sensor || !out_path || !count || 173 strlen(ic) >= HDR_STR_LEN || strlen(sensor) >= HDR_STR_LEN) { 174 usage(argv[0]); 175 return EXIT_FAILURE; 176 } 177 178 return fls_write(out_path, ic, sensor, entries, count) ? 179 EXIT_FAILURE : EXIT_SUCCESS; 180 } 181
This page was automatically generated by LXR 0.3.1. • OpenWrt