Print this page
    
11927 Log, or optionally panic, on zero-length kmem allocations
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Jason King <jason.brian.king@gmail.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/intel/promif/prom_emul.c
          +++ new/usr/src/uts/intel/promif/prom_emul.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License, Version 1.0 only
   6    6   * (the "License").  You may not use this file except in compliance
   7    7   * with the License.
   8    8   *
   9    9   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10   10   * or http://www.opensolaris.org/os/licensing.
  11   11   * See the License for the specific language governing permissions
  12   12   * and limitations under the License.
  13   13   *
  14   14   * When distributing Covered Code, include this CDDL HEADER in each
  15   15   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16   16   * If applicable, add the following below this CDDL HEADER, with the
  
    | 
      ↓ open down ↓ | 
    16 lines elided | 
    
      ↑ open up ↑ | 
  
  17   17   * fields enclosed by brackets "[]" replaced with your own identifying
  18   18   * information: Portions Copyright [yyyy] [name of copyright owner]
  19   19   *
  20   20   * CDDL HEADER END
  21   21   */
  22   22  /*
  23   23   * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27      -#pragma ident   "%Z%%M% %I%     %E% SMI"
       27 +/*
       28 + * Copyright (c) 2015 Joyent, Inc.  All rights reserved.
       29 + */
  28   30  
  29   31  #include <sys/promif.h>
  30   32  #include <sys/promimpl.h>
  31   33  #include <sys/prom_emul.h>
  32   34  #include <sys/obpdefs.h>
  33   35  #include <sys/sunddi.h>
  34   36  
  35   37  static prom_node_t *promif_top;
  36   38  
  37   39  static prom_node_t *promif_find_node(pnode_t nodeid);
  38   40  static int getproplen(prom_node_t *pnp, char *name);
  
    | 
      ↓ open down ↓ | 
    1 lines elided | 
    
      ↑ open up ↑ | 
  
  39   41  static void *getprop(prom_node_t *pnp, char *name);
  40   42  
  41   43  static void
  42   44  promif_create_prop(prom_node_t *pnp, char *name, void *val, int len, int flags)
  43   45  {
  44   46          struct prom_prop *p, *q;
  45   47  
  46   48          q = kmem_zalloc(sizeof (*q), KM_SLEEP);
  47   49          q->pp_name = kmem_zalloc(strlen(name) + 1, KM_SLEEP);
  48   50          (void) strcpy(q->pp_name, name);
  49      -        q->pp_val = kmem_alloc(len, KM_SLEEP);
       51 +        q->pp_val = len > 0 ? kmem_alloc(len, KM_SLEEP) : NULL;
  50   52          q->pp_len = len;
  51   53          switch (flags) {
  52   54          case DDI_PROP_TYPE_INT:
  53   55          case DDI_PROP_TYPE_INT64:
  54   56                  /*
  55   57                   * Technically, we need byte-swapping to conform to 1275.
  56   58                   * However, the old x86 prom simulator used little endian
  57   59                   * representation, so we don't swap here either.
  58   60                   *
  59   61                   * NOTE: this is inconsistent with ddi_prop_lookup_*()
  60   62                   * which does byte-swapping when looking up prom properties.
  61   63                   * Since all kernel nodes are SID nodes, drivers no longer
  62   64                   * access PROM properties on x86.
  63   65                   */
  64   66          default:        /* no byte swapping */
  65   67                  (void) bcopy(val, q->pp_val, len);
  66   68                  break;
  67   69          }
  68   70  
  69   71          if (pnp->pn_propp == NULL) {
  70   72                  pnp->pn_propp = q;
  71   73                  return;
  72   74          }
  73   75  
  74   76          for (p = pnp->pn_propp; p->pp_next != NULL; p = p->pp_next)
  75   77                  /* empty */;
  76   78  
  77   79          p->pp_next = q;
  78   80  }
  79   81  
  80   82  static prom_node_t *
  81   83  promif_create_node(dev_info_t *dip)
  82   84  {
  83   85          prom_node_t *pnp;
  84   86          ddi_prop_t *hwprop;
  85   87          char *nodename;
  86   88  
  87   89          pnp = kmem_zalloc(sizeof (prom_node_t), KM_SLEEP);
  88   90          pnp->pn_nodeid = DEVI(dip)->devi_nodeid;
  89   91  
  90   92          hwprop = DEVI(dip)->devi_hw_prop_ptr;
  91   93          while (hwprop != NULL) {
  92   94                  /* need to encode to proper endianness */
  93   95                  promif_create_prop(pnp, hwprop->prop_name, hwprop->prop_val,
  94   96                      hwprop->prop_len, hwprop->prop_flags & DDI_PROP_TYPE_MASK);
  95   97                  hwprop = hwprop->prop_next;
  96   98          }
  97   99          nodename = ddi_node_name(dip);
  98  100          promif_create_prop(pnp, "name", nodename, strlen(nodename) + 1,
  99  101              DDI_PROP_TYPE_STRING);
 100  102  
 101  103          return (pnp);
 102  104  }
 103  105  
 104  106  static void promif_create_children(prom_node_t *, dev_info_t *);
 105  107  
 106  108  static void
 107  109  promif_create_peers(prom_node_t *pnp, dev_info_t *dip)
 108  110  {
 109  111          dev_info_t *ndip = ddi_get_next_sibling(dip);
 110  112  
 111  113          while (ndip) {
 112  114                  pnp->pn_sibling = promif_create_node(ndip);
 113  115                  promif_create_children(pnp->pn_sibling, ndip);
 114  116                  pnp = pnp->pn_sibling;
 115  117                  ndip = ddi_get_next_sibling(ndip);
 116  118          }
 117  119  }
 118  120  
 119  121  static void
 120  122  promif_create_children(prom_node_t *pnp, dev_info_t *dip)
 121  123  {
 122  124          dev_info_t *cdip = ddi_get_child(dip);
 123  125  
 124  126          while (cdip) {
 125  127                  pnp->pn_child = promif_create_node(cdip);
 126  128                  promif_create_peers(pnp->pn_child, cdip);
 127  129                  pnp = pnp->pn_child;
 128  130                  cdip = ddi_get_child(cdip);
 129  131          }
 130  132  }
 131  133  
 132  134  void
 133  135  promif_create_device_tree(void)
 134  136  {
 135  137          promif_top = promif_create_node(ddi_root_node());
 136  138          promif_create_children(promif_top, ddi_root_node());
 137  139  }
 138  140  
 139  141  static prom_node_t *
 140  142  find_node_work(prom_node_t *pnp, pnode_t n)
 141  143  {
 142  144          prom_node_t *qnp;
 143  145  
 144  146          if (pnp->pn_nodeid == n)
 145  147                  return (pnp);
 146  148  
 147  149          if (pnp->pn_child)
 148  150                  if ((qnp = find_node_work(pnp->pn_child, n)) != NULL)
 149  151                          return (qnp);
 150  152  
 151  153          if (pnp->pn_sibling)
 152  154                  if ((qnp = find_node_work(pnp->pn_sibling, n)) != NULL)
 153  155                          return (qnp);
 154  156  
 155  157          return (NULL);
 156  158  }
 157  159  
 158  160  static prom_node_t *
 159  161  promif_find_node(pnode_t nodeid)
 160  162  {
 161  163          if (nodeid == OBP_NONODE)
 162  164                  return (promif_top);
 163  165  
 164  166          if (promif_top == NULL)
 165  167                  return (NULL);
 166  168  
 167  169          return (find_node_work(promif_top, nodeid));
 168  170  }
 169  171  
 170  172  pnode_t
 171  173  promif_nextnode(pnode_t nodeid)
 172  174  {
 173  175          prom_node_t *pnp;
 174  176  
 175  177          /*
 176  178           * Note: next(0) returns the root node
 177  179           */
 178  180          pnp = promif_find_node(nodeid);
 179  181          if (pnp && (nodeid == OBP_NONODE))
 180  182                  return (pnp->pn_nodeid);
 181  183          if (pnp && pnp->pn_sibling)
 182  184                  return (pnp->pn_sibling->pn_nodeid);
 183  185  
 184  186          return (OBP_NONODE);
 185  187  }
 186  188  
 187  189  pnode_t
 188  190  promif_childnode(pnode_t nodeid)
 189  191  {
 190  192          prom_node_t *pnp;
 191  193  
 192  194          pnp = promif_find_node(nodeid);
 193  195          if (pnp && pnp->pn_child)
 194  196                  return (pnp->pn_child->pn_nodeid);
 195  197  
 196  198          return (OBP_NONODE);
 197  199  }
 198  200  
 199  201  /*
 200  202   * Retrieve a PROM property (len and value)
 201  203   */
 202  204  
 203  205  static int
 204  206  getproplen(prom_node_t *pnp, char *name)
 205  207  {
 206  208          struct prom_prop *propp;
 207  209  
 208  210          for (propp = pnp->pn_propp; propp != NULL; propp = propp->pp_next)
 209  211                  if (strcmp(propp->pp_name, name) == 0)
 210  212                          return (propp->pp_len);
 211  213  
 212  214          return (-1);
 213  215  }
 214  216  
 215  217  int
 216  218  promif_getproplen(pnode_t nodeid, char *name)
 217  219  {
 218  220          prom_node_t *pnp;
 219  221  
 220  222          pnp = promif_find_node(nodeid);
 221  223          if (pnp == NULL)
 222  224                  return (-1);
 223  225  
 224  226          return (getproplen(pnp, name));
 225  227  }
 226  228  
 227  229  static void *
 228  230  getprop(prom_node_t *pnp, char *name)
 229  231  {
 230  232          struct prom_prop *propp;
 231  233  
 232  234          for (propp = pnp->pn_propp; propp != NULL; propp = propp->pp_next)
 233  235                  if (strcmp(propp->pp_name, name) == 0)
 234  236                          return (propp->pp_val);
 235  237  
 236  238          return (NULL);
 237  239  }
 238  240  
 239  241  int
 240  242  promif_getprop(pnode_t nodeid, char *name, void *value)
 241  243  {
 242  244          prom_node_t *pnp;
 243  245          void *v;
 244  246          int len;
 245  247  
 246  248          pnp = promif_find_node(nodeid);
 247  249          if (pnp == NULL)
 248  250                  return (-1);
 249  251  
 250  252          len = getproplen(pnp, name);
 251  253          if (len > 0) {
 252  254                  v = getprop(pnp, name);
 253  255                  bcopy(v, value, len);
 254  256          }
 255  257          return (len);
 256  258  }
 257  259  
 258  260  static char *
 259  261  nextprop(prom_node_t *pnp, char *name)
 260  262  {
 261  263          struct prom_prop *propp;
 262  264  
 263  265          /*
 264  266           * getting next of NULL or a null string returns the first prop name
 265  267           */
 266  268          if (name == NULL || *name == '\0')
 267  269                  if (pnp->pn_propp)
 268  270                          return (pnp->pn_propp->pp_name);
 269  271  
 270  272          for (propp = pnp->pn_propp; propp != NULL; propp = propp->pp_next)
 271  273                  if (strcmp(propp->pp_name, name) == 0)
 272  274                          if (propp->pp_next)
 273  275                                  return (propp->pp_next->pp_name);
 274  276  
 275  277          return (NULL);
 276  278  }
 277  279  
 278  280  char *
 279  281  promif_nextprop(pnode_t nodeid, char *name, char *next)
 280  282  {
 281  283          prom_node_t *pnp;
 282  284          char *s;
 283  285  
 284  286          next[0] = '\0';
 285  287  
 286  288          pnp = promif_find_node(nodeid);
 287  289          if (pnp == NULL)
 288  290                  return (NULL);
 289  291  
 290  292          s = nextprop(pnp, name);
 291  293          if (s == NULL)
 292  294                  return (next);
 293  295  
 294  296          (void) strcpy(next, s);
 295  297          return (next);
 296  298  }
  
    | 
      ↓ open down ↓ | 
    237 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX