Skip to content

Instantly share code, notes, and snippets.

@apritzel
Created November 20, 2024 11:21
Show Gist options
  • Save apritzel/0fe8efd8e57f6e0d5cc13695412e8ce6 to your computer and use it in GitHub Desktop.
Save apritzel/0fe8efd8e57f6e0d5cc13695412e8ce6 to your computer and use it in GitHub Desktop.
tool to find DTB headers in (image) files
#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