Created
November 20, 2024 11:21
-
-
Save apritzel/0fe8efd8e57f6e0d5cc13695412e8ce6 to your computer and use it in GitHub Desktop.
tool to find DTB headers in (image) files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <getopt.h> | |
#include <arpa/inet.h> // for htonl | |
struct fdt_header { | |
uint32_t magic; | |
uint32_t totalsize; | |
uint32_t off_dt_struct; | |
uint32_t off_dt_strings; | |
uint32_t off_mem_rsvmap; | |
uint32_t version; | |
uint32_t last_comp_version; | |
uint32_t boot_cpuid_phys; | |
uint32_t size_dt_strings; | |
uint32_t size_dt_struct; | |
}; | |
#define DTB_MAGIC 0xd00dfeed | |
#define BUFSIZE 65536 | |
int main(int argc, char **argv) | |
{ | |
FILE *inf = stdin; | |
size_t ret; | |
off_t fpos = 0; | |
struct fdt_header header; | |
int nr = 1, extract = 0; | |
int header_words = sizeof(header) / sizeof(uint32_t); | |
bool verbose = false; | |
uint32_t size, version; | |
int option; | |
void *buf = NULL; | |
while ((option = getopt(argc, argv, "ve:h")) != -1) { | |
switch (option) { | |
case 'v': | |
verbose = true; | |
break; | |
case 'e': | |
extract = atoi(optarg); | |
break; | |
case 'h': | |
fprintf(stdout, "usage: %s [-hv] [-e <nr>] [<file>]\n", | |
argv[0]); | |
return 0; | |
} | |
} | |
if (optind < argc) { | |
inf = fopen(argv[optind], "rb"); | |
if (!inf) { | |
perror(argv[optind]); | |
return -2; | |
} | |
} | |
if (extract) | |
buf = malloc(BUFSIZE); | |
while (!feof(inf)) { | |
ret = fread(&header, sizeof(header.magic), 1, inf); | |
if (ret < 1) | |
break; | |
if (ntohl(header.magic) != DTB_MAGIC) { | |
fpos += sizeof(uint32_t); | |
continue; | |
} | |
/* read in the rest of the DTB header */ | |
ret = fread(&header.totalsize, | |
sizeof(uint32_t), header_words - 1, inf); | |
version = ntohl(header.version); | |
size = ntohl(header.totalsize); | |
/* | |
* additional sanity check, to avoid false positives on | |
* just finding the DTB magic somewhere in the data. | |
*/ | |
if (ntohl(header.last_comp_version) != 16 || version != 17) { | |
if (verbose && !extract) | |
fprintf(stdout, "DTB signature found at 0x%llx, version: %d, size: %d bytes\n", | |
(unsigned long long)fpos, version, | |
size); | |
fpos += sizeof(header); | |
continue; | |
} | |
if (!extract) | |
fprintf(stdout, "%2d: found DTB v17 at 0x%llx, %d bytes\n", | |
nr, (unsigned long long)fpos, size); | |
fpos += sizeof(header); | |
if (nr == extract) { | |
ret = fwrite(&header, | |
sizeof(uint32_t), header_words, stdout); | |
size -= sizeof(header); | |
while (size > 0) { | |
int toread = size; | |
if (toread > BUFSIZE) | |
toread = BUFSIZE; | |
ret = fread(buf, 1, toread, inf); | |
fpos += ret; | |
if (ferror(inf)) { | |
perror("reading input file"); | |
return 3; | |
} | |
if (ret > 0) | |
fwrite(buf, 1, ret, stdout); | |
size -= ret; | |
} | |
break; | |
} | |
nr++; | |
} | |
if (extract) | |
free(buf); | |
fclose(inf); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment