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