Re: [RFC PATCH v3 2/4] dtc: Add a live tree API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



Hi Andrei,

On Sun, 6 Sep 2020 at 07:13, Andrei Ziureaev <andreiziureaev@xxxxxxxxx> wrote:
>
> The purpose of this API is to completely abstract away the internal live
> tree implementation.
>
> This API can traverse the tree and read its values. This is enough to
> validate the tree in Python, for example. We could add more
> functionality, documentation and tests, and turn it into a separate
> library.
>
> Signed-off-by: Andrei Ziureaev <andrei.ziureaev@xxxxxxx>
> Signed-off-by: Andrei Ziureaev <andreiziureaev@xxxxxxxxx>
> ---
>  Makefile.dtc |   1 +
>  dt.c         | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  dt.h         |  63 ++++++++++++++++++++
>  3 files changed, 222 insertions(+)
>  create mode 100644 dt.c
>  create mode 100644 dt.h
>
> diff --git a/Makefile.dtc b/Makefile.dtc
> index 9c467b0..09b3123 100644
> --- a/Makefile.dtc
> +++ b/Makefile.dtc
> @@ -7,6 +7,7 @@
>  DTC_SRCS = \
>         checks.c \
>         data.c \
> +       dt.c \
>         dtc.c \
>         flattree.c \
>         fstree.c \
> diff --git a/dt.c b/dt.c
> new file mode 100644
> index 0000000..5024e63
> --- /dev/null
> +++ b/dt.c
> @@ -0,0 +1,158 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * (C) Copyright Arm Holdings.  2020
> + */
> +
> +#include "dt.h"
> +#include "dtc.h"
> +
> +struct node *dt_root(struct dt_info *dti)
> +{
> +       return dti->dt;
> +}
> +
> +struct node *dt_first_child(struct node *node)
> +{
> +       return node->children;
> +}
> +
> +struct node *dt_next_sibling(struct node *node)
> +{
> +       return node->next_sibling;
> +}
> +
> +struct property *dt_first_property(struct node *node)
> +{
> +       return node->proplist;
> +}
> +
> +struct property *dt_next_property(struct property *prop)
> +{
> +       return prop->next;
> +}
> +
> +struct marker *dt_first_row(struct property *prop)
> +{
> +       return next_type_marker(prop->val.markers);
> +}
> +
> +struct marker *dt_next_row(struct marker *row)
> +{
> +       return next_type_marker(row->next);
> +}
> +
> +int dt_row_length(struct property *prop, struct marker *row)
> +{
> +       int length_bytes = type_marker_length(row) ? : prop->val.len - row->offset;
> +       return length_bytes / dt_cell_width_bytes(row);
> +}
> +
> +uint64_t dt_uint(struct property *prop, struct marker *row, int col)
> +{
> +       int width = dt_cell_width_bytes(row);
> +       const char *p = &dt_string(prop, row)[col * width];
> +
> +       switch(width) {
> +       case 2:
> +               return dtb_ld16(p);
> +       case 4:
> +               return dtb_ld32(p);
> +       case 8:
> +               return dtb_ld64(p);
> +       default:
> +               return *(const uint8_t*)p;
> +       }
> +}
> +
> +bool dt_cell_is_phandle(struct property *prop, struct marker *row, int col)
> +{
> +       int width = dt_cell_width_bytes(row);
> +       int off = row->offset + col * width;
> +
> +       if (width != 4)
> +               return false;
> +
> +       return markers_have_type_at_offset(row, REF_PHANDLE, off);
> +}
> +
> +const char *dt_string(struct property *prop, struct marker *row)
> +{
> +       return &prop->val.val[row->offset];
> +}
> +
> +enum dt_type dt_row_type(struct marker *row)
> +{
> +       switch (row->type) {
> +       /* fallthrough */
> +       case TYPE_UINT8:
> +       case TYPE_UINT16:
> +       case TYPE_UINT32:
> +       case TYPE_UINT64:
> +               return DT_TYPE_UINT;
> +       case TYPE_STRING:
> +               return DT_TYPE_STRING;
> +       default:
> +               return DT_TYPE_NONE;
> +       }
> +}
> +
> +const char *dt_row_type_name(struct marker *row)
> +{
> +       switch (dt_row_type(row)) {
> +       case DT_TYPE_UINT:
> +               return "uint";
> +       case DT_TYPE_STRING:
> +               return "string";
> +       default:
> +               return "none";
> +       }
> +}
> +
> +int dt_cell_width_bytes(struct marker *row)
> +{
> +       switch (row->type) {
> +       case TYPE_UINT16:
> +               return 2;
> +       case TYPE_UINT32:
> +               return 4;
> +       case TYPE_UINT64:
> +               return 8;
> +       default:
> +               return 1;
> +       }
> +}
> +
> +const char *dt_node_name(struct node *node)
> +{
> +       return *node->name ? node->name : "/";
> +}
> +
> +struct srcpos *dt_node_srcpos(struct node *node)
> +{
> +       return node->srcpos;
> +}
> +
> +const char *dt_property_name(struct property *prop)
> +{
> +       return prop->name;
> +}
> +
> +struct srcpos *dt_property_srcpos(struct property *prop)
> +{
> +       return prop->srcpos;
> +}
> +
> +const char *dt_srcpos_dir(struct srcpos *srcpos)
> +{
> +       return srcpos->file->dir;
> +}
> +
> +const char *dt_srcpos_file_name(struct srcpos *srcpos)
> +{
> +       return srcpos->file->name;
> +}
> +
> +int dt_srcpos_first_line(struct srcpos *srcpos)
> +{
> +       return srcpos->first_line;
> +}
> diff --git a/dt.h b/dt.h
> new file mode 100644
> index 0000000..c6af112
> --- /dev/null
> +++ b/dt.h
> @@ -0,0 +1,63 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +#ifndef DT_H
> +#define DT_H
> +
> +/*
> + * (C) Copyright Arm Holdings.  2020
> + */
> +
> +#include <stdint.h>
> +#include <stdbool.h>
> +
> +#include "srcpos.h"
> +
> +struct dt_info;
> +struct node;
> +struct property;
> +struct marker;
> +
> +enum dt_type {
> +       DT_TYPE_NONE,
> +       DT_TYPE_UINT,
> +       DT_TYPE_STRING,
> +};
> +
> +/* Traversal */
> +struct node *dt_root(struct dt_info *dti);
> +
> +struct node *dt_first_child(struct node *node);
> +struct node *dt_next_sibling(struct node *node);
> +
> +struct property *dt_first_property(struct node *node);
> +struct property *dt_next_property(struct property *prop);
> +
> +/* A property value resembles a matrix (or a table). A marker with data
> + * type information can represent a row.
> + *
> + * So, each property has a linked list of rows. */
> +struct marker *dt_first_row(struct property *prop);
> +struct marker *dt_next_row(struct marker *row);
> +
> +/* Accessing data. Each row is an array of cells. */
> +int dt_row_length(struct property *prop, struct marker *row);
> +
> +uint64_t dt_uint(struct property *prop, struct marker *row, int col);
> +bool dt_cell_is_phandle(struct property *prop, struct marker *row, int col);
> +const char *dt_string(struct property *prop, struct marker *row);
> +
> +/* Accessing metadata */
> +enum dt_type dt_row_type(struct marker *row);
> +const char *dt_row_type_name(struct marker *row);
> +int dt_cell_width_bytes(struct marker *row);
> +
> +const char *dt_node_name(struct node *node);
> +struct srcpos *dt_node_srcpos(struct node *node);
> +
> +const char *dt_property_name(struct property *prop);
> +struct srcpos *dt_property_srcpos(struct property *prop);
> +
> +const char *dt_srcpos_dir(struct srcpos *srcpos);
> +const char *dt_srcpos_file_name(struct srcpos *srcpos);
> +int dt_srcpos_first_line(struct srcpos *srcpos);

How about adding full comments for these functions?

> +
> +#endif /* DT_H */
> --
> 2.17.1
>

Regards,
Simon



[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux