Home | History | Annotate | Download | only in libfruutils
      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 *
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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