File:  [Qemu by Fabrice Bellard] / qemu / device_tree.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:18:02 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, qemu1001, HEAD
qemu 1.0.1

    1: /*
    2:  * Functions to help device tree manipulation using libfdt.
    3:  * It also provides functions to read entries from device tree proc
    4:  * interface.
    5:  *
    6:  * Copyright 2008 IBM Corporation.
    7:  * Authors: Jerone Young <jyoung5@us.ibm.com>
    8:  *          Hollis Blanchard <hollisb@us.ibm.com>
    9:  *
   10:  * This work is licensed under the GNU GPL license version 2 or later.
   11:  *
   12:  */
   13: 
   14: #include <stdio.h>
   15: #include <sys/types.h>
   16: #include <sys/stat.h>
   17: #include <fcntl.h>
   18: #include <unistd.h>
   19: #include <stdlib.h>
   20: 
   21: #include "config.h"
   22: #include "qemu-common.h"
   23: #include "device_tree.h"
   24: #include "hw/loader.h"
   25: 
   26: #include <libfdt.h>
   27: 
   28: void *load_device_tree(const char *filename_path, int *sizep)
   29: {
   30:     int dt_size;
   31:     int dt_file_load_size;
   32:     int ret;
   33:     void *fdt = NULL;
   34: 
   35:     *sizep = 0;
   36:     dt_size = get_image_size(filename_path);
   37:     if (dt_size < 0) {
   38:         printf("Unable to get size of device tree file '%s'\n",
   39:             filename_path);
   40:         goto fail;
   41:     }
   42: 
   43:     /* Expand to 2x size to give enough room for manipulation.  */
   44:     dt_size += 10000;
   45:     dt_size *= 2;
   46:     /* First allocate space in qemu for device tree */
   47:     fdt = g_malloc0(dt_size);
   48: 
   49:     dt_file_load_size = load_image(filename_path, fdt);
   50:     if (dt_file_load_size < 0) {
   51:         printf("Unable to open device tree file '%s'\n",
   52:                filename_path);
   53:         goto fail;
   54:     }
   55: 
   56:     ret = fdt_open_into(fdt, fdt, dt_size);
   57:     if (ret) {
   58:         printf("Unable to copy device tree in memory\n");
   59:         goto fail;
   60:     }
   61: 
   62:     /* Check sanity of device tree */
   63:     if (fdt_check_header(fdt)) {
   64:         printf ("Device tree file loaded into memory is invalid: %s\n",
   65:             filename_path);
   66:         goto fail;
   67:     }
   68:     *sizep = dt_size;
   69:     return fdt;
   70: 
   71: fail:
   72:     g_free(fdt);
   73:     return NULL;
   74: }
   75: 
   76: static int findnode_nofail(void *fdt, const char *node_path)
   77: {
   78:     int offset;
   79: 
   80:     offset = fdt_path_offset(fdt, node_path);
   81:     if (offset < 0) {
   82:         fprintf(stderr, "%s Couldn't find node %s: %s\n", __func__, node_path,
   83:                 fdt_strerror(offset));
   84:         exit(1);
   85:     }
   86: 
   87:     return offset;
   88: }
   89: 
   90: int qemu_devtree_setprop(void *fdt, const char *node_path,
   91:                          const char *property, void *val_array, int size)
   92: {
   93:     int r;
   94: 
   95:     r = fdt_setprop(fdt, findnode_nofail(fdt, node_path), property, val_array, size);
   96:     if (r < 0) {
   97:         fprintf(stderr, "%s: Couldn't set %s/%s: %s\n", __func__, node_path,
   98:                 property, fdt_strerror(r));
   99:         exit(1);
  100:     }
  101: 
  102:     return r;
  103: }
  104: 
  105: int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
  106:                               const char *property, uint32_t val)
  107: {
  108:     int r;
  109: 
  110:     r = fdt_setprop_cell(fdt, findnode_nofail(fdt, node_path), property, val);
  111:     if (r < 0) {
  112:         fprintf(stderr, "%s: Couldn't set %s/%s = %#08x: %s\n", __func__,
  113:                 node_path, property, val, fdt_strerror(r));
  114:         exit(1);
  115:     }
  116: 
  117:     return r;
  118: }
  119: 
  120: int qemu_devtree_setprop_string(void *fdt, const char *node_path,
  121:                                 const char *property, const char *string)
  122: {
  123:     int r;
  124: 
  125:     r = fdt_setprop_string(fdt, findnode_nofail(fdt, node_path), property, string);
  126:     if (r < 0) {
  127:         fprintf(stderr, "%s: Couldn't set %s/%s = %s: %s\n", __func__,
  128:                 node_path, property, string, fdt_strerror(r));
  129:         exit(1);
  130:     }
  131: 
  132:     return r;
  133: }
  134: 
  135: int qemu_devtree_nop_node(void *fdt, const char *node_path)
  136: {
  137:     int r;
  138: 
  139:     r = fdt_nop_node(fdt, findnode_nofail(fdt, node_path));
  140:     if (r < 0) {
  141:         fprintf(stderr, "%s: Couldn't nop node %s: %s\n", __func__, node_path,
  142:                 fdt_strerror(r));
  143:         exit(1);
  144:     }
  145: 
  146:     return r;
  147: }
  148: 
  149: int qemu_devtree_add_subnode(void *fdt, const char *name)
  150: {
  151:     char *dupname = g_strdup(name);
  152:     char *basename = strrchr(dupname, '/');
  153:     int retval;
  154: 
  155:     if (!basename) {
  156:         g_free(dupname);
  157:         return -1;
  158:     }
  159: 
  160:     basename[0] = '\0';
  161:     basename++;
  162: 
  163:     retval = fdt_add_subnode(fdt, findnode_nofail(fdt, dupname), basename);
  164:     if (retval < 0) {
  165:         fprintf(stderr, "FDT: Failed to create subnode %s: %s\n", name,
  166:                 fdt_strerror(retval));
  167:         exit(1);
  168:     }
  169: 
  170:     g_free(dupname);
  171:     return retval;
  172: }

unix.superglobalmegacorp.com