8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libipmi / common / ipmi_fru.c
blobd652c23cd47f910fab7833e6c0e064a5e4619900
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <libipmi.h>
29 #include <string.h>
31 #include "ipmi_impl.h"
34 * Extracts bits between index h (high, inclusive) and l (low, exclusive) from
35 * u, which must be an unsigned integer.
37 #define BITX(u, h, l) (((u) >> (l)) & ((1LU << ((h) - (l) + 1LU)) - 1LU))
39 typedef struct ipmi_fru_read
41 uint8_t ifr_devid;
42 uint8_t ifr_offset_lsb;
43 uint8_t ifr_offset_msb;
44 uint8_t ifr_count;
45 } ipmi_fru_read_t;
48 * returns: size of FRU inventory data in bytes, on success
49 * -1, otherwise
51 int
52 ipmi_fru_read(ipmi_handle_t *ihp, ipmi_sdr_fru_locator_t *fru_loc, char **buf)
54 ipmi_cmd_t cmd, *resp;
55 uint8_t count, devid;
56 uint16_t sz, offset = 0;
57 ipmi_fru_read_t cmd_data_in;
58 char *tmp;
60 devid = fru_loc->_devid_or_slaveaddr._logical._is_fl_devid;
62 * First we issue a command to retrieve the size of the specified FRU's
63 * inventory area
65 cmd.ic_netfn = IPMI_NETFN_STORAGE;
66 cmd.ic_cmd = IPMI_CMD_GET_FRU_INV_AREA;
67 cmd.ic_data = &devid;
68 cmd.ic_dlen = sizeof (uint8_t);
69 cmd.ic_lun = 0;
71 if ((resp = ipmi_send(ihp, &cmd)) == NULL)
72 return (-1);
74 if (resp->ic_dlen != 3) {
75 (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL);
76 return (-1);
79 (void) memcpy(&sz, resp->ic_data, sizeof (uint16_t));
80 if ((tmp = malloc(sz)) == NULL) {
81 (void) ipmi_set_error(ihp, EIPMI_NOMEM, NULL);
82 return (-1);
85 while (offset < sz) {
86 cmd_data_in.ifr_devid = devid;
87 cmd_data_in.ifr_offset_lsb = BITX(offset, 7, 0);
88 cmd_data_in.ifr_offset_msb = BITX(offset, 15, 8);
89 if ((sz - offset) < 128)
90 cmd_data_in.ifr_count = sz - offset;
91 else
92 cmd_data_in.ifr_count = 128;
94 cmd.ic_netfn = IPMI_NETFN_STORAGE;
95 cmd.ic_cmd = IPMI_CMD_READ_FRU_DATA;
96 cmd.ic_data = &cmd_data_in;
97 cmd.ic_dlen = sizeof (ipmi_fru_read_t);
98 cmd.ic_lun = 0;
100 if ((resp = ipmi_send(ihp, &cmd)) == NULL) {
101 free(tmp);
102 return (-1);
105 (void) memcpy(&count, resp->ic_data, sizeof (uint8_t));
106 if (count != cmd_data_in.ifr_count) {
107 (void) ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH,
108 NULL);
109 free(tmp);
110 return (-1);
112 (void) memcpy(tmp+offset, (char *)(resp->ic_data)+1, count);
113 offset += count;
115 *buf = tmp;
116 return (sz);
120 ipmi_fru_parse_product(ipmi_handle_t *ihp, char *fru_area,
121 ipmi_fru_prod_info_t *buf)
123 ipmi_fru_hdr_t fru_hdr;
124 char *tmp;
125 uint8_t len, typelen;
127 (void) memcpy(&fru_hdr, fru_area, sizeof (ipmi_fru_hdr_t));
130 * We get the offset to the product info area from the FRU common
131 * header which is at the start of the FRU inventory area.
133 * The product info area is optional, so if the offset is NULL,
134 * indicating that it doesn't exist, then we return an error.
136 if (!fru_hdr.ifh_product_info_off) {
137 (void) ipmi_set_error(ihp, EIPMI_NOT_PRESENT, NULL);
138 return (-1);
141 tmp = fru_area + (fru_hdr.ifh_product_info_off * 8) + 3;
143 (void) memcpy(&typelen, tmp, sizeof (uint8_t));
144 len = BITX(typelen, 5, 0);
145 ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifpi_manuf_name);
146 tmp += len + 1;
148 (void) memcpy(&typelen, tmp, sizeof (uint8_t));
149 len = BITX(typelen, 5, 0);
150 ipmi_decode_string((typelen >> 6), len, tmp+1,
151 buf->ifpi_product_name);
152 tmp += len + 1;
154 (void) memcpy(&typelen, tmp, sizeof (uint8_t));
155 len = BITX(typelen, 5, 0);
156 ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifpi_part_number);
157 tmp += len + 1;
159 (void) memcpy(&typelen, tmp, sizeof (uint8_t));
160 len = BITX(typelen, 5, 0);
161 ipmi_decode_string((typelen >> 6), len, tmp+1,
162 buf->ifpi_product_version);
163 tmp += len + 1;
165 (void) memcpy(&typelen, tmp, sizeof (uint8_t));
166 len = BITX(typelen, 5, 0);
167 ipmi_decode_string((typelen >> 6), len, tmp+1,
168 buf->ifpi_product_serial);
169 tmp += len + 1;
171 (void) memcpy(&typelen, tmp, sizeof (uint8_t));
172 len = BITX(typelen, 5, 0);
173 ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifpi_asset_tag);
175 return (0);
180 * The Board Info area is described in Sect 11 of the IPMI Platform Management
181 * FRU Information Storage Definition (v1.1).
184 ipmi_fru_parse_board(ipmi_handle_t *ihp, char *fru_area,
185 ipmi_fru_brd_info_t *buf)
187 ipmi_fru_hdr_t fru_hdr;
188 char *tmp;
189 uint8_t len, typelen;
191 (void) memcpy(&fru_hdr, fru_area, sizeof (ipmi_fru_hdr_t));
194 * We get the offset to the board info area from the FRU common
195 * header which is at the start of the FRU inventory area.
197 * The board info area is optional, so if the offset is NULL,
198 * indicating that it doesn't exist, then we return an error.
200 if (!fru_hdr.ifh_board_info_off) {
201 (void) ipmi_set_error(ihp, EIPMI_NOT_PRESENT, NULL);
202 return (-1);
204 tmp = fru_area + (fru_hdr.ifh_board_info_off * 8) + 3;
206 (void) memcpy(buf->ifbi_manuf_date, tmp, 3);
207 tmp += 3;
209 (void) memcpy(&typelen, tmp, sizeof (uint8_t));
210 len = BITX(typelen, 5, 0);
211 ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifbi_manuf_name);
212 tmp += len + 1;
214 (void) memcpy(&typelen, tmp, sizeof (uint8_t));
215 len = BITX(typelen, 5, 0);
216 ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifbi_board_name);
217 tmp += len + 1;
219 (void) memcpy(&typelen, tmp, sizeof (uint8_t));
220 len = BITX(typelen, 5, 0);
221 ipmi_decode_string((typelen >> 6), len, tmp+1,
222 buf->ifbi_product_serial);
223 tmp += len + 1;
225 (void) memcpy(&typelen, tmp, sizeof (uint8_t));
226 len = BITX(typelen, 5, 0);
227 ipmi_decode_string((typelen >> 6), len, tmp+1, buf->ifbi_part_number);
229 return (0);