Last active
January 21, 2018 12:43
-
-
Save xypron/b3fd929b48a03494839b05917dbdd332 to your computer and use it in GitHub Desktop.
Show how a flattend file tree is traversed.
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
/* | |
* 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