From 0fd1bc1004bb1069f124a97dd47a0d8c885a26df Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Fri, 11 May 2012 16:13:39 +0200 Subject: [PATCH] bin2fex: split across script_bin and script_fex --- bin2fex.c | 210 --------------------------------------------------- script_bin.c | 107 +++++++++++++++++++++++++- script_fex.c | 119 +++++++++++++++++++++++++++-- 3 files changed, 216 insertions(+), 220 deletions(-) delete mode 100644 bin2fex.c diff --git a/bin2fex.c b/bin2fex.c deleted file mode 100644 index 20e1693..0000000 --- a/bin2fex.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2012 Alejandro Mery - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include -#include - -#define pr_info(F, ...) do { \ - fprintf(stderr, "bin2fex: " F, __VA_ARGS__); \ - fprintf(out, "; bin2fex: " F, __VA_ARGS__); \ - } while(0) - -#define pr_err(F, ...) pr_info("ERROR: " F, __VA_ARGS__) - -#define PTR(B, OFF) (void*)((char*)(B)+(OFF)) - -/** - */ -static inline size_t strlen2(const char *s) -{ - size_t l = strlen(s); - const char *p = &s[l-1]; - while (l && *p >= '0' && *p <= '9') { - l--; - p--; - } - return l; -} - -static int find_full_match(const char *s, size_t l, const char **list) -{ - while (*list) { - if (memcmp(s, *list, l) == 0) - return 1; - list++; - } - - return 0; -} - -/** - */ -static inline int decompile_gpio(struct script_bin_section *section, - struct script_bin_entry *entry, - struct script_bin_gpio_value *gpio, - int words, FILE *out) -{ - int ok = 1; - char port = '?'; - - if (words != 6) { - pr_err("%s.%s: invalid length %d (assuming %d)\n", - section->name, entry->name, words, 6); - ok = 0; - } - - if (gpio->port < 1 || gpio->port > 10) { - pr_err("%s.%s: unknown GPIO port type %d\n", - section->name, entry->name, gpio->port); - ok = 0; - } else { - port = 'A' + (gpio->port-1); - } - - fprintf(out, "%s\t= port:P%c%02d", entry->name, port, gpio->port_num); - for (const int *p = &gpio->mul_sel, *pe = p+4; p != pe; p++) { - if (*p == -1) - fputs("", out); - else - fprintf(out, "<%d>", *p); - } - fputc('\n', out); - - return ok; -} - -/** - */ -static int decompile_single_mode(const char *name) -{ - static const char *hexa_entries[] = { - "dram_baseaddr", "dram_zq", "dram_tpr", "dram_emr", - "g2d_size", - "rtp_press_threshold", "rtp_sensitive_level", - "ctp_twi_addr", "csi_twi_addr", "csi_twi_addr_b", "tkey_twi_addr", - "lcd_gamma_tbl_", - "gsensor_twi_addr", - NULL }; - size_t l = strlen2(name); - - if (find_full_match(name, l, hexa_entries)) - return 0; - else - return -1; -} -static inline int decompile_single(struct script_bin_section *section, - struct script_bin_entry *entry, - int32_t *d, - int words, FILE *out) -{ - int ok = 1; - int mode; - - if (words != 1) { - pr_err("%s.%s: invalid length %d (assuming %d)\n", - section->name, entry->name, words, 1); - ok = 0; - } - - mode = decompile_single_mode(entry->name); - - fprintf(out, "%s\t= ", entry->name); - if (mode < 0) - fprintf(out, "%d", *d); - else if (mode > 0) - fprintf(out, "0x%0*x", mode, *d); - else - fprintf(out, "0x%x", *d); - - fputc('\n', out); - - return ok; -} - -/** - */ -static int decompile_section(void *bin, size_t UNUSED(bin_size), - struct script_bin_section *section, - FILE *out) -{ - struct script_bin_entry *entry = PTR(bin, section->offset<<2); - int ok = 1; - - fprintf(out, "[%s]\n", section->name); - for (int i = section->length; i--; entry++) { - void *data = PTR(bin, entry->offset<<2); - unsigned type, words; - type = (entry->pattern >> 16) & 0xffff; - words = (entry->pattern >> 0) & 0xffff; - - switch(type) { - case SCRIPT_VALUE_TYPE_SINGLE_WORD: - if (!decompile_single(section, entry, data, words, out)) - ok = 0; - break; - case SCRIPT_VALUE_TYPE_STRING: { - size_t bytes = words << 2; - const char *p, *pe, *s = data; - - for(p=s, pe=s+bytes; *p && p!=pe; p++) - ; /* seek end-of-string */ - - fprintf(out, "%s\t= \"%.*s\"\n", entry->name, - (int)(p-s), s); - }; break; - case SCRIPT_VALUE_TYPE_GPIO: - if (!decompile_gpio(section, entry, data, words, out)) - ok = 0; - break; - case SCRIPT_VALUE_TYPE_NULL: - fprintf(out, "%s\t=\n", entry->name); - break; - default: - pr_err("%s.%s: unknown type %d\n", - section->name, entry->name, type); - fprintf(out, "%s\t=\n", entry->name); - ok = 0; - break; - } - } - fputc('\n', out); - - return ok; -} -/** - */ -static int decompile(void *bin, size_t bin_size, FILE *out) -{ - int i; - struct script_bin_head *script = bin; - - pr_info("version: %d.%d.%d\n", script->version[0], - script->version[1], script->version[2]); - pr_info("size: %zu (%d sections)\n", bin_size, - script->sections); - - /* TODO: SANITY: compare head.sections with bin_size */ - for (i=0; i < script->sections; i++) { - struct script_bin_section *section = &script->section[i]; - - if (!decompile_section(bin, bin_size, section, out)) - return 1; /* failure */ - } - return 0; /* success */ -} diff --git a/script_bin.c b/script_bin.c index ede5bc7..99d738e 100644 --- a/script_bin.c +++ b/script_bin.c @@ -17,6 +17,7 @@ #include "common.h" +#include #include #include #include @@ -28,9 +29,11 @@ #define pr_info(...) fprintf(stderr, "fex2bin: " __VA_ARGS__) #define pr_err(...) pr_info("E: " __VA_ARGS__) +#define PTR(B, OFF) (void*)((char*)(B)+(OFF)) #define WORDS(S) (((S)+(sizeof(uint32_t)-1))/(sizeof(uint32_t))) -/** +/* + * generator */ size_t script_bin_size(struct script *script, size_t *sections, size_t *entries) @@ -209,9 +212,105 @@ int script_generate_bin(void *bin, size_t UNUSED(bin_size), return 1; } -int script_decompile_bin(void *UNUSED(bin), size_t UNUSED(bin_size), - const char *UNUSED(filename), - struct script *UNUSED(script)) +/* + * decompiler + */ +static int decompile_section(void *bin, size_t UNUSED(bin_size), + const char *filename, + struct script_bin_section *section, + struct script *script) { + struct script_bin_entry *entry = PTR(bin, section->offset<<2); + struct script_section *s; + + if ((s = script_section_new(script, section->name)) == NULL) + goto malloc_error; + + for (int i = section->length; i--; entry++) { + void *data = PTR(bin, entry->offset<<2); + unsigned type, words; + type = (entry->pattern >> 16) & 0xffff; + words = (entry->pattern >> 0) & 0xffff; + + switch(type) { + case SCRIPT_VALUE_TYPE_SINGLE_WORD: { + uint32_t *v = data; + if (words != 1) { + pr_err("%s: %s.%s: invalid length %d (assuming %d)\n", + filename, section->name, entry->name, words, 1); + } + if (!script_single_entry_new(s, entry->name, *v)) + goto malloc_error; + }; break; + case SCRIPT_VALUE_TYPE_STRING: { + size_t bytes = words << 2; + const char *p, *pe, *v = data; + + for(p=v, pe=v+bytes; *p && p!=pe; p++) + ; /* seek end-of-string */ + + if (!script_string_entry_new(s, entry->name, p-v, v)) + goto malloc_error; + }; break; + case SCRIPT_VALUE_TYPE_GPIO: { + struct script_bin_gpio_value *gpio = data; + int32_t v[4]; + if (words != 6) { + pr_err("%s: %s.%s: invalid length %d (assuming %d)\n", + filename, section->name, entry->name, words, 6); + } else if (gpio->port < 1 || gpio->port > 10) { + pr_err("%s: %s.%s: unknown GPIO port type %d\n", + filename, section->name, entry->name, gpio->port); + goto failure; + } + v[0] = gpio->mul_sel; + v[1] = gpio->pull; + v[2] = gpio->drv_level; + v[3] = gpio->data; + + if (!script_gpio_entry_new(s, entry->name, + gpio->port, gpio->port_num, + v)) + goto malloc_error; + }; break; + case SCRIPT_VALUE_TYPE_NULL: + if (!script_null_entry_new(s, entry->name)) + goto malloc_error; + break; + default: + pr_err("%s: %s.%s: unknown type %d\n", + filename, section->name, entry->name, type); + goto failure; + } + } + return 1; + +malloc_error: + pr_err("%s: %s\n", "malloc", strerror(errno)); +failure: return 0; } + +int script_decompile_bin(void *bin, size_t bin_size, + const char *filename, + struct script *script) +{ + int i; + struct script_bin_head *head = bin; + + pr_info("%s: version: %d.%d.%d\n", filename, + head->version[0], head->version[1], + head->version[2]); + pr_info("%s: size: %zu (%d sections)\n", filename, + bin_size, head->sections); + + /* TODO: SANITY: compare head.sections with bin_size */ + for (i=0; i < head->sections; i++) { + struct script_bin_section *section = &head->section[i]; + + if (!decompile_section(bin, bin_size, filename, + section, script)) + return 0; + } + return 1; +} diff --git a/script_fex.c b/script_fex.c index bb1ab80..6c55f12 100644 --- a/script_fex.c +++ b/script_fex.c @@ -30,6 +30,119 @@ #define pr_info(...) fprintf(stderr, "fex2bin: " __VA_ARGS__) #define pr_err(...) pr_info("E: " __VA_ARGS__) +/* + * generator + */ +static inline size_t strlen2(const char *s) +{ + size_t l = strlen(s); + const char *p = &s[l-1]; + while (l && *p >= '0' && *p <= '9') { + l--; + p--; + } + return l; +} + +static int find_full_match(const char *s, size_t l, const char **list) +{ + while (*list) { + if (memcmp(s, *list, l) == 0) + return 1; + list++; + } + + return 0; +} + +/** + */ +static int decompile_single_mode(const char *name) +{ + static const char *hexa_entries[] = { + "dram_baseaddr", "dram_zq", "dram_tpr", "dram_emr", + "g2d_size", + "rtp_press_threshold", "rtp_sensitive_level", + "ctp_twi_addr", "csi_twi_addr", "csi_twi_addr_b", "tkey_twi_addr", + "lcd_gamma_tbl_", + "gsensor_twi_addr", + NULL }; + size_t l = strlen2(name); + + if (find_full_match(name, l, hexa_entries)) + return 0; + else + return -1; +} + +int script_generate_fex(FILE *out, const char *UNUSED(filename), + struct script *script) +{ + struct list_entry *ls, *le; + struct script_section *section; + struct script_entry *entry; + + for (ls = list_first(&script->sections); ls; + ls = list_next(&script->sections, ls)) { + section = container_of(ls, struct script_section, sections); + + fprintf(out, "[%s]\n", section->name); + for (le = list_first(§ion->entries); le; + le = list_next(§ion->entries, le)) { + entry = container_of(le, struct script_entry, entries); + + switch(entry->type) { + case SCRIPT_VALUE_TYPE_SINGLE_WORD: { + int mode = decompile_single_mode(entry->name); + struct script_single_entry *single; + single = container_of(entry, struct script_single_entry, entry); + + fprintf(out, "%s\t= ", entry->name); + if (mode < 0) + fprintf(out, "%d", single->value); + else if (mode > 0) + fprintf(out, "0x%0*x", mode, single->value); + else + fprintf(out, "0x%x", single->value); + fputc('\n', out); + }; break; + case SCRIPT_VALUE_TYPE_STRING: { + struct script_string_entry *string; + string = container_of(entry, struct script_string_entry, entry); + fprintf(out, "%s\t= \"%.*s\"\n", entry->name, + (int)string->l, string->string); + }; break; + case SCRIPT_VALUE_TYPE_MULTI_WORD: + abort(); + case SCRIPT_VALUE_TYPE_GPIO: { + char port = 'A'-1; + struct script_gpio_entry *gpio; + gpio = container_of(entry, struct script_gpio_entry, entry); + + port += gpio->port; + fprintf(out, "%s\t= port:P%c%02d", entry->name, port, gpio->port_num); + for (const int *p = gpio->data, *pe = p+4; p != pe; p++) { + if (*p == -1) + fputs("", out); + else + fprintf(out, "<%d>", *p); + } + fputc('\n', out); + }; break; + case SCRIPT_VALUE_TYPE_NULL: + fprintf(out, "%s\t=\n", entry->name); + break; + } + } + fputc('\n', out); + } + return 0; +} + +/* + * parser + */ + /** find first not blank char */ static inline char *skip_blank(char *p) { @@ -220,9 +333,3 @@ parse_error: ok = 0; return ok; } - -int script_generate_fex(FILE *UNUSED(out), const char *UNUSED(filename), - struct script *UNUSED(script)) -{ - return 0; -}