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 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "Ancestor.h"
33
34 /* ========================================================================= */
35 /* Ancestor object definitions. */
36
Ancestor(Str field,fru_tag_t t,const fru_regdef_t * d)37 Ancestor::Ancestor(Str field, fru_tag_t t, const fru_regdef_t *d)
38 : field_name(field),
39 tag(t),
40 def(d),
41 numInstances(0),
42 numBufs(1),
43 next(NULL)
44 {
45 offsets = (uint32_t *)malloc(sizeof (uint32_t)
46 * ANCESTOR_INST_BUF_SIZE);
47 paths = (char **)malloc(sizeof (char *)
48 * ANCESTOR_INST_BUF_SIZE);
49 }
50
~Ancestor()51 Ancestor::~Ancestor()
52 {
53 free(offsets);
54 if (paths != NULL) {
55 for (int i = 0; i < numInstances; i++) {
56 free(paths[i]);
57 }
58 }
59 free(paths);
60 delete next;
61 }
62
63 /*
64 void
65 Ancestor::print(void)
66 {
67 fprintf(stderr, "Ancestor Information\n");
68 fprintf(stderr, "Tag Name: %s\n", def->name);
69 fprintf(stderr, "Tag Type: %s\n",
70 get_tagtype_str(get_tag_type(&tag)));
71 fprintf(stderr, "Num instances: %d\n", numInstances);
72 fprintf(stderr, " offsets:\n");
73 for (int i = 0; i < numInstances; i++) {
74 fprintf(stderr, " %d\n", offsets[i]);
75 }
76
77 if (next != NULL) {
78 next->print();
79 }
80 }
81 */
82
83 void
addInstance(const char * path,uint32_t offset)84 Ancestor::addInstance(const char *path, uint32_t offset)
85 {
86 if (numInstances >= ANCESTOR_INST_BUF_SIZE) {
87 numBufs++;
88 offsets = (uint32_t *)realloc(offsets,
89 (sizeof (uint32_t) *
90 (ANCESTOR_INST_BUF_SIZE * numBufs)));
91 paths = (char **)realloc(offsets,
92 (sizeof (char *) *
93 (ANCESTOR_INST_BUF_SIZE * numBufs)));
94 }
95 offsets[numInstances] = offset;
96 paths[numInstances++] = strdup(path);
97 }
98
99 Str
getFieldName(void)100 Ancestor::getFieldName(void)
101 {
102 return (field_name);
103 }
104
105 fru_tag_t
getTag(void)106 Ancestor::getTag(void)
107 {
108 return (tag);
109 }
110
111 const fru_regdef_t *
getDef(void)112 Ancestor::getDef(void)
113 {
114 return (def);
115 }
116
117 int
getNumInstances(void)118 Ancestor::getNumInstances(void)
119 {
120 return (numInstances);
121 }
122
123 uint32_t
getInstOffset(int num)124 Ancestor::getInstOffset(int num)
125 {
126 if (num < numInstances)
127 return (offsets[num]);
128 else
129 return (offsets[numInstances]);
130 }
131
132 const char *
getPath(int num)133 Ancestor::getPath(int num)
134 {
135 if (num < numInstances)
136 return (paths[num]);
137 else
138 return (paths[numInstances]);
139 }
140
141
142 Ancestor *
listTaggedAncestors(char * element)143 Ancestor::listTaggedAncestors(char *element)
144 {
145 Ancestor *rc = NULL;
146 fru_regdef_t *def = NULL;
147 int i = 0;
148
149 unsigned int number = 0;
150 char **data_elems = fru_reg_list_entries(&number);
151
152 if (data_elems == NULL) {
153 return (NULL);
154 }
155
156 // look through all the elements.
157 for (i = 0; i < number; i++) {
158 def = (fru_regdef_t *)
159 fru_reg_lookup_def_by_name(data_elems[i]);
160 Ancestor *ant = createTaggedAncestor(def, element);
161 if (ant != NULL) {
162 if (rc == NULL) {
163 rc = ant;
164 } else {
165 Ancestor *tmp = rc;
166 while (tmp->next != NULL) {
167 tmp = tmp->next;
168 }
169 tmp->next = ant;
170 }
171 }
172 }
173
174 for (i = 0; i < number; i++) {
175 free(data_elems[i]);
176 }
177 free(data_elems);
178
179 return (rc);
180 }
181
182 Ancestor *
createTaggedAncestor(const fru_regdef_t * def,Str element)183 Ancestor::createTaggedAncestor(const fru_regdef_t *def, Str element)
184 {
185 // ancestors have to be tagged.
186 if (def->tagType == FRU_X)
187 return (NULL);
188
189 fru_tag_t tag;
190 mk_tag(def->tagType, def->tagDense, def->payloadLen, &tag);
191 Ancestor *rc = new Ancestor(element, tag, def);
192
193 if (element.compare(def->name) == 0) {
194 rc->addInstance("", 0);
195 return (rc);
196 }
197
198 int found = 0;
199 if (def->dataType == FDTYPE_Record) {
200 uint32_t offset = 0;
201 for (int i = 0; i < def->enumCount; i++) {
202 const fru_regdef_t *tmp
203 = fru_reg_lookup_def_by_name
204 ((char *)def->enumTable[i].text);
205 Str path = "/";
206 path << def->name;
207 int f = definitionContains(tmp, def, element,
208 offset, rc, path);
209 if (f == 1) found = 1; // found needs to latch at one.
210 offset += tmp->payloadLen;
211 }
212 }
213
214 if (!found) {
215 delete rc;
216 return (NULL);
217 }
218
219 return (rc);
220 }
221
222 int
definitionContains(const fru_regdef_t * def,const fru_regdef_t * parent_def,Str element,uint32_t offset,Ancestor * ant,Str path)223 Ancestor::definitionContains(const fru_regdef_t *def,
224 const fru_regdef_t *parent_def,
225 Str element,
226 uint32_t offset,
227 Ancestor *ant,
228 Str path)
229 {
230 if (element.compare(def->name) == 0) {
231 if (parent_def->iterationType != FRU_NOT_ITERATED) {
232 offset += 4;
233 for (int i = 0; i < parent_def->iterationCount; i++) {
234 Str tmp = path;
235 tmp << "[" << i << "]/";
236 ant->addInstance(tmp.peak(), offset);
237 offset += (parent_def->payloadLen - 4) /
238 parent_def->iterationCount;
239 }
240 } else {
241 path << "/";
242 ant->addInstance(path.peak(), offset);
243 }
244 return (1);
245 }
246
247 int found = 0;
248 if (def->dataType == FDTYPE_Record) {
249 for (int i = 0; i < def->enumCount; i++) {
250 const fru_regdef_t *tmp
251 = fru_reg_lookup_def_by_name
252 ((char *)def->enumTable[i].text);
253 Str newPath = path;
254 newPath << "/" << def->name;
255 int f = definitionContains(tmp, def, element,
256 offset, ant, newPath);
257 if (f == 1) found = 1; // found needs to latch at one.
258 offset += tmp->payloadLen;
259 }
260 }
261
262 return (found);
263 }
264