1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2000-2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #include <stdlib.h> 28 #include <string.h> 29 30 #include "Ancestor.h" 31 32 /* ========================================================================= */ 33 /* Ancestor object definitions. */ 34 35 Ancestor::Ancestor(Str field, fru_tag_t t, const fru_regdef_t *d) 36 : field_name(field), 37 tag(t), 38 def(d), 39 numInstances(0), 40 numBufs(1), 41 next(NULL) 42 { 43 offsets = (uint32_t *)malloc(sizeof (uint32_t) 44 * ANCESTOR_INST_BUF_SIZE); 45 paths = (char **)malloc(sizeof (char *) 46 * ANCESTOR_INST_BUF_SIZE); 47 } 48 49 Ancestor::~Ancestor() 50 { 51 free(offsets); 52 if (paths != NULL) { 53 for (int i = 0; i < numInstances; i++) { 54 free(paths[i]); 55 } 56 } 57 free(paths); 58 delete next; 59 } 60 61 /* 62 void 63 Ancestor::print(void) 64 { 65 fprintf(stderr, "Ancestor Information\n"); 66 fprintf(stderr, "Tag Name: %s\n", def->name); 67 fprintf(stderr, "Tag Type: %s\n", 68 get_tagtype_str(get_tag_type(&tag))); 69 fprintf(stderr, "Num instances: %d\n", numInstances); 70 fprintf(stderr, " offsets:\n"); 71 for (int i = 0; i < numInstances; i++) { 72 fprintf(stderr, " %d\n", offsets[i]); 73 } 74 75 if (next != NULL) { 76 next->print(); 77 } 78 } 79 */ 80 81 void 82 Ancestor::addInstance(const char *path, uint32_t offset) 83 { 84 if (numInstances >= ANCESTOR_INST_BUF_SIZE) { 85 numBufs++; 86 offsets = (uint32_t *)realloc(offsets, 87 (sizeof (uint32_t) * 88 (ANCESTOR_INST_BUF_SIZE * numBufs))); 89 paths = (char **)realloc(offsets, 90 (sizeof (char *) * 91 (ANCESTOR_INST_BUF_SIZE * numBufs))); 92 } 93 offsets[numInstances] = offset; 94 paths[numInstances++] = strdup(path); 95 } 96 97 Str 98 Ancestor::getFieldName(void) 99 { 100 return (field_name); 101 } 102 103 fru_tag_t 104 Ancestor::getTag(void) 105 { 106 return (tag); 107 } 108 109 const fru_regdef_t * 110 Ancestor::getDef(void) 111 { 112 return (def); 113 } 114 115 int 116 Ancestor::getNumInstances(void) 117 { 118 return (numInstances); 119 } 120 121 uint32_t 122 Ancestor::getInstOffset(int num) 123 { 124 if (num < numInstances) 125 return (offsets[num]); 126 else 127 return (offsets[numInstances]); 128 } 129 130 const char * 131 Ancestor::getPath(int num) 132 { 133 if (num < numInstances) 134 return (paths[num]); 135 else 136 return (paths[numInstances]); 137 } 138 139 140 Ancestor * 141 Ancestor::listTaggedAncestors(char *element) 142 { 143 Ancestor *rc = NULL; 144 fru_regdef_t *def = NULL; 145 int i = 0; 146 147 unsigned int number = 0; 148 char **data_elems = fru_reg_list_entries(&number); 149 150 if (data_elems == NULL) { 151 return (NULL); 152 } 153 154 // look through all the elements. 155 for (i = 0; i < number; i++) { 156 def = (fru_regdef_t *) 157 fru_reg_lookup_def_by_name(data_elems[i]); 158 Ancestor *ant = createTaggedAncestor(def, element); 159 if (ant != NULL) { 160 if (rc == NULL) { 161 rc = ant; 162 } else { 163 Ancestor *tmp = rc; 164 while (tmp->next != NULL) { 165 tmp = tmp->next; 166 } 167 tmp->next = ant; 168 } 169 } 170 } 171 172 for (i = 0; i < number; i++) { 173 free(data_elems[i]); 174 } 175 free(data_elems); 176 177 return (rc); 178 } 179 180 Ancestor * 181 Ancestor::createTaggedAncestor(const fru_regdef_t *def, Str element) 182 { 183 // ancestors have to be tagged. 184 if (def->tagType == FRU_X) 185 return (NULL); 186 187 fru_tag_t tag; 188 mk_tag(def->tagType, def->tagDense, def->payloadLen, &tag); 189 Ancestor *rc = new Ancestor(element, tag, def); 190 191 if (element.compare(def->name) == 0) { 192 rc->addInstance("", 0); 193 return (rc); 194 } 195 196 int found = 0; 197 if (def->dataType == FDTYPE_Record) { 198 uint32_t offset = 0; 199 for (int i = 0; i < def->enumCount; i++) { 200 const fru_regdef_t *tmp 201 = fru_reg_lookup_def_by_name 202 ((char *)def->enumTable[i].text); 203 Str path = "/"; 204 path << def->name; 205 int f = definitionContains(tmp, def, element, 206 offset, rc, path); 207 if (f == 1) found = 1; // found needs to latch at one. 208 offset += tmp->payloadLen; 209 } 210 } 211 212 if (!found) { 213 delete rc; 214 return (NULL); 215 } 216 217 return (rc); 218 } 219 220 int 221 Ancestor::definitionContains(const fru_regdef_t *def, 222 const fru_regdef_t *parent_def, 223 Str element, 224 uint32_t offset, 225 Ancestor *ant, 226 Str path) 227 { 228 if (element.compare(def->name) == 0) { 229 if (parent_def->iterationType != FRU_NOT_ITERATED) { 230 offset += 4; 231 for (int i = 0; i < parent_def->iterationCount; i++) { 232 Str tmp = path; 233 tmp << "[" << i << "]/"; 234 ant->addInstance(tmp.peak(), offset); 235 offset += (parent_def->payloadLen - 4) / 236 parent_def->iterationCount; 237 } 238 } else { 239 path << "/"; 240 ant->addInstance(path.peak(), offset); 241 } 242 return (1); 243 } 244 245 int found = 0; 246 if (def->dataType == FDTYPE_Record) { 247 for (int i = 0; i < def->enumCount; i++) { 248 const fru_regdef_t *tmp 249 = fru_reg_lookup_def_by_name 250 ((char *)def->enumTable[i].text); 251 Str newPath = path; 252 newPath << "/" << def->name; 253 int f = definitionContains(tmp, def, element, 254 offset, ant, newPath); 255 if (f == 1) found = 1; // found needs to latch at one. 256 offset += tmp->payloadLen; 257 } 258 } 259 260 return (found); 261 } 262