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

Sources/firmware-utils/src/mkhsfls.c

  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