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, 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 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 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 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 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 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 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 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