Changeset c13e400 in rtems


Ignore:
Timestamp:
Jan 25, 2018, 5:13:40 AM (21 months ago)
Author:
Nathan Whitehorn <nwhitehorn@…>
Branches:
master
Children:
85d1769
Parents:
4e5f848
git-author:
Nathan Whitehorn <nwhitehorn@…> (01/25/18 05:13:40)
git-committer:
Sebastian Huber <sebastian.huber@…> (07/19/18 05:01:11)
Message:

Add limited read-only support for older (V2 and V3) device tree to libfdt.

This can be useful in particular in the kernel when booting on systems
with FDT-emitting firmware that is out of date. Releases of kexec-tools
on ppc64 prior to the end of 2014 are notable examples of such.

Signed-off-by: Nathan Whitehorn <nwhitehorn@…>
[dwg: Some whitespace cleanups]
Signed-off-by: David Gibson <david@…>

Location:
cpukit
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • cpukit/dtc/libfdt/fdt.c

    r4e5f848 rc13e400  
    124124                offset += sizeof(struct fdt_property) - FDT_TAGSIZE
    125125                        + fdt32_to_cpu(*lenp);
     126                if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
     127                    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
     128                        offset += 4;
    126129                break;
    127130
  • cpukit/dtc/libfdt/fdt_ro.c

    r4e5f848 rc13e400  
    5959                            const char *s, int len)
    6060{
    61         const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
    62 
    63         if (!p)
     61        int olen;
     62        const char *p = fdt_get_name(fdt, offset, &olen);
     63
     64        if (!p || olen < len)
    6465                /* short match */
    6566                return 0;
     
    234235{
    235236        const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
     237        const char *nameptr;
    236238        int err;
    237239
     
    240242                        goto fail;
    241243
     244        nameptr = nh->name;
     245
     246        if (fdt_version(fdt) < 0x10) {
     247                /*
     248                 * For old FDT versions, match the naming conventions of V16:
     249                 * give only the leaf name (after all /). The actual tree
     250                 * contents are loosely checked.
     251                 */
     252                const char *leaf;
     253                leaf = strrchr(nameptr, '/');
     254                if (leaf == NULL) {
     255                        err = -FDT_ERR_BADSTRUCTURE;
     256                        goto fail;
     257                }
     258                nameptr = leaf+1;
     259        }
     260
    242261        if (len)
    243                 *len = strlen(nh->name);
    244 
    245         return nh->name;
     262                *len = strlen(nameptr);
     263
     264        return nameptr;
    246265
    247266 fail:
     
    269288}
    270289
    271 const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
    272                                                       int offset,
    273                                                       int *lenp)
     290static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
     291                                                              int offset,
     292                                                              int *lenp)
    274293{
    275294        int err;
     
    290309}
    291310
     311const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
     312                                                      int offset,
     313                                                      int *lenp)
     314{
     315        /* Prior to version 16, properties may need realignment
     316         * and this API does not work. fdt_getprop_*() will, however. */
     317
     318        if (fdt_version(fdt) < 0x10) {
     319                if (lenp)
     320                        *lenp = -FDT_ERR_BADVERSION;
     321                return NULL;
     322        }
     323
     324        return fdt_get_property_by_offset_(fdt, offset, lenp);
     325}
     326
     327static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
     328                                                            int offset,
     329                                                            const char *name,
     330                                                            int namelen,
     331                                                            int *lenp,
     332                                                            int *poffset)
     333{
     334        for (offset = fdt_first_property_offset(fdt, offset);
     335             (offset >= 0);
     336             (offset = fdt_next_property_offset(fdt, offset))) {
     337                const struct fdt_property *prop;
     338
     339                if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
     340                        offset = -FDT_ERR_INTERNAL;
     341                        break;
     342                }
     343                if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
     344                                   name, namelen)) {
     345                        if (poffset)
     346                                *poffset = offset;
     347                        return prop;
     348                }
     349        }
     350
     351        if (lenp)
     352                *lenp = offset;
     353        return NULL;
     354}
     355
     356
    292357const struct fdt_property *fdt_get_property_namelen(const void *fdt,
    293358                                                    int offset,
     
    295360                                                    int namelen, int *lenp)
    296361{
    297         for (offset = fdt_first_property_offset(fdt, offset);
    298              (offset >= 0);
    299              (offset = fdt_next_property_offset(fdt, offset))) {
    300                 const struct fdt_property *prop;
    301 
    302                 if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
    303                         offset = -FDT_ERR_INTERNAL;
    304                         break;
    305                 }
    306                 if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
    307                                    name, namelen))
    308                         return prop;
    309         }
    310 
    311         if (lenp)
    312                 *lenp = offset;
    313         return NULL;
    314 }
     362        /* Prior to version 16, properties may need realignment
     363         * and this API does not work. fdt_getprop_*() will, however. */
     364        if (fdt_version(fdt) < 0x10) {
     365                if (lenp)
     366                        *lenp = -FDT_ERR_BADVERSION;
     367                return NULL;
     368        }
     369
     370        return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
     371                                         NULL);
     372}
     373
    315374
    316375const struct fdt_property *fdt_get_property(const void *fdt,
     
    325384                                const char *name, int namelen, int *lenp)
    326385{
     386        int poffset;
    327387        const struct fdt_property *prop;
    328388
    329         prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
     389        prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
     390                                         &poffset);
    330391        if (!prop)
    331392                return NULL;
    332393
     394        /* Handle realignment */
     395        if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
     396            fdt32_to_cpu(prop->len) >= 8)
     397                return prop->data + 4;
    333398        return prop->data;
    334399}
     
    339404        const struct fdt_property *prop;
    340405
    341         prop = fdt_get_property_by_offset(fdt, offset, lenp);
     406        prop = fdt_get_property_by_offset_(fdt, offset, lenp);
    342407        if (!prop)
    343408                return NULL;
    344409        if (namep)
    345410                *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
     411
     412        /* Handle realignment */
     413        if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
     414            fdt32_to_cpu(prop->len) >= 8)
     415                return prop->data + 4;
    346416        return prop->data;
    347417}
  • cpukit/include/libfdt.h

    r4e5f848 rc13e400  
    5555#include <fdt.h>
    5656
    57 #define FDT_FIRST_SUPPORTED_VERSION     0x10
     57#define FDT_FIRST_SUPPORTED_VERSION     0x02
    5858#define FDT_LAST_SUPPORTED_VERSION      0x11
    5959
     
    528528 * also returned, in the integer pointed to by lenp.
    529529 *
     530 * Note that this code only works on device tree versions >= 16. fdt_getprop()
     531 * works on all versions.
     532 *
    530533 * returns:
    531534 *      pointer to the structure representing the property
Note: See TracChangeset for help on using the changeset viewer.