Skip to content

Instantly share code, notes, and snippets.

@apritzel
Created May 30, 2024 23:58
Show Gist options
  • Save apritzel/00d9447027e59512e11aeeeb76fccd27 to your computer and use it in GitHub Desktop.
Save apritzel/00d9447027e59512e11aeeeb76fccd27 to your computer and use it in GitHub Desktop.
find_dtbs: scan a binary file for devicetree binary magic bytes, and allow extracting the DTBs
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (C) 2018-2024 Andre Przywara <osp@apritzel.eu>
#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 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;
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, 4, 1, inf);
if (ret < 1)
break;
if (ntohl(header.magic) != 0xd00dfeed) {
fpos += 4;
continue;
}
ret = fread(&header.totalsize, 4, 9, inf);
version = ntohl(header.version);
size = ntohl(header.totalsize);
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 += (ret + 1) * 4;
continue;
}
if (!extract)
fprintf(stdout, "%2d: found DTB v17 at 0x%llx, %d bytes\n",
nr, (unsigned long long)fpos, size);
fpos += (ret + 1) * 4;
if (nr == extract) {
ret = fwrite(&header, 4, 10, stdout);
size -= 40;
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