~ubuntu-branches/ubuntu/wily/qemu-kvm-spice/wily

« back to all changes in this revision

Viewing changes to kvm/libfdt/fdt.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-10-19 10:44:56 UTC
  • Revision ID: james.westby@ubuntu.com-20111019104456-xgvskumk3sxi97f4
Tags: upstream-0.15.0+noroms
ImportĀ upstreamĀ versionĀ 0.15.0+noroms

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libfdt - Flat Device Tree manipulation
 
3
 * Copyright (C) 2006 David Gibson, IBM Corporation.
 
4
 *
 
5
 * libfdt is dual licensed: you can use it either under the terms of
 
6
 * the GPL, or the BSD license, at your option.
 
7
 *
 
8
 *  a) This library is free software; you can redistribute it and/or
 
9
 *     modify it under the terms of the GNU General Public License as
 
10
 *     published by the Free Software Foundation; either version 2 of the
 
11
 *     License, or (at your option) any later version.
 
12
 *
 
13
 *     This library is distributed in the hope that it will be useful,
 
14
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 *     GNU General Public License for more details.
 
17
 *
 
18
 *     You should have received a copy of the GNU General Public
 
19
 *     License along with this library; if not, write to the Free
 
20
 *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 
21
 *     MA 02110-1301 USA
 
22
 *
 
23
 * Alternatively,
 
24
 *
 
25
 *  b) Redistribution and use in source and binary forms, with or
 
26
 *     without modification, are permitted provided that the following
 
27
 *     conditions are met:
 
28
 *
 
29
 *     1. Redistributions of source code must retain the above
 
30
 *        copyright notice, this list of conditions and the following
 
31
 *        disclaimer.
 
32
 *     2. Redistributions in binary form must reproduce the above
 
33
 *        copyright notice, this list of conditions and the following
 
34
 *        disclaimer in the documentation and/or other materials
 
35
 *        provided with the distribution.
 
36
 *
 
37
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 
38
 *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 
39
 *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
40
 *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
41
 *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 
42
 *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
43
 *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
44
 *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
45
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
46
 *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
47
 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
48
 *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 
49
 *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
50
 */
 
51
#include "libfdt_env.h"
 
52
 
 
53
#include <fdt.h>
 
54
#include <libfdt.h>
 
55
 
 
56
#include "libfdt_internal.h"
 
57
 
 
58
int fdt_check_header(const void *fdt)
 
59
{
 
60
        if (fdt_magic(fdt) == FDT_MAGIC) {
 
61
                /* Complete tree */
 
62
                if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
 
63
                        return -FDT_ERR_BADVERSION;
 
64
                if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
 
65
                        return -FDT_ERR_BADVERSION;
 
66
        } else if (fdt_magic(fdt) == SW_MAGIC) {
 
67
                /* Unfinished sequential-write blob */
 
68
                if (fdt_size_dt_struct(fdt) == 0)
 
69
                        return -FDT_ERR_BADSTATE;
 
70
        } else {
 
71
                return -FDT_ERR_BADMAGIC;
 
72
        }
 
73
 
 
74
        return 0;
 
75
}
 
76
 
 
77
const void *fdt_offset_ptr(const void *fdt, int offset, int len)
 
78
{
 
79
        const void *p;
 
80
 
 
81
        if (fdt_version(fdt) >= 0x11)
 
82
                if (((offset + len) < offset)
 
83
                    || ((offset + len) > fdt_size_dt_struct(fdt)))
 
84
                        return NULL;
 
85
 
 
86
        p = _fdt_offset_ptr(fdt, offset);
 
87
 
 
88
        if (p + len < p)
 
89
                return NULL;
 
90
        return p;
 
91
}
 
92
 
 
93
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
 
94
{
 
95
        const uint32_t *tagp, *lenp;
 
96
        uint32_t tag;
 
97
        const char *p;
 
98
 
 
99
        if (offset % FDT_TAGSIZE)
 
100
                return -1;
 
101
 
 
102
        tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
 
103
        if (! tagp)
 
104
                return FDT_END; /* premature end */
 
105
        tag = fdt32_to_cpu(*tagp);
 
106
        offset += FDT_TAGSIZE;
 
107
 
 
108
        switch (tag) {
 
109
        case FDT_BEGIN_NODE:
 
110
                /* skip name */
 
111
                do {
 
112
                        p = fdt_offset_ptr(fdt, offset++, 1);
 
113
                } while (p && (*p != '\0'));
 
114
                if (! p)
 
115
                        return FDT_END;
 
116
                break;
 
117
        case FDT_PROP:
 
118
                lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
 
119
                if (! lenp)
 
120
                        return FDT_END;
 
121
                /* skip name offset, length and value */
 
122
                offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
 
123
                break;
 
124
        }
 
125
 
 
126
        if (nextoffset)
 
127
                *nextoffset = ALIGN(offset, FDT_TAGSIZE);
 
128
 
 
129
        return tag;
 
130
}
 
131
 
 
132
int fdt_next_node(const void *fdt, int offset, int *depth)
 
133
{
 
134
        int nextoffset = 0;
 
135
        uint32_t tag;
 
136
 
 
137
        if (offset >= 0) {
 
138
                tag = fdt_next_tag(fdt, offset, &nextoffset);
 
139
                if (tag != FDT_BEGIN_NODE)
 
140
                        return -FDT_ERR_BADOFFSET;
 
141
        }
 
142
 
 
143
        do {
 
144
                offset = nextoffset;
 
145
                tag = fdt_next_tag(fdt, offset, &nextoffset);
 
146
 
 
147
                switch (tag) {
 
148
                case FDT_PROP:
 
149
                case FDT_NOP:
 
150
                        break;
 
151
 
 
152
                case FDT_BEGIN_NODE:
 
153
                        if (depth)
 
154
                                (*depth)++;
 
155
                        break;
 
156
 
 
157
                case FDT_END_NODE:
 
158
                        if (depth)
 
159
                                (*depth)--;
 
160
                        break;
 
161
 
 
162
                case FDT_END:
 
163
                        return -FDT_ERR_NOTFOUND;
 
164
 
 
165
                default:
 
166
                        return -FDT_ERR_BADSTRUCTURE;
 
167
                }
 
168
        } while (tag != FDT_BEGIN_NODE);
 
169
 
 
170
        return offset;
 
171
}
 
172
 
 
173
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
 
174
{
 
175
        int len = strlen(s) + 1;
 
176
        const char *last = strtab + tabsize - len;
 
177
        const char *p;
 
178
 
 
179
        for (p = strtab; p <= last; p++)
 
180
                if (memeq(p, s, len))
 
181
                        return p;
 
182
        return NULL;
 
183
}
 
184
 
 
185
int fdt_move(const void *fdt, void *buf, int bufsize)
 
186
{
 
187
        CHECK_HEADER(fdt);
 
188
 
 
189
        if (fdt_totalsize(fdt) > bufsize)
 
190
                return -FDT_ERR_NOSPACE;
 
191
 
 
192
        memmove(buf, fdt, fdt_totalsize(fdt));
 
193
        return 0;
 
194
}