diff --git a/main.c b/main.c index 488de82..f31b7e6 100644 --- a/main.c +++ b/main.c @@ -12,6 +12,8 @@ #define debug(...) #endif +static int reads_counter = 0; + static int firmware_fdt_read_blob(const char *filename, char **buffp, int *len) { int fd = 0; /* assume stdin */ @@ -60,7 +62,7 @@ static int firmware_fdt_read_blob(const char *filename, char **buffp, int *len) return ret; } -static int firmware_fdt_read_chunk(const char *filename, char *buf, int len, int offset) +static int firmware_fdt_read_chunk(const char *filename, char *buf, int offset, int len) { int fd = 0; /* assume stdin */ int ret = 0; @@ -99,6 +101,7 @@ static int firmware_fdt_read_chunk(const char *filename, char *buf, int len, int close(fd); memset(buf + readed, 0, len - readed); + reads_counter++; return readed; } @@ -106,7 +109,7 @@ int a() { int len = 0; char *buf = NULL; - const char *filename = "/tmp/esr1x.firmware"; + const char *filename = "/tmp/firmware"; firmware_fdt_read_blob(filename, &buf, &len); @@ -116,36 +119,32 @@ int a() node = fdt_path_offset(buf, "/images/sbi@1"); printf("fdt_path_offset of sbi@1: %x\n", node); int d = 0; -#if 0 - node = fdt_next_node(buf, 0, &d); - node = fdt_next_node(buf, node, &d); - node = fdt_next_node(buf, node, &d); - node = fdt_next_node(buf, node, &d); - node = fdt_next_node(buf, node, &d); - node = fdt_next_node(buf, node, &d); - node = fdt_next_node(buf, node, &d); - node = fdt_next_node(buf, node, &d); - printf("node: %x\n", node); -#endif return 0; } static inline const void *fdt_offset_ptr_(const void *fdt, const void *buf, int buf_offset) { - debug("fdt_offset_ptr_: %p + %d + %x\n", buf, fdt_off_dt_struct(fdt), buf_offset); - return (const char *)buf + fdt_off_dt_struct(fdt) + buf_offset; + debug("fdt_offset_ptr_: %p + %x\n", buf, buf_offset); + return (const char *)buf + buf_offset; +} + +static inline const int fdt_offset_to_file_offset(const void *fdt, int buf_offset) +{ + debug("fdt_offset_ptr_: %x\n", buf_offset); + return buf_offset + fdt_off_dt_struct(fdt); } #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) /* Do not touch any forward data, caller will validate it later */ -int guess_next_tag(char * fdt, int offset, char * buf) +int guess_next_tag(char * fdt, int offset, char * buf, int buf_offset) { - const unsigned * val = fdt_offset_ptr_(fdt, buf, 0); + const unsigned * val = fdt_offset_ptr_(fdt, buf, buf_offset); unsigned tag = fdt32_to_cpu(*val); char * ptr = NULL; + int offset_adjust = 0; switch (tag) { case FDT_BEGIN_NODE: @@ -154,29 +153,31 @@ int guess_next_tag(char * fdt, int offset, char * buf) debug("Starts: '%s'\n", ptr); while (*ptr != '\0') ptr++; - offset += ptr - (char *)val + 1; - debug("skipped %d chars\n", ptr - (char *)val + 1); + offset_adjust += ptr - (char *)val + 1; + debug("skipped %d chars\n", offset_adjust - FDT_TAGSIZE); break; case FDT_PROP: ptr = (char *)val; ptr += FDT_TAGSIZE; int len = fdt32_to_cpu(*((int *)ptr)); debug("It's prop: len %d\n", len); - offset += sizeof(struct fdt_property) + len; + offset_adjust += sizeof(struct fdt_property) + len; break; case FDT_END: case FDT_END_NODE: case FDT_NOP: - offset += FDT_TAGSIZE; + offset_adjust += FDT_TAGSIZE; break; default: printf("Unknown label: %x\n", tag); return -1; } - offset = FDT_TAGALIGN(offset); + + offset += offset_adjust; + offset_adjust += FDT_TAGALIGN(offset) - offset; debug("Next tag offset: %x\n", offset); - return offset; + return offset_adjust; } int is_offset_valid(char * fdt, int offset, int len) @@ -200,45 +201,67 @@ int is_offset_valid(char * fdt, int offset, int len) return 1; } -#define WINDOW_SIZE 512 +#define WINDOW_SIZE (1024 * 100) + +int buf_offset_left_after_tag(int offset) +{ +#define GUESS_NODE_NAME_LEN 64 + /* In edge case we have: + * |----|----------------| + * |tag |node name 0| + * ^-- last readed byte + */ + return WINDOW_SIZE - offset - FDT_TAGSIZE - GUESS_NODE_NAME_LEN; +} static int fdt_node_get_prop(char * filename, char * fdt, char * strings, int offset, const char * prop_name, int * data_offset, int * data_len) { char * buf = malloc(WINDOW_SIZE); - int readed = firmware_fdt_read_chunk(filename, buf, WINDOW_SIZE, offset); + int readed = firmware_fdt_read_chunk(filename, buf, fdt_offset_to_file_offset(fdt, offset), + WINDOW_SIZE); if (readed <= 0) return -1; *data_offset = 0; *data_len = 0; + int buf_offset = 0; do { - int nextoffset = guess_next_tag(fdt, offset, buf); - readed = firmware_fdt_read_chunk(filename, buf, WINDOW_SIZE, nextoffset); - debug("DUMP: Read additional %d bytes from offset %x\n", readed, nextoffset); - int valid = is_offset_valid(fdt, offset, nextoffset - offset); + int offset_adjust = guess_next_tag(fdt, offset, buf, buf_offset); + int valid = is_offset_valid(fdt, offset, offset_adjust); if (!valid) { - printf("DUMP: next tag is not valid! (%d %d)\n", offset, nextoffset); + printf("DUMP: next tag is not valid! (%d + %d)\n", offset, offset_adjust); break; } - debug("DUMP: Offset %x is valid\n", nextoffset); - offset = nextoffset; + offset += offset_adjust; + buf_offset += offset_adjust; + debug("DUMP: Offset %x(%x) is valid\n", offset, buf_offset); - if (FDT_PROP == fdt32_to_cpu(*(int *)(fdt_offset_ptr_(fdt, buf, 0)))) + /* Check if we exceed the window */ + if (buf_offset_left_after_tag(buf_offset) < 0) { - const struct fdt_property *prop = fdt_offset_ptr_(fdt, buf, 0); + readed = firmware_fdt_read_chunk(filename, buf, + fdt_offset_to_file_offset(fdt, offset), + WINDOW_SIZE); + debug("DUMP: Read additional %d bytes from offset %x\n", readed, offset); + buf_offset = 0; + } + + if (FDT_PROP == fdt32_to_cpu(*(int *)(fdt_offset_ptr_(fdt, buf, buf_offset)))) + { + const struct fdt_property *prop = fdt_offset_ptr_(fdt, buf, buf_offset); debug("prop->nameoff: %x (%x)\n", fdt32_to_cpu(prop->nameoff), fdt_off_dt_strings(fdt)); char * name = strings + fdt32_to_cpu(prop->nameoff); debug("Property name: '%s'\n", name); - if (strcmp(name, "data")) + if (strcmp(name, prop_name)) continue; *data_offset = prop->data - (char *)prop + offset; *data_len = fdt32_to_cpu(prop->len); - debug("Property \"data\" at offset %x len %d\n", data_offset, data_len); + debug("Property \"%s\" at offset %x len %d\n", prop_name, data_offset, data_len); return 0; } - } while (FDT_END != fdt32_to_cpu(*(int *)(fdt_offset_ptr_(fdt, buf, 0)))); + } while (FDT_END != fdt32_to_cpu(*(int *)(fdt_offset_ptr_(fdt, buf, buf_offset)))); return -1; } @@ -251,11 +274,22 @@ static int fdt_dump_node_data(char * fdt, char * strings, const char *outname, c return -1; char * data = malloc(data_len); - int readed = firmware_fdt_read_chunk(filename, data, data_len, - fdt_off_dt_struct(fdt) + data_offset); + int readed = firmware_fdt_read_chunk(filename, data, + fdt_off_dt_struct(fdt) + data_offset, data_len); if (readed <= 0) return -1; -#if 1 + + if (fdt_node_get_prop(filename, fdt, strings, offset, "commit", &data_offset, &data_len)) + return -1; + + + char * buf = malloc(WINDOW_SIZE); + readed = firmware_fdt_read_chunk(filename, buf, + fdt_off_dt_struct(fdt) + data_offset, data_len); + char commit[42] = {0}; + strncpy(commit, buf, sizeof(commit)); + printf("Commit(len: %d): '%s'\n", data_len, commit); +#if 0 int fd = 0; /* assume stdin */ int ret = 0; @@ -296,32 +330,57 @@ static int fdt_dump_node_data(char * fdt, char * strings, const char *outname, c int b() { int len = 0; - const char *filename = "/tmp/esr1x.firmware"; + const char *filename = "/tmp/firmware"; + + char *fdt = malloc(WINDOW_SIZE); + int readed = firmware_fdt_read_chunk(filename, fdt, 0, WINDOW_SIZE); + if (readed <= 0) + return -1; char *buf = malloc(WINDOW_SIZE); - int file_offset = 0; - int readed = firmware_fdt_read_chunk(filename, buf, WINDOW_SIZE, file_offset); + readed = firmware_fdt_read_chunk(filename, buf, fdt_offset_to_file_offset(fdt, 0), + WINDOW_SIZE); if (readed <= 0) return -1; - char *fdt = buf; - buf = malloc(WINDOW_SIZE); - memcpy(buf, fdt, WINDOW_SIZE); printf("B:\n"); int offset = 0; struct { const char * name; int offset; } node_offsets[] = { - { "sbi@1", 0 }, - { "uboot-spi@1", 0 }, - { "uboot-nand@1", 0 } + { "bdk@1", 0 }, + { "bl1@1", 0 }, + { "uboot@1", 0 } }; + int buf_offset = 0; do { - if (FDT_BEGIN_NODE == fdt32_to_cpu(*(int *)(fdt_offset_ptr_(fdt, buf, 0)))) + int offset_adjust = guess_next_tag(fdt, offset, buf, buf_offset); + int valid = is_offset_valid(fdt, offset, offset_adjust); + if (!valid) + { + printf("READ: next tag is not valid! (%d + %d)\n", offset, offset_adjust); + break; + } + offset += offset_adjust; + buf_offset += offset_adjust; + debug("READ: Offset %x(%x) is valid\n", offset, buf_offset); + + /* Check if we exceed the window */ + if (buf_offset_left_after_tag(buf_offset) < 0) + { + readed = firmware_fdt_read_chunk(filename, buf, + fdt_offset_to_file_offset(fdt, offset), + WINDOW_SIZE); + debug("READ: Read additional %d bytes from offset %x\n", readed, offset); + buf_offset = 0; + } + + if (FDT_BEGIN_NODE == fdt32_to_cpu(*(int *)(fdt_offset_ptr_(fdt, buf, buf_offset)))) { debug("Search starts\n"); for (int i = 0; i < sizeof(node_offsets) / sizeof(*node_offsets); i++) { if (!strcmp(node_offsets[i].name, - (char *)(fdt_offset_ptr_(fdt, buf, FDT_TAGSIZE)))) + (char *)(fdt_offset_ptr_(fdt, buf, + buf_offset + FDT_TAGSIZE)))) { node_offsets[i].offset = offset; } @@ -329,32 +388,18 @@ int b() } debug("Search ends\n"); } - - int nextoffset = guess_next_tag(fdt, offset, buf); - readed = firmware_fdt_read_chunk(filename, buf, WINDOW_SIZE, nextoffset); - debug("Read additional %d bytes from offset %x\n", readed, nextoffset); - int valid = is_offset_valid(fdt, offset, nextoffset - offset); - if (!valid) - { - printf("next tag is not valid! (%d %d)\n", offset, nextoffset); - break; - } - debug("Offset %x is valid\n", nextoffset); - offset = nextoffset; - } while (FDT_END != fdt32_to_cpu(*(int *)(fdt_offset_ptr_(fdt, buf, 0)))); + } while (FDT_END != fdt32_to_cpu(*(int *)(fdt_offset_ptr_(fdt, buf, buf_offset)))); debug("Yay\n"); char * strings = malloc(WINDOW_SIZE); - readed = firmware_fdt_read_chunk(filename, strings, WINDOW_SIZE, fdt_off_dt_strings(fdt)); + readed = firmware_fdt_read_chunk(filename, strings, fdt_off_dt_strings(fdt), WINDOW_SIZE); if (readed <= 0) return -1; for (int i = 0; i < sizeof(node_offsets) / sizeof(*node_offsets); i++) { printf("%s offset: %x\n", node_offsets[i].name, node_offsets[i].offset); - readed = firmware_fdt_read_chunk(filename, buf, WINDOW_SIZE, - node_offsets[i].offset); int writed = fdt_dump_node_data(fdt, strings, node_offsets[i].name, filename, node_offsets[i].offset); printf("Written %d bytes\n", writed); } @@ -365,7 +410,7 @@ int b() int main(int argc, char *argv[]) { - a(); b(); + printf("Counter: %d\n", reads_counter); return 0; }