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, fru_tag_t *tag)
78 {
79 static fru_tag_t max = { 0xFFFFFFFFFFFFFFFFULL };
80 /* make sure the tag is clear. */
81 tag->raw_data = 0;
82
83 /* then fill it in with data. */
84 switch (type) {
85 case FRU_A:
86 if ((dense > max.a.dense) || (pl_len > max.a.pl_len)) {
87 errno = EINVAL;
88 return (-1);
89 }
90 tag->a.type = FRU_A_ID;
91 tag->a.dense = dense;
92 tag->a.pl_len = pl_len;
93 break;
94 case FRU_B:
95 if ((dense > max.b.dense) || (pl_len > max.b.pl_len)) {
96 errno = EINVAL;
97 return (-1);
98 }
99 tag->b.type = FRU_B_ID;
100 tag->b.dense = dense;
101 tag->b.pl_len = pl_len;
102 break;
103 case FRU_C:
104 if ((dense > max.c.dense) || (pl_len > max.c.pl_len)) {
105 errno = EINVAL;
106 return (-1);
107 }
108 tag->c.type = FRU_C_ID;
109 tag->c.dense = dense;
110 tag->c.pl_len = pl_len;
111 break;
112 case FRU_D:
113 if ((dense > max.d.dense) || (pl_len > max.d.pl_len)) {
114 errno = EINVAL;
115 return (-1);
116 }
117 tag->d.type = FRU_D_ID;
118 tag->d.dense = dense;
119 tag->d.pl_len = pl_len;
120 break;
121 case FRU_E:
122 if ((dense > max.e.dense) || (pl_len > max.e.pl_len)) {
123 errno = EINVAL;
124 return (-1);
125 }
126 tag->e.type = FRU_E_ID;
127 tag->e.dense = dense;
128 tag->e.pl_len = pl_len;
129 break;
130 case FRU_F:
131 if ((dense > max.f.dense) || (pl_len > max.f.pl_len)) {
132 errno = EINVAL;
133 return (-1);
134 }
135 tag->f.type = FRU_F_ID;
136 tag->f.dense = dense;
137 tag->f.pl_len = pl_len;
138 break;
139 case FRU_G:
140 if ((dense > max.g.dense) || (pl_len > max.g.pl_len)) {
141 errno = EINVAL;
142 return (-1);
143 }
144 tag->g.type = FRU_G_ID;
145 tag->g.dense = dense;
146 tag->g.pl_len = pl_len;
147 break;
148 default:
149 errno = EINVAL;
150 return (-1);
151 }
152
153 return (get_tag_size(type));
154 }
155
156 #if defined(_LITTLE_ENDIAN)
157 fru_tagtype_t
get_tag_type(fru_tag_t * tag)158 get_tag_type(fru_tag_t *tag)
159 {
160 uint64_t tmp64;
161 uint32_t tmp32;
162 fru_tag_t tmp;
163
164 if (tag->a.type == FRU_A_ID)
165 return (FRU_A);
166
167 tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1];
168 if (tmp.b.type == FRU_B_ID)
169 return (FRU_B);
170 if (tmp.c.type == FRU_C_ID)
171 return (FRU_C);
172
173 tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) | tag->byte[2];
174 tmp.raw_data = tmp32;
175 if (tmp.d.type == FRU_D_ID)
176 return (FRU_D);
177 if (tmp.e.type == FRU_E_ID)
178 return (FRU_E);
179
180 tmp32 = (tag->byte[0] << 24) | (tag->byte[1] << 16) |
181 (tag->byte[2] << 8) | tag->byte[3];
182 tmp.raw_data = tmp32;
183 if (tmp.f.type == FRU_F_ID)
184 return (FRU_F);
185
186 tmp64 = ((uint64_t)tag->byte[0] << 40) |
187 ((uint64_t)tag->byte[1] << 32) |
188 ((uint64_t)tag->byte[2] << 24) |
189 ((uint64_t)tag->byte[3] << 16) |
190 ((uint64_t)tag->byte[4] << 8) |
191 (uint64_t)tag->byte[5];
192 tmp.raw_data = tmp64;
193 if (tmp.g.type == FRU_G_ID)
194 return (FRU_G);
195
196 errno = EINVAL;
197 return (-1);
198 }
199 #else
200 fru_tagtype_t
get_tag_type(fru_tag_t * tag)201 get_tag_type(fru_tag_t *tag)
202 {
203 if (tag->a.type == FRU_A_ID)
204 return (FRU_A);
205 else if (tag->b.type == FRU_B_ID)
206 return (FRU_B);
207 else if (tag->c.type == FRU_C_ID)
208 return (FRU_C);
209 else if (tag->d.type == FRU_D_ID)
210 return (FRU_D);
211 else if (tag->e.type == FRU_E_ID)
212 return (FRU_E);
213 else if (tag->f.type == FRU_F_ID)
214 return (FRU_F);
215 else if (tag->g.type == FRU_G_ID)
216 return (FRU_G);
217
218 errno = EINVAL;
219 return (-1);
220 }
221 #endif /* _LITTLE_ENDIAN */
222
223 #if defined(_LITTLE_ENDIAN)
224 uint32_t
get_tag_dense(fru_tag_t * tag)225 get_tag_dense(fru_tag_t *tag)
226 {
227 uint64_t tmp64;
228 uint32_t tmp32;
229 fru_tag_t tmp;
230
231 tmp = *tag;
232 switch (get_tag_type(tag)) {
233 case FRU_A:
234 return (tag->a.dense);
235 case FRU_B:
236 tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1];
237 return (tmp.b.dense);
238 case FRU_C:
239 tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1];
240 return (tmp.c.dense);
241 case FRU_D:
242 tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) |
243 tag->byte[2];
244 tmp.raw_data = tmp32;
245 return (tmp.d.dense);
246 case FRU_E:
247 tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) |
248 tag->byte[2];
249 tmp.raw_data = tmp32;
250 return (tmp.e.dense);
251 case FRU_F:
252 tmp32 = (tag->byte[0] << 24) | (tag->byte[1] << 16) |
253 (tag->byte[2] << 8) | tag->byte[3];
254 tmp.raw_data = tmp32;
255 return (tmp.f.dense);
256 case FRU_G:
257 tmp64 = ((uint64_t)tag->byte[0] << 40) |
258 ((uint64_t)tag->byte[1] << 32) |
259 ((uint64_t)tag->byte[2] << 24) |
260 ((uint64_t)tag->byte[3] << 16) |
261 ((uint64_t)tag->byte[4] << 8) |
262 (uint64_t)tag->byte[5];
263 tmp.raw_data = tmp64;
264 return (tmp.g.dense);
265 default:
266 errno = EINVAL;
267 return ((uint32_t)-1);
268 }
269 }
270 #else
271 uint32_t
get_tag_dense(fru_tag_t * tag)272 get_tag_dense(fru_tag_t *tag)
273 {
274 switch (get_tag_type(tag)) {
275 case FRU_A:
276 return (tag->a.dense);
277 case FRU_B:
278 return (tag->b.dense);
279 case FRU_C:
280 return (tag->c.dense);
281 case FRU_D:
282 return (tag->d.dense);
283 case FRU_E:
284 return (tag->e.dense);
285 case FRU_F:
286 return (tag->f.dense);
287 case FRU_G:
288 return (tag->g.dense);
289 default:
290 errno = EINVAL;
291 return ((uint32_t)-1);
292 }
293 }
294 #endif /* _LITTLE_ENDIAN */
295
296 #if defined(_LITTLE_ENDIAN)
297 size_t
get_payload_length(fru_tag_t * tag)298 get_payload_length(fru_tag_t *tag)
299 {
300 uint64_t tmp64;
301 uint32_t tmp32;
302 fru_tag_t tmp;
303
304 tmp = *tag;
305 switch (get_tag_type(tag)) {
306 case FRU_A:
307 return (tag->a.pl_len);
308 case FRU_B:
309 tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1];
310 return (tmp.b.pl_len);
311 case FRU_C:
312 tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1];
313 return (tmp.c.pl_len);
314 case FRU_D:
315 tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) |
316 tag->byte[2];
317 tmp.raw_data = tmp32;
318 return (tmp.d.pl_len);
319 case FRU_E:
320 tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) |
321 tag->byte[2];
322 tmp.raw_data = tmp32;
323 return (tmp.e.pl_len);
324 case FRU_F:
325 tmp32 = (tag->byte[0] << 24) | (tag->byte[1] << 16) |
326 (tag->byte[2] << 8) | tag->byte[3];
327 tmp.raw_data = tmp32;
328 return (tmp.f.pl_len);
329 case FRU_G:
330 tmp64 = ((uint64_t)tag->byte[0] << 40) |
331 ((uint64_t)tag->byte[1] << 32) |
332 ((uint64_t)tag->byte[2] << 24) |
333 ((uint64_t)tag->byte[3] << 16) |
334 ((uint64_t)tag->byte[4] << 8) |
335 (uint64_t)tag->byte[5];
336 tmp.raw_data = tmp64;
337 return (tmp.g.pl_len);
338 default:
339 errno = EINVAL;
340 return ((uint32_t)-1);
341 }
342 }
343 #else
344 size_t
get_payload_length(fru_tag_t * tag)345 get_payload_length(fru_tag_t *tag)
346 {
347 switch (get_tag_type(tag)) {
348 case FRU_A:
349 return (tag->a.pl_len);
350 case FRU_B:
351 return (tag->b.pl_len);
352 case FRU_C:
353 return (tag->c.pl_len);
354 case FRU_D:
355 return (tag->d.pl_len);
356 case FRU_E:
357 return (tag->e.pl_len);
358 case FRU_F:
359 return (tag->f.pl_len);
360 case FRU_G:
361 return (tag->g.pl_len);
362 default:
363 errno = EINVAL;
364 return ((uint32_t)-1);
365 }
366 }
367 #endif /* _LITTLE_ENDIAN */
368
369 int
tags_equal(fru_tag_t t1,fru_tag_t t2)370 tags_equal(fru_tag_t t1, fru_tag_t t2)
371 {
372 return ((get_tag_type(&t1) == get_tag_type(&t2)) &&
373 (get_tag_dense(&t1) == get_tag_dense(&t2)) &&
374 (get_payload_length(&t1) == get_payload_length(&t2)));
375 }
376