Subversion Repositories HelenOS

Rev

Rev 3864 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Pavel Rimsky
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup sparc64
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <debug.h>
  36. #include <panic.h>
  37. #include <func.h>
  38. #include <print.h>
  39. #include <arch/sun4v/md.h>
  40. #include <arch/sun4v/hypercall.h>
  41. #include <arch/mm/page.h>
  42.  
  43. /* maximum MD size estimate (in bytes) */
  44. #define MD_MAX_SIZE (64 * 1024)
  45.  
  46. /** element types (element tag values) */
  47. #define LIST_END    0x0 /**< End of element list */
  48. #define NODE        0x4e    /**< Start of node definition */
  49. #define NODE_END    0x45    /**< End of node definition */
  50. #define NOOP        0x20    /**< NOOP list element - to be ignored */
  51. #define PROP_ARC    0x61    /**< Node property arc'ing to another node */
  52. #define PROP_VAL    0x76    /**< Node property with an integer value */
  53. #define PROP_STR    0x73    /**< Node property with a string value */
  54. #define PROP_DATA   0x64    /**< Node property with a block of data */
  55.  
  56.  
  57. /** machine description header */
  58. typedef struct {
  59.     uint32_t transport_version; /**< Transport version number */
  60.     uint32_t node_blk_sz;       /**< Size in bytes of node block */
  61.     uint32_t name_blk_sz;       /**< Size in bytes of name block */
  62.     uint32_t data_blk_sz;       /**< Size in bytes of data block */
  63. } __attribute__ ((packed)) md_header_t;
  64.  
  65. /** machine description element (in the node block) */
  66. typedef struct {
  67.     uint8_t tag;            /**< Type of element */
  68.     uint8_t name_len;       /**< Length in bytes of element name */
  69.     uint16_t _reserved_field;   /**< reserved field (zeros) */
  70.     uint32_t name_offset;       /**< Location offset of name associated
  71.                          with this element relative to
  72.                          start of name block */
  73.     union {
  74.         /** for elements of type “PROP_STR” and of type “PROP_DATA” */
  75.         struct {
  76.             /** Length in bytes of data in data block */
  77.             uint32_t data_len;
  78.  
  79.             /**
  80.              * Location offset of data associated with this
  81.              * element relative to start of data block
  82.              */
  83.             uint32_t data_offset;
  84.         } y;
  85.  
  86.         /**
  87.          *  64 bit value for elements of tag type “NODE”, “PROP_VAL”
  88.          *  or “PROP_ARC”
  89.          */
  90.         uint64_t val;
  91.     } d;
  92. } __attribute__ ((packed)) md_element_t;
  93.  
  94. /** index of the element within the node block */
  95. typedef unsigned int element_idx_t;
  96.  
  97. /** buffer to which the machine description will be saved */
  98. static uint8_t mach_desc[MD_MAX_SIZE]
  99.      __attribute__ ((aligned (16)));
  100.  
  101.  
  102. /** returns pointer to the element at the given index */
  103. static md_element_t *get_element(element_idx_t idx)
  104. {
  105.     return (md_element_t *) (
  106.         mach_desc + sizeof(md_header_t) + idx * sizeof(md_element_t));
  107. }
  108.  
  109. /** returns the name of the element represented by the index */
  110. static const char *get_element_name(element_idx_t idx)
  111. {
  112.     md_header_t *md_header = (md_header_t *) mach_desc;
  113.     uintptr_t name_offset = get_element(idx)->name_offset;
  114.     return (char *) mach_desc + sizeof(md_header_t) +
  115.         md_header->node_blk_sz + name_offset;
  116. }
  117.  
  118. /** finds the name of the node represented by "node" */
  119. const char *md_get_node_name(md_node_t node)
  120. {
  121.     return get_element_name(node);
  122. }
  123.  
  124. /**
  125.  * Returns the value of the integer property of the given node.
  126.  *
  127.  * @param
  128.  */
  129. bool md_get_integer_property(md_node_t node, const char *key,
  130.     uint64_t *result)
  131. {
  132.     element_idx_t idx = node;  
  133.  
  134.     while (get_element(idx)->tag != NODE_END) {
  135.         idx++;
  136.         md_element_t *element = get_element(idx);
  137.         if (element->tag == PROP_VAL &&
  138.                 strcmp(key, get_element_name(idx)) == 0) {
  139.             *result = element->d.val;
  140.             return true;
  141.         }
  142.     }
  143.  
  144.     return false;
  145. }
  146.  
  147. /**
  148.  * Returns the value of the string property of the given node.
  149.  *
  150.  * @param
  151.  */
  152. bool md_get_string_property(md_node_t node, const char *key,
  153.     const char **result)
  154. {
  155.     md_header_t *md_header = (md_header_t *) mach_desc;
  156.     element_idx_t idx = node;
  157.  
  158.     while (get_element(idx)->tag != NODE_END) {
  159.         idx++;
  160.         md_element_t *element = get_element(idx);
  161.         if (element->tag == PROP_DATA &&
  162.                 strcmp(key, get_element_name(idx)) == 0) {
  163.             *result = (char *) mach_desc + sizeof(md_header_t) +
  164.                 md_header->node_blk_sz + md_header->name_blk_sz +
  165.                 element->d.y.data_offset;
  166.             return true;
  167.         }
  168.     }
  169.  
  170.     return false;
  171. }
  172.  
  173. /**
  174.  * Moves the child oterator to the next child (following sibling of the node
  175.  * the oterator currently points to).
  176.  *
  177.  * @param it    pointer to the iterator to be moved
  178.  */
  179. bool md_next_child(md_child_iter_t *it)
  180. {
  181.     element_idx_t backup = *it;
  182.  
  183.     while (get_element(*it)->tag != NODE_END) {
  184.         (*it)++;
  185.         md_element_t *element = get_element(*it);
  186.         if (element->tag == PROP_ARC &&
  187.                 strcmp("fwd", get_element_name(*it)) == 0) {
  188.             return true;
  189.         }
  190.     }
  191.  
  192.     *it = backup;
  193.     return false;
  194. }
  195.  
  196. /**
  197.  * Returns the node the iterator point to.
  198.  */
  199. md_node_t md_get_child_node(md_child_iter_t it)
  200. {
  201.     return get_element(it)->d.val;
  202. }
  203.  
  204. /**
  205.  * Helper function used to split a string to a part before the first
  206.  * slash sign and a part after the slash sign.
  207.  *
  208.  * @param str   pointer to the string to be split; when the function finishes,
  209.  *      it will contain only the part following the first slash sign of
  210.  *      the original string
  211.  * @param head  pointer to the string which will be set to the part before the
  212.  *      first slash sign
  213.  */
  214. static bool str_parse_head(char **str, char **head)
  215. {
  216.     *head = *str;
  217.  
  218.     char *cur = *str;
  219.     while (*cur != '\0') {
  220.         if (*cur == '/') {
  221.             *cur = '\0';
  222.             *str = cur + 1;
  223.             return true;
  224.         }
  225.         cur++;
  226.     }
  227.  
  228.     return false;
  229. }
  230.  
  231. /**
  232.  * Returns the descendant of the given node. The descendant is identified
  233.  * by a path where the node names are separated by a slash.
  234.  *
  235.  * Ex.: Let there be a node N with path "a/b/c/x/y/z" and let P represent the
  236.  * node with path "a/b/c". Then md_get_child(P, "x/y/z") will return N.
  237.  */
  238. md_node_t md_get_child(md_node_t node, char *name)
  239. {
  240.     bool more;
  241.  
  242.     do {
  243.         char *head;
  244.         more = str_parse_head(&name, &head);
  245.        
  246.         while (md_next_child(&node)) {
  247.             element_idx_t child = md_get_child_node(node);
  248.             if (strcmp(head, get_element_name(child)) == 0) {
  249.                 node = child;
  250.                 break;
  251.             }
  252.         }
  253.  
  254.     } while (more);
  255.  
  256.     return node;
  257. }
  258.  
  259. /** returns the root node of MD */
  260. md_node_t md_get_root(void)
  261. {
  262.     return 0;
  263. }
  264.  
  265. /**
  266.  * Returns the child iterator - a token to be passed to functions iterating
  267.  * through all the children of a node.
  268.  *
  269.  * @param node  a node whose children the iterator will be used
  270.  *      to iterate through
  271.  */
  272. md_child_iter_t md_get_child_iterator(md_node_t node)
  273. {
  274.     return node;
  275. }
  276.  
  277. /**
  278.  * Moves "node" to the node following "node" in the list of all the existing
  279.  * nodes of the MD whose name is "name".
  280.  */
  281. bool md_next_node(md_node_t *node, const char *name)
  282. {
  283.     md_element_t *element;
  284.     (*node)++;
  285.  
  286.     do {
  287.         element = get_element(*node);
  288.  
  289.         if (element->tag == NODE &&
  290.                 strcmp(name, get_element_name(*node)) == 0) {
  291.             return true;
  292.         }
  293.        
  294.         (*node)++;
  295.     } while (element->tag != LIST_END);
  296.  
  297.     return false;
  298. }
  299.  
  300. /**
  301.  * Retrieves the machine description from the hypervisor and saves it to
  302.  * a kernel buffer.
  303.  */
  304. void md_init(void)
  305. {
  306.     uint64_t retval = __hypercall_fast2(MACH_DESC, KA2PA(mach_desc),
  307.         MD_MAX_SIZE);
  308.  
  309.     retval = retval;
  310.     if (retval != EOK) {
  311.         printf("Could not retrieve machine description, error = %d.\n",
  312.             retval);
  313.     }
  314. }
  315.  
  316. /** @}
  317.  */
  318.