/* * Copyright (c) 2021 Maurizio Lombardi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #define MAX_LINE 4096 enum { TYPE_U8, TYPE_U16, TYPE_U32, TYPE_STR }; struct dslentry { long int offset; long int size; unsigned type; union { uint8_t u8; uint16_t u16; uint32_t u32; } v; void *str_value; struct dslentry *next; }; static uint8_t csum(uint8_t *buffer, int length) { int n; uint8_t sum = 0; for (n = 0; n < length; n++) { sum += buffer[n]; } return sum; } int main(int argc, char **argv) { char line[MAX_LINE]; char *linep = line; int ln = 0; char *fname; char *tok; char *save; int tok_len; FILE *fp; int i, fd; struct dslentry *list; struct dslentry *e; uint32_t highest_off = 0; void *fmap = NULL; if (argc != 2) return -1; list = malloc(sizeof(*list)); if (!list) { printf("Can't allocate the list\n"); return -1; } fname = argv[1]; fp = fopen(fname, "r"); if (!fp) { printf("Unable to open %s\n", fname); return -1; } e = list; while (fgets(line, MAX_LINE, fp)) { ln++; /* Ignore comments and empty lines */ if (line[0] == '/' || line[0] == '\n') continue; if (ln > 1) { e->next = malloc(sizeof(*e)); if (!e->next) { printf("Cannot allocate the buffer\n"); return -1; } e = e->next; e->next = NULL; } tok = strtok_r(linep, " ", &save); for (i = 0; i < 5; ++i) { if (!tok) { printf("Token is NULL\n"); goto malformed; } switch (i) { case 0: if (tok[0] != '[') { printf("Delimiter [ not found\n"); goto malformed; } tok++; e->offset = strtol(tok, NULL, 16); break; case 1: e->size = strtol(tok, NULL, 10); if (e->offset + e->size > highest_off) highest_off = e->offset + e->size; break; case 2: if (!strcmp(tok, "UINT8")) e->type = TYPE_U8; else if (!strcmp(tok, "UINT16")) e->type = TYPE_U16; else if (!strcmp(tok, "UINT32")) e->type = TYPE_U32; else if (!strcmp(tok, "String")) e->type = TYPE_STR; else { printf("Unrecognized type %s\n", tok); goto malformed; } break; case 3: if (tok[0] != ':') goto malformed; if (e->type == TYPE_STR) { tok = strtok_r(NULL, "\"", &save); continue; } break; case 4: switch (e->type) { case TYPE_STR: tok_len = strlen(tok); if (tok_len < 3) { printf("String too short\n"); goto malformed; } e->str_value = malloc(tok_len); if (!e->str_value) { printf("Cannot allocate the buffer\n"); return -1; } strcat(e->str_value, tok); break; case TYPE_U8: e->v.u8 = strtol(tok, NULL, 16); break; case TYPE_U16: e->v.u16 = strtol(tok, NULL, 16); break; case TYPE_U32: e->v.u32 = strtol(tok, NULL, 16); break; } } tok = strtok_r(NULL, " ", &save); } } fclose(fp); unlink("output.bin"); fd = open("output.bin", O_RDWR | O_CREAT, 0644); if (fd < 0) { printf("Cannot open the output file\n"); return -1; } lseek(fd, highest_off, SEEK_SET); write(fd, "\0", 1); fmap = mmap(NULL, highest_off, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (fmap == MAP_FAILED) { printf("Cannot map the file in memory\n"); return -1; } e = list; do { void *p = fmap + e->offset; switch (e->type) { case TYPE_STR: memcpy(p, e->str_value, e->size); break; case TYPE_U8: memcpy(p, &e->v.u8, 1); break; case TYPE_U16: memcpy(p, &e->v.u16, 2); break; case TYPE_U32: memcpy(p, &e->v.u32, 4); break; } e = e->next; } while (e); { uint8_t c; uint32_t flen = highest_off + 1; uint8_t *table = fmap; uint16_t heap_off, heap_len; /* Write table len */ memcpy(&table[0x04], &flen, 4); /* Calculate heap len */ memcpy(&heap_off, &table[0x26], 2); heap_len = flen - heap_off; memcpy(&table[0x24], &heap_len, 2); /* Write checksum */ c = csum(fmap, highest_off); table[0x09] = 0 - c - 1; } munmap(fmap, highest_off); return 0; malformed: printf("Error while reading line %d\n", ln); return -1; }