linux/drivers/of/fdt.c
<<
>>
Prefs
   1/*
   2 * Functions for working with the Flattened Device Tree data format
   3 *
   4 * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
   5 * benh@kernel.crashing.org
   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
  12#include <linux/kernel.h>
  13#include <linux/initrd.h>
  14#include <linux/module.h>
  15#include <linux/of.h>
  16#include <linux/of_fdt.h>
  17#include <linux/string.h>
  18#include <linux/errno.h>
  19#include <linux/slab.h>
  20
  21#include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
  22#ifdef CONFIG_PPC
  23#include <asm/machdep.h>
  24#endif /* CONFIG_PPC */
  25
  26#include <asm/page.h>
  27
  28char *of_fdt_get_string(struct boot_param_header *blob, u32 offset)
  29{
  30        return ((char *)blob) +
  31                be32_to_cpu(blob->off_dt_strings) + offset;
  32}
  33
  34/**
  35 * of_fdt_get_property - Given a node in the given flat blob, return
  36 * the property ptr
  37 */
  38void *of_fdt_get_property(struct boot_param_header *blob,
  39                       unsigned long node, const char *name,
  40                       unsigned long *size)
  41{
  42        unsigned long p = node;
  43
  44        do {
  45                u32 tag = be32_to_cpup((__be32 *)p);
  46                u32 sz, noff;
  47                const char *nstr;
  48
  49                p += 4;
  50                if (tag == OF_DT_NOP)
  51                        continue;
  52                if (tag != OF_DT_PROP)
  53                        return NULL;
  54
  55                sz = be32_to_cpup((__be32 *)p);
  56                noff = be32_to_cpup((__be32 *)(p + 4));
  57                p += 8;
  58                if (be32_to_cpu(blob->version) < 0x10)
  59                        p = ALIGN(p, sz >= 8 ? 8 : 4);
  60
  61                nstr = of_fdt_get_string(blob, noff);
  62                if (nstr == NULL) {
  63                        pr_warning("Can't find property index name !\n");
  64                        return NULL;
  65                }
  66                if (strcmp(name, nstr) == 0) {
  67                        if (size)
  68                                *size = sz;
  69                        return (void *)p;
  70                }
  71                p += sz;
  72                p = ALIGN(p, 4);
  73        } while (1);
  74}
  75
  76/**
  77 * of_fdt_is_compatible - Return true if given node from the given blob has
  78 * compat in its compatible list
  79 * @blob: A device tree blob
  80 * @node: node to test
  81 * @compat: compatible string to compare with compatible list.
  82 *
  83 * On match, returns a non-zero value with smaller values returned for more
  84 * specific compatible values.
  85 */
  86int of_fdt_is_compatible(struct boot_param_header *blob,
  87                      unsigned long node, const char *compat)
  88{
  89        const char *cp;
  90        unsigned long cplen, l, score = 0;
  91
  92        cp = of_fdt_get_property(blob, node, "compatible", &cplen);
  93        if (cp == NULL)
  94                return 0;
  95        while (cplen > 0) {
  96                score++;
  97                if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
  98                        return score;
  99                l = strlen(cp) + 1;
 100                cp += l;
 101                cplen -= l;
 102        }
 103
 104        return 0;
 105}
 106
 107/**
 108 * of_fdt_match - Return true if node matches a list of compatible values
 109 */
 110int of_fdt_match(struct boot_param_header *blob, unsigned long node,
 111                 const char *const *compat)
 112{
 113        unsigned int tmp, score = 0;
 114
 115        if (!compat)
 116                return 0;
 117
 118        while (*compat) {
 119                tmp = of_fdt_is_compatible(blob, node, *compat);
 120                if (tmp && (score == 0 || (tmp < score)))
 121                        score = tmp;
 122                compat++;
 123        }
 124
 125        return score;
 126}
 127
 128static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
 129                                       unsigned long align)
 130{
 131        void *res;
 132
 133        *mem = ALIGN(*mem, align);
 134        res = (void *)*mem;
 135        *mem += size;
 136
 137        return res;
 138}
 139
 140/**
 141 * unflatten_dt_node - Alloc and populate a device_node from the flat tree
 142 * @blob: The parent device tree blob
 143 * @mem: Memory chunk to use for allocating device nodes and properties
 144 * @p: pointer to node in flat tree
 145 * @dad: Parent struct device_node
 146 * @allnextpp: pointer to ->allnext from last allocated device_node
 147 * @fpsize: Size of the node path up at the current depth.
 148 */
 149static unsigned long unflatten_dt_node(struct boot_param_header *blob,
 150                                unsigned long mem,
 151                                unsigned long *p,
 152                                struct device_node *dad,
 153                                struct device_node ***allnextpp,
 154                                unsigned long fpsize)
 155{
 156        struct device_node *np;
 157        struct property *pp, **prev_pp = NULL;
 158        char *pathp;
 159        u32 tag;
 160        unsigned int l, allocl;
 161        int has_name = 0;
 162        int new_format = 0;
 163
 164        tag = be32_to_cpup((__be32 *)(*p));
 165        if (tag != OF_DT_BEGIN_NODE) {
 166                pr_err("Weird tag at start of node: %x\n", tag);
 167                return mem;
 168        }
 169        *p += 4;
 170        pathp = (char *)*p;
 171        l = allocl = strlen(pathp) + 1;
 172        *p = ALIGN(*p + l, 4);
 173
 174        /* version 0x10 has a more compact unit name here instead of the full
 175         * path. we accumulate the full path size using "fpsize", we'll rebuild
 176         * it later. We detect this because the first character of the name is
 177         * not '/'.
 178         */
 179        if ((*pathp) != '/') {
 180                new_format = 1;
 181                if (fpsize == 0) {
 182                        /* root node: special case. fpsize accounts for path
 183                         * plus terminating zero. root node only has '/', so
 184                         * fpsize should be 2, but we want to avoid the first
 185                         * level nodes to have two '/' so we use fpsize 1 here
 186                         */
 187                        fpsize = 1;
 188                        allocl = 2;
 189                } else {
 190                        /* account for '/' and path size minus terminal 0
 191                         * already in 'l'
 192                         */
 193                        fpsize += l;
 194                        allocl = fpsize;
 195                }
 196        }
 197
 198        np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
 199                                __alignof__(struct device_node));
 200        if (allnextpp) {
 201                memset(np, 0, sizeof(*np));
 202                np->full_name = ((char *)np) + sizeof(struct device_node);
 203                if (new_format) {
 204                        char *fn = np->full_name;
 205                        /* rebuild full path for new format */
 206                        if (dad && dad->parent) {
 207                                strcpy(fn, dad->full_name);
 208#ifdef DEBUG
 209                                if ((strlen(fn) + l + 1) != allocl) {
 210                                        pr_debug("%s: p: %d, l: %d, a: %d\n",
 211                                                pathp, (int)strlen(fn),
 212                                                l, allocl);
 213                                }
 214#endif
 215                                fn += strlen(fn);
 216                        }
 217                        *(fn++) = '/';
 218                        memcpy(fn, pathp, l);
 219                } else
 220                        memcpy(np->full_name, pathp, l);
 221                prev_pp = &np->properties;
 222                **allnextpp = np;
 223                *allnextpp = &np->allnext;
 224                if (dad != NULL) {
 225                        np->parent = dad;
 226                        /* we temporarily use the next field as `last_child'*/
 227                        if (dad->next == NULL)
 228                                dad->child = np;
 229                        else
 230                                dad->next->sibling = np;
 231                        dad->next = np;
 232                }
 233                kref_init(&np->kref);
 234        }
 235        /* process properties */
 236        while (1) {
 237                u32 sz, noff;
 238                char *pname;
 239
 240                tag = be32_to_cpup((__be32 *)(*p));
 241                if (tag == OF_DT_NOP) {
 242                        *p += 4;
 243                        continue;
 244                }
 245                if (tag != OF_DT_PROP)
 246                        break;
 247                *p += 4;
 248                sz = be32_to_cpup((__be32 *)(*p));
 249                noff = be32_to_cpup((__be32 *)((*p) + 4));
 250                *p += 8;
 251                if (be32_to_cpu(blob->version) < 0x10)
 252                        *p = ALIGN(*p, sz >= 8 ? 8 : 4);
 253
 254                pname = of_fdt_get_string(blob, noff);
 255                if (pname == NULL) {
 256                        pr_info("Can't find property name in list !\n");
 257                        break;
 258                }
 259                if (strcmp(pname, "name") == 0)
 260                        has_name = 1;
 261                l = strlen(pname) + 1;
 262                pp = unflatten_dt_alloc(&mem, sizeof(struct property),
 263                                        __alignof__(struct property));
 264                if (allnextpp) {
 265                        /* We accept flattened tree phandles either in
 266                         * ePAPR-style "phandle" properties, or the
 267                         * legacy "linux,phandle" properties.  If both
 268                         * appear and have different values, things
 269                         * will get weird.  Don't do that. */
 270                        if ((strcmp(pname, "phandle") == 0) ||
 271                            (strcmp(pname, "linux,phandle") == 0)) {
 272                                if (np->phandle == 0)
 273                                        np->phandle = be32_to_cpup((__be32*)*p);
 274                        }
 275                        /* And we process the "ibm,phandle" property
 276                         * used in pSeries dynamic device tree
 277                         * stuff */
 278                        if (strcmp(pname, "ibm,phandle") == 0)
 279                                np->phandle = be32_to_cpup((__be32 *)*p);
 280                        pp->name = pname;
 281                        pp->length = sz;
 282                        pp->value = (void *)*p;
 283                        *prev_pp = pp;
 284                        prev_pp = &pp->next;
 285                }
 286                *p = ALIGN((*p) + sz, 4);
 287        }
 288        /* with version 0x10 we may not have the name property, recreate
 289         * it here from the unit name if absent
 290         */
 291        if (!has_name) {
 292                char *p1 = pathp, *ps = pathp, *pa = NULL;
 293                int sz;
 294
 295                while (*p1) {
 296                        if ((*p1) == '@')
 297                                pa = p1;
 298                        if ((*p1) == '/')
 299                                ps = p1 + 1;
 300                        p1++;
 301                }
 302                if (pa < ps)
 303                        pa = p1;
 304                sz = (pa - ps) + 1;
 305                pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
 306                                        __alignof__(struct property));
 307                if (allnextpp) {
 308                        pp->name = "name";
 309                        pp->length = sz;
 310                        pp->value = pp + 1;
 311                        *prev_pp = pp;
 312                        prev_pp = &pp->next;
 313                        memcpy(pp->value, ps, sz - 1);
 314                        ((char *)pp->value)[sz - 1] = 0;
 315                        pr_debug("fixed up name for %s -> %s\n", pathp,
 316                                (char *)pp->value);
 317                }
 318        }
 319        if (allnextpp) {
 320                *prev_pp = NULL;
 321                np->name = of_get_property(np, "name", NULL);
 322                np->type = of_get_property(np, "device_type", NULL);
 323
 324                if (!np->name)
 325                        np->name = "<NULL>";
 326                if (!np->type)
 327                        np->type = "<NULL>";
 328        }
 329        while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) {
 330                if (tag == OF_DT_NOP)
 331                        *p += 4;
 332                else
 333                        mem = unflatten_dt_node(blob, mem, p, np, allnextpp,
 334                                                fpsize);
 335                tag = be32_to_cpup((__be32 *)(*p));
 336        }
 337        if (tag != OF_DT_END_NODE) {
 338                pr_err("Weird tag at end of node: %x\n", tag);
 339                return mem;
 340        }
 341        *p += 4;
 342        return mem;
 343}
 344
 345/**
 346 * __unflatten_device_tree - create tree of device_nodes from flat blob
 347 *
 348 * unflattens a device-tree, creating the
 349 * tree of struct device_node. It also fills the "name" and "type"
 350 * pointers of the nodes so the normal device-tree walking functions
 351 * can be used.
 352 * @blob: The blob to expand
 353 * @mynodes: The device_node tree created by the call
 354 * @dt_alloc: An allocator that provides a virtual address to memory
 355 * for the resulting tree
 356 */
 357static void __unflatten_device_tree(struct boot_param_header *blob,
 358                             struct device_node **mynodes,
 359                             void * (*dt_alloc)(u64 size, u64 align))
 360{
 361        unsigned long start, mem, size;
 362        struct device_node **allnextp = mynodes;
 363
 364        pr_debug(" -> unflatten_device_tree()\n");
 365
 366        if (!blob) {
 367                pr_debug("No device tree pointer\n");
 368                return;
 369        }
 370
 371        pr_debug("Unflattening device tree:\n");
 372        pr_debug("magic: %08x\n", be32_to_cpu(blob->magic));
 373        pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize));
 374        pr_debug("version: %08x\n", be32_to_cpu(blob->version));
 375
 376        if (be32_to_cpu(blob->magic) != OF_DT_HEADER) {
 377                pr_err("Invalid device tree blob header\n");
 378                return;
 379        }
 380
 381        /* First pass, scan for size */
 382        start = ((unsigned long)blob) +
 383                be32_to_cpu(blob->off_dt_struct);
 384        size = unflatten_dt_node(blob, 0, &start, NULL, NULL, 0);
 385        size = (size | 3) + 1;
 386
 387        pr_debug("  size is %lx, allocating...\n", size);
 388
 389        /* Allocate memory for the expanded device tree */
 390        mem = (unsigned long)
 391                dt_alloc(size + 4, __alignof__(struct device_node));
 392
 393        ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
 394
 395        pr_debug("  unflattening %lx...\n", mem);
 396
 397        /* Second pass, do actual unflattening */
 398        start = ((unsigned long)blob) +
 399                be32_to_cpu(blob->off_dt_struct);
 400        unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0);
 401        if (be32_to_cpup((__be32 *)start) != OF_DT_END)
 402                pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
 403        if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef)
 404                pr_warning("End of tree marker overwritten: %08x\n",
 405                           be32_to_cpu(((__be32 *)mem)[size / 4]));
 406        *allnextp = NULL;
 407
 408        pr_debug(" <- unflatten_device_tree()\n");
 409}
 410
 411static void *kernel_tree_alloc(u64 size, u64 align)
 412{
 413        return kzalloc(size, GFP_KERNEL);
 414}
 415
 416/**
 417 * of_fdt_unflatten_tree - create tree of device_nodes from flat blob
 418 *
 419 * unflattens the device-tree passed by the firmware, creating the
 420 * tree of struct device_node. It also fills the "name" and "type"
 421 * pointers of the nodes so the normal device-tree walking functions
 422 * can be used.
 423 */
 424void of_fdt_unflatten_tree(unsigned long *blob,
 425                        struct device_node **mynodes)
 426{
 427        struct boot_param_header *device_tree =
 428                (struct boot_param_header *)blob;
 429        __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc);
 430}
 431EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
 432
 433/* Everything below here references initial_boot_params directly. */
 434int __initdata dt_root_addr_cells;
 435int __initdata dt_root_size_cells;
 436
 437struct boot_param_header *initial_boot_params;
 438
 439#ifdef CONFIG_OF_EARLY_FLATTREE
 440
 441/**
 442 * of_scan_flat_dt - scan flattened tree blob and call callback on each.
 443 * @it: callback function
 444 * @data: context data pointer
 445 *
 446 * This function is used to scan the flattened device-tree, it is
 447 * used to extract the memory information at boot before we can
 448 * unflatten the tree
 449 */
 450int __init of_scan_flat_dt(int (*it)(unsigned long node,
 451                                     const char *uname, int depth,
 452                                     void *data),
 453                           void *data)
 454{
 455        unsigned long p = ((unsigned long)initial_boot_params) +
 456                be32_to_cpu(initial_boot_params->off_dt_struct);
 457        int rc = 0;
 458        int depth = -1;
 459
 460        do {
 461                u32 tag = be32_to_cpup((__be32 *)p);
 462                char *pathp;
 463
 464                p += 4;
 465                if (tag == OF_DT_END_NODE) {
 466                        depth--;
 467                        continue;
 468                }
 469                if (tag == OF_DT_NOP)
 470                        continue;
 471                if (tag == OF_DT_END)
 472                        break;
 473                if (tag == OF_DT_PROP) {
 474                        u32 sz = be32_to_cpup((__be32 *)p);
 475                        p += 8;
 476                        if (be32_to_cpu(initial_boot_params->version) < 0x10)
 477                                p = ALIGN(p, sz >= 8 ? 8 : 4);
 478                        p += sz;
 479                        p = ALIGN(p, 4);
 480                        continue;
 481                }
 482                if (tag != OF_DT_BEGIN_NODE) {
 483                        pr_err("Invalid tag %x in flat device tree!\n", tag);
 484                        return -EINVAL;
 485                }
 486                depth++;
 487                pathp = (char *)p;
 488                p = ALIGN(p + strlen(pathp) + 1, 4);
 489                if ((*pathp) == '/') {
 490                        char *lp, *np;
 491                        for (lp = NULL, np = pathp; *np; np++)
 492                                if ((*np) == '/')
 493                                        lp = np+1;
 494                        if (lp != NULL)
 495                                pathp = lp;
 496                }
 497                rc = it(p, pathp, depth, data);
 498                if (rc != 0)
 499                        break;
 500        } while (1);
 501
 502        return rc;
 503}
 504
 505/**
 506 * of_get_flat_dt_root - find the root node in the flat blob
 507 */
 508unsigned long __init of_get_flat_dt_root(void)
 509{
 510        unsigned long p = ((unsigned long)initial_boot_params) +
 511                be32_to_cpu(initial_boot_params->off_dt_struct);
 512
 513        while (be32_to_cpup((__be32 *)p) == OF_DT_NOP)
 514                p += 4;
 515        BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE);
 516        p += 4;
 517        return ALIGN(p + strlen((char *)p) + 1, 4);
 518}
 519
 520/**
 521 * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr
 522 *
 523 * This function can be used within scan_flattened_dt callback to get
 524 * access to properties
 525 */
 526void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
 527                                 unsigned long *size)
 528{
 529        return of_fdt_get_property(initial_boot_params, node, name, size);
 530}
 531
 532/**
 533 * of_flat_dt_is_compatible - Return true if given node has compat in compatible list
 534 * @node: node to test
 535 * @compat: compatible string to compare with compatible list.
 536 */
 537int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
 538{
 539        return of_fdt_is_compatible(initial_boot_params, node, compat);
 540}
 541
 542/**
 543 * of_flat_dt_match - Return true if node matches a list of compatible values
 544 */
 545int __init of_flat_dt_match(unsigned long node, const char *const *compat)
 546{
 547        return of_fdt_match(initial_boot_params, node, compat);
 548}
 549
 550#ifdef CONFIG_BLK_DEV_INITRD
 551/**
 552 * early_init_dt_check_for_initrd - Decode initrd location from flat tree
 553 * @node: reference to node containing initrd location ('chosen')
 554 */
 555void __init early_init_dt_check_for_initrd(unsigned long node)
 556{
 557        unsigned long start, end, len;
 558        __be32 *prop;
 559
 560        pr_debug("Looking for initrd properties... ");
 561
 562        prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
 563        if (!prop)
 564                return;
 565        start = of_read_ulong(prop, len/4);
 566
 567        prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len);
 568        if (!prop)
 569                return;
 570        end = of_read_ulong(prop, len/4);
 571
 572        early_init_dt_setup_initrd_arch(start, end);
 573        pr_debug("initrd_start=0x%lx  initrd_end=0x%lx\n", start, end);
 574}
 575#else
 576inline void early_init_dt_check_for_initrd(unsigned long node)
 577{
 578}
 579#endif /* CONFIG_BLK_DEV_INITRD */
 580
 581/**
 582 * early_init_dt_scan_root - fetch the top level address and size cells
 583 */
 584int __init early_init_dt_scan_root(unsigned long node, const char *uname,
 585                                   int depth, void *data)
 586{
 587        __be32 *prop;
 588
 589        if (depth != 0)
 590                return 0;
 591
 592        dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
 593        dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
 594
 595        prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
 596        if (prop)
 597                dt_root_size_cells = be32_to_cpup(prop);
 598        pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
 599
 600        prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
 601        if (prop)
 602                dt_root_addr_cells = be32_to_cpup(prop);
 603        pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
 604
 605        /* break now */
 606        return 1;
 607}
 608
 609u64 __init dt_mem_next_cell(int s, __be32 **cellp)
 610{
 611        __be32 *p = *cellp;
 612
 613        *cellp = p + s;
 614        return of_read_number(p, s);
 615}
 616
 617/**
 618 * early_init_dt_scan_memory - Look for an parse memory nodes
 619 */
 620int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
 621                                     int depth, void *data)
 622{
 623        char *type = of_get_flat_dt_prop(node, "device_type", NULL);
 624        __be32 *reg, *endp;
 625        unsigned long l;
 626
 627        /* We are scanning "memory" nodes only */
 628        if (type == NULL) {
 629                /*
 630                 * The longtrail doesn't have a device_type on the
 631                 * /memory node, so look for the node called /memory@0.
 632                 */
 633                if (depth != 1 || strcmp(uname, "memory@0") != 0)
 634                        return 0;
 635        } else if (strcmp(type, "memory") != 0)
 636                return 0;
 637
 638        reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
 639        if (reg == NULL)
 640                reg = of_get_flat_dt_prop(node, "reg", &l);
 641        if (reg == NULL)
 642                return 0;
 643
 644        endp = reg + (l / sizeof(__be32));
 645
 646        pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
 647            uname, l, reg[0], reg[1], reg[2], reg[3]);
 648
 649        while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
 650                u64 base, size;
 651
 652                base = dt_mem_next_cell(dt_root_addr_cells, &reg);
 653                size = dt_mem_next_cell(dt_root_size_cells, &reg);
 654
 655                if (size == 0)
 656                        continue;
 657                pr_debug(" - %llx ,  %llx\n", (unsigned long long)base,
 658                    (unsigned long long)size);
 659
 660                early_init_dt_add_memory_arch(base, size);
 661        }
 662
 663        return 0;
 664}
 665
 666int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
 667                                     int depth, void *data)
 668{
 669        unsigned long l;
 670        char *p;
 671
 672        pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
 673
 674        if (depth != 1 || !data ||
 675            (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
 676                return 0;
 677
 678        early_init_dt_check_for_initrd(node);
 679
 680        /* Retrieve command line */
 681        p = of_get_flat_dt_prop(node, "bootargs", &l);
 682        if (p != NULL && l > 0)
 683                strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
 684
 685        /*
 686         * CONFIG_CMDLINE is meant to be a default in case nothing else
 687         * managed to set the command line, unless CONFIG_CMDLINE_FORCE
 688         * is set in which case we override whatever was found earlier.
 689         */
 690#ifdef CONFIG_CMDLINE
 691#ifndef CONFIG_CMDLINE_FORCE
 692        if (!((char *)data)[0])
 693#endif
 694                strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
 695#endif /* CONFIG_CMDLINE */
 696
 697        pr_debug("Command line is: %s\n", (char*)data);
 698
 699        /* break now */
 700        return 1;
 701}
 702
 703/**
 704 * unflatten_device_tree - create tree of device_nodes from flat blob
 705 *
 706 * unflattens the device-tree passed by the firmware, creating the
 707 * tree of struct device_node. It also fills the "name" and "type"
 708 * pointers of the nodes so the normal device-tree walking functions
 709 * can be used.
 710 */
 711void __init unflatten_device_tree(void)
 712{
 713        __unflatten_device_tree(initial_boot_params, &allnodes,
 714                                early_init_dt_alloc_memory_arch);
 715
 716        /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
 717        of_alias_scan(early_init_dt_alloc_memory_arch);
 718}
 719
 720#endif /* CONFIG_OF_EARLY_FLATTREE */
 721
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.