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                        l = 1;
 190                        *pathp = '\0';
 191                } else {
 192                        /* account for '/' and path size minus terminal 0
 193                         * already in 'l'
 194                         */
 195                        fpsize += l;
 196                        allocl = fpsize;
 197                }
 198        }
 199
 200        np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
 201                                __alignof__(struct device_node));
 202        if (allnextpp) {
 203                char *fn;
 204                memset(np, 0, sizeof(*np));
 205                np->full_name = fn = ((char *)np) + sizeof(*np);
 206                if (new_format) {
 207                        /* rebuild full path for new format */
 208                        if (dad && dad->parent) {
 209                                strcpy(fn, dad->full_name);
 210#ifdef DEBUG
 211                                if ((strlen(fn) + l + 1) != allocl) {
 212                                        pr_debug("%s: p: %d, l: %d, a: %d\n",
 213                                                pathp, (int)strlen(fn),
 214                                                l, allocl);
 215                                }
 216#endif
 217                                fn += strlen(fn);
 218                        }
 219                        *(fn++) = '/';
 220                }
 221                memcpy(fn, pathp, l);
 222
 223                prev_pp = &np->properties;
 224                **allnextpp = np;
 225                *allnextpp = &np->allnext;
 226                if (dad != NULL) {
 227                        np->parent = dad;
 228                        /* we temporarily use the next field as `last_child'*/
 229                        if (dad->next == NULL)
 230                                dad->child = np;
 231                        else
 232                                dad->next->sibling = np;
 233                        dad->next = np;
 234                }
 235                kref_init(&np->kref);
 236        }
 237        /* process properties */
 238        while (1) {
 239                u32 sz, noff;
 240                char *pname;
 241
 242                tag = be32_to_cpup((__be32 *)(*p));
 243                if (tag == OF_DT_NOP) {
 244                        *p += 4;
 245                        continue;
 246                }
 247                if (tag != OF_DT_PROP)
 248                        break;
 249                *p += 4;
 250                sz = be32_to_cpup((__be32 *)(*p));
 251                noff = be32_to_cpup((__be32 *)((*p) + 4));
 252                *p += 8;
 253                if (be32_to_cpu(blob->version) < 0x10)
 254                        *p = ALIGN(*p, sz >= 8 ? 8 : 4);
 255
 256                pname = of_fdt_get_string(blob, noff);
 257                if (pname == NULL) {
 258                        pr_info("Can't find property name in list !\n");
 259                        break;
 260                }
 261                if (strcmp(pname, "name") == 0)
 262                        has_name = 1;
 263                l = strlen(pname) + 1;
 264                pp = unflatten_dt_alloc(&mem, sizeof(struct property),
 265                                        __alignof__(struct property));
 266                if (allnextpp) {
 267                        /* We accept flattened tree phandles either in
 268                         * ePAPR-style "phandle" properties, or the
 269                         * legacy "linux,phandle" properties.  If both
 270                         * appear and have different values, things
 271                         * will get weird.  Don't do that. */
 272                        if ((strcmp(pname, "phandle") == 0) ||
 273                            (strcmp(pname, "linux,phandle") == 0)) {
 274                                if (np->phandle == 0)
 275                                        np->phandle = be32_to_cpup((__be32*)*p);
 276                        }
 277                        /* And we process the "ibm,phandle" property
 278                         * used in pSeries dynamic device tree
 279                         * stuff */
 280                        if (strcmp(pname, "ibm,phandle") == 0)
 281                                np->phandle = be32_to_cpup((__be32 *)*p);
 282                        pp->name = pname;
 283                        pp->length = sz;
 284                        pp->value = (void *)*p;
 285                        *prev_pp = pp;
 286                        prev_pp = &pp->next;
 287                }
 288                *p = ALIGN((*p) + sz, 4);
 289        }
 290        /* with version 0x10 we may not have the name property, recreate
 291         * it here from the unit name if absent
 292         */
 293        if (!has_name) {
 294                char *p1 = pathp, *ps = pathp, *pa = NULL;
 295                int sz;
 296
 297                while (*p1) {
 298                        if ((*p1) == '@')
 299                                pa = p1;
 300                        if ((*p1) == '/')
 301                                ps = p1 + 1;
 302                        p1++;
 303                }
 304                if (pa < ps)
 305                        pa = p1;
 306                sz = (pa - ps) + 1;
 307                pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
 308                                        __alignof__(struct property));
 309                if (allnextpp) {
 310                        pp->name = "name";
 311                        pp->length = sz;
 312                        pp->value = pp + 1;
 313                        *prev_pp = pp;
 314                        prev_pp = &pp->next;
 315                        memcpy(pp->value, ps, sz - 1);
 316                        ((char *)pp->value)[sz - 1] = 0;
 317                        pr_debug("fixed up name for %s -> %s\n", pathp,
 318                                (char *)pp->value);
 319                }
 320        }
 321        if (allnextpp) {
 322                *prev_pp = NULL;
 323                np->name = of_get_property(np, "name", NULL);
 324                np->type = of_get_property(np, "device_type", NULL);
 325
 326                if (!np->name)
 327                        np->name = "<NULL>";
 328                if (!np->type)
 329                        np->type = "<NULL>";
 330        }
 331        while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) {
 332                if (tag == OF_DT_NOP)
 333                        *p += 4;
 334                else
 335                        mem = unflatten_dt_node(blob, mem, p, np, allnextpp,
 336                                                fpsize);
 337                tag = be32_to_cpup((__be32 *)(*p));
 338        }
 339        if (tag != OF_DT_END_NODE) {
 340                pr_err("Weird tag at end of node: %x\n", tag);
 341                return mem;
 342        }
 343        *p += 4;
 344        return mem;
 345}
 346
 347/**
 348 * __unflatten_device_tree - create tree of device_nodes from flat blob
 349 *
 350 * unflattens a device-tree, creating the
 351 * tree of struct device_node. It also fills the "name" and "type"
 352 * pointers of the nodes so the normal device-tree walking functions
 353 * can be used.
 354 * @blob: The blob to expand
 355 * @mynodes: The device_node tree created by the call
 356 * @dt_alloc: An allocator that provides a virtual address to memory
 357 * for the resulting tree
 358 */
 359static void __unflatten_device_tree(struct boot_param_header *blob,
 360                             struct device_node **mynodes,
 361                             void * (*dt_alloc)(u64 size, u64 align))
 362{
 363        unsigned long start, mem, size;
 364        struct device_node **allnextp = mynodes;
 365
 366        pr_debug(" -> unflatten_device_tree()\n");
 367
 368        if (!blob) {
 369                pr_debug("No device tree pointer\n");
 370                return;
 371        }
 372
 373        pr_debug("Unflattening device tree:\n");
 374        pr_debug("magic: %08x\n", be32_to_cpu(blob->magic));
 375        pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize));
 376        pr_debug("version: %08x\n", be32_to_cpu(blob->version));
 377
 378        if (be32_to_cpu(blob->magic) != OF_DT_HEADER) {
 379                pr_err("Invalid device tree blob header\n");
 380                return;
 381        }
 382
 383        /* First pass, scan for size */
 384        start = ((unsigned long)blob) +
 385                be32_to_cpu(blob->off_dt_struct);
 386        size = unflatten_dt_node(blob, 0, &start, NULL, NULL, 0);
 387        size = (size | 3) + 1;
 388
 389        pr_debug("  size is %lx, allocating...\n", size);
 390
 391        /* Allocate memory for the expanded device tree */
 392        mem = (unsigned long)
 393                dt_alloc(size + 4, __alignof__(struct device_node));
 394
 395        ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
 396
 397        pr_debug("  unflattening %lx...\n", mem);
 398
 399        /* Second pass, do actual unflattening */
 400        start = ((unsigned long)blob) +
 401                be32_to_cpu(blob->off_dt_struct);
 402        unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0);
 403        if (be32_to_cpup((__be32 *)start) != OF_DT_END)
 404                pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
 405        if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef)
 406                pr_warning("End of tree marker overwritten: %08x\n",
 407                           be32_to_cpu(((__be32 *)mem)[size / 4]));
 408        *allnextp = NULL;
 409
 410        pr_debug(" <- unflatten_device_tree()\n");
 411}
 412
 413static void *kernel_tree_alloc(u64 size, u64 align)
 414{
 415        return kzalloc(size, GFP_KERNEL);
 416}
 417
 418/**
 419 * of_fdt_unflatten_tree - create tree of device_nodes from flat blob
 420 *
 421 * unflattens the device-tree passed by the firmware, creating the
 422 * tree of struct device_node. It also fills the "name" and "type"
 423 * pointers of the nodes so the normal device-tree walking functions
 424 * can be used.
 425 */
 426void of_fdt_unflatten_tree(unsigned long *blob,
 427                        struct device_node **mynodes)
 428{
 429        struct boot_param_header *device_tree =
 430                (struct boot_param_header *)blob;
 431        __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc);
 432}
 433EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
 434
 435/* Everything below here references initial_boot_params directly. */
 436int __initdata dt_root_addr_cells;
 437int __initdata dt_root_size_cells;
 438
 439struct boot_param_header *initial_boot_params;
 440
 441#ifdef CONFIG_OF_EARLY_FLATTREE
 442
 443/**
 444 * of_scan_flat_dt - scan flattened tree blob and call callback on each.
 445 * @it: callback function
 446 * @data: context data pointer
 447 *
 448 * This function is used to scan the flattened device-tree, it is
 449 * used to extract the memory information at boot before we can
 450 * unflatten the tree
 451 */
 452int __init of_scan_flat_dt(int (*it)(unsigned long node,
 453                                     const char *uname, int depth,
 454                                     void *data),
 455                           void *data)
 456{
 457        unsigned long p = ((unsigned long)initial_boot_params) +
 458                be32_to_cpu(initial_boot_params->off_dt_struct);
 459        int rc = 0;
 460        int depth = -1;
 461
 462        do {
 463                u32 tag = be32_to_cpup((__be32 *)p);
 464                const char *pathp;
 465
 466                p += 4;
 467                if (tag == OF_DT_END_NODE) {
 468                        depth--;
 469                        continue;
 470                }
 471                if (tag == OF_DT_NOP)
 472                        continue;
 473                if (tag == OF_DT_END)
 474                        break;
 475                if (tag == OF_DT_PROP) {
 476                        u32 sz = be32_to_cpup((__be32 *)p);
 477                        p += 8;
 478                        if (be32_to_cpu(initial_boot_params->version) < 0x10)
 479                                p = ALIGN(p, sz >= 8 ? 8 : 4);
 480                        p += sz;
 481                        p = ALIGN(p, 4);
 482                        continue;
 483                }
 484                if (tag != OF_DT_BEGIN_NODE) {
 485                        pr_err("Invalid tag %x in flat device tree!\n", tag);
 486                        return -EINVAL;
 487                }
 488                depth++;
 489                pathp = (char *)p;
 490                p = ALIGN(p + strlen(pathp) + 1, 4);
 491                if (*pathp == '/')
 492                        pathp = kbasename(pathp);
 493                rc = it(p, pathp, depth, data);
 494                if (rc != 0)
 495                        break;
 496        } while (1);
 497
 498        return rc;
 499}
 500
 501/**
 502 * of_get_flat_dt_root - find the root node in the flat blob
 503 */
 504unsigned long __init of_get_flat_dt_root(void)
 505{
 506        unsigned long p = ((unsigned long)initial_boot_params) +
 507                be32_to_cpu(initial_boot_params->off_dt_struct);
 508
 509        while (be32_to_cpup((__be32 *)p) == OF_DT_NOP)
 510                p += 4;
 511        BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE);
 512        p += 4;
 513        return ALIGN(p + strlen((char *)p) + 1, 4);
 514}
 515
 516/**
 517 * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr
 518 *
 519 * This function can be used within scan_flattened_dt callback to get
 520 * access to properties
 521 */
 522void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
 523                                 unsigned long *size)
 524{
 525        return of_fdt_get_property(initial_boot_params, node, name, size);
 526}
 527
 528/**
 529 * of_flat_dt_is_compatible - Return true if given node has compat in compatible list
 530 * @node: node to test
 531 * @compat: compatible string to compare with compatible list.
 532 */
 533int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
 534{
 535        return of_fdt_is_compatible(initial_boot_params, node, compat);
 536}
 537
 538/**
 539 * of_flat_dt_match - Return true if node matches a list of compatible values
 540 */
 541int __init of_flat_dt_match(unsigned long node, const char *const *compat)
 542{
 543        return of_fdt_match(initial_boot_params, node, compat);
 544}
 545
 546#ifdef CONFIG_BLK_DEV_INITRD
 547/**
 548 * early_init_dt_check_for_initrd - Decode initrd location from flat tree
 549 * @node: reference to node containing initrd location ('chosen')
 550 */
 551void __init early_init_dt_check_for_initrd(unsigned long node)
 552{
 553        unsigned long start, end, len;
 554        __be32 *prop;
 555
 556        pr_debug("Looking for initrd properties... ");
 557
 558        prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
 559        if (!prop)
 560                return;
 561        start = of_read_ulong(prop, len/4);
 562
 563        prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len);
 564        if (!prop)
 565                return;
 566        end = of_read_ulong(prop, len/4);
 567
 568        early_init_dt_setup_initrd_arch(start, end);
 569        pr_debug("initrd_start=0x%lx  initrd_end=0x%lx\n", start, end);
 570}
 571#else
 572inline void early_init_dt_check_for_initrd(unsigned long node)
 573{
 574}
 575#endif /* CONFIG_BLK_DEV_INITRD */
 576
 577/**
 578 * early_init_dt_scan_root - fetch the top level address and size cells
 579 */
 580int __init early_init_dt_scan_root(unsigned long node, const char *uname,
 581                                   int depth, void *data)
 582{
 583        __be32 *prop;
 584
 585        if (depth != 0)
 586                return 0;
 587
 588        dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
 589        dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
 590
 591        prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
 592        if (prop)
 593                dt_root_size_cells = be32_to_cpup(prop);
 594        pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
 595
 596        prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
 597        if (prop)
 598                dt_root_addr_cells = be32_to_cpup(prop);
 599        pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
 600
 601        /* break now */
 602        return 1;
 603}
 604
 605u64 __init dt_mem_next_cell(int s, __be32 **cellp)
 606{
 607        __be32 *p = *cellp;
 608
 609        *cellp = p + s;
 610        return of_read_number(p, s);
 611}
 612
 613/**
 614 * early_init_dt_scan_memory - Look for an parse memory nodes
 615 */
 616int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
 617                                     int depth, void *data)
 618{
 619        char *type = of_get_flat_dt_prop(node, "device_type", NULL);
 620        __be32 *reg, *endp;
 621        unsigned long l;
 622
 623        /* We are scanning "memory" nodes only */
 624        if (type == NULL) {
 625                /*
 626                 * The longtrail doesn't have a device_type on the
 627                 * /memory node, so look for the node called /memory@0.
 628                 */
 629                if (depth != 1 || strcmp(uname, "memory@0") != 0)
 630                        return 0;
 631        } else if (strcmp(type, "memory") != 0)
 632                return 0;
 633
 634        reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
 635        if (reg == NULL)
 636                reg = of_get_flat_dt_prop(node, "reg", &l);
 637        if (reg == NULL)
 638                return 0;
 639
 640        endp = reg + (l / sizeof(__be32));
 641
 642        pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
 643            uname, l, reg[0], reg[1], reg[2], reg[3]);
 644
 645        while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
 646                u64 base, size;
 647
 648                base = dt_mem_next_cell(dt_root_addr_cells, &reg);
 649                size = dt_mem_next_cell(dt_root_size_cells, &reg);
 650
 651                if (size == 0)
 652                        continue;
 653                pr_debug(" - %llx ,  %llx\n", (unsigned long long)base,
 654                    (unsigned long long)size);
 655
 656                early_init_dt_add_memory_arch(base, size);
 657        }
 658
 659        return 0;
 660}
 661
 662int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
 663                                     int depth, void *data)
 664{
 665        unsigned long l;
 666        char *p;
 667
 668        pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
 669
 670        if (depth != 1 || !data ||
 671            (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
 672                return 0;
 673
 674        early_init_dt_check_for_initrd(node);
 675
 676        /* Retrieve command line */
 677        p = of_get_flat_dt_prop(node, "bootargs", &l);
 678        if (p != NULL && l > 0)
 679                strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
 680
 681        /*
 682         * CONFIG_CMDLINE is meant to be a default in case nothing else
 683         * managed to set the command line, unless CONFIG_CMDLINE_FORCE
 684         * is set in which case we override whatever was found earlier.
 685         */
 686#ifdef CONFIG_CMDLINE
 687#ifndef CONFIG_CMDLINE_FORCE
 688        if (!((char *)data)[0])
 689#endif
 690                strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
 691#endif /* CONFIG_CMDLINE */
 692
 693        pr_debug("Command line is: %s\n", (char*)data);
 694
 695        /* break now */
 696        return 1;
 697}
 698
 699/**
 700 * unflatten_device_tree - create tree of device_nodes from flat blob
 701 *
 702 * unflattens the device-tree passed by the firmware, creating the
 703 * tree of struct device_node. It also fills the "name" and "type"
 704 * pointers of the nodes so the normal device-tree walking functions
 705 * can be used.
 706 */
 707void __init unflatten_device_tree(void)
 708{
 709        __unflatten_device_tree(initial_boot_params, &of_allnodes,
 710                                early_init_dt_alloc_memory_arch);
 711
 712        /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
 713        of_alias_scan(early_init_dt_alloc_memory_arch);
 714}
 715
 716#endif /* CONFIG_OF_EARLY_FLATTREE */
 717
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.