Skip to content

Instantly share code, notes, and snippets.

@xypron
Last active January 21, 2018 12:43
Show Gist options
  • Save xypron/b3fd929b48a03494839b05917dbdd332 to your computer and use it in GitHub Desktop.
Save xypron/b3fd929b48a03494839b05917dbdd332 to your computer and use it in GitHub Desktop.
Show how a flattend file tree is traversed.
/*
* Find value of top level property in device tree.
*
* Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <libfdt.h>
/* This should be sufficent for */
#define BUFFERSIZE 0x100000
/*
* Convert FDT value to host endianness.
*
* @val FDT value
* @return converted value
*/
static uint32_t f2h(fdt32_t val) {
char *buf = (char *)&val;
char i;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
i = buf[0]; buf[0] = buf[3]; buf[3] = i;
i = buf[1]; buf[1] = buf[2]; buf[2] = i;
#endif
return *(uint32_t *)buf;
}
/*
* Return the value of a property of an FDT node.
*
* @node FDT node
* @name name of the property
* @return value of the property
*/
static const char *get_property(const char *node, const char *property)
{
struct fdt_header *header = (struct fdt_header *)node;
const fdt32_t *fdt;
const char *strings;
if (FDT_MAGIC != f2h(header->magic)) {
printf("Wrong magic\n");
return NULL;
}
fdt = (fdt32_t *)(node + f2h(header->off_dt_struct));
strings = node + f2h(header->off_dt_strings);
for (;;) {
switch (f2h(fdt[0])) {
case FDT_BEGIN_NODE: {
char *c = (char *)&fdt[1];
size_t i;
for (i = 0; c[i]; ++i);
fdt = &fdt[2 + (i >> 2)];
break;
}
case FDT_PROP: {
struct fdt_property *prop =
(struct fdt_property *)fdt;
const char *label =
&strings[f2h(prop->nameoff)];
if (!strcmp(label, property))
return (char *)&fdt[3];
fdt = &fdt[3 + ((f2h(prop->len) + 3) >> 2)];
break;
}
case FDT_NOP:
fdt = &fdt[1];
break;
default:
return NULL;
}
}
}
int main(int argc, const char *argv[])
{
FILE *file;
char *buf;
size_t n;
if (argc < 3) {
printf("Usage\n %s FILE PROPERTY\n", argv[0]);
exit(EXIT_FAILURE);
}
file = fopen(argv[1], "r");
if (!file) {
perror("fopen");
exit(EXIT_FAILURE);
}
buf = malloc(BUFFERSIZE);
if (!buf) {
perror("malloc");
exit(EXIT_FAILURE);
}
memset(buf, 0, BUFFERSIZE);
n = fread(buf, 1, BUFFERSIZE, file);
if (!n) {
perror("fread");
goto out;
}
if (n == BUFFERSIZE) {
fprintf(stderr, "Internal buffer is too small\n");
goto out;
}
printf("%s = %s\n", argv[2], get_property(buf, argv[2]));
out:
fclose(file);
free(buf);
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment