xref: /illumos-gate/usr/src/lib/libfruutils/fru_tag.c (revision 522f3fed)
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