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
Ancestor(Str field,fru_tag_t t,const fru_regdef_t * d)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
~Ancestor()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
addInstance(const char * path,uint32_t offset)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
getFieldName(void)98 Ancestor::getFieldName(void)
99 {
100 return (field_name);
101 }
102
103 fru_tag_t
getTag(void)104 Ancestor::getTag(void)
105 {
106 return (tag);
107 }
108
109 const fru_regdef_t *
getDef(void)110 Ancestor::getDef(void)
111 {
112 return (def);
113 }
114
115 int
getNumInstances(void)116 Ancestor::getNumInstances(void)
117 {
118 return (numInstances);
119 }
120
121 uint32_t
getInstOffset(int num)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 *
getPath(int num)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 *
listTaggedAncestors(char * element)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 *
createTaggedAncestor(const fru_regdef_t * def,Str element)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
definitionContains(const fru_regdef_t * def,const fru_regdef_t * parent_def,Str element,uint32_t offset,Ancestor * ant,Str path)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