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