2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License, Version 1.0 only
2N/A * (the "License"). You may not use this file except in compliance
2N/A * with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
2N/A * All rights reserved.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A
2N/A#include "Ancestor.h"
2N/A
2N/A/* ========================================================================= */
2N/A/* Ancestor object definitions. */
2N/A
2N/AAncestor::Ancestor(Str field, fru_tag_t t, const fru_regdef_t *d)
2N/A : field_name(field),
2N/A tag(t),
2N/A def(d),
2N/A numInstances(0),
2N/A numBufs(1),
2N/A next(NULL)
2N/A{
2N/A offsets = (uint32_t *)malloc(sizeof (uint32_t)
2N/A * ANCESTOR_INST_BUF_SIZE);
2N/A paths = (char **)malloc(sizeof (char *)
2N/A * ANCESTOR_INST_BUF_SIZE);
2N/A}
2N/A
2N/AAncestor::~Ancestor()
2N/A{
2N/A free(offsets);
2N/A if (paths != NULL) {
2N/A for (int i = 0; i < numInstances; i++) {
2N/A free(paths[i]);
2N/A }
2N/A }
2N/A free(paths);
2N/A delete next;
2N/A}
2N/A
2N/A/*
2N/Avoid
2N/AAncestor::print(void)
2N/A{
2N/A fprintf(stderr, "Ancestor Information\n");
2N/A fprintf(stderr, "Tag Name: %s\n", def->name);
2N/A fprintf(stderr, "Tag Type: %s\n",
2N/A get_tagtype_str(get_tag_type(&tag)));
2N/A fprintf(stderr, "Num instances: %d\n", numInstances);
2N/A fprintf(stderr, " offsets:\n");
2N/A for (int i = 0; i < numInstances; i++) {
2N/A fprintf(stderr, " %d\n", offsets[i]);
2N/A }
2N/A
2N/A if (next != NULL) {
2N/A next->print();
2N/A }
2N/A}
2N/A*/
2N/A
2N/Avoid
2N/AAncestor::addInstance(const char *path, uint32_t offset)
2N/A{
2N/A if (numInstances >= ANCESTOR_INST_BUF_SIZE) {
2N/A numBufs++;
2N/A offsets = (uint32_t *)realloc(offsets,
2N/A (sizeof (uint32_t) *
2N/A (ANCESTOR_INST_BUF_SIZE * numBufs)));
2N/A paths = (char **)realloc(offsets,
2N/A (sizeof (char *) *
2N/A (ANCESTOR_INST_BUF_SIZE * numBufs)));
2N/A }
2N/A offsets[numInstances] = offset;
2N/A paths[numInstances++] = strdup(path);
2N/A}
2N/A
2N/AStr
2N/AAncestor::getFieldName(void)
2N/A{
2N/A return (field_name);
2N/A}
2N/A
2N/Afru_tag_t
2N/AAncestor::getTag(void)
2N/A{
2N/A return (tag);
2N/A}
2N/A
2N/Aconst fru_regdef_t *
2N/AAncestor::getDef(void)
2N/A{
2N/A return (def);
2N/A}
2N/A
2N/Aint
2N/AAncestor::getNumInstances(void)
2N/A{
2N/A return (numInstances);
2N/A}
2N/A
2N/Auint32_t
2N/AAncestor::getInstOffset(int num)
2N/A{
2N/A if (num < numInstances)
2N/A return (offsets[num]);
2N/A else
2N/A return (offsets[numInstances]);
2N/A}
2N/A
2N/Aconst char *
2N/AAncestor::getPath(int num)
2N/A{
2N/A if (num < numInstances)
2N/A return (paths[num]);
2N/A else
2N/A return (paths[numInstances]);
2N/A}
2N/A
2N/A
2N/AAncestor *
2N/AAncestor::listTaggedAncestors(char *element)
2N/A{
2N/A Ancestor *rc = NULL;
2N/A fru_regdef_t *def = NULL;
2N/A int i = 0;
2N/A
2N/A unsigned int number = 0;
2N/A char **data_elems = fru_reg_list_entries(&number);
2N/A
2N/A if (data_elems == NULL) {
2N/A return (NULL);
2N/A }
2N/A
2N/A // look through all the elements.
2N/A for (i = 0; i < number; i++) {
2N/A def = (fru_regdef_t *)
2N/A fru_reg_lookup_def_by_name(data_elems[i]);
2N/A Ancestor *ant = createTaggedAncestor(def, element);
2N/A if (ant != NULL) {
2N/A if (rc == NULL) {
2N/A rc = ant;
2N/A } else {
2N/A Ancestor *tmp = rc;
2N/A while (tmp->next != NULL) {
2N/A tmp = tmp->next;
2N/A }
2N/A tmp->next = ant;
2N/A }
2N/A }
2N/A }
2N/A
2N/A for (i = 0; i < number; i++) {
2N/A free(data_elems[i]);
2N/A }
2N/A free(data_elems);
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/AAncestor *
2N/AAncestor::createTaggedAncestor(const fru_regdef_t *def, Str element)
2N/A{
2N/A // ancestors have to be tagged.
2N/A if (def->tagType == FRU_X)
2N/A return (NULL);
2N/A
2N/A fru_tag_t tag;
2N/A mk_tag(def->tagType, def->tagDense, def->payloadLen, &tag);
2N/A Ancestor *rc = new Ancestor(element, tag, def);
2N/A
2N/A if (element.compare(def->name) == 0) {
2N/A rc->addInstance("", 0);
2N/A return (rc);
2N/A }
2N/A
2N/A int found = 0;
2N/A if (def->dataType == FDTYPE_Record) {
2N/A uint32_t offset = 0;
2N/A for (int i = 0; i < def->enumCount; i++) {
2N/A const fru_regdef_t *tmp
2N/A = fru_reg_lookup_def_by_name
2N/A ((char *)def->enumTable[i].text);
2N/A Str path = "/";
2N/A path << def->name;
2N/A int f = definitionContains(tmp, def, element,
2N/A offset, rc, path);
2N/A if (f == 1) found = 1; // found needs to latch at one.
2N/A offset += tmp->payloadLen;
2N/A }
2N/A }
2N/A
2N/A if (!found) {
2N/A delete rc;
2N/A return (NULL);
2N/A }
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/Aint
2N/AAncestor::definitionContains(const fru_regdef_t *def,
2N/A const fru_regdef_t *parent_def,
2N/A Str element,
2N/A uint32_t offset,
2N/A Ancestor *ant,
2N/A Str path)
2N/A{
2N/A if (element.compare(def->name) == 0) {
2N/A if (parent_def->iterationType != FRU_NOT_ITERATED) {
2N/A offset += 4;
2N/A for (int i = 0; i < parent_def->iterationCount; i++) {
2N/A Str tmp = path;
2N/A tmp << "[" << i << "]/";
2N/A ant->addInstance(tmp.peak(), offset);
2N/A offset += (parent_def->payloadLen - 4) /
2N/A parent_def->iterationCount;
2N/A }
2N/A } else {
2N/A path << "/";
2N/A ant->addInstance(path.peak(), offset);
2N/A }
2N/A return (1);
2N/A }
2N/A
2N/A int found = 0;
2N/A if (def->dataType == FDTYPE_Record) {
2N/A for (int i = 0; i < def->enumCount; i++) {
2N/A const fru_regdef_t *tmp
2N/A = fru_reg_lookup_def_by_name
2N/A ((char *)def->enumTable[i].text);
2N/A Str newPath = path;
2N/A newPath << "/" << def->name;
2N/A int f = definitionContains(tmp, def, element,
2N/A offset, ant, newPath);
2N/A if (f == 1) found = 1; // found needs to latch at one.
2N/A offset += tmp->payloadLen;
2N/A }
2N/A }
2N/A
2N/A return (found);
2N/A}