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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <errno.h>
28
29 #include "fru_tag.h"
30
31 char *
get_tagtype_str(fru_tagtype_t e)32 get_tagtype_str(fru_tagtype_t e)
33 {
34 switch (e) {
35 case FRU_A:
36 return ("A");
37 case FRU_B:
38 return ("B");
39 case FRU_C:
40 return ("C");
41 case FRU_D:
42 return ("D");
43 case FRU_E:
44 return ("E");
45 case FRU_F:
46 return ("F");
47 case FRU_G:
48 return ("G");
49 case FRU_X:
50 return ("X");
51 }
52 return ("?");
53 }
54
55 size_t
get_tag_size(fru_tagtype_t tag)56 get_tag_size(fru_tagtype_t tag)
57 {
58 switch (tag) {
59 case FRU_A:
60 return (1);
61 case FRU_B:
62 case FRU_C:
63 return (2);
64 case FRU_D:
65 case FRU_E:
66 return (3);
67 case FRU_F:
68 return (4);
69 case FRU_G:
70 return (6);
71 }
72 errno = EINVAL;
73 return (-1);
74 }
75
76 int
mk_tag(fru_tagtype_t type,uint32_t dense,size_t pl_len,fru_tag_t * tag)77 mk_tag(fru_tagtype_t type, uint32_t dense, size_t pl_len,
78 fru_tag_t *tag)
79 {
80 static fru_tag_t max = { 0xFFFFFFFFFFFFFFFFULL };
81 /* make sure the tag is clear. */
82 tag->raw_data = 0;
83
84 /* then fill it in with data. */
85 switch (type) {
86 case FRU_A:
87 if ((dense > max.a.dense) || (pl_len > max.a.pl_len)) {
88 errno = EINVAL;
89 return (-1);
90 }
91 tag->a.type = FRU_A_ID;
92 tag->a.dense = dense;
93 tag->a.pl_len = pl_len;
94 break;
95 case FRU_B:
96 if ((dense > max.b.dense) || (pl_len > max.b.pl_len)) {
97 errno = EINVAL;
98 return (-1);
99 }
100 tag->b.type = FRU_B_ID;
101 tag->b.dense = dense;
102 tag->b.pl_len = pl_len;
103 break;
104 case FRU_C:
105 if ((dense > max.c.dense) || (pl_len > max.c.pl_len)) {
106 errno = EINVAL;
107 return (-1);
108 }
109 tag->c.type = FRU_C_ID;
110 tag->c.dense = dense;
111 tag->c.pl_len = pl_len;
112 break;
113 case FRU_D:
114 if ((dense > max.d.dense) || (pl_len > max.d.pl_len)) {
115 errno = EINVAL;
116 return (-1);
117 }
118 tag->d.type = FRU_D_ID;
119 tag->d.dense = dense;
120 tag->d.pl_len = pl_len;
121 break;
122 case FRU_E:
123 if ((dense > max.e.dense) || (pl_len > max.e.pl_len)) {
124 errno = EINVAL;
125 return (-1);
126 }
127 tag->e.type = FRU_E_ID;
128 tag->e.dense = dense;
129 tag->e.pl_len = pl_len;
130 break;
131 case FRU_F:
132 if ((dense > max.f.dense) || (pl_len > max.f.pl_len)) {
133 errno = EINVAL;
134 return (-1);
135 }
136 tag->f.type = FRU_F_ID;
137 tag->f.dense = dense;
138 tag->f.pl_len = pl_len;
139 break;
140 case FRU_G:
141 if ((dense > max.g.dense) || (pl_len > max.g.pl_len)) {
142 errno = EINVAL;
143 return (-1);
144 }
145 tag->g.type = FRU_G_ID;
146 tag->g.dense = dense;
147 tag->g.pl_len = pl_len;
148 break;
149 default:
150 errno = EINVAL;
151 return (-1);
152 }
153
154 return (get_tag_size(type));
155 }
156
157 #if defined(_LITTLE_ENDIAN)
158 fru_tagtype_t
get_tag_type(fru_tag_t * tag)159 get_tag_type(fru_tag_t *tag)
160 {
161 uint64_t tmp64;
162 uint32_t tmp32;
163 fru_tag_t tmp;
164
165 if (tag->a.type == FRU_A_ID)
166 return (FRU_A);
167
168 tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1];
169 if (tmp.b.type == FRU_B_ID)
170 return (FRU_B);
171 if (tmp.c.type == FRU_C_ID)
172 return (FRU_C);
173
174 tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) | tag->byte[2];
175 tmp.raw_data = tmp32;
176 if (tmp.d.type == FRU_D_ID)
177 return (FRU_D);
178 if (tmp.e.type == FRU_E_ID)
179 return (FRU_E);
180
181 tmp32 = (tag->byte[0] << 24) | (tag->byte[1] << 16) |
182 (tag->byte[2] << 8) | tag->byte[3];
183 tmp.raw_data = tmp32;
184 if (tmp.f.type == FRU_F_ID)
185 return (FRU_F);
186
187 tmp64 = ((uint64_t)tag->byte[0] << 40) |
188 ((uint64_t)tag->byte[1] << 32) |
189 ((uint64_t)tag->byte[2] << 24) |
190 ((uint64_t)tag->byte[3] << 16) |
191 ((uint64_t)tag->byte[4] << 8) |
192 (uint64_t)tag->byte[5];
193 tmp.raw_data = tmp64;
194 if (tmp.g.type == FRU_G_ID)
195 return (FRU_G);
196
197 errno = EINVAL;
198 return (-1);
199 }
200 #else
201 fru_tagtype_t
get_tag_type(fru_tag_t * tag)202 get_tag_type(fru_tag_t *tag)
203 {
204 if (tag->a.type == FRU_A_ID)
205 return (FRU_A);
206 else if (tag->b.type == FRU_B_ID)
207 return (FRU_B);
208 else if (tag->c.type == FRU_C_ID)
209 return (FRU_C);
210 else if (tag->d.type == FRU_D_ID)
211 return (FRU_D);
212 else if (tag->e.type == FRU_E_ID)
213 return (FRU_E);
214 else if (tag->f.type == FRU_F_ID)
215 return (FRU_F);
216 else if (tag->g.type == FRU_G_ID)
217 return (FRU_G);
218 else
219 errno = EINVAL;
220 return (-1);
221 }
222 #endif /* _LITTLE_ENDIAN */
223
224 #if defined(_LITTLE_ENDIAN)
225 uint32_t
get_tag_dense(fru_tag_t * tag)226 get_tag_dense(fru_tag_t *tag)
227 {
228 uint64_t tmp64;
229 uint32_t tmp32;
230 fru_tag_t tmp;
231
232 tmp = *tag;
233 switch (get_tag_type(tag)) {
234 case FRU_A:
235 return (tag->a.dense);
236 case FRU_B:
237 tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1];
238 return (tmp.b.dense);
239 case FRU_C:
240 tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1];
241 return (tmp.c.dense);
242 case FRU_D:
243 tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) |
244 tag->byte[2];
245 tmp.raw_data = tmp32;
246 return (tmp.d.dense);
247 case FRU_E:
248 tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) |
249 tag->byte[2];
250 tmp.raw_data = tmp32;
251 return (tmp.e.dense);
252 case FRU_F:
253 tmp32 = (tag->byte[0] << 24) | (tag->byte[1] << 16) |
254 (tag->byte[2] << 8) | tag->byte[3];
255 tmp.raw_data = tmp32;
256 return (tmp.f.dense);
257 case FRU_G:
258 tmp64 = ((uint64_t)tag->byte[0] << 40) |
259 ((uint64_t)tag->byte[1] << 32) |
260 ((uint64_t)tag->byte[2] << 24) |
261 ((uint64_t)tag->byte[3] << 16) |
262 ((uint64_t)tag->byte[4] << 8) |
263 (uint64_t)tag->byte[5];
264 tmp.raw_data = tmp64;
265 return (tmp.g.dense);
266 default:
267 errno = EINVAL;
268 return ((uint32_t)-1);
269 }
270 }
271 #else
272 uint32_t
get_tag_dense(fru_tag_t * tag)273 get_tag_dense(fru_tag_t *tag)
274 {
275 switch (get_tag_type(tag)) {
276 case FRU_A:
277 return (tag->a.dense);
278 case FRU_B:
279 return (tag->b.dense);
280 case FRU_C:
281 return (tag->c.dense);
282 case FRU_D:
283 return (tag->d.dense);
284 case FRU_E:
285 return (tag->e.dense);
286 case FRU_F:
287 return (tag->f.dense);
288 case FRU_G:
289 return (tag->g.dense);
290 default:
291 errno = EINVAL;
292 return ((uint32_t)-1);
293 }
294 }
295 #endif /* _LITTLE_ENDIAN */
296
297 #if defined(_LITTLE_ENDIAN)
298 size_t
get_payload_length(fru_tag_t * tag)299 get_payload_length(fru_tag_t *tag)
300 {
301 uint64_t tmp64;
302 uint32_t tmp32;
303 fru_tag_t tmp;
304
305 tmp = *tag;
306 switch (get_tag_type(tag)) {
307 case FRU_A:
308 return (tag->a.pl_len);
309 case FRU_B:
310 tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1];
311 return (tmp.b.pl_len);
312 case FRU_C:
313 tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1];
314 return (tmp.c.pl_len);
315 case FRU_D:
316 tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) |
317 tag->byte[2];
318 tmp.raw_data = tmp32;
319 return (tmp.d.pl_len);
320 case FRU_E:
321 tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) |
322 tag->byte[2];
323 tmp.raw_data = tmp32;
324 return (tmp.e.pl_len);
325 case FRU_F:
326 tmp32 = (tag->byte[0] << 24) | (tag->byte[1] << 16) |
327 (tag->byte[2] << 8) | tag->byte[3];
328 tmp.raw_data = tmp32;
329 return (tmp.f.pl_len);
330 case FRU_G:
331 tmp64 = ((uint64_t)tag->byte[0] << 40) |
332 ((uint64_t)tag->byte[1] << 32) |
333 ((uint64_t)tag->byte[2] << 24) |
334 ((uint64_t)tag->byte[3] << 16) |
335 ((uint64_t)tag->byte[4] << 8) |
336 (uint64_t)tag->byte[5];
337 tmp.raw_data = tmp64;
338 return (tmp.g.pl_len);
339 default:
340 errno = EINVAL;
341 return ((uint32_t)-1);
342 }
343 }
344 #else
345 size_t
get_payload_length(fru_tag_t * tag)346 get_payload_length(fru_tag_t *tag)
347 {
348 switch (get_tag_type(tag)) {
349 case FRU_A:
350 return (tag->a.pl_len);
351 case FRU_B:
352 return (tag->b.pl_len);
353 case FRU_C:
354 return (tag->c.pl_len);
355 case FRU_D:
356 return (tag->d.pl_len);
357 case FRU_E:
358 return (tag->e.pl_len);
359 case FRU_F:
360 return (tag->f.pl_len);
361 case FRU_G:
362 return (tag->g.pl_len);
363 default:
364 errno = EINVAL;
365 return ((uint32_t)-1);
366 }
367 }
368 #endif /* _LITTLE_ENDIAN */
369
370 int
tags_equal(fru_tag_t t1,fru_tag_t t2)371 tags_equal(fru_tag_t t1, fru_tag_t t2)
372 {
373 return ((get_tag_type(&t1) == get_tag_type(&t2)) &&
374 (get_tag_dense(&t1) == get_tag_dense(&t2)) &&
375 (get_payload_length(&t1) == get_payload_length(&t2)));
376 }
377