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