Coverage Report

Created: 2026-10-13 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/barebox/common/state/backend_format_dtb.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2012-2014 Pengutronix, Jan Luebbe <j.luebbe@pengutronix.de>
3
 * Copyright (C) 2013-2014 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
4
 * Copyright (C) 2015 Pengutronix, Marc Kleine-Budde <mkl@pengutronix.de>
5
 * Copyright (C) 2016 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License
9
 * version 2, as published by the Free Software Foundation.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 */
17
18
#include <common.h>
19
#include <of.h>
20
#include <linux/kernel.h>
21
#include <malloc.h>
22
23
#include "state.h"
24
25
struct state_backend_format_dtb {
26
  struct state_backend_format format;
27
28
  struct device_node *root;
29
30
  /* For outputs */
31
  struct device *dev;
32
};
33
34
static inline struct state_backend_format_dtb *get_format_dtb(struct
35
                    state_backend_format
36
                    *format)
37
0
{
38
0
  return container_of(format, struct state_backend_format_dtb, format);
39
0
}
40
41
static int state_backend_format_dtb_verify(struct state_backend_format *format,
42
             uint32_t magic, const void * buf,
43
             ssize_t *lenp, enum state_flags flags)
44
0
{
45
0
  struct state_backend_format_dtb *fdtb = get_format_dtb(format);
46
0
  struct device_node *root;
47
0
  struct fdt_header *fdt = (struct fdt_header *)buf;
48
0
  size_t dtb_len;
49
0
  size_t len = *lenp;
50
51
0
  if (len < sizeof(*fdt))
52
0
    return -EINVAL;
53
54
0
  dtb_len = fdt32_to_cpu(fdt->totalsize);
55
0
  if (dtb_len > len) {
56
0
    dev_err(fdtb->dev, "Error, stored DTB length (%zd) longer than read buffer (%zd)\n",
57
0
      dtb_len, len);
58
0
    return -EINVAL;
59
0
  }
60
61
0
  if (fdtb->root) {
62
0
    of_delete_node(fdtb->root);
63
0
    fdtb->root = NULL;
64
0
  }
65
66
0
  root = of_unflatten_dtb(buf, dtb_len);
67
0
  if (IS_ERR(root)) {
68
0
    dev_err(fdtb->dev, "Failed to unflatten dtb from buffer with length %zd, %ld\n",
69
0
      len, PTR_ERR(root));
70
0
    return PTR_ERR(root);
71
0
  }
72
73
0
  fdtb->root = root;
74
75
0
  *lenp = be32_to_cpu(fdt->totalsize);
76
77
0
  return 0;
78
0
}
79
80
static int state_backend_format_dtb_unpack(struct state_backend_format *format,
81
             struct state *state,
82
             const void * buf, ssize_t len)
83
0
{
84
0
  struct state_backend_format_dtb *fdtb = get_format_dtb(format);
85
0
  int ret;
86
87
0
  if (!fdtb->root) {
88
0
    state_backend_format_dtb_verify(format, 0, buf, &len, 0);
89
0
  }
90
91
0
  ret = state_from_node(state, fdtb->root, 0);
92
0
  of_delete_node(fdtb->root);
93
0
  fdtb->root = NULL;
94
95
0
  return ret;
96
0
}
97
98
static int state_backend_format_dtb_pack(struct state_backend_format *format,
99
           struct state *state, void ** buf,
100
           ssize_t * len)
101
0
{
102
0
  struct state_backend_format_dtb *fdtb = get_format_dtb(format);
103
0
  struct device_node *root;
104
0
  struct fdt_header *fdt;
105
106
0
  root = state_to_node(state, NULL, STATE_CONVERT_TO_NODE);
107
0
  if (IS_ERR(root)) {
108
0
    dev_err(fdtb->dev, "Failed to convert state to device node, %ld\n",
109
0
      PTR_ERR(root));
110
0
    return PTR_ERR(root);
111
0
  }
112
113
0
  fdt = of_flatten_dtb(root);
114
0
  if (!fdt) {
115
0
    dev_err(fdtb->dev, "Failed to create flattened dtb\n");
116
0
    of_delete_node(root);
117
0
    return -EINVAL;
118
0
  }
119
120
0
  *buf = (uint8_t *) fdt;
121
0
  *len = fdt32_to_cpu(fdt->totalsize);
122
123
0
  if (fdtb->root)
124
0
    of_delete_node(fdtb->root);
125
0
  fdtb->root = root;
126
127
0
  return 0;
128
0
}
129
130
static void state_backend_format_dtb_free(struct state_backend_format *format)
131
0
{
132
0
  struct state_backend_format_dtb *fdtb = get_format_dtb(format);
133
134
0
  free(fdtb);
135
0
}
136
137
int backend_format_dtb_create(struct state_backend_format **format,
138
            struct device *dev)
139
0
{
140
0
  struct state_backend_format_dtb *dtb;
141
142
0
  dtb = xzalloc(sizeof(*dtb));
143
144
0
  dtb->dev = dev;
145
0
  dtb->format.pack = state_backend_format_dtb_pack;
146
0
  dtb->format.unpack = state_backend_format_dtb_unpack;
147
0
  dtb->format.verify = state_backend_format_dtb_verify;
148
0
  dtb->format.free = state_backend_format_dtb_free;
149
0
  dtb->format.name = "dtb";
150
0
  *format = &dtb->format;
151
152
0
  return 0;
153
0
}