03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License, Version 1.0 only
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (the "License"). You may not use this file except in compliance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel#pragma ident "%Z%%M% %I% %E% SMI"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For machines that support the openprom, fetch and print the list
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of devices that the kernel has fetched from the prom or conjured up.
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern char *progname;
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern char *promdev;
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void getppdata();
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void printppdata();
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Define DPRINT for run-time debugging printf's...
03831d35f7499c87d51205817c93e9a8d42c4baestevel * #define DPRINT 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DPRINT */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*VARARGS1*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern int errno;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel register unsigned int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = (unsigned int)((unsigned char)opp->oprom_array[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((i & OPROMCONS_OPENPROM) == OPROMCONS_OPENPROM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read all properties and values from nodes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy the properties read into the prom_node passsed in.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* clear out pointers in pnode */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get first prop by asking for null string */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* allocate space for the property */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get property
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Now copy over temp's data to new. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * First copy over temp->name's data. The
03831d35f7499c87d51205817c93e9a8d42c4baestevel * temp->name.opp.opio_u union always contains char[]
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (as opposed to an int or int []).
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->name.opp.oprom_size = temp->name.opp.oprom_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Then copy over temp->value's data.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * temp->value.opp.opio_u could contain char[], int or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * int []. If *(temp->value.opp.oprom_array) is '\0',
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this indicates int or int []. int is the norm, but
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to be safe we assume int [] and copy over
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OPROM_NODE_SIZE int elements.
03831d35f7499c87d51205817c93e9a8d42c4baestevel new->value.opp.oprom_size = temp->value.opp.oprom_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < OPROM_NODE_SIZE; i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * temp->value.opp.oprom_array can contain one
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or more embedded NULLs. These trip-up the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * standard string copying functions, so we do
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the copy by hand. temp->value.opp.oprom_array
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will be NULL-terminated. oprom_size includes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this terminating NULL.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* everything worked so link the property list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*CONSTCOND*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*NOTREACHED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(_error(dgettext(TEXT_DOMAIN, "close error on %s"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read the value of the property from the PROM device tree
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* LINTED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* LINTED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* LINTED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* LINTED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check if the Prom node passed in contains a property called
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "board#".
03831d35f7499c87d51205817c93e9a8d42c4baestevel * walk thru all properties in this PROM node and look for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board# prop
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(prop->name.opp.oprom_array, "board#") == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of has_board_num() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Retrieve the value of the board number property from this Prom
03831d35f7499c87d51205817c93e9a8d42c4baestevel * node. It has the type of int.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * walk thru all properties in this PROM node and look for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board# prop
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(prop->name.opp.oprom_array, "board#") == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of get_board_num() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find the requested board struct in the system device tree.
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((bnode != NULL) && (board != bnode->board_num))
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of find_board() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add a board to the system list in order. Initialize all pointer
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields to NULL.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((bnode = (Board_node *) malloc(sizeof (Board_node))) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((temp->next != NULL) && (board > temp->next->board_num))
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of insert_board() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function searches through the properties of the node passed in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and returns a pointer to the value of the name property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of get_node_name() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function searches through the properties of the node passed in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and returns a pointer to the value of the name property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp("device_type", prop->name.opp.oprom_array) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of get_node_type() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do a depth-first walk of a device tree and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return the first node with the name matching.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Search for and return a node of the required type. If no node is found,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then return NULL.
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_find_node_by_type(root, "device_type", type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start from the current node and return the next node besides the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * current one which has the requested type property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_next_node_by_type(root, "device_type", type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Search a device tree and return the first failed node that is found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (has a 'status' property)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search the child */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search the siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pnode = find_failed_node(root->sibling)) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of find_failed_node() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start from the current node and return the next node besides
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the current one which is failed. (has a 'status' property)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search the child */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pnode = find_failed_node(root->child)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search the siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pnode = find_failed_node(root->sibling)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* backtracking the search up through parents' siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pnode = find_failed_node(parent->sibling)) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of find_failed_node() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * node_failed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function determines if the current Prom node is failed. This
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is defined by having a status property containing the token 'fail'.
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search the local node */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((value = get_prop_val(find_prop(node, "status"))) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((value != NULL) && strstr((char *)value, status))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get a property's value. Must be void * since the property can
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be any data type. Caller must know the *PROPER* way to use this
03831d35f7499c87d51205817c93e9a8d42c4baestevel} /* end of get_prop_val() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Search a Prom node and retrieve the property with the correct
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) printf("%s", dgettext(TEXT_DOMAIN, "Prom node has "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "no properties\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((prop != NULL) && (strcmp(prop->name.opp.oprom_array, name)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function adds a board node to the board structure where that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that node's physical component lives.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* add this node to the Board list of the appropriate board */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* board is 0 if not on Sunfire */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* find the node with the same board number */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* now attach this prom node to the board list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Insert this node at the end of the list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find the device on the current board with the requested device ID
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and name. If this rountine is passed a NULL pointer, it simply returns
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* find the first cpu node */
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_find_node_by_type(Prom_node *root, char *type, char *property)
03831d35f7499c87d51205817c93e9a8d42c4baestevel type_prop = (char *)get_prop_val(find_prop(root, type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* look at your children first */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* now look at your siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((node = dev_find_node_by_type(root->sibling, type,
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_next_node_by_type(Prom_node *root, char *type, char *property)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* look at your children first */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* now look at your siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((node = dev_find_node_by_type(root->sibling, type,
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* now look at papa's siblings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((node = dev_find_node_by_type(root->parent->sibling,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do a depth-first walk of a device tree and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return the first node with the matching compatible.
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_find_node_by_compatible(Prom_node *root, char *compatible)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((prop = find_prop(root, "compatible")) != NULL &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (compatible_array = (char *)get_prop_val(prop)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The Prop structure returned by find_prop() is supposed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to contain an indication of how big the value of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * compatible property is. Since it is an array of strings
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this is our only means of determining just how many
03831d35f7499c87d51205817c93e9a8d42c4baestevel * strings might be in this property. However, this size
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is often left as zero even though there is at least one
03831d35f7499c87d51205817c93e9a8d42c4baestevel * string present. When this is the case, all we can do
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is examine the first string in the compatible property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_find_node_by_compatible(root->child, compatible);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note the very deliberate use of tail recursion here. A good
03831d35f7499c87d51205817c93e9a8d42c4baestevel * compiler (such as Sun's) will recognize this and generate code
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that does not allocate another stack frame. Instead, it will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * overlay the existing stack frame with the new one, the only change
03831d35f7499c87d51205817c93e9a8d42c4baestevel * having been to replace the original root with its sibling.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This has the potential to create some confusion for anyone
03831d35f7499c87d51205817c93e9a8d42c4baestevel * trying to debug this code from a core dump, since the stack
03831d35f7499c87d51205817c93e9a8d42c4baestevel * trace will not reveal recursion on siblings, only on children.
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (dev_find_node_by_compatible(root->sibling, compatible));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start from the current node and return the next node besides
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the current one which has the requested compatible property.
03831d35f7499c87d51205817c93e9a8d42c4baesteveldev_next_node_by_compatible(Prom_node *root, char *compatible)
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_find_node_by_compatible(root->child, compatible);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * More tail recursion. Even though it is a different function,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this will overlay the current stack frame. Caveat exterminator.
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = dev_find_node_by_compatible(root->sibling, compatible);