Created
May 30, 2024 23:58
-
-
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
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
// SPDX-License-Identifier: GPL-2.0-only | |
// Copyright (C) 2018-2024 Andre Przywara <[email protected]> | |
#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