diff options
Diffstat (limited to 'scripts/dtc/treesource.c')
| -rw-r--r-- | scripts/dtc/treesource.c | 121 |
1 files changed, 73 insertions, 48 deletions
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c index 1af36628b75f..d25f01fc6937 100644 --- a/scripts/dtc/treesource.c +++ b/scripts/dtc/treesource.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" @@ -125,13 +110,13 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) fprintf(f, "%02"PRIx8, *(const uint8_t*)p); break; case 2: - fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); + fprintf(f, "0x%02"PRIx16, dtb_ld16(p)); break; case 4: - fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); + fprintf(f, "0x%02"PRIx32, dtb_ld32(p)); break; case 8: - fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); + fprintf(f, "0x%02"PRIx64, dtb_ld64(p)); break; } if (p + width < end) @@ -139,27 +124,6 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) } } -static bool has_data_type_information(struct marker *m) -{ - return m->type >= TYPE_UINT8; -} - -static struct marker *next_type_marker(struct marker *m) -{ - while (m && !has_data_type_information(m)) - m = m->next; - return m; -} - -size_t type_marker_length(struct marker *m) -{ - struct marker *next = next_type_marker(m->next); - - if (next) - return next->offset - m->offset; - return 0; -} - static const char *delim_start[] = { [TYPE_UINT8] = "[", [TYPE_UINT16] = "/bits/ 16 <", @@ -175,6 +139,50 @@ static const char *delim_end[] = { [TYPE_STRING] = "", }; +/* + * The invariants in the marker list are: + * - offsets are non-strictly monotonically increasing + * - for a single offset there is at most one type marker + * - for a single offset that has both a type marker and non-type markers, the + * type marker appears before the others. + */ +static struct marker **add_marker(struct marker **mi, + enum markertype type, unsigned int offset, char *ref) +{ + struct marker *nm; + + while (*mi && (*mi)->offset < offset) + mi = &(*mi)->next; + + if (*mi && (*mi)->offset == offset && is_type_marker((*mi)->type)) { + if (is_type_marker(type)) + return mi; + mi = &(*mi)->next; + } + + if (*mi && (*mi)->offset == offset && type == (*mi)->type) + return mi; + + nm = xmalloc(sizeof(*nm)); + nm->type = type; + nm->offset = offset; + nm->ref = ref; + nm->next = *mi; + *mi = nm; + + return &nm->next; +} + +static void add_string_markers(struct property *prop) +{ + int l, len = prop->val.len; + const char *p = prop->val.val; + struct marker **mi = &prop->val.markers; + + for (l = strlen(p) + 1; l < len; l += strlen(p + l) + 1) + mi = add_marker(mi, TYPE_STRING, l, NULL); +} + static enum markertype guess_value_type(struct property *prop) { int len = prop->val.len; @@ -198,8 +206,10 @@ static enum markertype guess_value_type(struct property *prop) nnotcelllbl++; } - if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) + if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul)) && (nnotstringlbl == 0)) { + if (nnul > 1) + add_string_markers(prop); return TYPE_STRING; } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { return TYPE_UINT32; @@ -244,26 +254,41 @@ static void write_propval(FILE *f, struct property *prop) size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; size_t data_len = type_marker_length(m) ? : len - m->offset; const char *p = &prop->val.val[m->offset]; + struct marker *m_phandle; - if (has_data_type_information(m)) { + if (is_type_marker(m->type)) { emit_type = m->type; fprintf(f, " %s", delim_start[emit_type]); } else if (m->type == LABEL) fprintf(f, " %s:", m->ref); - else if (m->offset) - fputc(' ', f); - if (emit_type == TYPE_NONE) { - assert(chunk_len == 0); + if (emit_type == TYPE_NONE || chunk_len == 0) continue; - } switch(emit_type) { case TYPE_UINT16: write_propval_int(f, p, chunk_len, 2); break; case TYPE_UINT32: - write_propval_int(f, p, chunk_len, 4); + m_phandle = prop->val.markers; + for_each_marker_of_type(m_phandle, REF_PHANDLE) + if (m->offset == m_phandle->offset) + break; + + if (m_phandle) { + if (m_phandle->ref[0] == '/') + fprintf(f, "&{%s}", m_phandle->ref); + else + fprintf(f, "&%s", m_phandle->ref); + if (chunk_len > 4) { + fputc(' ', f); + write_propval_int(f, p + 4, chunk_len - 4, 4); + } + } else { + write_propval_int(f, p, chunk_len, 4); + } + if (data_len > chunk_len) + fputc(' ', f); break; case TYPE_UINT64: write_propval_int(f, p, chunk_len, 8); |
