/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include "fru_tag.h" char * get_tagtype_str(fru_tagtype_t e) { switch (e) { case FRU_A: return ("A"); case FRU_B: return ("B"); case FRU_C: return ("C"); case FRU_D: return ("D"); case FRU_E: return ("E"); case FRU_F: return ("F"); case FRU_G: return ("G"); case FRU_X: return ("X"); } return ("?"); } size_t get_tag_size(fru_tagtype_t tag) { switch (tag) { case FRU_A: return (1); case FRU_B: case FRU_C: return (2); case FRU_D: case FRU_E: return (3); case FRU_F: return (4); case FRU_G: return (6); } errno = EINVAL; return (-1); } int mk_tag(fru_tagtype_t type, uint32_t dense, size_t pl_len, fru_tag_t *tag) { static fru_tag_t max = { 0xFFFFFFFFFFFFFFFFULL }; /* make sure the tag is clear. */ tag->raw_data = 0; /* then fill it in with data. */ switch (type) { case FRU_A: if ((dense > max.a.dense) || (pl_len > max.a.pl_len)) { errno = EINVAL; return (-1); } tag->a.type = FRU_A_ID; tag->a.dense = dense; tag->a.pl_len = pl_len; break; case FRU_B: if ((dense > max.b.dense) || (pl_len > max.b.pl_len)) { errno = EINVAL; return (-1); } tag->b.type = FRU_B_ID; tag->b.dense = dense; tag->b.pl_len = pl_len; break; case FRU_C: if ((dense > max.c.dense) || (pl_len > max.c.pl_len)) { errno = EINVAL; return (-1); } tag->c.type = FRU_C_ID; tag->c.dense = dense; tag->c.pl_len = pl_len; break; case FRU_D: if ((dense > max.d.dense) || (pl_len > max.d.pl_len)) { errno = EINVAL; return (-1); } tag->d.type = FRU_D_ID; tag->d.dense = dense; tag->d.pl_len = pl_len; break; case FRU_E: if ((dense > max.e.dense) || (pl_len > max.e.pl_len)) { errno = EINVAL; return (-1); } tag->e.type = FRU_E_ID; tag->e.dense = dense; tag->e.pl_len = pl_len; break; case FRU_F: if ((dense > max.f.dense) || (pl_len > max.f.pl_len)) { errno = EINVAL; return (-1); } tag->f.type = FRU_F_ID; tag->f.dense = dense; tag->f.pl_len = pl_len; break; case FRU_G: if ((dense > max.g.dense) || (pl_len > max.g.pl_len)) { errno = EINVAL; return (-1); } tag->g.type = FRU_G_ID; tag->g.dense = dense; tag->g.pl_len = pl_len; break; default: errno = EINVAL; return (-1); } return (get_tag_size(type)); } #if defined(_LITTLE_ENDIAN) fru_tagtype_t get_tag_type(fru_tag_t *tag) { uint64_t tmp64; uint32_t tmp32; fru_tag_t tmp; if (tag->a.type == FRU_A_ID) return (FRU_A); tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1]; if (tmp.b.type == FRU_B_ID) return (FRU_B); if (tmp.c.type == FRU_C_ID) return (FRU_C); tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) | tag->byte[2]; tmp.raw_data = tmp32; if (tmp.d.type == FRU_D_ID) return (FRU_D); if (tmp.e.type == FRU_E_ID) return (FRU_E); tmp32 = (tag->byte[0] << 24) | (tag->byte[1] << 16) | (tag->byte[2] << 8) | tag->byte[3]; tmp.raw_data = tmp32; if (tmp.f.type == FRU_F_ID) return (FRU_F); tmp64 = ((uint64_t)tag->byte[0] << 40) | ((uint64_t)tag->byte[1] << 32) | ((uint64_t)tag->byte[2] << 24) | ((uint64_t)tag->byte[3] << 16) | ((uint64_t)tag->byte[4] << 8) | (uint64_t)tag->byte[5]; tmp.raw_data = tmp64; if (tmp.g.type == FRU_G_ID) return (FRU_G); errno = EINVAL; return (-1); } #else fru_tagtype_t get_tag_type(fru_tag_t *tag) { if (tag->a.type == FRU_A_ID) return (FRU_A); else if (tag->b.type == FRU_B_ID) return (FRU_B); else if (tag->c.type == FRU_C_ID) return (FRU_C); else if (tag->d.type == FRU_D_ID) return (FRU_D); else if (tag->e.type == FRU_E_ID) return (FRU_E); else if (tag->f.type == FRU_F_ID) return (FRU_F); else if (tag->g.type == FRU_G_ID) return (FRU_G); errno = EINVAL; return (-1); } #endif /* _LITTLE_ENDIAN */ #if defined(_LITTLE_ENDIAN) uint32_t get_tag_dense(fru_tag_t *tag) { uint64_t tmp64; uint32_t tmp32; fru_tag_t tmp; tmp = *tag; switch (get_tag_type(tag)) { case FRU_A: return (tag->a.dense); case FRU_B: tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1]; return (tmp.b.dense); case FRU_C: tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1]; return (tmp.c.dense); case FRU_D: tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) | tag->byte[2]; tmp.raw_data = tmp32; return (tmp.d.dense); case FRU_E: tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) | tag->byte[2]; tmp.raw_data = tmp32; return (tmp.e.dense); case FRU_F: tmp32 = (tag->byte[0] << 24) | (tag->byte[1] << 16) | (tag->byte[2] << 8) | tag->byte[3]; tmp.raw_data = tmp32; return (tmp.f.dense); case FRU_G: tmp64 = ((uint64_t)tag->byte[0] << 40) | ((uint64_t)tag->byte[1] << 32) | ((uint64_t)tag->byte[2] << 24) | ((uint64_t)tag->byte[3] << 16) | ((uint64_t)tag->byte[4] << 8) | (uint64_t)tag->byte[5]; tmp.raw_data = tmp64; return (tmp.g.dense); default: errno = EINVAL; return ((uint32_t)-1); } } #else uint32_t get_tag_dense(fru_tag_t *tag) { switch (get_tag_type(tag)) { case FRU_A: return (tag->a.dense); case FRU_B: return (tag->b.dense); case FRU_C: return (tag->c.dense); case FRU_D: return (tag->d.dense); case FRU_E: return (tag->e.dense); case FRU_F: return (tag->f.dense); case FRU_G: return (tag->g.dense); default: errno = EINVAL; return ((uint32_t)-1); } } #endif /* _LITTLE_ENDIAN */ #if defined(_LITTLE_ENDIAN) size_t get_payload_length(fru_tag_t *tag) { uint64_t tmp64; uint32_t tmp32; fru_tag_t tmp; tmp = *tag; switch (get_tag_type(tag)) { case FRU_A: return (tag->a.pl_len); case FRU_B: tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1]; return (tmp.b.pl_len); case FRU_C: tmp.raw_data = (tag->byte[0] << 8) | tag->byte[1]; return (tmp.c.pl_len); case FRU_D: tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) | tag->byte[2]; tmp.raw_data = tmp32; return (tmp.d.pl_len); case FRU_E: tmp32 = (tag->byte[0] << 16) | (tag->byte[1] << 8) | tag->byte[2]; tmp.raw_data = tmp32; return (tmp.e.pl_len); case FRU_F: tmp32 = (tag->byte[0] << 24) | (tag->byte[1] << 16) | (tag->byte[2] << 8) | tag->byte[3]; tmp.raw_data = tmp32; return (tmp.f.pl_len); case FRU_G: tmp64 = ((uint64_t)tag->byte[0] << 40) | ((uint64_t)tag->byte[1] << 32) | ((uint64_t)tag->byte[2] << 24) | ((uint64_t)tag->byte[3] << 16) | ((uint64_t)tag->byte[4] << 8) | (uint64_t)tag->byte[5]; tmp.raw_data = tmp64; return (tmp.g.pl_len); default: errno = EINVAL; return ((uint32_t)-1); } } #else size_t get_payload_length(fru_tag_t *tag) { switch (get_tag_type(tag)) { case FRU_A: return (tag->a.pl_len); case FRU_B: return (tag->b.pl_len); case FRU_C: return (tag->c.pl_len); case FRU_D: return (tag->d.pl_len); case FRU_E: return (tag->e.pl_len); case FRU_F: return (tag->f.pl_len); case FRU_G: return (tag->g.pl_len); default: errno = EINVAL; return ((uint32_t)-1); } } #endif /* _LITTLE_ENDIAN */ int tags_equal(fru_tag_t t1, fru_tag_t t2) { return ((get_tag_type(&t1) == get_tag_type(&t2)) && (get_tag_dense(&t1) == get_tag_dense(&t2)) && (get_payload_length(&t1) == get_payload_length(&t2))); }