1c18ec02fSPetter Reinholdtsen /*
2c18ec02fSPetter Reinholdtsen * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3c18ec02fSPetter Reinholdtsen *
4c18ec02fSPetter Reinholdtsen * Redistribution and use in source and binary forms, with or without
5c18ec02fSPetter Reinholdtsen * modification, are permitted provided that the following conditions
6c18ec02fSPetter Reinholdtsen * are met:
7c18ec02fSPetter Reinholdtsen *
8c18ec02fSPetter Reinholdtsen * Redistribution of source code must retain the above copyright
9c18ec02fSPetter Reinholdtsen * notice, this list of conditions and the following disclaimer.
10c18ec02fSPetter Reinholdtsen *
11c18ec02fSPetter Reinholdtsen * Redistribution in binary form must reproduce the above copyright
12c18ec02fSPetter Reinholdtsen * notice, this list of conditions and the following disclaimer in the
13c18ec02fSPetter Reinholdtsen * documentation and/or other materials provided with the distribution.
14c18ec02fSPetter Reinholdtsen *
15c18ec02fSPetter Reinholdtsen * Neither the name of Sun Microsystems, Inc. or the names of
16c18ec02fSPetter Reinholdtsen * contributors may be used to endorse or promote products derived
17c18ec02fSPetter Reinholdtsen * from this software without specific prior written permission.
18c18ec02fSPetter Reinholdtsen *
19c18ec02fSPetter Reinholdtsen * This software is provided "AS IS," without a warranty of any kind.
20c18ec02fSPetter Reinholdtsen * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21c18ec02fSPetter Reinholdtsen * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22c18ec02fSPetter Reinholdtsen * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23c18ec02fSPetter Reinholdtsen * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24c18ec02fSPetter Reinholdtsen * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25c18ec02fSPetter Reinholdtsen * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
26c18ec02fSPetter Reinholdtsen * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27c18ec02fSPetter Reinholdtsen * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28c18ec02fSPetter Reinholdtsen * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29c18ec02fSPetter Reinholdtsen * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30c18ec02fSPetter Reinholdtsen * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31c18ec02fSPetter Reinholdtsen */
32c18ec02fSPetter Reinholdtsen
33c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
34c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
35c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
36c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
37c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_fru.h>
38c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_mc.h>
39c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sdr.h>
40c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_strings.h> /* IANA id strings */
41c18ec02fSPetter Reinholdtsen
42c18ec02fSPetter Reinholdtsen #include <stdlib.h>
43c18ec02fSPetter Reinholdtsen #include <string.h>
44c18ec02fSPetter Reinholdtsen #include <time.h>
45c18ec02fSPetter Reinholdtsen #include <errno.h>
46c18ec02fSPetter Reinholdtsen
47c18ec02fSPetter Reinholdtsen #if HAVE_CONFIG_H
48c18ec02fSPetter Reinholdtsen # include <config.h>
49c18ec02fSPetter Reinholdtsen #endif
50c18ec02fSPetter Reinholdtsen
51c18ec02fSPetter Reinholdtsen #define FRU_MULTIREC_CHUNK_SIZE (255 + sizeof(struct fru_multirec_header))
52c18ec02fSPetter Reinholdtsen
53c18ec02fSPetter Reinholdtsen extern int verbose;
54c18ec02fSPetter Reinholdtsen
55c18ec02fSPetter Reinholdtsen static void ipmi_fru_read_to_bin(struct ipmi_intf * intf, char * pFileName, uint8_t fruId);
56c18ec02fSPetter Reinholdtsen static void ipmi_fru_write_from_bin(struct ipmi_intf * intf, char * pFileName, uint8_t fruId);
57c18ec02fSPetter Reinholdtsen static int ipmi_fru_upg_ekeying(struct ipmi_intf * intf, char * pFileName, uint8_t fruId);
58c18ec02fSPetter Reinholdtsen static int ipmi_fru_get_multirec_location_from_fru(struct ipmi_intf * intf, uint8_t fruId,
59c18ec02fSPetter Reinholdtsen struct fru_info *pFruInfo, uint32_t * pRetLocation,
60c18ec02fSPetter Reinholdtsen uint32_t * pRetSize);
61c18ec02fSPetter Reinholdtsen static int ipmi_fru_get_multirec_from_file(char * pFileName, uint8_t * pBufArea,
62c18ec02fSPetter Reinholdtsen uint32_t size, uint32_t offset);
63c18ec02fSPetter Reinholdtsen static int ipmi_fru_get_multirec_size_from_file(char * pFileName, uint32_t * pSize, uint32_t * pOffset);
64c18ec02fSPetter Reinholdtsen int ipmi_fru_get_adjust_size_from_buffer(uint8_t *pBufArea, uint32_t *pSize);
65c18ec02fSPetter Reinholdtsen static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length);
66c18ec02fSPetter Reinholdtsen
67c18ec02fSPetter Reinholdtsen static int ipmi_fru_set_field_string(struct ipmi_intf * intf, unsigned
68c18ec02fSPetter Reinholdtsen char fruId, uint8_t f_type, uint8_t f_index, char *f_string);
69c18ec02fSPetter Reinholdtsen static int
70c18ec02fSPetter Reinholdtsen ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
71c18ec02fSPetter Reinholdtsen struct fru_info fru, struct fru_header header,
72c18ec02fSPetter Reinholdtsen uint8_t f_type, uint8_t f_index, char *f_string);
73c18ec02fSPetter Reinholdtsen
74c18ec02fSPetter Reinholdtsen static void
75c18ec02fSPetter Reinholdtsen fru_area_print_multirec_bloc(struct ipmi_intf * intf, struct fru_info * fru,
76c18ec02fSPetter Reinholdtsen uint8_t id, uint32_t offset);
77c18ec02fSPetter Reinholdtsen int
78c18ec02fSPetter Reinholdtsen read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
79c18ec02fSPetter Reinholdtsen uint32_t offset, uint32_t length, uint8_t *frubuf);
80c18ec02fSPetter Reinholdtsen void free_fru_bloc(t_ipmi_fru_bloc *bloc);
81c18ec02fSPetter Reinholdtsen
82c18ec02fSPetter Reinholdtsen /* get_fru_area_str - Parse FRU area string from raw data
83c18ec02fSPetter Reinholdtsen *
84c18ec02fSPetter Reinholdtsen * @data: raw FRU data
85c18ec02fSPetter Reinholdtsen * @offset: offset into data for area
86c18ec02fSPetter Reinholdtsen *
87c18ec02fSPetter Reinholdtsen * returns pointer to FRU area string
88c18ec02fSPetter Reinholdtsen */
get_fru_area_str(uint8_t * data,uint32_t * offset)89c18ec02fSPetter Reinholdtsen char * get_fru_area_str(uint8_t * data, uint32_t * offset)
90c18ec02fSPetter Reinholdtsen {
91c18ec02fSPetter Reinholdtsen static const char bcd_plus[] = "0123456789 -.:,_";
92c18ec02fSPetter Reinholdtsen char * str;
93c18ec02fSPetter Reinholdtsen int len, off, size, i, j, k, typecode;
94c18ec02fSPetter Reinholdtsen union {
95c18ec02fSPetter Reinholdtsen uint32_t bits;
96c18ec02fSPetter Reinholdtsen char chars[4];
97c18ec02fSPetter Reinholdtsen } u;
98c18ec02fSPetter Reinholdtsen
99c18ec02fSPetter Reinholdtsen size = 0;
100c18ec02fSPetter Reinholdtsen off = *offset;
101c18ec02fSPetter Reinholdtsen
102c18ec02fSPetter Reinholdtsen /* bits 6:7 contain format */
103c18ec02fSPetter Reinholdtsen typecode = ((data[off] & 0xC0) >> 6);
104c18ec02fSPetter Reinholdtsen
105c18ec02fSPetter Reinholdtsen // printf("Typecode:%i\n", typecode);
106c18ec02fSPetter Reinholdtsen /* bits 0:5 contain length */
107c18ec02fSPetter Reinholdtsen len = data[off++];
108c18ec02fSPetter Reinholdtsen len &= 0x3f;
109c18ec02fSPetter Reinholdtsen
110c18ec02fSPetter Reinholdtsen switch (typecode) {
111c18ec02fSPetter Reinholdtsen case 0: /* 00b: binary/unspecified */
112c18ec02fSPetter Reinholdtsen /* hex dump -> 2x length */
113c18ec02fSPetter Reinholdtsen size = (len*2);
114c18ec02fSPetter Reinholdtsen break;
115c18ec02fSPetter Reinholdtsen case 2: /* 10b: 6-bit ASCII */
116c18ec02fSPetter Reinholdtsen /* 4 chars per group of 1-3 bytes */
117c18ec02fSPetter Reinholdtsen size = ((((len+2)*4)/3) & ~3);
118c18ec02fSPetter Reinholdtsen break;
119c18ec02fSPetter Reinholdtsen case 3: /* 11b: 8-bit ASCII */
120c18ec02fSPetter Reinholdtsen case 1: /* 01b: BCD plus */
121c18ec02fSPetter Reinholdtsen /* no length adjustment */
122c18ec02fSPetter Reinholdtsen size = len;
123c18ec02fSPetter Reinholdtsen break;
124c18ec02fSPetter Reinholdtsen }
125c18ec02fSPetter Reinholdtsen
126c18ec02fSPetter Reinholdtsen if (size < 1) {
127c18ec02fSPetter Reinholdtsen *offset = off;
128c18ec02fSPetter Reinholdtsen return NULL;
129c18ec02fSPetter Reinholdtsen }
130c18ec02fSPetter Reinholdtsen str = malloc(size+1);
131c18ec02fSPetter Reinholdtsen if (str == NULL)
132c18ec02fSPetter Reinholdtsen return NULL;
133c18ec02fSPetter Reinholdtsen memset(str, 0, size+1);
134c18ec02fSPetter Reinholdtsen
135c18ec02fSPetter Reinholdtsen if (len == 0) {
136c18ec02fSPetter Reinholdtsen str[0] = '\0';
137c18ec02fSPetter Reinholdtsen *offset = off;
138c18ec02fSPetter Reinholdtsen return str;
139c18ec02fSPetter Reinholdtsen }
140c18ec02fSPetter Reinholdtsen
141c18ec02fSPetter Reinholdtsen switch (typecode) {
142c18ec02fSPetter Reinholdtsen case 0: /* Binary */
143c18ec02fSPetter Reinholdtsen strncpy(str, buf2str(&data[off], len), len*2);
144c18ec02fSPetter Reinholdtsen break;
145c18ec02fSPetter Reinholdtsen
146c18ec02fSPetter Reinholdtsen case 1: /* BCD plus */
147c18ec02fSPetter Reinholdtsen for (k=0; k<len; k++)
148c18ec02fSPetter Reinholdtsen str[k] = bcd_plus[(data[off+k] & 0x0f)];
149c18ec02fSPetter Reinholdtsen str[k] = '\0';
150c18ec02fSPetter Reinholdtsen break;
151c18ec02fSPetter Reinholdtsen
152c18ec02fSPetter Reinholdtsen case 2: /* 6-bit ASCII */
153c18ec02fSPetter Reinholdtsen for (i=j=0; i<len; i+=3) {
154c18ec02fSPetter Reinholdtsen u.bits = 0;
155c18ec02fSPetter Reinholdtsen k = ((len-i) < 3 ? (len-i) : 3);
156c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN
157c18ec02fSPetter Reinholdtsen u.chars[3] = data[off+i];
158c18ec02fSPetter Reinholdtsen u.chars[2] = (k > 1 ? data[off+i+1] : 0);
159c18ec02fSPetter Reinholdtsen u.chars[1] = (k > 2 ? data[off+i+2] : 0);
160c18ec02fSPetter Reinholdtsen #define CHAR_IDX 3
161c18ec02fSPetter Reinholdtsen #else
162c18ec02fSPetter Reinholdtsen memcpy((void *)&u.bits, &data[off+i], k);
163c18ec02fSPetter Reinholdtsen #define CHAR_IDX 0
164c18ec02fSPetter Reinholdtsen #endif
165c18ec02fSPetter Reinholdtsen for (k=0; k<4; k++) {
166c18ec02fSPetter Reinholdtsen str[j++] = ((u.chars[CHAR_IDX] & 0x3f) + 0x20);
167c18ec02fSPetter Reinholdtsen u.bits >>= 6;
168c18ec02fSPetter Reinholdtsen }
169c18ec02fSPetter Reinholdtsen }
170c18ec02fSPetter Reinholdtsen str[j] = '\0';
171c18ec02fSPetter Reinholdtsen break;
172c18ec02fSPetter Reinholdtsen
173c18ec02fSPetter Reinholdtsen case 3:
174c18ec02fSPetter Reinholdtsen memcpy(str, &data[off], len);
175c18ec02fSPetter Reinholdtsen str[len] = '\0';
176c18ec02fSPetter Reinholdtsen break;
177c18ec02fSPetter Reinholdtsen }
178c18ec02fSPetter Reinholdtsen
179c18ec02fSPetter Reinholdtsen off += len;
180c18ec02fSPetter Reinholdtsen *offset = off;
181c18ec02fSPetter Reinholdtsen
182c18ec02fSPetter Reinholdtsen return str;
183c18ec02fSPetter Reinholdtsen }
184c18ec02fSPetter Reinholdtsen
185c18ec02fSPetter Reinholdtsen /* is_valid_filename - checks file/path supplied by user
186c18ec02fSPetter Reinholdtsen *
187c18ec02fSPetter Reinholdtsen * input_filename - user input string
188c18ec02fSPetter Reinholdtsen *
189c18ec02fSPetter Reinholdtsen * returns 0 if path is ok
190c18ec02fSPetter Reinholdtsen * returns (-1) if path is NULL
191c18ec02fSPetter Reinholdtsen * returns (-2) if path is too short
192c18ec02fSPetter Reinholdtsen * returns (-3) if path is too long
193c18ec02fSPetter Reinholdtsen */
194c18ec02fSPetter Reinholdtsen int
is_valid_filename(const char * input_filename)195c18ec02fSPetter Reinholdtsen is_valid_filename(const char *input_filename)
196c18ec02fSPetter Reinholdtsen {
197c18ec02fSPetter Reinholdtsen if (input_filename == NULL) {
198c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ERROR: NULL pointer passed.");
199c18ec02fSPetter Reinholdtsen return (-1);
200c18ec02fSPetter Reinholdtsen }
201c18ec02fSPetter Reinholdtsen
202c18ec02fSPetter Reinholdtsen if (strlen(input_filename) < 1) {
203c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "File/path is invalid.");
204c18ec02fSPetter Reinholdtsen return (-2);
205c18ec02fSPetter Reinholdtsen }
206c18ec02fSPetter Reinholdtsen
207c18ec02fSPetter Reinholdtsen if (strlen(input_filename) >= 512) {
208c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "File/path must be shorter than 512 bytes.");
209c18ec02fSPetter Reinholdtsen return (-3);
210c18ec02fSPetter Reinholdtsen }
211c18ec02fSPetter Reinholdtsen
212c18ec02fSPetter Reinholdtsen return 0;
213c18ec02fSPetter Reinholdtsen } /* is_valid_filename() */
214c18ec02fSPetter Reinholdtsen
215c18ec02fSPetter Reinholdtsen /* build_fru_bloc - build fru bloc for write protection
216c18ec02fSPetter Reinholdtsen *
217c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
218c18ec02fSPetter Reinholdtsen * @fru_info: information about FRU device
219c18ec02fSPetter Reinholdtsen * @id : Fru id
220c18ec02fSPetter Reinholdtsen * @soffset : Source offset (from buffer)
221c18ec02fSPetter Reinholdtsen * @doffset : Destination offset (in device)
222c18ec02fSPetter Reinholdtsen * @length : Size of data to write (in bytes)
223c18ec02fSPetter Reinholdtsen * @pFrubuf : Pointer on data to write
224c18ec02fSPetter Reinholdtsen *
225c18ec02fSPetter Reinholdtsen * returns 0 on success
226c18ec02fSPetter Reinholdtsen * returns -1 on error
227c18ec02fSPetter Reinholdtsen */
228c18ec02fSPetter Reinholdtsen #define FRU_NUM_BLOC_COMMON_HEADER 6
229c18ec02fSPetter Reinholdtsen t_ipmi_fru_bloc *
build_fru_bloc(struct ipmi_intf * intf,struct fru_info * fru,uint8_t id)230c18ec02fSPetter Reinholdtsen build_fru_bloc(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id)
231c18ec02fSPetter Reinholdtsen {
232c18ec02fSPetter Reinholdtsen t_ipmi_fru_bloc * p_first, * p_bloc, * p_new;
233c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
234c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
235c18ec02fSPetter Reinholdtsen struct fru_header header;
236c18ec02fSPetter Reinholdtsen struct fru_multirec_header rec_hdr;
237c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
238c18ec02fSPetter Reinholdtsen uint32_t off;
239c18ec02fSPetter Reinholdtsen uint16_t i;
240c18ec02fSPetter Reinholdtsen
241c18ec02fSPetter Reinholdtsen /*
242c18ec02fSPetter Reinholdtsen * get COMMON Header format
243c18ec02fSPetter Reinholdtsen */
244c18ec02fSPetter Reinholdtsen msg_data[0] = id;
245c18ec02fSPetter Reinholdtsen msg_data[1] = 0;
246c18ec02fSPetter Reinholdtsen msg_data[2] = 0;
247c18ec02fSPetter Reinholdtsen msg_data[3] = 8;
248c18ec02fSPetter Reinholdtsen
249c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
250c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
251c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_DATA;
252c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
253c18ec02fSPetter Reinholdtsen req.msg.data_len = 4;
254c18ec02fSPetter Reinholdtsen
255c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
256c18ec02fSPetter Reinholdtsen
257c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
258c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Device not present (No Response)");
259c18ec02fSPetter Reinholdtsen return NULL;
260c18ec02fSPetter Reinholdtsen }
261c18ec02fSPetter Reinholdtsen
262c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
263c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR," Device not present (%s)",
264c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
265c18ec02fSPetter Reinholdtsen return NULL;
266c18ec02fSPetter Reinholdtsen }
267c18ec02fSPetter Reinholdtsen
268c18ec02fSPetter Reinholdtsen if (verbose > 1) {
269c18ec02fSPetter Reinholdtsen printbuf(rsp->data, rsp->data_len, "FRU DATA");
270c18ec02fSPetter Reinholdtsen }
271c18ec02fSPetter Reinholdtsen
272c18ec02fSPetter Reinholdtsen memcpy(&header, rsp->data + 1, 8);
273c18ec02fSPetter Reinholdtsen
274c18ec02fSPetter Reinholdtsen /* verify header checksum */
275c18ec02fSPetter Reinholdtsen if (ipmi_csum((uint8_t *)&header, 8)) {
276c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Bad header checksum");
277c18ec02fSPetter Reinholdtsen return NULL;
278c18ec02fSPetter Reinholdtsen }
279c18ec02fSPetter Reinholdtsen
280c18ec02fSPetter Reinholdtsen if (header.version != 1) {
281c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Unknown FRU header version 0x%02x", header.version);
282c18ec02fSPetter Reinholdtsen return NULL;
283c18ec02fSPetter Reinholdtsen }
284c18ec02fSPetter Reinholdtsen
285c18ec02fSPetter Reinholdtsen /******************************************
286c18ec02fSPetter Reinholdtsen Malloc and fill up the bloc contents
287c18ec02fSPetter Reinholdtsen *******************************************/
288c18ec02fSPetter Reinholdtsen
289c18ec02fSPetter Reinholdtsen // Common header
290c18ec02fSPetter Reinholdtsen p_first = malloc(sizeof(struct ipmi_fru_bloc));
291c18ec02fSPetter Reinholdtsen if (!p_first) {
292c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure");
293c18ec02fSPetter Reinholdtsen return NULL;
294c18ec02fSPetter Reinholdtsen }
295c18ec02fSPetter Reinholdtsen
296c18ec02fSPetter Reinholdtsen p_bloc = p_first;
297c18ec02fSPetter Reinholdtsen p_bloc->next = NULL;
298c18ec02fSPetter Reinholdtsen p_bloc->start= 0;
299c18ec02fSPetter Reinholdtsen p_bloc->size = fru->size;
300c18ec02fSPetter Reinholdtsen strcpy((char *)p_bloc->blocId, "Common Header Section");
301c18ec02fSPetter Reinholdtsen
302c18ec02fSPetter Reinholdtsen for (i = 0; i < 4; i++) {
303c18ec02fSPetter Reinholdtsen if (header.offsets[i]) {
304c18ec02fSPetter Reinholdtsen p_new = malloc(sizeof(struct ipmi_fru_bloc));
305c18ec02fSPetter Reinholdtsen if (!p_new) {
306c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure");
307c18ec02fSPetter Reinholdtsen free_fru_bloc(p_first);
308c18ec02fSPetter Reinholdtsen return NULL;
309c18ec02fSPetter Reinholdtsen }
310c18ec02fSPetter Reinholdtsen
311c18ec02fSPetter Reinholdtsen p_new->next = NULL;
312c18ec02fSPetter Reinholdtsen p_new->start = header.offsets[i] * 8;
313c18ec02fSPetter Reinholdtsen p_new->size = fru->size - p_new->start;
314c18ec02fSPetter Reinholdtsen
315c18ec02fSPetter Reinholdtsen strncpy((char *)p_new->blocId, section_id[i], sizeof(p_new->blocId));
316c18ec02fSPetter Reinholdtsen /* Make sure string is null terminated */
317c18ec02fSPetter Reinholdtsen p_new->blocId[sizeof(p_new->blocId)-1] = 0;
318c18ec02fSPetter Reinholdtsen
319c18ec02fSPetter Reinholdtsen p_bloc->next = p_new;
320c18ec02fSPetter Reinholdtsen p_bloc->size = p_new->start - p_bloc->start;
321c18ec02fSPetter Reinholdtsen p_bloc = p_new;
322c18ec02fSPetter Reinholdtsen }
323c18ec02fSPetter Reinholdtsen }
324c18ec02fSPetter Reinholdtsen
325c18ec02fSPetter Reinholdtsen // Multi
326c18ec02fSPetter Reinholdtsen if (header.offset.multi) {
327c18ec02fSPetter Reinholdtsen off = header.offset.multi * 8;
328c18ec02fSPetter Reinholdtsen
329c18ec02fSPetter Reinholdtsen do {
330c18ec02fSPetter Reinholdtsen /*
331c18ec02fSPetter Reinholdtsen * check for odd offset for the case of fru devices
332c18ec02fSPetter Reinholdtsen * accessed by words
333c18ec02fSPetter Reinholdtsen */
334c18ec02fSPetter Reinholdtsen if (fru->access && (off & 1)) {
335c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Unaligned offset for a block: %d", off);
336c18ec02fSPetter Reinholdtsen /* increment offset */
337c18ec02fSPetter Reinholdtsen off++;
338c18ec02fSPetter Reinholdtsen break;
339c18ec02fSPetter Reinholdtsen }
340c18ec02fSPetter Reinholdtsen
341c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, fru, id, off, 5,
342c18ec02fSPetter Reinholdtsen (uint8_t *) &rec_hdr) < 0) {
343c18ec02fSPetter Reinholdtsen break;
344c18ec02fSPetter Reinholdtsen }
345c18ec02fSPetter Reinholdtsen
346c18ec02fSPetter Reinholdtsen p_new = malloc(sizeof(struct ipmi_fru_bloc));
347c18ec02fSPetter Reinholdtsen if (!p_new) {
348c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure");
349c18ec02fSPetter Reinholdtsen free_fru_bloc(p_first);
350c18ec02fSPetter Reinholdtsen return NULL;
351c18ec02fSPetter Reinholdtsen }
352c18ec02fSPetter Reinholdtsen
353c18ec02fSPetter Reinholdtsen p_new->next = NULL;
354c18ec02fSPetter Reinholdtsen p_new->start = off;
355c18ec02fSPetter Reinholdtsen p_new->size = fru->size - p_new->start;
356c18ec02fSPetter Reinholdtsen sprintf((char *)p_new->blocId, "Multi-Rec Area: Type %i",
357c18ec02fSPetter Reinholdtsen rec_hdr.type);
358c18ec02fSPetter Reinholdtsen
359c18ec02fSPetter Reinholdtsen p_bloc->next = p_new;
360c18ec02fSPetter Reinholdtsen p_bloc->size = p_new->start - p_bloc->start;
361c18ec02fSPetter Reinholdtsen p_bloc = p_new;
362c18ec02fSPetter Reinholdtsen
363c18ec02fSPetter Reinholdtsen off += rec_hdr.len + sizeof(struct fru_multirec_header);
364c18ec02fSPetter Reinholdtsen
365c18ec02fSPetter Reinholdtsen /* verify record header */
366c18ec02fSPetter Reinholdtsen if (ipmi_csum((uint8_t *)&rec_hdr,
367c18ec02fSPetter Reinholdtsen sizeof(struct fru_multirec_header))) {
368c18ec02fSPetter Reinholdtsen /* can't reliably judge for the rest space */
369c18ec02fSPetter Reinholdtsen break;
370c18ec02fSPetter Reinholdtsen }
371c18ec02fSPetter Reinholdtsen } while (!(rec_hdr.format & 0x80) && (off < fru->size));
372c18ec02fSPetter Reinholdtsen
373c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,"Multi-Record area ends at: %i (%xh)", off, off);
374c18ec02fSPetter Reinholdtsen
375c18ec02fSPetter Reinholdtsen if (fru->size > off) {
376c18ec02fSPetter Reinholdtsen // Bloc for remaining space
377c18ec02fSPetter Reinholdtsen p_new = malloc(sizeof(struct ipmi_fru_bloc));
378c18ec02fSPetter Reinholdtsen if (!p_new) {
379c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure");
380c18ec02fSPetter Reinholdtsen free_fru_bloc(p_first);
381c18ec02fSPetter Reinholdtsen return NULL;
382c18ec02fSPetter Reinholdtsen }
383c18ec02fSPetter Reinholdtsen
384c18ec02fSPetter Reinholdtsen p_new->next = NULL;
385c18ec02fSPetter Reinholdtsen p_new->start = off;
386c18ec02fSPetter Reinholdtsen p_new->size = fru->size - p_new->start;
387c18ec02fSPetter Reinholdtsen strcpy((char *)p_new->blocId, "Unused space");
388c18ec02fSPetter Reinholdtsen
389c18ec02fSPetter Reinholdtsen p_bloc->next = p_new;
390c18ec02fSPetter Reinholdtsen p_bloc->size = p_new->start - p_bloc->start;
391c18ec02fSPetter Reinholdtsen }
392c18ec02fSPetter Reinholdtsen }
393c18ec02fSPetter Reinholdtsen
394c18ec02fSPetter Reinholdtsen /* Dump blocs */
395c18ec02fSPetter Reinholdtsen for(p_bloc = p_first, i = 0; p_bloc; p_bloc = p_bloc->next) {
396c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG ,"Bloc Numb : %i", i++);
397c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG ,"Bloc Id : %s", p_bloc->blocId);
398c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG ,"Bloc Start: %i", p_bloc->start);
399c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG ,"Bloc Size : %i", p_bloc->size);
400c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG ,"");
401c18ec02fSPetter Reinholdtsen }
402c18ec02fSPetter Reinholdtsen
403c18ec02fSPetter Reinholdtsen return p_first;
404c18ec02fSPetter Reinholdtsen }
405c18ec02fSPetter Reinholdtsen
406c18ec02fSPetter Reinholdtsen void
free_fru_bloc(t_ipmi_fru_bloc * bloc)407c18ec02fSPetter Reinholdtsen free_fru_bloc(t_ipmi_fru_bloc *bloc)
408c18ec02fSPetter Reinholdtsen {
409c18ec02fSPetter Reinholdtsen t_ipmi_fru_bloc * del;
410c18ec02fSPetter Reinholdtsen
411c18ec02fSPetter Reinholdtsen while (bloc) {
412c18ec02fSPetter Reinholdtsen del = bloc;
413c18ec02fSPetter Reinholdtsen bloc = bloc->next;
414c18ec02fSPetter Reinholdtsen free(del);
415c18ec02fSPetter Reinholdtsen del = NULL;
416c18ec02fSPetter Reinholdtsen }
417c18ec02fSPetter Reinholdtsen }
418c18ec02fSPetter Reinholdtsen
419c18ec02fSPetter Reinholdtsen /*
420c18ec02fSPetter Reinholdtsen * write FRU[doffset:length] from the pFrubuf[soffset:length]
421c18ec02fSPetter Reinholdtsen * rc=1 on success
422c18ec02fSPetter Reinholdtsen **/
423c18ec02fSPetter Reinholdtsen int
write_fru_area(struct ipmi_intf * intf,struct fru_info * fru,uint8_t id,uint16_t soffset,uint16_t doffset,uint16_t length,uint8_t * pFrubuf)424c18ec02fSPetter Reinholdtsen write_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
425c18ec02fSPetter Reinholdtsen uint16_t soffset, uint16_t doffset,
426c18ec02fSPetter Reinholdtsen uint16_t length, uint8_t *pFrubuf)
427c18ec02fSPetter Reinholdtsen {
428c18ec02fSPetter Reinholdtsen uint16_t tmp, finish;
429c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
430c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
431c18ec02fSPetter Reinholdtsen uint8_t msg_data[255+3];
432c18ec02fSPetter Reinholdtsen uint16_t writeLength;
433c18ec02fSPetter Reinholdtsen uint16_t found_bloc = 0;
434c18ec02fSPetter Reinholdtsen
435c18ec02fSPetter Reinholdtsen finish = doffset + length; /* destination offset */
436c18ec02fSPetter Reinholdtsen if (finish > fru->size)
437c18ec02fSPetter Reinholdtsen {
438c18ec02fSPetter Reinholdtsen lprintf(LOG_ERROR, "Return error");
439c18ec02fSPetter Reinholdtsen return -1;
440c18ec02fSPetter Reinholdtsen }
441c18ec02fSPetter Reinholdtsen
442c18ec02fSPetter Reinholdtsen if (fru->access && ((doffset & 1) || (length & 1))) {
443c18ec02fSPetter Reinholdtsen lprintf(LOG_ERROR, "Odd offset or length specified");
444c18ec02fSPetter Reinholdtsen return (-1);
445c18ec02fSPetter Reinholdtsen }
446c18ec02fSPetter Reinholdtsen
447c18ec02fSPetter Reinholdtsen t_ipmi_fru_bloc * fru_bloc = build_fru_bloc(intf, fru, id);
448c18ec02fSPetter Reinholdtsen t_ipmi_fru_bloc * saved_fru_bloc = fru_bloc;
449c18ec02fSPetter Reinholdtsen
450c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
451c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
452c18ec02fSPetter Reinholdtsen req.msg.cmd = SET_FRU_DATA;
453c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
454c18ec02fSPetter Reinholdtsen
455c18ec02fSPetter Reinholdtsen /* initialize request size only once */
456c18ec02fSPetter Reinholdtsen if (fru->max_write_size == 0) {
45723e9340bSZdenek Styblik uint16_t max_rq_size = ipmi_intf_get_max_request_data_size(intf);
45823e9340bSZdenek Styblik
45923e9340bSZdenek Styblik /* validate lower bound of the maximum request data size */
46023e9340bSZdenek Styblik if (max_rq_size <= 3) {
46123e9340bSZdenek Styblik lprintf(LOG_ERROR, "Maximum request size is too small to send "
46223e9340bSZdenek Styblik "a write request");
46323e9340bSZdenek Styblik return -1;
46423e9340bSZdenek Styblik }
46523e9340bSZdenek Styblik
46623e9340bSZdenek Styblik /*
46723e9340bSZdenek Styblik * Write FRU Info command returns the number of written bytes in
46823e9340bSZdenek Styblik * a single byte field.
46923e9340bSZdenek Styblik */
47023e9340bSZdenek Styblik if (max_rq_size - 3 > 255) {
47123e9340bSZdenek Styblik /* Limit the max write size with 255 bytes. */
47223e9340bSZdenek Styblik fru->max_write_size = 255;
473c18ec02fSPetter Reinholdtsen } else {
474c18ec02fSPetter Reinholdtsen /* subtract 1 byte for FRU ID an 2 bytes for offset */
47523e9340bSZdenek Styblik fru->max_write_size = max_rq_size - 3;
476c18ec02fSPetter Reinholdtsen }
477c18ec02fSPetter Reinholdtsen
478c18ec02fSPetter Reinholdtsen /* check word access */
479c18ec02fSPetter Reinholdtsen if (fru->access) {
480c18ec02fSPetter Reinholdtsen fru->max_write_size &= ~1;
481c18ec02fSPetter Reinholdtsen }
482c18ec02fSPetter Reinholdtsen }
483c18ec02fSPetter Reinholdtsen
484c18ec02fSPetter Reinholdtsen do {
485c18ec02fSPetter Reinholdtsen uint16_t end_bloc;
486c18ec02fSPetter Reinholdtsen uint8_t protected_bloc = 0;
487c18ec02fSPetter Reinholdtsen
488c18ec02fSPetter Reinholdtsen /* Write per bloc, try to find the end of a bloc*/
489c18ec02fSPetter Reinholdtsen while (fru_bloc && fru_bloc->start + fru_bloc->size <= doffset) {
490c18ec02fSPetter Reinholdtsen fru_bloc = fru_bloc->next;
491c18ec02fSPetter Reinholdtsen found_bloc++;
492c18ec02fSPetter Reinholdtsen }
493c18ec02fSPetter Reinholdtsen
494c18ec02fSPetter Reinholdtsen if (fru_bloc && fru_bloc->start + fru_bloc->size < finish) {
495c18ec02fSPetter Reinholdtsen end_bloc = fru_bloc->start + fru_bloc->size;
496c18ec02fSPetter Reinholdtsen } else {
497c18ec02fSPetter Reinholdtsen end_bloc = finish;
498c18ec02fSPetter Reinholdtsen }
499c18ec02fSPetter Reinholdtsen
500c18ec02fSPetter Reinholdtsen /* calculate write length */
501c18ec02fSPetter Reinholdtsen tmp = end_bloc - doffset;
502c18ec02fSPetter Reinholdtsen
503c18ec02fSPetter Reinholdtsen /* check that write length is more than maximum request size */
504c18ec02fSPetter Reinholdtsen if (tmp > fru->max_write_size) {
505c18ec02fSPetter Reinholdtsen writeLength = fru->max_write_size;
506c18ec02fSPetter Reinholdtsen } else {
507c18ec02fSPetter Reinholdtsen writeLength = tmp;
508c18ec02fSPetter Reinholdtsen }
509c18ec02fSPetter Reinholdtsen
510c18ec02fSPetter Reinholdtsen /* copy fru data */
511c18ec02fSPetter Reinholdtsen memcpy(&msg_data[3], pFrubuf + soffset, writeLength);
512c18ec02fSPetter Reinholdtsen
513c18ec02fSPetter Reinholdtsen /* check word access */
514c18ec02fSPetter Reinholdtsen if (fru->access) {
515c18ec02fSPetter Reinholdtsen writeLength &= ~1;
516c18ec02fSPetter Reinholdtsen }
517c18ec02fSPetter Reinholdtsen
518c18ec02fSPetter Reinholdtsen tmp = doffset;
519c18ec02fSPetter Reinholdtsen if (fru->access) {
520c18ec02fSPetter Reinholdtsen tmp >>= 1;
521c18ec02fSPetter Reinholdtsen }
522c18ec02fSPetter Reinholdtsen
523c18ec02fSPetter Reinholdtsen msg_data[0] = id;
524c18ec02fSPetter Reinholdtsen msg_data[1] = (uint8_t)tmp;
525c18ec02fSPetter Reinholdtsen msg_data[2] = (uint8_t)(tmp >> 8);
526c18ec02fSPetter Reinholdtsen req.msg.data_len = writeLength + 3;
527c18ec02fSPetter Reinholdtsen
528c18ec02fSPetter Reinholdtsen if(fru_bloc) {
529c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO,"Writing %d bytes (Bloc #%i: %s)",
530c18ec02fSPetter Reinholdtsen writeLength, found_bloc, fru_bloc->blocId);
531c18ec02fSPetter Reinholdtsen } else {
532c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO,"Writing %d bytes", writeLength);
533c18ec02fSPetter Reinholdtsen }
534c18ec02fSPetter Reinholdtsen
535c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
536c18ec02fSPetter Reinholdtsen if (!rsp) {
537c18ec02fSPetter Reinholdtsen break;
538c18ec02fSPetter Reinholdtsen }
539c18ec02fSPetter Reinholdtsen
540c18ec02fSPetter Reinholdtsen if (rsp->ccode == 0xc7 || rsp->ccode == 0xc8 || rsp->ccode == 0xca) {
541c18ec02fSPetter Reinholdtsen if (fru->max_write_size > 8) {
542c18ec02fSPetter Reinholdtsen fru->max_write_size -= 8;
543c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "Retrying FRU write with request size %d",
544c18ec02fSPetter Reinholdtsen fru->max_write_size);
545c18ec02fSPetter Reinholdtsen continue;
546c18ec02fSPetter Reinholdtsen }
547c18ec02fSPetter Reinholdtsen } else if(rsp->ccode == 0x80) {
548c18ec02fSPetter Reinholdtsen rsp->ccode = 0;
549c18ec02fSPetter Reinholdtsen // Write protected section
550c18ec02fSPetter Reinholdtsen protected_bloc = 1;
551c18ec02fSPetter Reinholdtsen }
552c18ec02fSPetter Reinholdtsen
553c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0)
554c18ec02fSPetter Reinholdtsen break;
555c18ec02fSPetter Reinholdtsen
556c18ec02fSPetter Reinholdtsen if (protected_bloc == 0) {
557c18ec02fSPetter Reinholdtsen // Write OK, bloc not protected, continue
558c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO,"Wrote %d bytes", writeLength);
559c18ec02fSPetter Reinholdtsen doffset += writeLength;
560c18ec02fSPetter Reinholdtsen soffset += writeLength;
561c18ec02fSPetter Reinholdtsen } else {
562c18ec02fSPetter Reinholdtsen if(fru_bloc) {
563c18ec02fSPetter Reinholdtsen // Bloc protected, advise user and jump over protected bloc
564c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO,
565c18ec02fSPetter Reinholdtsen "Bloc [%s] protected at offset: %i (size %i bytes)",
566c18ec02fSPetter Reinholdtsen fru_bloc->blocId, fru_bloc->start, fru_bloc->size);
567c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO,"Jumping over this bloc");
568c18ec02fSPetter Reinholdtsen } else {
569c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO,
570c18ec02fSPetter Reinholdtsen "Remaining FRU is protected following offset: %i",
571c18ec02fSPetter Reinholdtsen doffset);
572c18ec02fSPetter Reinholdtsen }
573c18ec02fSPetter Reinholdtsen soffset += end_bloc - doffset;
574c18ec02fSPetter Reinholdtsen doffset = end_bloc;
575c18ec02fSPetter Reinholdtsen }
576c18ec02fSPetter Reinholdtsen } while (doffset < finish);
577c18ec02fSPetter Reinholdtsen
578c18ec02fSPetter Reinholdtsen if (saved_fru_bloc) {
579c18ec02fSPetter Reinholdtsen free_fru_bloc(saved_fru_bloc);
580c18ec02fSPetter Reinholdtsen }
581c18ec02fSPetter Reinholdtsen
582c18ec02fSPetter Reinholdtsen return doffset >= finish;
583c18ec02fSPetter Reinholdtsen }
584c18ec02fSPetter Reinholdtsen
585c18ec02fSPetter Reinholdtsen /* read_fru_area - fill in frubuf[offset:length] from the FRU[offset:length]
586c18ec02fSPetter Reinholdtsen *
587c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
588c18ec02fSPetter Reinholdtsen * @fru: fru info
589c18ec02fSPetter Reinholdtsen * @id: fru id
590c18ec02fSPetter Reinholdtsen * @offset: offset into buffer
591c18ec02fSPetter Reinholdtsen * @length: how much to read
592c18ec02fSPetter Reinholdtsen * @frubuf: buffer read into
593c18ec02fSPetter Reinholdtsen *
594c18ec02fSPetter Reinholdtsen * returns -1 on error
595c18ec02fSPetter Reinholdtsen * returns 0 if successful
596c18ec02fSPetter Reinholdtsen */
597c18ec02fSPetter Reinholdtsen int
read_fru_area(struct ipmi_intf * intf,struct fru_info * fru,uint8_t id,uint32_t offset,uint32_t length,uint8_t * frubuf)598c18ec02fSPetter Reinholdtsen read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
599c18ec02fSPetter Reinholdtsen uint32_t offset, uint32_t length, uint8_t *frubuf)
600c18ec02fSPetter Reinholdtsen {
601c18ec02fSPetter Reinholdtsen uint32_t off = offset, tmp, finish;
602c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
603c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
604c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
605c18ec02fSPetter Reinholdtsen
606c18ec02fSPetter Reinholdtsen if (offset > fru->size) {
607c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Read FRU Area offset incorrect: %d > %d",
608c18ec02fSPetter Reinholdtsen offset, fru->size);
609c18ec02fSPetter Reinholdtsen return -1;
610c18ec02fSPetter Reinholdtsen }
611c18ec02fSPetter Reinholdtsen
612c18ec02fSPetter Reinholdtsen finish = offset + length;
613c18ec02fSPetter Reinholdtsen if (finish > fru->size) {
614c18ec02fSPetter Reinholdtsen finish = fru->size;
615c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
616c18ec02fSPetter Reinholdtsen "Adjusting to %d",
617c18ec02fSPetter Reinholdtsen offset + length, finish - offset);
618c18ec02fSPetter Reinholdtsen }
619c18ec02fSPetter Reinholdtsen
620c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
621c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
622c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_DATA;
623c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
624c18ec02fSPetter Reinholdtsen req.msg.data_len = 4;
625c18ec02fSPetter Reinholdtsen
626c18ec02fSPetter Reinholdtsen if (fru->max_read_size == 0) {
62723e9340bSZdenek Styblik uint16_t max_rs_size = ipmi_intf_get_max_response_data_size(intf) - 1;
62823e9340bSZdenek Styblik
62923e9340bSZdenek Styblik /* validate lower bound of the maximum response data size */
63023e9340bSZdenek Styblik if (max_rs_size <= 1) {
63123e9340bSZdenek Styblik lprintf(LOG_ERROR, "Maximum response size is too small to send "
63223e9340bSZdenek Styblik "a read request");
63323e9340bSZdenek Styblik return -1;
63423e9340bSZdenek Styblik }
63523e9340bSZdenek Styblik
63623e9340bSZdenek Styblik /*
63723e9340bSZdenek Styblik * Read FRU Info command may read up to 255 bytes of data.
63823e9340bSZdenek Styblik */
63923e9340bSZdenek Styblik if (max_rs_size - 1 > 255) {
64023e9340bSZdenek Styblik /* Limit the max read size with 255 bytes. */
64123e9340bSZdenek Styblik fru->max_read_size = 255;
64223e9340bSZdenek Styblik } else {
64323e9340bSZdenek Styblik /* subtract 1 byte for bytes count */
644166ae1daSZdenek Styblik fru->max_read_size = max_rs_size - 1;
64523e9340bSZdenek Styblik }
646c18ec02fSPetter Reinholdtsen
647c18ec02fSPetter Reinholdtsen /* check word access */
648c18ec02fSPetter Reinholdtsen if (fru->access) {
649c18ec02fSPetter Reinholdtsen fru->max_read_size &= ~1;
650c18ec02fSPetter Reinholdtsen }
651c18ec02fSPetter Reinholdtsen }
652c18ec02fSPetter Reinholdtsen
653c18ec02fSPetter Reinholdtsen do {
654c18ec02fSPetter Reinholdtsen tmp = fru->access ? off >> 1 : off;
655c18ec02fSPetter Reinholdtsen msg_data[0] = id;
656c18ec02fSPetter Reinholdtsen msg_data[1] = (uint8_t)(tmp & 0xff);
657c18ec02fSPetter Reinholdtsen msg_data[2] = (uint8_t)(tmp >> 8);
658c18ec02fSPetter Reinholdtsen tmp = finish - off;
659c18ec02fSPetter Reinholdtsen if (tmp > fru->max_read_size)
660c18ec02fSPetter Reinholdtsen msg_data[3] = (uint8_t)fru->max_read_size;
661c18ec02fSPetter Reinholdtsen else
662c18ec02fSPetter Reinholdtsen msg_data[3] = (uint8_t)tmp;
663c18ec02fSPetter Reinholdtsen
664c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
665c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
666c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "FRU Read failed");
667c18ec02fSPetter Reinholdtsen break;
668c18ec02fSPetter Reinholdtsen }
669c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
670c18ec02fSPetter Reinholdtsen /* if we get C8h or CAh completion code then we requested too
671c18ec02fSPetter Reinholdtsen * many bytes at once so try again with smaller size */
672c18ec02fSPetter Reinholdtsen if ((rsp->ccode == 0xc8 || rsp->ccode == 0xca)
673c18ec02fSPetter Reinholdtsen && fru->max_read_size > 8) {
674c18ec02fSPetter Reinholdtsen if (fru->max_read_size > 32) {
675c18ec02fSPetter Reinholdtsen /* subtract read length more aggressively */
676c18ec02fSPetter Reinholdtsen fru->max_read_size -= 8;
677c18ec02fSPetter Reinholdtsen } else {
678c18ec02fSPetter Reinholdtsen /* subtract length less aggressively */
679c18ec02fSPetter Reinholdtsen fru->max_read_size--;
680c18ec02fSPetter Reinholdtsen }
681c18ec02fSPetter Reinholdtsen
682c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "Retrying FRU read with request size %d",
683c18ec02fSPetter Reinholdtsen fru->max_read_size);
684c18ec02fSPetter Reinholdtsen continue;
685c18ec02fSPetter Reinholdtsen }
686c18ec02fSPetter Reinholdtsen
687c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "FRU Read failed: %s",
688c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
689c18ec02fSPetter Reinholdtsen break;
690c18ec02fSPetter Reinholdtsen }
691c18ec02fSPetter Reinholdtsen
692c18ec02fSPetter Reinholdtsen tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
693c18ec02fSPetter Reinholdtsen memcpy(frubuf, rsp->data + 1, tmp);
694c18ec02fSPetter Reinholdtsen off += tmp;
695c18ec02fSPetter Reinholdtsen frubuf += tmp;
696c18ec02fSPetter Reinholdtsen /* sometimes the size returned in the Info command
697c18ec02fSPetter Reinholdtsen * is too large. return 0 so higher level function
698c18ec02fSPetter Reinholdtsen * still attempts to parse what was returned */
699c18ec02fSPetter Reinholdtsen if (tmp == 0 && off < finish) {
700c18ec02fSPetter Reinholdtsen return 0;
701c18ec02fSPetter Reinholdtsen }
702c18ec02fSPetter Reinholdtsen } while (off < finish);
703c18ec02fSPetter Reinholdtsen
704c18ec02fSPetter Reinholdtsen if (off < finish) {
705c18ec02fSPetter Reinholdtsen return -1;
706c18ec02fSPetter Reinholdtsen }
707c18ec02fSPetter Reinholdtsen
708c18ec02fSPetter Reinholdtsen return 0;
709c18ec02fSPetter Reinholdtsen }
710c18ec02fSPetter Reinholdtsen
711c18ec02fSPetter Reinholdtsen /* read_fru_area - fill in frubuf[offset:length] from the FRU[offset:length]
712c18ec02fSPetter Reinholdtsen *
713c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
714c18ec02fSPetter Reinholdtsen * @fru: fru info
715c18ec02fSPetter Reinholdtsen * @id: fru id
716c18ec02fSPetter Reinholdtsen * @offset: offset into buffer
717c18ec02fSPetter Reinholdtsen * @length: how much to read
718c18ec02fSPetter Reinholdtsen * @frubuf: buffer read into
719c18ec02fSPetter Reinholdtsen *
720c18ec02fSPetter Reinholdtsen * returns -1 on error
721c18ec02fSPetter Reinholdtsen * returns 0 if successful
722c18ec02fSPetter Reinholdtsen */
723c18ec02fSPetter Reinholdtsen int
read_fru_area_section(struct ipmi_intf * intf,struct fru_info * fru,uint8_t id,uint32_t offset,uint32_t length,uint8_t * frubuf)724c18ec02fSPetter Reinholdtsen read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
725c18ec02fSPetter Reinholdtsen uint32_t offset, uint32_t length, uint8_t *frubuf)
726c18ec02fSPetter Reinholdtsen {
727c18ec02fSPetter Reinholdtsen static uint32_t fru_data_rqst_size = 20;
728c18ec02fSPetter Reinholdtsen uint32_t off = offset, tmp, finish;
729c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
730c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
731c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
732c18ec02fSPetter Reinholdtsen
733c18ec02fSPetter Reinholdtsen if (offset > fru->size) {
734c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Read FRU Area offset incorrect: %d > %d",
735c18ec02fSPetter Reinholdtsen offset, fru->size);
736c18ec02fSPetter Reinholdtsen return -1;
737c18ec02fSPetter Reinholdtsen }
738c18ec02fSPetter Reinholdtsen
739c18ec02fSPetter Reinholdtsen finish = offset + length;
740c18ec02fSPetter Reinholdtsen if (finish > fru->size) {
741c18ec02fSPetter Reinholdtsen finish = fru->size;
742c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
743c18ec02fSPetter Reinholdtsen "Adjusting to %d",
744c18ec02fSPetter Reinholdtsen offset + length, finish - offset);
745c18ec02fSPetter Reinholdtsen }
746c18ec02fSPetter Reinholdtsen
747c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
748c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
749c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_DATA;
750c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
751c18ec02fSPetter Reinholdtsen req.msg.data_len = 4;
752c18ec02fSPetter Reinholdtsen
753c18ec02fSPetter Reinholdtsen #ifdef LIMIT_ALL_REQUEST_SIZE
754c18ec02fSPetter Reinholdtsen if (fru_data_rqst_size > 16)
755c18ec02fSPetter Reinholdtsen #else
756c18ec02fSPetter Reinholdtsen if (fru->access && fru_data_rqst_size > 16)
757c18ec02fSPetter Reinholdtsen #endif
758c18ec02fSPetter Reinholdtsen fru_data_rqst_size = 16;
759c18ec02fSPetter Reinholdtsen do {
760c18ec02fSPetter Reinholdtsen tmp = fru->access ? off >> 1 : off;
761c18ec02fSPetter Reinholdtsen msg_data[0] = id;
762c18ec02fSPetter Reinholdtsen msg_data[1] = (uint8_t)(tmp & 0xff);
763c18ec02fSPetter Reinholdtsen msg_data[2] = (uint8_t)(tmp >> 8);
764c18ec02fSPetter Reinholdtsen tmp = finish - off;
765c18ec02fSPetter Reinholdtsen if (tmp > fru_data_rqst_size)
766c18ec02fSPetter Reinholdtsen msg_data[3] = (uint8_t)fru_data_rqst_size;
767c18ec02fSPetter Reinholdtsen else
768c18ec02fSPetter Reinholdtsen msg_data[3] = (uint8_t)tmp;
769c18ec02fSPetter Reinholdtsen
770c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
771c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
772c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "FRU Read failed");
773c18ec02fSPetter Reinholdtsen break;
774c18ec02fSPetter Reinholdtsen }
775c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
776c18ec02fSPetter Reinholdtsen /* if we get C7 or C8 or CA return code then we requested too
777c18ec02fSPetter Reinholdtsen * many bytes at once so try again with smaller size */
778c18ec02fSPetter Reinholdtsen if ((rsp->ccode == 0xc7 || rsp->ccode == 0xc8 || rsp->ccode == 0xca) &&
779c18ec02fSPetter Reinholdtsen (--fru_data_rqst_size > 8)) {
780c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "Retrying FRU read with request size %d",
781c18ec02fSPetter Reinholdtsen fru_data_rqst_size);
782c18ec02fSPetter Reinholdtsen continue;
783c18ec02fSPetter Reinholdtsen }
784c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "FRU Read failed: %s",
785c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
786c18ec02fSPetter Reinholdtsen break;
787c18ec02fSPetter Reinholdtsen }
788c18ec02fSPetter Reinholdtsen
789c18ec02fSPetter Reinholdtsen tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
790c18ec02fSPetter Reinholdtsen memcpy((frubuf + off)-offset, rsp->data + 1, tmp);
791c18ec02fSPetter Reinholdtsen off += tmp;
792c18ec02fSPetter Reinholdtsen
793c18ec02fSPetter Reinholdtsen /* sometimes the size returned in the Info command
794c18ec02fSPetter Reinholdtsen * is too large. return 0 so higher level function
795c18ec02fSPetter Reinholdtsen * still attempts to parse what was returned */
796c18ec02fSPetter Reinholdtsen if (tmp == 0 && off < finish)
797c18ec02fSPetter Reinholdtsen return 0;
798c18ec02fSPetter Reinholdtsen
799c18ec02fSPetter Reinholdtsen } while (off < finish);
800c18ec02fSPetter Reinholdtsen
801c18ec02fSPetter Reinholdtsen if (off < finish)
802c18ec02fSPetter Reinholdtsen return -1;
803c18ec02fSPetter Reinholdtsen
804c18ec02fSPetter Reinholdtsen return 0;
805c18ec02fSPetter Reinholdtsen }
806c18ec02fSPetter Reinholdtsen
807c18ec02fSPetter Reinholdtsen
808c18ec02fSPetter Reinholdtsen static void
fru_area_print_multirec_bloc(struct ipmi_intf * intf,struct fru_info * fru,uint8_t id,uint32_t offset)809c18ec02fSPetter Reinholdtsen fru_area_print_multirec_bloc(struct ipmi_intf * intf, struct fru_info * fru,
810c18ec02fSPetter Reinholdtsen uint8_t id, uint32_t offset)
811c18ec02fSPetter Reinholdtsen {
812c18ec02fSPetter Reinholdtsen uint8_t * fru_data = NULL;
813c18ec02fSPetter Reinholdtsen uint32_t fru_len, i;
814c18ec02fSPetter Reinholdtsen struct fru_multirec_header * h;
815c18ec02fSPetter Reinholdtsen uint32_t last_off, len;
816c18ec02fSPetter Reinholdtsen
817c18ec02fSPetter Reinholdtsen i = last_off = offset;
818c18ec02fSPetter Reinholdtsen fru_len = 0;
819c18ec02fSPetter Reinholdtsen
820c18ec02fSPetter Reinholdtsen fru_data = malloc(fru->size + 1);
821c18ec02fSPetter Reinholdtsen if (fru_data == NULL) {
822c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Out of memory!");
823c18ec02fSPetter Reinholdtsen return;
824c18ec02fSPetter Reinholdtsen }
825c18ec02fSPetter Reinholdtsen
826c18ec02fSPetter Reinholdtsen memset(fru_data, 0, fru->size + 1);
827c18ec02fSPetter Reinholdtsen
828c18ec02fSPetter Reinholdtsen do {
829c18ec02fSPetter Reinholdtsen h = (struct fru_multirec_header *) (fru_data + i);
830c18ec02fSPetter Reinholdtsen
831c18ec02fSPetter Reinholdtsen // read area in (at most) FRU_MULTIREC_CHUNK_SIZE bytes at a time
832c18ec02fSPetter Reinholdtsen if ((last_off < (i + sizeof(*h))) || (last_off < (i + h->len)))
833c18ec02fSPetter Reinholdtsen {
834c18ec02fSPetter Reinholdtsen len = fru->size - last_off;
835c18ec02fSPetter Reinholdtsen if (len > FRU_MULTIREC_CHUNK_SIZE)
836c18ec02fSPetter Reinholdtsen len = FRU_MULTIREC_CHUNK_SIZE;
837c18ec02fSPetter Reinholdtsen
838c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, fru, id, last_off, len, fru_data) < 0)
839c18ec02fSPetter Reinholdtsen break;
840c18ec02fSPetter Reinholdtsen
841c18ec02fSPetter Reinholdtsen last_off += len;
842c18ec02fSPetter Reinholdtsen }
843c18ec02fSPetter Reinholdtsen
844c18ec02fSPetter Reinholdtsen //printf("Bloc Numb : %i\n", counter);
845c18ec02fSPetter Reinholdtsen printf("Bloc Start: %i\n", i);
846c18ec02fSPetter Reinholdtsen printf("Bloc Size : %i\n", h->len);
847c18ec02fSPetter Reinholdtsen printf("\n");
848c18ec02fSPetter Reinholdtsen
849c18ec02fSPetter Reinholdtsen i += h->len + sizeof (struct fru_multirec_header);
850c18ec02fSPetter Reinholdtsen } while (!(h->format & 0x80));
851c18ec02fSPetter Reinholdtsen
852c18ec02fSPetter Reinholdtsen i = offset;
853c18ec02fSPetter Reinholdtsen do {
854c18ec02fSPetter Reinholdtsen h = (struct fru_multirec_header *) (fru_data + i);
855c18ec02fSPetter Reinholdtsen
856c18ec02fSPetter Reinholdtsen printf("Bloc Start: %i\n", i);
857c18ec02fSPetter Reinholdtsen printf("Bloc Size : %i\n", h->len);
858c18ec02fSPetter Reinholdtsen printf("\n");
859c18ec02fSPetter Reinholdtsen
860c18ec02fSPetter Reinholdtsen i += h->len + sizeof (struct fru_multirec_header);
861c18ec02fSPetter Reinholdtsen } while (!(h->format & 0x80));
862c18ec02fSPetter Reinholdtsen
863c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG ,"Multi-Record area ends at: %i (%xh)",i,i);
864c18ec02fSPetter Reinholdtsen
865c18ec02fSPetter Reinholdtsen free(fru_data);
866c18ec02fSPetter Reinholdtsen fru_data = NULL;
867c18ec02fSPetter Reinholdtsen }
868c18ec02fSPetter Reinholdtsen
869c18ec02fSPetter Reinholdtsen
870c18ec02fSPetter Reinholdtsen /* fru_area_print_chassis - Print FRU Chassis Area
871c18ec02fSPetter Reinholdtsen *
872c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
873c18ec02fSPetter Reinholdtsen * @fru: fru info
874c18ec02fSPetter Reinholdtsen * @id: fru id
875c18ec02fSPetter Reinholdtsen * @offset: offset pointer
876c18ec02fSPetter Reinholdtsen */
877c18ec02fSPetter Reinholdtsen static void
fru_area_print_chassis(struct ipmi_intf * intf,struct fru_info * fru,uint8_t id,uint32_t offset)878c18ec02fSPetter Reinholdtsen fru_area_print_chassis(struct ipmi_intf * intf, struct fru_info * fru,
879c18ec02fSPetter Reinholdtsen uint8_t id, uint32_t offset)
880c18ec02fSPetter Reinholdtsen {
881c18ec02fSPetter Reinholdtsen char * fru_area;
882c18ec02fSPetter Reinholdtsen uint8_t * fru_data;
883c18ec02fSPetter Reinholdtsen uint32_t fru_len, i;
884c18ec02fSPetter Reinholdtsen uint8_t tmp[2];
885c18ec02fSPetter Reinholdtsen
886c18ec02fSPetter Reinholdtsen fru_len = 0;
887c18ec02fSPetter Reinholdtsen
888c18ec02fSPetter Reinholdtsen /* read enough to check length field */
889c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, fru, id, offset, 2, tmp) == 0) {
890c18ec02fSPetter Reinholdtsen fru_len = 8 * tmp[1];
891c18ec02fSPetter Reinholdtsen }
892c18ec02fSPetter Reinholdtsen
893c18ec02fSPetter Reinholdtsen if (fru_len == 0) {
894c18ec02fSPetter Reinholdtsen return;
895c18ec02fSPetter Reinholdtsen }
896c18ec02fSPetter Reinholdtsen
897c18ec02fSPetter Reinholdtsen fru_data = malloc(fru_len);
898c18ec02fSPetter Reinholdtsen if (fru_data == NULL) {
899c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure");
900c18ec02fSPetter Reinholdtsen return;
901c18ec02fSPetter Reinholdtsen }
902c18ec02fSPetter Reinholdtsen
903c18ec02fSPetter Reinholdtsen memset(fru_data, 0, fru_len);
904c18ec02fSPetter Reinholdtsen
905c18ec02fSPetter Reinholdtsen /* read in the full fru */
906c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, fru, id, offset, fru_len, fru_data) < 0) {
907c18ec02fSPetter Reinholdtsen free(fru_data);
908c18ec02fSPetter Reinholdtsen fru_data = NULL;
909c18ec02fSPetter Reinholdtsen return;
910c18ec02fSPetter Reinholdtsen }
911c18ec02fSPetter Reinholdtsen
912c18ec02fSPetter Reinholdtsen /*
913c18ec02fSPetter Reinholdtsen * skip first two bytes which specify
914c18ec02fSPetter Reinholdtsen * fru area version and fru area length
915c18ec02fSPetter Reinholdtsen */
916c18ec02fSPetter Reinholdtsen i = 2;
917c18ec02fSPetter Reinholdtsen
918c18ec02fSPetter Reinholdtsen printf(" Chassis Type : %s\n",
919c18ec02fSPetter Reinholdtsen chassis_type_desc[fru_data[i] >
920c18ec02fSPetter Reinholdtsen (sizeof(chassis_type_desc)/sizeof(chassis_type_desc[0])) - 1 ?
921c18ec02fSPetter Reinholdtsen 2 : fru_data[i]]);
922c18ec02fSPetter Reinholdtsen
923c18ec02fSPetter Reinholdtsen i++;
924c18ec02fSPetter Reinholdtsen
925c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
926c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
927c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
928c18ec02fSPetter Reinholdtsen printf(" Chassis Part Number : %s\n", fru_area);
929c18ec02fSPetter Reinholdtsen }
930c18ec02fSPetter Reinholdtsen free(fru_area);
931c18ec02fSPetter Reinholdtsen fru_area = NULL;
932c18ec02fSPetter Reinholdtsen }
933c18ec02fSPetter Reinholdtsen
934c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
935c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
936c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
937c18ec02fSPetter Reinholdtsen printf(" Chassis Serial : %s\n", fru_area);
938c18ec02fSPetter Reinholdtsen }
939c18ec02fSPetter Reinholdtsen free(fru_area);
940c18ec02fSPetter Reinholdtsen fru_area = NULL;
941c18ec02fSPetter Reinholdtsen }
942c18ec02fSPetter Reinholdtsen
943c18ec02fSPetter Reinholdtsen /* read any extra fields */
944c18ec02fSPetter Reinholdtsen while ((fru_data[i] != 0xc1) && (i < fru_len))
945c18ec02fSPetter Reinholdtsen {
946c18ec02fSPetter Reinholdtsen int j = i;
947c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
948c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
949c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
950c18ec02fSPetter Reinholdtsen printf(" Chassis Extra : %s\n", fru_area);
951c18ec02fSPetter Reinholdtsen }
952c18ec02fSPetter Reinholdtsen free(fru_area);
953c18ec02fSPetter Reinholdtsen fru_area = NULL;
954c18ec02fSPetter Reinholdtsen }
955c18ec02fSPetter Reinholdtsen
956c18ec02fSPetter Reinholdtsen if (i == j) {
957c18ec02fSPetter Reinholdtsen break;
958c18ec02fSPetter Reinholdtsen }
959c18ec02fSPetter Reinholdtsen }
960c18ec02fSPetter Reinholdtsen
96199721b52SZdenek Styblik if (fru_data != NULL) {
962c18ec02fSPetter Reinholdtsen free(fru_data);
963c18ec02fSPetter Reinholdtsen fru_data = NULL;
964c18ec02fSPetter Reinholdtsen }
965c18ec02fSPetter Reinholdtsen }
966c18ec02fSPetter Reinholdtsen
967c18ec02fSPetter Reinholdtsen /* fru_area_print_board - Print FRU Board Area
968c18ec02fSPetter Reinholdtsen *
969c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
970c18ec02fSPetter Reinholdtsen * @fru: fru info
971c18ec02fSPetter Reinholdtsen * @id: fru id
972c18ec02fSPetter Reinholdtsen * @offset: offset pointer
973c18ec02fSPetter Reinholdtsen */
974c18ec02fSPetter Reinholdtsen static void
fru_area_print_board(struct ipmi_intf * intf,struct fru_info * fru,uint8_t id,uint32_t offset)975c18ec02fSPetter Reinholdtsen fru_area_print_board(struct ipmi_intf * intf, struct fru_info * fru,
976c18ec02fSPetter Reinholdtsen uint8_t id, uint32_t offset)
977c18ec02fSPetter Reinholdtsen {
978c18ec02fSPetter Reinholdtsen char * fru_area;
979c18ec02fSPetter Reinholdtsen uint8_t * fru_data;
980c18ec02fSPetter Reinholdtsen uint32_t fru_len;
981c18ec02fSPetter Reinholdtsen uint32_t i;
982c18ec02fSPetter Reinholdtsen time_t tval;
983c18ec02fSPetter Reinholdtsen uint8_t tmp[2];
984c18ec02fSPetter Reinholdtsen
985c18ec02fSPetter Reinholdtsen fru_len = 0;
986c18ec02fSPetter Reinholdtsen
987c18ec02fSPetter Reinholdtsen /* read enough to check length field */
988c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, fru, id, offset, 2, tmp) == 0) {
989c18ec02fSPetter Reinholdtsen fru_len = 8 * tmp[1];
990c18ec02fSPetter Reinholdtsen }
991c18ec02fSPetter Reinholdtsen
992c18ec02fSPetter Reinholdtsen if (fru_len <= 0) {
993c18ec02fSPetter Reinholdtsen return;
994c18ec02fSPetter Reinholdtsen }
995c18ec02fSPetter Reinholdtsen
996c18ec02fSPetter Reinholdtsen fru_data = malloc(fru_len);
997c18ec02fSPetter Reinholdtsen if (fru_data == NULL) {
998c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure");
999c18ec02fSPetter Reinholdtsen return;
1000c18ec02fSPetter Reinholdtsen }
1001c18ec02fSPetter Reinholdtsen
1002c18ec02fSPetter Reinholdtsen memset(fru_data, 0, fru_len);
1003c18ec02fSPetter Reinholdtsen
1004c18ec02fSPetter Reinholdtsen /* read in the full fru */
1005c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, fru, id, offset, fru_len, fru_data) < 0) {
1006c18ec02fSPetter Reinholdtsen free(fru_data);
1007c18ec02fSPetter Reinholdtsen fru_data = NULL;
1008c18ec02fSPetter Reinholdtsen return;
1009c18ec02fSPetter Reinholdtsen }
1010c18ec02fSPetter Reinholdtsen
1011c18ec02fSPetter Reinholdtsen /*
1012c18ec02fSPetter Reinholdtsen * skip first three bytes which specify
1013c18ec02fSPetter Reinholdtsen * fru area version, fru area length
1014c18ec02fSPetter Reinholdtsen * and fru board language
1015c18ec02fSPetter Reinholdtsen */
1016c18ec02fSPetter Reinholdtsen i = 3;
1017c18ec02fSPetter Reinholdtsen
1018c18ec02fSPetter Reinholdtsen tval=((fru_data[i+2] << 16) + (fru_data[i+1] << 8) + (fru_data[i]));
1019c18ec02fSPetter Reinholdtsen tval=tval * 60;
1020c18ec02fSPetter Reinholdtsen tval=tval + secs_from_1970_1996;
1021c18ec02fSPetter Reinholdtsen printf(" Board Mfg Date : %s", asctime(localtime(&tval)));
1022c18ec02fSPetter Reinholdtsen i += 3; /* skip mfg. date time */
1023c18ec02fSPetter Reinholdtsen
1024c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1025c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1026c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1027c18ec02fSPetter Reinholdtsen printf(" Board Mfg : %s\n", fru_area);
1028c18ec02fSPetter Reinholdtsen }
1029c18ec02fSPetter Reinholdtsen free(fru_area);
1030c18ec02fSPetter Reinholdtsen fru_area = NULL;
1031c18ec02fSPetter Reinholdtsen }
1032c18ec02fSPetter Reinholdtsen
1033c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1034c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1035c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1036c18ec02fSPetter Reinholdtsen printf(" Board Product : %s\n", fru_area);
1037c18ec02fSPetter Reinholdtsen }
1038c18ec02fSPetter Reinholdtsen free(fru_area);
1039c18ec02fSPetter Reinholdtsen fru_area = NULL;
1040c18ec02fSPetter Reinholdtsen }
1041c18ec02fSPetter Reinholdtsen
1042c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1043c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1044c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1045c18ec02fSPetter Reinholdtsen printf(" Board Serial : %s\n", fru_area);
1046c18ec02fSPetter Reinholdtsen }
1047c18ec02fSPetter Reinholdtsen free(fru_area);
1048c18ec02fSPetter Reinholdtsen fru_area = NULL;
1049c18ec02fSPetter Reinholdtsen }
1050c18ec02fSPetter Reinholdtsen
1051c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1052c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1053c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1054c18ec02fSPetter Reinholdtsen printf(" Board Part Number : %s\n", fru_area);
1055c18ec02fSPetter Reinholdtsen }
1056c18ec02fSPetter Reinholdtsen free(fru_area);
1057c18ec02fSPetter Reinholdtsen fru_area = NULL;
1058c18ec02fSPetter Reinholdtsen }
1059c18ec02fSPetter Reinholdtsen
1060c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1061c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1062c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0 && verbose > 0) {
1063c18ec02fSPetter Reinholdtsen printf(" Board FRU ID : %s\n", fru_area);
1064c18ec02fSPetter Reinholdtsen }
1065c18ec02fSPetter Reinholdtsen free(fru_area);
1066c18ec02fSPetter Reinholdtsen fru_area = NULL;
1067c18ec02fSPetter Reinholdtsen }
1068c18ec02fSPetter Reinholdtsen
1069c18ec02fSPetter Reinholdtsen /* read any extra fields */
1070c18ec02fSPetter Reinholdtsen while ((fru_data[i] != 0xc1) && (i < fru_len))
1071c18ec02fSPetter Reinholdtsen {
1072c18ec02fSPetter Reinholdtsen int j = i;
1073c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1074c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1075c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1076c18ec02fSPetter Reinholdtsen printf(" Board Extra : %s\n", fru_area);
1077c18ec02fSPetter Reinholdtsen }
1078c18ec02fSPetter Reinholdtsen free(fru_area);
1079c18ec02fSPetter Reinholdtsen fru_area = NULL;
1080c18ec02fSPetter Reinholdtsen }
1081c18ec02fSPetter Reinholdtsen if (i == j)
1082c18ec02fSPetter Reinholdtsen break;
1083c18ec02fSPetter Reinholdtsen }
1084c18ec02fSPetter Reinholdtsen
10850b54fac7SZdenek Styblik if (fru_data != NULL) {
1086c18ec02fSPetter Reinholdtsen free(fru_data);
1087c18ec02fSPetter Reinholdtsen fru_data = NULL;
1088c18ec02fSPetter Reinholdtsen }
1089c18ec02fSPetter Reinholdtsen }
1090c18ec02fSPetter Reinholdtsen
1091c18ec02fSPetter Reinholdtsen /* fru_area_print_product - Print FRU Product Area
1092c18ec02fSPetter Reinholdtsen *
1093c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
1094c18ec02fSPetter Reinholdtsen * @fru: fru info
1095c18ec02fSPetter Reinholdtsen * @id: fru id
1096c18ec02fSPetter Reinholdtsen * @offset: offset pointer
1097c18ec02fSPetter Reinholdtsen */
1098c18ec02fSPetter Reinholdtsen static void
fru_area_print_product(struct ipmi_intf * intf,struct fru_info * fru,uint8_t id,uint32_t offset)1099c18ec02fSPetter Reinholdtsen fru_area_print_product(struct ipmi_intf * intf, struct fru_info * fru,
1100c18ec02fSPetter Reinholdtsen uint8_t id, uint32_t offset)
1101c18ec02fSPetter Reinholdtsen {
1102c18ec02fSPetter Reinholdtsen char * fru_area;
1103c18ec02fSPetter Reinholdtsen uint8_t * fru_data;
1104c18ec02fSPetter Reinholdtsen uint32_t fru_len, i;
1105c18ec02fSPetter Reinholdtsen uint8_t tmp[2];
1106c18ec02fSPetter Reinholdtsen
1107c18ec02fSPetter Reinholdtsen fru_len = 0;
1108c18ec02fSPetter Reinholdtsen
1109c18ec02fSPetter Reinholdtsen /* read enough to check length field */
1110c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, fru, id, offset, 2, tmp) == 0) {
1111c18ec02fSPetter Reinholdtsen fru_len = 8 * tmp[1];
1112c18ec02fSPetter Reinholdtsen }
1113c18ec02fSPetter Reinholdtsen
1114c18ec02fSPetter Reinholdtsen if (fru_len == 0) {
1115c18ec02fSPetter Reinholdtsen return;
1116c18ec02fSPetter Reinholdtsen }
1117c18ec02fSPetter Reinholdtsen
1118c18ec02fSPetter Reinholdtsen fru_data = malloc(fru_len);
1119c18ec02fSPetter Reinholdtsen if (fru_data == NULL) {
1120c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure");
1121c18ec02fSPetter Reinholdtsen return;
1122c18ec02fSPetter Reinholdtsen }
1123c18ec02fSPetter Reinholdtsen
1124c18ec02fSPetter Reinholdtsen memset(fru_data, 0, fru_len);
1125c18ec02fSPetter Reinholdtsen
1126c18ec02fSPetter Reinholdtsen
1127c18ec02fSPetter Reinholdtsen /* read in the full fru */
1128c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, fru, id, offset, fru_len, fru_data) < 0) {
1129c18ec02fSPetter Reinholdtsen free(fru_data);
1130c18ec02fSPetter Reinholdtsen fru_data = NULL;
1131c18ec02fSPetter Reinholdtsen return;
1132c18ec02fSPetter Reinholdtsen }
1133c18ec02fSPetter Reinholdtsen
1134c18ec02fSPetter Reinholdtsen /*
1135c18ec02fSPetter Reinholdtsen * skip first three bytes which specify
1136c18ec02fSPetter Reinholdtsen * fru area version, fru area length
1137c18ec02fSPetter Reinholdtsen * and fru board language
1138c18ec02fSPetter Reinholdtsen */
1139c18ec02fSPetter Reinholdtsen i = 3;
1140c18ec02fSPetter Reinholdtsen
1141c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1142c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1143c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1144c18ec02fSPetter Reinholdtsen printf(" Product Manufacturer : %s\n", fru_area);
1145c18ec02fSPetter Reinholdtsen }
1146c18ec02fSPetter Reinholdtsen free(fru_area);
1147c18ec02fSPetter Reinholdtsen fru_area = NULL;
1148c18ec02fSPetter Reinholdtsen }
1149c18ec02fSPetter Reinholdtsen
1150c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1151c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1152c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1153c18ec02fSPetter Reinholdtsen printf(" Product Name : %s\n", fru_area);
1154c18ec02fSPetter Reinholdtsen }
1155c18ec02fSPetter Reinholdtsen free(fru_area);
1156c18ec02fSPetter Reinholdtsen fru_area = NULL;
1157c18ec02fSPetter Reinholdtsen }
1158c18ec02fSPetter Reinholdtsen
1159c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1160c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1161c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1162c18ec02fSPetter Reinholdtsen printf(" Product Part Number : %s\n", fru_area);
1163c18ec02fSPetter Reinholdtsen }
1164c18ec02fSPetter Reinholdtsen free(fru_area);
1165c18ec02fSPetter Reinholdtsen fru_area = NULL;
1166c18ec02fSPetter Reinholdtsen }
1167c18ec02fSPetter Reinholdtsen
1168c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1169c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1170c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1171c18ec02fSPetter Reinholdtsen printf(" Product Version : %s\n", fru_area);
1172c18ec02fSPetter Reinholdtsen }
1173c18ec02fSPetter Reinholdtsen free(fru_area);
1174c18ec02fSPetter Reinholdtsen fru_area = NULL;
1175c18ec02fSPetter Reinholdtsen }
1176c18ec02fSPetter Reinholdtsen
1177c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1178c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1179c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1180c18ec02fSPetter Reinholdtsen printf(" Product Serial : %s\n", fru_area);
1181c18ec02fSPetter Reinholdtsen }
1182c18ec02fSPetter Reinholdtsen free(fru_area);
1183c18ec02fSPetter Reinholdtsen fru_area = NULL;
1184c18ec02fSPetter Reinholdtsen }
1185c18ec02fSPetter Reinholdtsen
1186c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1187c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1188c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1189c18ec02fSPetter Reinholdtsen printf(" Product Asset Tag : %s\n", fru_area);
1190c18ec02fSPetter Reinholdtsen }
1191c18ec02fSPetter Reinholdtsen free(fru_area);
1192c18ec02fSPetter Reinholdtsen fru_area = NULL;
1193c18ec02fSPetter Reinholdtsen }
1194c18ec02fSPetter Reinholdtsen
1195c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1196c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1197c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0 && verbose > 0) {
1198c18ec02fSPetter Reinholdtsen printf(" Product FRU ID : %s\n", fru_area);
1199c18ec02fSPetter Reinholdtsen }
1200c18ec02fSPetter Reinholdtsen free(fru_area);
1201c18ec02fSPetter Reinholdtsen fru_area = NULL;
1202c18ec02fSPetter Reinholdtsen }
1203c18ec02fSPetter Reinholdtsen
1204c18ec02fSPetter Reinholdtsen /* read any extra fields */
1205c18ec02fSPetter Reinholdtsen while ((fru_data[i] != 0xc1) && (i < fru_len))
1206c18ec02fSPetter Reinholdtsen {
1207c18ec02fSPetter Reinholdtsen int j = i;
1208c18ec02fSPetter Reinholdtsen fru_area = get_fru_area_str(fru_data, &i);
1209c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
1210c18ec02fSPetter Reinholdtsen if (strlen(fru_area) > 0) {
1211c18ec02fSPetter Reinholdtsen printf(" Product Extra : %s\n", fru_area);
1212c18ec02fSPetter Reinholdtsen }
1213c18ec02fSPetter Reinholdtsen free(fru_area);
1214c18ec02fSPetter Reinholdtsen fru_area = NULL;
1215c18ec02fSPetter Reinholdtsen }
1216c18ec02fSPetter Reinholdtsen if (i == j)
1217c18ec02fSPetter Reinholdtsen break;
1218c18ec02fSPetter Reinholdtsen }
1219c18ec02fSPetter Reinholdtsen
1220*ece5e557SZdenek Styblik if (fru_data != NULL) {
1221c18ec02fSPetter Reinholdtsen free(fru_data);
1222c18ec02fSPetter Reinholdtsen fru_data = NULL;
1223c18ec02fSPetter Reinholdtsen }
1224c18ec02fSPetter Reinholdtsen }
1225c18ec02fSPetter Reinholdtsen
1226c18ec02fSPetter Reinholdtsen /* fru_area_print_multirec - Print FRU Multi Record Area
1227c18ec02fSPetter Reinholdtsen *
1228c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
1229c18ec02fSPetter Reinholdtsen * @fru: fru info
1230c18ec02fSPetter Reinholdtsen * @id: fru id
1231c18ec02fSPetter Reinholdtsen * @offset: offset pointer
1232c18ec02fSPetter Reinholdtsen */
1233c18ec02fSPetter Reinholdtsen static void
fru_area_print_multirec(struct ipmi_intf * intf,struct fru_info * fru,uint8_t id,uint32_t offset)1234c18ec02fSPetter Reinholdtsen fru_area_print_multirec(struct ipmi_intf * intf, struct fru_info * fru,
1235c18ec02fSPetter Reinholdtsen uint8_t id, uint32_t offset)
1236c18ec02fSPetter Reinholdtsen {
1237c18ec02fSPetter Reinholdtsen uint8_t * fru_data;
1238c18ec02fSPetter Reinholdtsen struct fru_multirec_header * h;
1239c18ec02fSPetter Reinholdtsen struct fru_multirec_powersupply * ps;
1240c18ec02fSPetter Reinholdtsen struct fru_multirec_dcoutput * dc;
1241c18ec02fSPetter Reinholdtsen struct fru_multirec_dcload * dl;
1242c18ec02fSPetter Reinholdtsen uint16_t peak_capacity;
1243c18ec02fSPetter Reinholdtsen uint8_t peak_hold_up_time;
1244c18ec02fSPetter Reinholdtsen uint32_t last_off;
1245c18ec02fSPetter Reinholdtsen
1246c18ec02fSPetter Reinholdtsen last_off = offset;
1247c18ec02fSPetter Reinholdtsen
1248c18ec02fSPetter Reinholdtsen fru_data = malloc(FRU_MULTIREC_CHUNK_SIZE);
1249c18ec02fSPetter Reinholdtsen if (fru_data == NULL) {
1250c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure");
1251c18ec02fSPetter Reinholdtsen return;
1252c18ec02fSPetter Reinholdtsen }
1253c18ec02fSPetter Reinholdtsen
1254c18ec02fSPetter Reinholdtsen memset(fru_data, 0, FRU_MULTIREC_CHUNK_SIZE);
1255c18ec02fSPetter Reinholdtsen
1256c18ec02fSPetter Reinholdtsen h = (struct fru_multirec_header *) (fru_data);
1257c18ec02fSPetter Reinholdtsen
1258c18ec02fSPetter Reinholdtsen do {
1259c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, fru, id, last_off, sizeof(*h), fru_data) < 0) {
1260c18ec02fSPetter Reinholdtsen break;
1261c18ec02fSPetter Reinholdtsen }
1262c18ec02fSPetter Reinholdtsen
1263c18ec02fSPetter Reinholdtsen if (h->len && read_fru_area(intf, fru, id,
1264c18ec02fSPetter Reinholdtsen last_off + sizeof(*h), h->len, fru_data + sizeof(*h)) < 0) {
1265c18ec02fSPetter Reinholdtsen break;
1266c18ec02fSPetter Reinholdtsen }
1267c18ec02fSPetter Reinholdtsen
1268c18ec02fSPetter Reinholdtsen last_off += h->len + sizeof(*h);
1269c18ec02fSPetter Reinholdtsen
1270c18ec02fSPetter Reinholdtsen switch (h->type) {
1271c18ec02fSPetter Reinholdtsen case FRU_RECORD_TYPE_POWER_SUPPLY_INFORMATION:
1272c18ec02fSPetter Reinholdtsen ps = (struct fru_multirec_powersupply *)
1273c18ec02fSPetter Reinholdtsen (fru_data + sizeof(struct fru_multirec_header));
1274c18ec02fSPetter Reinholdtsen
1275c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN
1276c18ec02fSPetter Reinholdtsen ps->capacity = BSWAP_16(ps->capacity);
1277c18ec02fSPetter Reinholdtsen ps->peak_va = BSWAP_16(ps->peak_va);
1278c18ec02fSPetter Reinholdtsen ps->lowend_input1 = BSWAP_16(ps->lowend_input1);
1279c18ec02fSPetter Reinholdtsen ps->highend_input1 = BSWAP_16(ps->highend_input1);
1280c18ec02fSPetter Reinholdtsen ps->lowend_input2 = BSWAP_16(ps->lowend_input2);
1281c18ec02fSPetter Reinholdtsen ps->highend_input2 = BSWAP_16(ps->highend_input2);
1282c18ec02fSPetter Reinholdtsen ps->combined_capacity = BSWAP_16(ps->combined_capacity);
1283c18ec02fSPetter Reinholdtsen ps->peak_cap_ht = BSWAP_16(ps->peak_cap_ht);
1284c18ec02fSPetter Reinholdtsen #endif
1285c18ec02fSPetter Reinholdtsen peak_hold_up_time = (ps->peak_cap_ht & 0xf000) >> 12;
1286c18ec02fSPetter Reinholdtsen peak_capacity = ps->peak_cap_ht & 0x0fff;
1287c18ec02fSPetter Reinholdtsen
1288c18ec02fSPetter Reinholdtsen printf (" Power Supply Record\n");
1289c18ec02fSPetter Reinholdtsen printf (" Capacity : %d W\n",
1290c18ec02fSPetter Reinholdtsen ps->capacity);
1291c18ec02fSPetter Reinholdtsen printf (" Peak VA : %d VA\n",
1292c18ec02fSPetter Reinholdtsen ps->peak_va);
1293c18ec02fSPetter Reinholdtsen printf (" Inrush Current : %d A\n",
1294c18ec02fSPetter Reinholdtsen ps->inrush_current);
1295c18ec02fSPetter Reinholdtsen printf (" Inrush Interval : %d ms\n",
1296c18ec02fSPetter Reinholdtsen ps->inrush_interval);
1297c18ec02fSPetter Reinholdtsen printf (" Input Voltage Range 1 : %d-%d V\n",
1298c18ec02fSPetter Reinholdtsen ps->lowend_input1 / 100, ps->highend_input1 / 100);
1299c18ec02fSPetter Reinholdtsen printf (" Input Voltage Range 2 : %d-%d V\n",
1300c18ec02fSPetter Reinholdtsen ps->lowend_input2 / 100, ps->highend_input2 / 100);
1301c18ec02fSPetter Reinholdtsen printf (" Input Frequency Range : %d-%d Hz\n",
1302c18ec02fSPetter Reinholdtsen ps->lowend_freq, ps->highend_freq);
1303c18ec02fSPetter Reinholdtsen printf (" A/C Dropout Tolerance : %d ms\n",
1304c18ec02fSPetter Reinholdtsen ps->dropout_tolerance);
1305c18ec02fSPetter Reinholdtsen printf (" Flags : %s%s%s%s%s\n",
1306c18ec02fSPetter Reinholdtsen ps->predictive_fail ? "'Predictive fail' " : "",
1307c18ec02fSPetter Reinholdtsen ps->pfc ? "'Power factor correction' " : "",
1308c18ec02fSPetter Reinholdtsen ps->autoswitch ? "'Autoswitch voltage' " : "",
1309c18ec02fSPetter Reinholdtsen ps->hotswap ? "'Hot swap' " : "",
1310c18ec02fSPetter Reinholdtsen ps->predictive_fail ? ps->rps_threshold ?
1311c18ec02fSPetter Reinholdtsen ps->tach ? "'Two pulses per rotation'" : "'One pulse per rotation'" :
1312c18ec02fSPetter Reinholdtsen ps->tach ? "'Failure on pin de-assertion'" : "'Failure on pin assertion'" : "");
1313c18ec02fSPetter Reinholdtsen printf (" Peak capacity : %d W\n",
1314c18ec02fSPetter Reinholdtsen peak_capacity);
1315c18ec02fSPetter Reinholdtsen printf (" Peak capacity holdup : %d s\n",
1316c18ec02fSPetter Reinholdtsen peak_hold_up_time);
1317c18ec02fSPetter Reinholdtsen if (ps->combined_capacity == 0)
1318c18ec02fSPetter Reinholdtsen printf (" Combined capacity : not specified\n");
1319c18ec02fSPetter Reinholdtsen else
1320c18ec02fSPetter Reinholdtsen printf (" Combined capacity : %d W (%s and %s)\n",
1321c18ec02fSPetter Reinholdtsen ps->combined_capacity,
1322c18ec02fSPetter Reinholdtsen combined_voltage_desc [ps->combined_voltage1],
1323c18ec02fSPetter Reinholdtsen combined_voltage_desc [ps->combined_voltage2]);
1324c18ec02fSPetter Reinholdtsen if (ps->predictive_fail)
1325c18ec02fSPetter Reinholdtsen printf (" Fan lower threshold : %d RPS\n",
1326c18ec02fSPetter Reinholdtsen ps->rps_threshold);
1327c18ec02fSPetter Reinholdtsen break;
1328c18ec02fSPetter Reinholdtsen
1329c18ec02fSPetter Reinholdtsen case FRU_RECORD_TYPE_DC_OUTPUT:
1330c18ec02fSPetter Reinholdtsen dc = (struct fru_multirec_dcoutput *)
1331c18ec02fSPetter Reinholdtsen (fru_data + sizeof(struct fru_multirec_header));
1332c18ec02fSPetter Reinholdtsen
1333c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN
1334c18ec02fSPetter Reinholdtsen dc->nominal_voltage = BSWAP_16(dc->nominal_voltage);
1335c18ec02fSPetter Reinholdtsen dc->max_neg_dev = BSWAP_16(dc->max_neg_dev);
1336c18ec02fSPetter Reinholdtsen dc->max_pos_dev = BSWAP_16(dc->max_pos_dev);
1337c18ec02fSPetter Reinholdtsen dc->ripple_and_noise = BSWAP_16(dc->ripple_and_noise);
1338c18ec02fSPetter Reinholdtsen dc->min_current = BSWAP_16(dc->min_current);
1339c18ec02fSPetter Reinholdtsen dc->max_current = BSWAP_16(dc->max_current);
1340c18ec02fSPetter Reinholdtsen #endif
1341c18ec02fSPetter Reinholdtsen
1342c18ec02fSPetter Reinholdtsen printf (" DC Output Record\n");
1343c18ec02fSPetter Reinholdtsen printf (" Output Number : %d\n",
1344c18ec02fSPetter Reinholdtsen dc->output_number);
1345c18ec02fSPetter Reinholdtsen printf (" Standby power : %s\n",
1346c18ec02fSPetter Reinholdtsen dc->standby ? "Yes" : "No");
1347c18ec02fSPetter Reinholdtsen printf (" Nominal voltage : %.2f V\n",
1348c18ec02fSPetter Reinholdtsen (double) dc->nominal_voltage / 100);
1349c18ec02fSPetter Reinholdtsen printf (" Max negative deviation : %.2f V\n",
1350c18ec02fSPetter Reinholdtsen (double) dc->max_neg_dev / 100);
1351c18ec02fSPetter Reinholdtsen printf (" Max positive deviation : %.2f V\n",
1352c18ec02fSPetter Reinholdtsen (double) dc->max_pos_dev / 100);
1353c18ec02fSPetter Reinholdtsen printf (" Ripple and noise pk-pk : %d mV\n",
1354c18ec02fSPetter Reinholdtsen dc->ripple_and_noise);
1355c18ec02fSPetter Reinholdtsen printf (" Minimum current draw : %.3f A\n",
1356c18ec02fSPetter Reinholdtsen (double) dc->min_current / 1000);
1357c18ec02fSPetter Reinholdtsen printf (" Maximum current draw : %.3f A\n",
1358c18ec02fSPetter Reinholdtsen (double) dc->max_current / 1000);
1359c18ec02fSPetter Reinholdtsen break;
1360c18ec02fSPetter Reinholdtsen
1361c18ec02fSPetter Reinholdtsen case FRU_RECORD_TYPE_DC_LOAD:
1362c18ec02fSPetter Reinholdtsen dl = (struct fru_multirec_dcload *)
1363c18ec02fSPetter Reinholdtsen (fru_data + sizeof(struct fru_multirec_header));
1364c18ec02fSPetter Reinholdtsen
1365c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN
1366c18ec02fSPetter Reinholdtsen dl->nominal_voltage = BSWAP_16(dl->nominal_voltage);
1367c18ec02fSPetter Reinholdtsen dl->min_voltage = BSWAP_16(dl->min_voltage);
1368c18ec02fSPetter Reinholdtsen dl->max_voltage = BSWAP_16(dl->max_voltage);
1369c18ec02fSPetter Reinholdtsen dl->ripple_and_noise = BSWAP_16(dl->ripple_and_noise);
1370c18ec02fSPetter Reinholdtsen dl->min_current = BSWAP_16(dl->min_current);
1371c18ec02fSPetter Reinholdtsen dl->max_current = BSWAP_16(dl->max_current);
1372c18ec02fSPetter Reinholdtsen #endif
1373c18ec02fSPetter Reinholdtsen
1374c18ec02fSPetter Reinholdtsen printf (" DC Load Record\n");
1375c18ec02fSPetter Reinholdtsen printf (" Output Number : %d\n",
1376c18ec02fSPetter Reinholdtsen dl->output_number);
1377c18ec02fSPetter Reinholdtsen printf (" Nominal voltage : %.2f V\n",
1378c18ec02fSPetter Reinholdtsen (double) dl->nominal_voltage / 100);
1379c18ec02fSPetter Reinholdtsen printf (" Min voltage allowed : %.2f V\n",
1380c18ec02fSPetter Reinholdtsen (double) dl->min_voltage / 100);
1381c18ec02fSPetter Reinholdtsen printf (" Max voltage allowed : %.2f V\n",
1382c18ec02fSPetter Reinholdtsen (double) dl->max_voltage / 100);
1383c18ec02fSPetter Reinholdtsen printf (" Ripple and noise pk-pk : %d mV\n",
1384c18ec02fSPetter Reinholdtsen dl->ripple_and_noise);
1385c18ec02fSPetter Reinholdtsen printf (" Minimum current load : %.3f A\n",
1386c18ec02fSPetter Reinholdtsen (double) dl->min_current / 1000);
1387c18ec02fSPetter Reinholdtsen printf (" Maximum current load : %.3f A\n",
1388c18ec02fSPetter Reinholdtsen (double) dl->max_current / 1000);
1389c18ec02fSPetter Reinholdtsen break;
1390c18ec02fSPetter Reinholdtsen case FRU_RECORD_TYPE_OEM_EXTENSION:
1391c18ec02fSPetter Reinholdtsen {
1392c18ec02fSPetter Reinholdtsen struct fru_multirec_oem_header *oh=(struct fru_multirec_oem_header *)
1393c18ec02fSPetter Reinholdtsen &fru_data[sizeof(struct fru_multirec_header)];
1394c18ec02fSPetter Reinholdtsen uint32_t iana = oh->mfg_id[0] | oh->mfg_id[1]<<8 | oh->mfg_id[2]<<16;
1395c18ec02fSPetter Reinholdtsen
1396c18ec02fSPetter Reinholdtsen /* Now makes sure this is really PICMG record */
1397c18ec02fSPetter Reinholdtsen
1398c18ec02fSPetter Reinholdtsen if( iana == IPMI_OEM_PICMG ){
1399c18ec02fSPetter Reinholdtsen printf(" PICMG Extension Record\n");
1400c18ec02fSPetter Reinholdtsen ipmi_fru_picmg_ext_print(fru_data,
1401c18ec02fSPetter Reinholdtsen sizeof(struct fru_multirec_header),
1402c18ec02fSPetter Reinholdtsen h->len);
1403c18ec02fSPetter Reinholdtsen }
1404c18ec02fSPetter Reinholdtsen /* FIXME: Add OEM record support here */
1405c18ec02fSPetter Reinholdtsen else{
1406c18ec02fSPetter Reinholdtsen printf(" OEM (%s) Record\n", val2str( iana, ipmi_oem_info));
1407c18ec02fSPetter Reinholdtsen }
1408c18ec02fSPetter Reinholdtsen }
1409c18ec02fSPetter Reinholdtsen break;
1410c18ec02fSPetter Reinholdtsen }
1411c18ec02fSPetter Reinholdtsen } while (!(h->format & 0x80));
1412c18ec02fSPetter Reinholdtsen
1413c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG ,"Multi-Record area ends at: %i (%xh)", last_off, last_off);
1414c18ec02fSPetter Reinholdtsen
1415c18ec02fSPetter Reinholdtsen free(fru_data);
1416c18ec02fSPetter Reinholdtsen }
1417c18ec02fSPetter Reinholdtsen
1418c18ec02fSPetter Reinholdtsen /* ipmi_fru_query_new_value - Query new values to replace original FRU content
1419c18ec02fSPetter Reinholdtsen *
1420c18ec02fSPetter Reinholdtsen * @data: FRU data
1421c18ec02fSPetter Reinholdtsen * @offset: offset of the bytes to be modified in data
1422c18ec02fSPetter Reinholdtsen * @len: size of the modified data
1423c18ec02fSPetter Reinholdtsen *
1424c18ec02fSPetter Reinholdtsen * returns : TRUE if data changed
1425c18ec02fSPetter Reinholdtsen * returns : FALSE if data not changed
1426c18ec02fSPetter Reinholdtsen */
ipmi_fru_query_new_value(uint8_t * data,int offset,size_t len)1427c18ec02fSPetter Reinholdtsen int ipmi_fru_query_new_value(uint8_t *data,int offset, size_t len)
1428c18ec02fSPetter Reinholdtsen {
1429c18ec02fSPetter Reinholdtsen int status=FALSE;
1430c18ec02fSPetter Reinholdtsen int ret;
1431c18ec02fSPetter Reinholdtsen char answer;
1432c18ec02fSPetter Reinholdtsen
1433c18ec02fSPetter Reinholdtsen printf("Would you like to change this value <y/n> ? ");
1434c18ec02fSPetter Reinholdtsen ret = scanf("%c", &answer);
1435c18ec02fSPetter Reinholdtsen if (ret != 1) {
1436c18ec02fSPetter Reinholdtsen return FALSE;
1437c18ec02fSPetter Reinholdtsen }
1438c18ec02fSPetter Reinholdtsen
1439c18ec02fSPetter Reinholdtsen if( answer == 'y' || answer == 'Y' ){
1440c18ec02fSPetter Reinholdtsen int i;
1441c18ec02fSPetter Reinholdtsen unsigned int *holder;
1442c18ec02fSPetter Reinholdtsen
1443c18ec02fSPetter Reinholdtsen holder = malloc(len);
1444c18ec02fSPetter Reinholdtsen printf(
1445c18ec02fSPetter Reinholdtsen "Enter hex values for each of the %d entries (lsb first), "
1446c18ec02fSPetter Reinholdtsen "hit <enter> between entries\n", (int)len);
1447c18ec02fSPetter Reinholdtsen
1448c18ec02fSPetter Reinholdtsen /* I can't assign scanf' %x into a single char */
1449c18ec02fSPetter Reinholdtsen for( i=0;i<len;i++ ){
1450c18ec02fSPetter Reinholdtsen ret = scanf("%x", holder+i);
1451c18ec02fSPetter Reinholdtsen if (ret != 1) {
1452c18ec02fSPetter Reinholdtsen free(holder);
1453c18ec02fSPetter Reinholdtsen return FALSE;
1454c18ec02fSPetter Reinholdtsen }
1455c18ec02fSPetter Reinholdtsen }
1456c18ec02fSPetter Reinholdtsen for( i=0;i<len;i++ ){
1457c18ec02fSPetter Reinholdtsen data[offset++] = (unsigned char) *(holder+i);
1458c18ec02fSPetter Reinholdtsen }
1459c18ec02fSPetter Reinholdtsen /* &data[offset++] */
1460c18ec02fSPetter Reinholdtsen free(holder);
1461c18ec02fSPetter Reinholdtsen holder = NULL;
1462c18ec02fSPetter Reinholdtsen status = TRUE;
1463c18ec02fSPetter Reinholdtsen }
1464c18ec02fSPetter Reinholdtsen else{
1465c18ec02fSPetter Reinholdtsen printf("Entered %c\n",answer);
1466c18ec02fSPetter Reinholdtsen }
1467c18ec02fSPetter Reinholdtsen
1468c18ec02fSPetter Reinholdtsen return status;
1469c18ec02fSPetter Reinholdtsen }
1470c18ec02fSPetter Reinholdtsen
1471c18ec02fSPetter Reinholdtsen /* ipmi_fru_oemkontron_edit -
1472c18ec02fSPetter Reinholdtsen * Query new values to replace original FRU content
1473c18ec02fSPetter Reinholdtsen * This is a generic enough to support any type of 'OEM' record
1474c18ec02fSPetter Reinholdtsen * because the user supplies 'IANA number' , 'record Id' and 'record' version'
1475c18ec02fSPetter Reinholdtsen *
1476c18ec02fSPetter Reinholdtsen * However, the parser must have 'apriori' knowledge of the record format
1477c18ec02fSPetter Reinholdtsen * The currently supported record is :
1478c18ec02fSPetter Reinholdtsen *
1479c18ec02fSPetter Reinholdtsen * IANA : 15000 (Kontron)
1480c18ec02fSPetter Reinholdtsen * RECORD ID : 3
1481c18ec02fSPetter Reinholdtsen * RECORD VERSION: 0 (or 1)
1482c18ec02fSPetter Reinholdtsen *
1483c18ec02fSPetter Reinholdtsen * I would have like to put that stuff in an OEM specific file, but apart for
1484c18ec02fSPetter Reinholdtsen * the record format information, all commands are really standard 'FRU' command
1485c18ec02fSPetter Reinholdtsen *
1486c18ec02fSPetter Reinholdtsen *
1487c18ec02fSPetter Reinholdtsen * @data: FRU data
1488c18ec02fSPetter Reinholdtsen * @offset: start of the current multi record (start of header)
1489c18ec02fSPetter Reinholdtsen * @len: len of the current record (excluding header)
1490c18ec02fSPetter Reinholdtsen * @h: pointer to record header
1491c18ec02fSPetter Reinholdtsen * @oh: pointer to OEM /PICMG header
1492c18ec02fSPetter Reinholdtsen *
1493c18ec02fSPetter Reinholdtsen * returns: TRUE if data changed
1494c18ec02fSPetter Reinholdtsen * returns: FALSE if data not changed
1495c18ec02fSPetter Reinholdtsen */
1496c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_INFORMATION_RECORD 3
1497c18ec02fSPetter Reinholdtsen
1498c18ec02fSPetter Reinholdtsen #define EDIT_OEM_KONTRON_COMPLETE_ARG_COUNT 12
1499c18ec02fSPetter Reinholdtsen #define GET_OEM_KONTRON_COMPLETE_ARG_COUNT 5
1500c18ec02fSPetter Reinholdtsen /*
1501c18ec02fSPetter Reinholdtsen ./src/ipmitool fru edit 0
1502c18ec02fSPetter Reinholdtsen oem 15000 3 0 name instance FIELD1 FIELD2 FIELD3 crc32
1503c18ec02fSPetter Reinholdtsen */
1504c18ec02fSPetter Reinholdtsen
1505c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_SUBCOMMAND_ARG_POS 2
1506c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_IANA_ARG_POS 3
1507c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_RECORDID_ARG_POS 4
1508c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_FORMAT_ARG_POS 5
1509c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_NAME_ARG_POS 6
1510c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_INSTANCE_ARG_POS 7
1511c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_VERSION_ARG_POS 8
1512c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_BUILDDATE_ARG_POS 9
1513c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_UPDATEDATE_ARG_POS 10
1514c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_CRC32_ARG_POS 11
1515c18ec02fSPetter Reinholdtsen
1516c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_FIELD_SIZE 8
1517c18ec02fSPetter Reinholdtsen #define OEM_KONTRON_VERSION_FIELD_SIZE 10
1518c18ec02fSPetter Reinholdtsen
1519c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
1520c18ec02fSPetter Reinholdtsen #pragma pack(1)
1521c18ec02fSPetter Reinholdtsen #endif
1522c18ec02fSPetter Reinholdtsen typedef struct OemKontronInformationRecordV0{
1523c18ec02fSPetter Reinholdtsen uint8_t field1TypeLength;
1524c18ec02fSPetter Reinholdtsen uint8_t field1[OEM_KONTRON_FIELD_SIZE];
1525c18ec02fSPetter Reinholdtsen uint8_t field2TypeLength;
1526c18ec02fSPetter Reinholdtsen uint8_t field2[OEM_KONTRON_FIELD_SIZE];
1527c18ec02fSPetter Reinholdtsen uint8_t field3TypeLength;
1528c18ec02fSPetter Reinholdtsen uint8_t field3[OEM_KONTRON_FIELD_SIZE];
1529c18ec02fSPetter Reinholdtsen uint8_t crcTypeLength;
1530c18ec02fSPetter Reinholdtsen uint8_t crc32[OEM_KONTRON_FIELD_SIZE];
1531c18ec02fSPetter Reinholdtsen }tOemKontronInformationRecordV0;
1532c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
1533c18ec02fSPetter Reinholdtsen #pragma pack(0)
1534c18ec02fSPetter Reinholdtsen #endif
1535c18ec02fSPetter Reinholdtsen
1536c18ec02fSPetter Reinholdtsen
1537c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
1538c18ec02fSPetter Reinholdtsen #pragma pack(1)
1539c18ec02fSPetter Reinholdtsen #endif
1540c18ec02fSPetter Reinholdtsen typedef struct OemKontronInformationRecordV1{
1541c18ec02fSPetter Reinholdtsen uint8_t field1TypeLength;
1542c18ec02fSPetter Reinholdtsen uint8_t field1[OEM_KONTRON_VERSION_FIELD_SIZE];
1543c18ec02fSPetter Reinholdtsen uint8_t field2TypeLength;
1544c18ec02fSPetter Reinholdtsen uint8_t field2[OEM_KONTRON_FIELD_SIZE];
1545c18ec02fSPetter Reinholdtsen uint8_t field3TypeLength;
1546c18ec02fSPetter Reinholdtsen uint8_t field3[OEM_KONTRON_FIELD_SIZE];
1547c18ec02fSPetter Reinholdtsen uint8_t crcTypeLength;
1548c18ec02fSPetter Reinholdtsen uint8_t crc32[OEM_KONTRON_FIELD_SIZE];
1549c18ec02fSPetter Reinholdtsen }tOemKontronInformationRecordV1;
1550c18ec02fSPetter Reinholdtsen #ifdef HAVE_PRAGMA_PACK
1551c18ec02fSPetter Reinholdtsen #pragma pack(0)
1552c18ec02fSPetter Reinholdtsen #endif
1553c18ec02fSPetter Reinholdtsen
1554c18ec02fSPetter Reinholdtsen /*
1555c18ec02fSPetter Reinholdtsen ./src/ipmitool fru get 0 oem iana 3
1556c18ec02fSPetter Reinholdtsen
1557c18ec02fSPetter Reinholdtsen */
1558c18ec02fSPetter Reinholdtsen
ipmi_fru_oemkontron_get(int argc,char ** argv,uint8_t * fru_data,int off,int len,struct fru_multirec_header * h,struct fru_multirec_oem_header * oh)1559c18ec02fSPetter Reinholdtsen static void ipmi_fru_oemkontron_get( int argc, char ** argv,uint8_t * fru_data,
1560c18ec02fSPetter Reinholdtsen int off,int len,
1561c18ec02fSPetter Reinholdtsen struct fru_multirec_header *h,
1562c18ec02fSPetter Reinholdtsen struct fru_multirec_oem_header *oh)
1563c18ec02fSPetter Reinholdtsen {
1564c18ec02fSPetter Reinholdtsen static int badParams=FALSE;
1565c18ec02fSPetter Reinholdtsen int start = off;
1566c18ec02fSPetter Reinholdtsen int offset = start;
1567c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_multirec_oem_header);
1568c18ec02fSPetter Reinholdtsen
1569c18ec02fSPetter Reinholdtsen if(!badParams){
1570c18ec02fSPetter Reinholdtsen /* the 'OEM' field is already checked in caller */
1571c18ec02fSPetter Reinholdtsen if( argc > OEM_KONTRON_SUBCOMMAND_ARG_POS ){
1572c18ec02fSPetter Reinholdtsen if(strncmp("oem", argv[OEM_KONTRON_SUBCOMMAND_ARG_POS],3)){
1573c18ec02fSPetter Reinholdtsen printf("usage: fru get <id> <oem>\n");
1574c18ec02fSPetter Reinholdtsen badParams = TRUE;
1575c18ec02fSPetter Reinholdtsen return;
1576c18ec02fSPetter Reinholdtsen }
1577c18ec02fSPetter Reinholdtsen }
1578c18ec02fSPetter Reinholdtsen if( argc<GET_OEM_KONTRON_COMPLETE_ARG_COUNT ){
1579c18ec02fSPetter Reinholdtsen printf("usage: oem <iana> <recordid>\n");
1580c18ec02fSPetter Reinholdtsen printf("usage: oem 15000 3\n");
1581c18ec02fSPetter Reinholdtsen badParams = TRUE;
1582c18ec02fSPetter Reinholdtsen return;
1583c18ec02fSPetter Reinholdtsen }
1584c18ec02fSPetter Reinholdtsen }
1585c18ec02fSPetter Reinholdtsen
1586c18ec02fSPetter Reinholdtsen if(!badParams){
1587c18ec02fSPetter Reinholdtsen
1588c18ec02fSPetter Reinholdtsen if(oh->record_id == OEM_KONTRON_INFORMATION_RECORD ) {
1589c18ec02fSPetter Reinholdtsen
1590c18ec02fSPetter Reinholdtsen uint8_t version;
1591c18ec02fSPetter Reinholdtsen
1592c18ec02fSPetter Reinholdtsen printf("Kontron OEM Information Record\n");
1593c18ec02fSPetter Reinholdtsen version = oh->record_version;
1594c18ec02fSPetter Reinholdtsen
1595c18ec02fSPetter Reinholdtsen int blockstart;
1596c18ec02fSPetter Reinholdtsen uint8_t blockCount;
1597c18ec02fSPetter Reinholdtsen uint8_t blockIndex=0;
1598c18ec02fSPetter Reinholdtsen
1599c18ec02fSPetter Reinholdtsen unsigned int matchInstance = 0;
1600c18ec02fSPetter Reinholdtsen uint8_t instance = 0;
1601c18ec02fSPetter Reinholdtsen
1602c18ec02fSPetter Reinholdtsen if (str2uchar(argv[OEM_KONTRON_INSTANCE_ARG_POS], &instance) != 0) {
1603c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
1604c18ec02fSPetter Reinholdtsen "Instance argument '%s' is either invalid or out of range.",
1605c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_INSTANCE_ARG_POS]);
1606c18ec02fSPetter Reinholdtsen badParams = TRUE;
1607c18ec02fSPetter Reinholdtsen return;
1608c18ec02fSPetter Reinholdtsen }
1609c18ec02fSPetter Reinholdtsen
1610c18ec02fSPetter Reinholdtsen blockCount = fru_data[offset++];
1611c18ec02fSPetter Reinholdtsen
1612c18ec02fSPetter Reinholdtsen for(blockIndex=0;blockIndex<blockCount;blockIndex++){
1613c18ec02fSPetter Reinholdtsen void * pRecordData;
1614c18ec02fSPetter Reinholdtsen uint8_t nameLen;
1615c18ec02fSPetter Reinholdtsen
1616c18ec02fSPetter Reinholdtsen blockstart = offset;
1617c18ec02fSPetter Reinholdtsen nameLen = ( fru_data[offset++] &= 0x3F );
1618c18ec02fSPetter Reinholdtsen printf(" Name: %*.*s\n",nameLen, nameLen, (const char *)(fru_data+offset));
1619c18ec02fSPetter Reinholdtsen
1620c18ec02fSPetter Reinholdtsen offset+=nameLen;
1621c18ec02fSPetter Reinholdtsen
1622c18ec02fSPetter Reinholdtsen pRecordData = &fru_data[offset];
1623c18ec02fSPetter Reinholdtsen
1624c18ec02fSPetter Reinholdtsen printf(" Record Version: %d\n", version);
1625c18ec02fSPetter Reinholdtsen if( version == 0 )
1626c18ec02fSPetter Reinholdtsen {
1627c18ec02fSPetter Reinholdtsen printf(" Version: %*.*s\n",
1628c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1629c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1630c18ec02fSPetter Reinholdtsen ((tOemKontronInformationRecordV0 *) pRecordData)->field1);
1631c18ec02fSPetter Reinholdtsen printf(" Build Date: %*.*s\n",
1632c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1633c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1634c18ec02fSPetter Reinholdtsen ((tOemKontronInformationRecordV0 *) pRecordData)->field2);
1635c18ec02fSPetter Reinholdtsen printf(" Update Date: %*.*s\n",
1636c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1637c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1638c18ec02fSPetter Reinholdtsen ((tOemKontronInformationRecordV0 *) pRecordData)->field3);
1639c18ec02fSPetter Reinholdtsen printf(" Checksum: %*.*s\n\n",
1640c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1641c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1642c18ec02fSPetter Reinholdtsen ((tOemKontronInformationRecordV0 *) pRecordData)->crc32);
1643c18ec02fSPetter Reinholdtsen matchInstance++;
1644c18ec02fSPetter Reinholdtsen offset+= sizeof(tOemKontronInformationRecordV0);
1645c18ec02fSPetter Reinholdtsen offset++;
1646c18ec02fSPetter Reinholdtsen }
1647c18ec02fSPetter Reinholdtsen else if ( version == 1 )
1648c18ec02fSPetter Reinholdtsen {
1649c18ec02fSPetter Reinholdtsen printf(" Version: %*.*s\n",
1650c18ec02fSPetter Reinholdtsen OEM_KONTRON_VERSION_FIELD_SIZE,
1651c18ec02fSPetter Reinholdtsen OEM_KONTRON_VERSION_FIELD_SIZE,
1652c18ec02fSPetter Reinholdtsen ((tOemKontronInformationRecordV1 *) pRecordData)->field1);
1653c18ec02fSPetter Reinholdtsen printf(" Build Date: %*.*s\n",
1654c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1655c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1656c18ec02fSPetter Reinholdtsen ((tOemKontronInformationRecordV1 *) pRecordData)->field2);
1657c18ec02fSPetter Reinholdtsen printf(" Update Date: %*.*s\n",
1658c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1659c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1660c18ec02fSPetter Reinholdtsen ((tOemKontronInformationRecordV1 *) pRecordData)->field3);
1661c18ec02fSPetter Reinholdtsen printf(" Checksum: %*.*s\n\n",
1662c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1663c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE,
1664c18ec02fSPetter Reinholdtsen ((tOemKontronInformationRecordV1 *) pRecordData)->crc32);
1665c18ec02fSPetter Reinholdtsen matchInstance++;
1666c18ec02fSPetter Reinholdtsen offset+= sizeof(tOemKontronInformationRecordV1);
1667c18ec02fSPetter Reinholdtsen offset++;
1668c18ec02fSPetter Reinholdtsen }
1669c18ec02fSPetter Reinholdtsen else
1670c18ec02fSPetter Reinholdtsen {
1671c18ec02fSPetter Reinholdtsen printf (" Unsupported version %d\n",version);
1672c18ec02fSPetter Reinholdtsen }
1673c18ec02fSPetter Reinholdtsen }
1674c18ec02fSPetter Reinholdtsen }
1675c18ec02fSPetter Reinholdtsen }
1676c18ec02fSPetter Reinholdtsen }
1677c18ec02fSPetter Reinholdtsen
ipmi_fru_oemkontron_edit(int argc,char ** argv,uint8_t * fru_data,int off,int len,struct fru_multirec_header * h,struct fru_multirec_oem_header * oh)1678c18ec02fSPetter Reinholdtsen static int ipmi_fru_oemkontron_edit( int argc, char ** argv,uint8_t * fru_data,
1679c18ec02fSPetter Reinholdtsen int off,int len,
1680c18ec02fSPetter Reinholdtsen struct fru_multirec_header *h,
1681c18ec02fSPetter Reinholdtsen struct fru_multirec_oem_header *oh)
1682c18ec02fSPetter Reinholdtsen {
1683c18ec02fSPetter Reinholdtsen static int badParams=FALSE;
1684c18ec02fSPetter Reinholdtsen int hasChanged = FALSE;
1685c18ec02fSPetter Reinholdtsen int start = off;
1686c18ec02fSPetter Reinholdtsen int offset = start;
1687c18ec02fSPetter Reinholdtsen int length = len;
1688c18ec02fSPetter Reinholdtsen int i;
1689c18ec02fSPetter Reinholdtsen uint8_t record_id = 0;
1690c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_multirec_oem_header);
1691c18ec02fSPetter Reinholdtsen
1692c18ec02fSPetter Reinholdtsen if(!badParams){
1693c18ec02fSPetter Reinholdtsen /* the 'OEM' field is already checked in caller */
1694c18ec02fSPetter Reinholdtsen if( argc > OEM_KONTRON_SUBCOMMAND_ARG_POS ){
1695c18ec02fSPetter Reinholdtsen if(strncmp("oem", argv[OEM_KONTRON_SUBCOMMAND_ARG_POS],3)){
1696c18ec02fSPetter Reinholdtsen printf("usage: fru edit <id> <oem> <args...>\n");
1697c18ec02fSPetter Reinholdtsen badParams = TRUE;
1698c18ec02fSPetter Reinholdtsen return hasChanged;
1699c18ec02fSPetter Reinholdtsen }
1700c18ec02fSPetter Reinholdtsen }
1701c18ec02fSPetter Reinholdtsen if( argc<EDIT_OEM_KONTRON_COMPLETE_ARG_COUNT ){
1702c18ec02fSPetter Reinholdtsen printf("usage: oem <iana> <recordid> <format> <args...>\n");
1703c18ec02fSPetter Reinholdtsen printf("usage: oem 15000 3 0 <name> <instance> <field1>"\
1704c18ec02fSPetter Reinholdtsen " <field2> <field3> <crc32>\n");
1705c18ec02fSPetter Reinholdtsen badParams = TRUE;
1706c18ec02fSPetter Reinholdtsen return hasChanged;
1707c18ec02fSPetter Reinholdtsen }
1708c18ec02fSPetter Reinholdtsen if (str2uchar(argv[OEM_KONTRON_RECORDID_ARG_POS], &record_id) != 0) {
1709c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
1710c18ec02fSPetter Reinholdtsen "Record ID argument '%s' is either invalid or out of range.",
1711c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_RECORDID_ARG_POS]);
1712c18ec02fSPetter Reinholdtsen badParams = TRUE;
1713c18ec02fSPetter Reinholdtsen return hasChanged;
1714c18ec02fSPetter Reinholdtsen }
1715c18ec02fSPetter Reinholdtsen if (record_id == OEM_KONTRON_INFORMATION_RECORD) {
1716c18ec02fSPetter Reinholdtsen for(i=OEM_KONTRON_VERSION_ARG_POS;i<=OEM_KONTRON_CRC32_ARG_POS;i++){
1717c18ec02fSPetter Reinholdtsen if( (strlen(argv[i]) != OEM_KONTRON_FIELD_SIZE) &&
1718c18ec02fSPetter Reinholdtsen (strlen(argv[i]) != OEM_KONTRON_VERSION_FIELD_SIZE)) {
1719c18ec02fSPetter Reinholdtsen printf("error: version fields must have %d characters\n",
1720c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE);
1721c18ec02fSPetter Reinholdtsen badParams = TRUE;
1722c18ec02fSPetter Reinholdtsen return hasChanged;
1723c18ec02fSPetter Reinholdtsen }
1724c18ec02fSPetter Reinholdtsen }
1725c18ec02fSPetter Reinholdtsen }
1726c18ec02fSPetter Reinholdtsen }
1727c18ec02fSPetter Reinholdtsen
1728c18ec02fSPetter Reinholdtsen if(!badParams){
1729c18ec02fSPetter Reinholdtsen
1730c18ec02fSPetter Reinholdtsen if(oh->record_id == OEM_KONTRON_INFORMATION_RECORD ) {
1731c18ec02fSPetter Reinholdtsen uint8_t formatVersion = 0;
1732c18ec02fSPetter Reinholdtsen uint8_t version;
1733c18ec02fSPetter Reinholdtsen
1734c18ec02fSPetter Reinholdtsen if (str2uchar(argv[OEM_KONTRON_FORMAT_ARG_POS], &formatVersion) != 0) {
1735c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
1736c18ec02fSPetter Reinholdtsen "Format argument '%s' is either invalid or out of range.",
1737c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_FORMAT_ARG_POS]);
1738c18ec02fSPetter Reinholdtsen badParams = TRUE;
1739c18ec02fSPetter Reinholdtsen return hasChanged;
1740c18ec02fSPetter Reinholdtsen }
1741c18ec02fSPetter Reinholdtsen
1742c18ec02fSPetter Reinholdtsen printf(" Kontron OEM Information Record\n");
1743c18ec02fSPetter Reinholdtsen version = oh->record_version;
1744c18ec02fSPetter Reinholdtsen
1745c18ec02fSPetter Reinholdtsen if( version == formatVersion ){
1746c18ec02fSPetter Reinholdtsen int blockstart;
1747c18ec02fSPetter Reinholdtsen uint8_t blockCount;
1748c18ec02fSPetter Reinholdtsen uint8_t blockIndex=0;
1749c18ec02fSPetter Reinholdtsen
1750c18ec02fSPetter Reinholdtsen uint8_t matchInstance = 0;
1751c18ec02fSPetter Reinholdtsen uint8_t instance = 0;
1752c18ec02fSPetter Reinholdtsen
1753c18ec02fSPetter Reinholdtsen if (str2uchar(argv[OEM_KONTRON_INSTANCE_ARG_POS], &instance) != 0) {
1754c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
1755c18ec02fSPetter Reinholdtsen "Instance argument '%s' is either invalid or out of range.",
1756c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_INSTANCE_ARG_POS]);
1757c18ec02fSPetter Reinholdtsen badParams = TRUE;
1758c18ec02fSPetter Reinholdtsen return hasChanged;
1759c18ec02fSPetter Reinholdtsen }
1760c18ec02fSPetter Reinholdtsen
1761c18ec02fSPetter Reinholdtsen blockCount = fru_data[offset++];
1762c18ec02fSPetter Reinholdtsen printf(" blockCount: %d\n",blockCount);
1763c18ec02fSPetter Reinholdtsen
1764c18ec02fSPetter Reinholdtsen for(blockIndex=0;blockIndex<blockCount;blockIndex++){
1765c18ec02fSPetter Reinholdtsen void * pRecordData;
1766c18ec02fSPetter Reinholdtsen uint8_t nameLen;
1767c18ec02fSPetter Reinholdtsen
1768c18ec02fSPetter Reinholdtsen blockstart = offset;
1769c18ec02fSPetter Reinholdtsen
1770c18ec02fSPetter Reinholdtsen nameLen = ( fru_data[offset++] & 0x3F );
1771c18ec02fSPetter Reinholdtsen
1772c18ec02fSPetter Reinholdtsen if( version == 0 || version == 1 )
1773c18ec02fSPetter Reinholdtsen {
1774c18ec02fSPetter Reinholdtsen if(!strncmp((char *)argv[OEM_KONTRON_NAME_ARG_POS],
1775c18ec02fSPetter Reinholdtsen (const char *)(fru_data+offset),nameLen)&& (matchInstance == instance)){
1776c18ec02fSPetter Reinholdtsen
1777c18ec02fSPetter Reinholdtsen printf ("Found : %s\n",argv[OEM_KONTRON_NAME_ARG_POS]);
1778c18ec02fSPetter Reinholdtsen offset+=nameLen;
1779c18ec02fSPetter Reinholdtsen
1780c18ec02fSPetter Reinholdtsen pRecordData = &fru_data[offset];
1781c18ec02fSPetter Reinholdtsen
1782c18ec02fSPetter Reinholdtsen if( version == 0 )
1783c18ec02fSPetter Reinholdtsen {
1784c18ec02fSPetter Reinholdtsen memcpy( ((tOemKontronInformationRecordV0 *)
1785c18ec02fSPetter Reinholdtsen pRecordData)->field1 ,
1786c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_VERSION_ARG_POS] ,
1787c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE);
1788c18ec02fSPetter Reinholdtsen memcpy( ((tOemKontronInformationRecordV0 *)
1789c18ec02fSPetter Reinholdtsen pRecordData)->field2 ,
1790c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_BUILDDATE_ARG_POS],
1791c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE);
1792c18ec02fSPetter Reinholdtsen memcpy( ((tOemKontronInformationRecordV0 *)
1793c18ec02fSPetter Reinholdtsen pRecordData)->field3 ,
1794c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_UPDATEDATE_ARG_POS],
1795c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE);
1796c18ec02fSPetter Reinholdtsen memcpy( ((tOemKontronInformationRecordV0 *)
1797c18ec02fSPetter Reinholdtsen pRecordData)->crc32 ,
1798c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_CRC32_ARG_POS] ,
1799c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE);
1800c18ec02fSPetter Reinholdtsen }
1801c18ec02fSPetter Reinholdtsen else
1802c18ec02fSPetter Reinholdtsen {
1803c18ec02fSPetter Reinholdtsen memcpy( ((tOemKontronInformationRecordV1 *)
1804c18ec02fSPetter Reinholdtsen pRecordData)->field1 ,
1805c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_VERSION_ARG_POS] ,
1806c18ec02fSPetter Reinholdtsen OEM_KONTRON_VERSION_FIELD_SIZE);
1807c18ec02fSPetter Reinholdtsen memcpy( ((tOemKontronInformationRecordV1 *)
1808c18ec02fSPetter Reinholdtsen pRecordData)->field2 ,
1809c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_BUILDDATE_ARG_POS],
1810c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE);
1811c18ec02fSPetter Reinholdtsen memcpy( ((tOemKontronInformationRecordV1 *)
1812c18ec02fSPetter Reinholdtsen pRecordData)->field3 ,
1813c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_UPDATEDATE_ARG_POS],
1814c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE);
1815c18ec02fSPetter Reinholdtsen memcpy( ((tOemKontronInformationRecordV1 *)
1816c18ec02fSPetter Reinholdtsen pRecordData)->crc32 ,
1817c18ec02fSPetter Reinholdtsen argv[OEM_KONTRON_CRC32_ARG_POS] ,
1818c18ec02fSPetter Reinholdtsen OEM_KONTRON_FIELD_SIZE);
1819c18ec02fSPetter Reinholdtsen }
1820c18ec02fSPetter Reinholdtsen
1821c18ec02fSPetter Reinholdtsen matchInstance++;
1822c18ec02fSPetter Reinholdtsen hasChanged = TRUE;
1823c18ec02fSPetter Reinholdtsen }
1824c18ec02fSPetter Reinholdtsen else if(!strncmp((char *)argv[OEM_KONTRON_NAME_ARG_POS],
1825c18ec02fSPetter Reinholdtsen (const char *)(fru_data+offset), nameLen)){
1826c18ec02fSPetter Reinholdtsen printf ("Skipped : %s [instance %d]\n",argv[OEM_KONTRON_NAME_ARG_POS],
1827c18ec02fSPetter Reinholdtsen (unsigned int)matchInstance);
1828c18ec02fSPetter Reinholdtsen matchInstance++;
1829c18ec02fSPetter Reinholdtsen offset+=nameLen;
1830c18ec02fSPetter Reinholdtsen }
1831c18ec02fSPetter Reinholdtsen else {
1832c18ec02fSPetter Reinholdtsen offset+=nameLen;
1833c18ec02fSPetter Reinholdtsen }
1834c18ec02fSPetter Reinholdtsen
1835c18ec02fSPetter Reinholdtsen if( version == 0 )
1836c18ec02fSPetter Reinholdtsen {
1837c18ec02fSPetter Reinholdtsen offset+= sizeof(tOemKontronInformationRecordV0);
1838c18ec02fSPetter Reinholdtsen }
1839c18ec02fSPetter Reinholdtsen else
1840c18ec02fSPetter Reinholdtsen {
1841c18ec02fSPetter Reinholdtsen offset+= sizeof(tOemKontronInformationRecordV1);
1842c18ec02fSPetter Reinholdtsen }
1843c18ec02fSPetter Reinholdtsen offset++;
1844c18ec02fSPetter Reinholdtsen }
1845c18ec02fSPetter Reinholdtsen else
1846c18ec02fSPetter Reinholdtsen {
1847c18ec02fSPetter Reinholdtsen printf (" Unsupported version %d\n",version);
1848c18ec02fSPetter Reinholdtsen }
1849c18ec02fSPetter Reinholdtsen }
1850c18ec02fSPetter Reinholdtsen }
1851c18ec02fSPetter Reinholdtsen else{
1852c18ec02fSPetter Reinholdtsen printf(" Version: %d\n",version);
1853c18ec02fSPetter Reinholdtsen }
1854c18ec02fSPetter Reinholdtsen }
1855c18ec02fSPetter Reinholdtsen if( hasChanged ){
1856c18ec02fSPetter Reinholdtsen
1857c18ec02fSPetter Reinholdtsen uint8_t record_checksum =0;
1858c18ec02fSPetter Reinholdtsen uint8_t header_checksum =0;
1859c18ec02fSPetter Reinholdtsen int index;
1860c18ec02fSPetter Reinholdtsen
1861c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,"Initial record checksum : %x",h->record_checksum);
1862c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,"Initial header checksum : %x",h->header_checksum);
1863c18ec02fSPetter Reinholdtsen for(index=0;index<length;index++){
1864c18ec02fSPetter Reinholdtsen record_checksum+= fru_data[start+index];
1865c18ec02fSPetter Reinholdtsen }
1866c18ec02fSPetter Reinholdtsen /* Update Record checksum */
1867c18ec02fSPetter Reinholdtsen h->record_checksum = ~record_checksum + 1;
1868c18ec02fSPetter Reinholdtsen
1869c18ec02fSPetter Reinholdtsen
1870c18ec02fSPetter Reinholdtsen for(index=0;index<(sizeof(struct fru_multirec_header) -1);index++){
1871c18ec02fSPetter Reinholdtsen uint8_t data= *( (uint8_t *)h+ index);
1872c18ec02fSPetter Reinholdtsen header_checksum+=data;
1873c18ec02fSPetter Reinholdtsen }
1874c18ec02fSPetter Reinholdtsen /* Update header checksum */
1875c18ec02fSPetter Reinholdtsen h->header_checksum = ~header_checksum + 1;
1876c18ec02fSPetter Reinholdtsen
1877c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,"Final record checksum : %x",h->record_checksum);
1878c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,"Final header checksum : %x",h->header_checksum);
1879c18ec02fSPetter Reinholdtsen
1880c18ec02fSPetter Reinholdtsen /* write back data */
1881c18ec02fSPetter Reinholdtsen }
1882c18ec02fSPetter Reinholdtsen }
1883c18ec02fSPetter Reinholdtsen
1884c18ec02fSPetter Reinholdtsen return hasChanged;
1885c18ec02fSPetter Reinholdtsen }
1886c18ec02fSPetter Reinholdtsen
1887c18ec02fSPetter Reinholdtsen /* ipmi_fru_picmg_ext_edit - Query new values to replace original FRU content
1888c18ec02fSPetter Reinholdtsen *
1889c18ec02fSPetter Reinholdtsen * @data: FRU data
1890c18ec02fSPetter Reinholdtsen * @offset: start of the current multi record (start of header)
1891c18ec02fSPetter Reinholdtsen * @len: len of the current record (excluding header)
1892c18ec02fSPetter Reinholdtsen * @h: pointer to record header
1893c18ec02fSPetter Reinholdtsen * @oh: pointer to OEM /PICMG header
1894c18ec02fSPetter Reinholdtsen *
1895c18ec02fSPetter Reinholdtsen * returns: TRUE if data changed
1896c18ec02fSPetter Reinholdtsen * returns: FALSE if data not changed
1897c18ec02fSPetter Reinholdtsen */
ipmi_fru_picmg_ext_edit(uint8_t * fru_data,int off,int len,struct fru_multirec_header * h,struct fru_multirec_oem_header * oh)1898c18ec02fSPetter Reinholdtsen static int ipmi_fru_picmg_ext_edit(uint8_t * fru_data,
1899c18ec02fSPetter Reinholdtsen int off,int len,
1900c18ec02fSPetter Reinholdtsen struct fru_multirec_header *h,
1901c18ec02fSPetter Reinholdtsen struct fru_multirec_oem_header *oh)
1902c18ec02fSPetter Reinholdtsen {
1903c18ec02fSPetter Reinholdtsen int hasChanged = FALSE;
1904c18ec02fSPetter Reinholdtsen int start = off;
1905c18ec02fSPetter Reinholdtsen int offset = start;
1906c18ec02fSPetter Reinholdtsen int length = len;
1907c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_multirec_oem_header);
1908c18ec02fSPetter Reinholdtsen
1909c18ec02fSPetter Reinholdtsen switch (oh->record_id)
1910c18ec02fSPetter Reinholdtsen {
1911c18ec02fSPetter Reinholdtsen case FRU_AMC_ACTIVATION:
1912c18ec02fSPetter Reinholdtsen printf(" FRU_AMC_ACTIVATION\n");
1913c18ec02fSPetter Reinholdtsen {
1914c18ec02fSPetter Reinholdtsen int index=offset;
1915c18ec02fSPetter Reinholdtsen uint16_t max_current;
1916c18ec02fSPetter Reinholdtsen
1917c18ec02fSPetter Reinholdtsen max_current = fru_data[offset];
1918c18ec02fSPetter Reinholdtsen max_current |= fru_data[++offset]<<8;
1919c18ec02fSPetter Reinholdtsen
1920c18ec02fSPetter Reinholdtsen printf(" Maximum Internal Current(@12V): %.2f A (0x%02x)\n",
1921c18ec02fSPetter Reinholdtsen (float)max_current / 10.0f, max_current);
1922c18ec02fSPetter Reinholdtsen
1923c18ec02fSPetter Reinholdtsen if( ipmi_fru_query_new_value(fru_data,index,2) ){
1924c18ec02fSPetter Reinholdtsen max_current = fru_data[index];
1925c18ec02fSPetter Reinholdtsen max_current |= fru_data[++index]<<8;
1926c18ec02fSPetter Reinholdtsen printf(" New Maximum Internal Current(@12V): %.2f A (0x%02x)\n",
1927c18ec02fSPetter Reinholdtsen (float)max_current / 10.0f, max_current);
1928c18ec02fSPetter Reinholdtsen hasChanged = TRUE;
1929c18ec02fSPetter Reinholdtsen
1930c18ec02fSPetter Reinholdtsen }
1931c18ec02fSPetter Reinholdtsen
1932c18ec02fSPetter Reinholdtsen printf(" Module Activation Readiness: %i sec.\n", fru_data[++offset]);
1933c18ec02fSPetter Reinholdtsen printf(" Descriptor Count: %i\n", fru_data[++offset]);
1934c18ec02fSPetter Reinholdtsen printf("\n");
1935c18ec02fSPetter Reinholdtsen
1936c18ec02fSPetter Reinholdtsen for (++offset;
1937c18ec02fSPetter Reinholdtsen offset < (off + length);
1938c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_picmgext_activation_record)) {
1939c18ec02fSPetter Reinholdtsen struct fru_picmgext_activation_record * a =
1940c18ec02fSPetter Reinholdtsen (struct fru_picmgext_activation_record *) &fru_data[offset];
1941c18ec02fSPetter Reinholdtsen
1942c18ec02fSPetter Reinholdtsen printf(" IPMB-Address: 0x%x\n", a->ibmb_addr);
1943c18ec02fSPetter Reinholdtsen printf(" Max. Module Current: %.2f A\n", (float)a->max_module_curr / 10.0f);
1944c18ec02fSPetter Reinholdtsen
1945c18ec02fSPetter Reinholdtsen printf("\n");
1946c18ec02fSPetter Reinholdtsen }
1947c18ec02fSPetter Reinholdtsen }
1948c18ec02fSPetter Reinholdtsen break;
1949c18ec02fSPetter Reinholdtsen
1950c18ec02fSPetter Reinholdtsen case FRU_AMC_CURRENT:
1951c18ec02fSPetter Reinholdtsen printf(" FRU_AMC_CURRENT\n");
1952c18ec02fSPetter Reinholdtsen {
1953c18ec02fSPetter Reinholdtsen int index=offset;
1954c18ec02fSPetter Reinholdtsen unsigned char current;
1955c18ec02fSPetter Reinholdtsen
1956c18ec02fSPetter Reinholdtsen current = fru_data[index];
1957c18ec02fSPetter Reinholdtsen
1958c18ec02fSPetter Reinholdtsen printf(" Current draw(@12V): %.2f A (0x%02x)\n",
1959c18ec02fSPetter Reinholdtsen (float)current / 10.0f, current);
1960c18ec02fSPetter Reinholdtsen
1961c18ec02fSPetter Reinholdtsen if( ipmi_fru_query_new_value(fru_data, index, 1) ){
1962c18ec02fSPetter Reinholdtsen current = fru_data[index];
1963c18ec02fSPetter Reinholdtsen
1964c18ec02fSPetter Reinholdtsen printf(" New Current draw(@12V): %.2f A (0x%02x)\n",
1965c18ec02fSPetter Reinholdtsen (float)current / 10.0f, current);
1966c18ec02fSPetter Reinholdtsen hasChanged = TRUE;
1967c18ec02fSPetter Reinholdtsen }
1968c18ec02fSPetter Reinholdtsen }
1969c18ec02fSPetter Reinholdtsen break;
1970c18ec02fSPetter Reinholdtsen }
1971c18ec02fSPetter Reinholdtsen
1972c18ec02fSPetter Reinholdtsen if( hasChanged ){
1973c18ec02fSPetter Reinholdtsen
1974c18ec02fSPetter Reinholdtsen uint8_t record_checksum =0;
1975c18ec02fSPetter Reinholdtsen uint8_t header_checksum =0;
1976c18ec02fSPetter Reinholdtsen int index;
1977c18ec02fSPetter Reinholdtsen
1978c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,"Initial record checksum : %x",h->record_checksum);
1979c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,"Initial header checksum : %x",h->header_checksum);
1980c18ec02fSPetter Reinholdtsen for(index=0;index<length;index++){
1981c18ec02fSPetter Reinholdtsen record_checksum+= fru_data[start+index];
1982c18ec02fSPetter Reinholdtsen }
1983c18ec02fSPetter Reinholdtsen /* Update Record checksum */
1984c18ec02fSPetter Reinholdtsen h->record_checksum = ~record_checksum + 1;
1985c18ec02fSPetter Reinholdtsen
1986c18ec02fSPetter Reinholdtsen
1987c18ec02fSPetter Reinholdtsen for(index=0;index<(sizeof(struct fru_multirec_header) -1);index++){
1988c18ec02fSPetter Reinholdtsen uint8_t data= *( (uint8_t *)h+ index);
1989c18ec02fSPetter Reinholdtsen header_checksum+=data;
1990c18ec02fSPetter Reinholdtsen }
1991c18ec02fSPetter Reinholdtsen /* Update header checksum */
1992c18ec02fSPetter Reinholdtsen h->header_checksum = ~header_checksum + 1;
1993c18ec02fSPetter Reinholdtsen
1994c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,"Final record checksum : %x",h->record_checksum);
1995c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,"Final header checksum : %x",h->header_checksum);
1996c18ec02fSPetter Reinholdtsen
1997c18ec02fSPetter Reinholdtsen /* write back data */
1998c18ec02fSPetter Reinholdtsen }
1999c18ec02fSPetter Reinholdtsen
2000c18ec02fSPetter Reinholdtsen return hasChanged;
2001c18ec02fSPetter Reinholdtsen }
2002c18ec02fSPetter Reinholdtsen
2003c18ec02fSPetter Reinholdtsen /* ipmi_fru_picmg_ext_print - prints OEM fru record (PICMG)
2004c18ec02fSPetter Reinholdtsen *
2005c18ec02fSPetter Reinholdtsen * @fru_data: FRU data
2006c18ec02fSPetter Reinholdtsen * @offset: offset of the bytes to be modified in data
2007c18ec02fSPetter Reinholdtsen * @length: size of the record
2008c18ec02fSPetter Reinholdtsen *
2009c18ec02fSPetter Reinholdtsen * returns : n/a
2010c18ec02fSPetter Reinholdtsen */
ipmi_fru_picmg_ext_print(uint8_t * fru_data,int off,int length)2011c18ec02fSPetter Reinholdtsen static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length)
2012c18ec02fSPetter Reinholdtsen {
2013c18ec02fSPetter Reinholdtsen struct fru_multirec_oem_header *h;
2014c18ec02fSPetter Reinholdtsen int guid_count;
2015c18ec02fSPetter Reinholdtsen int offset = off;
2016c18ec02fSPetter Reinholdtsen int start_offset = off;
2017c18ec02fSPetter Reinholdtsen int i;
2018c18ec02fSPetter Reinholdtsen
2019c18ec02fSPetter Reinholdtsen h = (struct fru_multirec_oem_header *) &fru_data[offset];
2020c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_multirec_oem_header);
2021c18ec02fSPetter Reinholdtsen
2022c18ec02fSPetter Reinholdtsen switch (h->record_id)
2023c18ec02fSPetter Reinholdtsen {
2024c18ec02fSPetter Reinholdtsen case FRU_PICMG_BACKPLANE_P2P:
2025c18ec02fSPetter Reinholdtsen {
2026c18ec02fSPetter Reinholdtsen uint8_t index;
2027c18ec02fSPetter Reinholdtsen unsigned int data;
2028c18ec02fSPetter Reinholdtsen struct fru_picmgext_slot_desc *slot_d;
2029c18ec02fSPetter Reinholdtsen
2030c18ec02fSPetter Reinholdtsen slot_d =
2031c18ec02fSPetter Reinholdtsen (struct fru_picmgext_slot_desc*)&fru_data[offset];
2032c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_picmgext_slot_desc);
2033c18ec02fSPetter Reinholdtsen printf(" FRU_PICMG_BACKPLANE_P2P\n");
2034c18ec02fSPetter Reinholdtsen
2035c18ec02fSPetter Reinholdtsen while (offset <= (start_offset+length)) {
2036c18ec02fSPetter Reinholdtsen printf("\n");
2037c18ec02fSPetter Reinholdtsen printf(" Channel Type: ");
2038c18ec02fSPetter Reinholdtsen switch (slot_d->chan_type)
2039c18ec02fSPetter Reinholdtsen {
2040c18ec02fSPetter Reinholdtsen case 0x00:
2041c18ec02fSPetter Reinholdtsen case 0x07:
2042c18ec02fSPetter Reinholdtsen printf("PICMG 2.9\n");
2043c18ec02fSPetter Reinholdtsen break;
2044c18ec02fSPetter Reinholdtsen case 0x08:
2045c18ec02fSPetter Reinholdtsen printf("Single Port Fabric IF\n");
2046c18ec02fSPetter Reinholdtsen break;
2047c18ec02fSPetter Reinholdtsen case 0x09:
2048c18ec02fSPetter Reinholdtsen printf("Double Port Fabric IF\n");
2049c18ec02fSPetter Reinholdtsen break;
2050c18ec02fSPetter Reinholdtsen case 0x0a:
2051c18ec02fSPetter Reinholdtsen printf("Full Channel Fabric IF\n");
2052c18ec02fSPetter Reinholdtsen break;
2053c18ec02fSPetter Reinholdtsen case 0x0b:
2054c18ec02fSPetter Reinholdtsen printf("Base IF\n");
2055c18ec02fSPetter Reinholdtsen break;
2056c18ec02fSPetter Reinholdtsen case 0x0c:
2057c18ec02fSPetter Reinholdtsen printf("Update Channel IF\n");
2058c18ec02fSPetter Reinholdtsen break;
2059c18ec02fSPetter Reinholdtsen case 0x0d:
2060c18ec02fSPetter Reinholdtsen printf("ShMC Cross Connect\n");
2061c18ec02fSPetter Reinholdtsen break;
2062c18ec02fSPetter Reinholdtsen default:
2063c18ec02fSPetter Reinholdtsen printf("Unknown IF (0x%x)\n",
2064c18ec02fSPetter Reinholdtsen slot_d->chan_type);
2065c18ec02fSPetter Reinholdtsen break;
2066c18ec02fSPetter Reinholdtsen }
2067c18ec02fSPetter Reinholdtsen printf(" Slot Addr. : %02x\n",
2068c18ec02fSPetter Reinholdtsen slot_d->slot_addr );
2069c18ec02fSPetter Reinholdtsen printf(" Channel Count: %i\n",
2070c18ec02fSPetter Reinholdtsen slot_d->chn_count);
2071c18ec02fSPetter Reinholdtsen
2072c18ec02fSPetter Reinholdtsen for (index = 0;
2073c18ec02fSPetter Reinholdtsen index < (slot_d->chn_count);
2074c18ec02fSPetter Reinholdtsen index++) {
2075c18ec02fSPetter Reinholdtsen struct fru_picmgext_chn_desc *d;
2076c18ec02fSPetter Reinholdtsen data = (fru_data[offset+0]) |
2077c18ec02fSPetter Reinholdtsen (fru_data[offset+1] << 8) |
2078c18ec02fSPetter Reinholdtsen (fru_data[offset+2] << 16);
2079c18ec02fSPetter Reinholdtsen d = (struct fru_picmgext_chn_desc *)&data;
2080c18ec02fSPetter Reinholdtsen if (verbose) {
2081c18ec02fSPetter Reinholdtsen printf( " "
2082c18ec02fSPetter Reinholdtsen "Chn: %02x -> "
2083c18ec02fSPetter Reinholdtsen "Chn: %02x in "
2084c18ec02fSPetter Reinholdtsen "Slot: %02x\n",
2085c18ec02fSPetter Reinholdtsen d->local_chn,
2086c18ec02fSPetter Reinholdtsen d->remote_chn,
2087c18ec02fSPetter Reinholdtsen d->remote_slot);
2088c18ec02fSPetter Reinholdtsen }
2089c18ec02fSPetter Reinholdtsen offset += FRU_PICMGEXT_CHN_DESC_RECORD_SIZE;
2090c18ec02fSPetter Reinholdtsen }
2091c18ec02fSPetter Reinholdtsen slot_d = (struct fru_picmgext_slot_desc*)&fru_data[offset];
2092c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_picmgext_slot_desc);
2093c18ec02fSPetter Reinholdtsen }
2094c18ec02fSPetter Reinholdtsen }
2095c18ec02fSPetter Reinholdtsen break;
2096c18ec02fSPetter Reinholdtsen
2097c18ec02fSPetter Reinholdtsen case FRU_PICMG_ADDRESS_TABLE:
2098c18ec02fSPetter Reinholdtsen {
2099c18ec02fSPetter Reinholdtsen unsigned int hwaddr;
2100c18ec02fSPetter Reinholdtsen unsigned int sitetype;
2101c18ec02fSPetter Reinholdtsen unsigned int sitenum;
2102c18ec02fSPetter Reinholdtsen unsigned int entries;
2103c18ec02fSPetter Reinholdtsen unsigned int i;
2104c18ec02fSPetter Reinholdtsen char *picmg_site_type_strings[] = {
2105c18ec02fSPetter Reinholdtsen "AdvancedTCA Board",
2106c18ec02fSPetter Reinholdtsen "Power Entry",
2107c18ec02fSPetter Reinholdtsen "Shelf FRU Information",
2108c18ec02fSPetter Reinholdtsen "Dedicated ShMC",
2109c18ec02fSPetter Reinholdtsen "Fan Tray",
2110c18ec02fSPetter Reinholdtsen "Fan Filter Tray",
2111c18ec02fSPetter Reinholdtsen "Alarm",
2112c18ec02fSPetter Reinholdtsen "AdvancedMC Module",
2113c18ec02fSPetter Reinholdtsen "PMC",
2114c18ec02fSPetter Reinholdtsen "Rear Transition Module"};
2115c18ec02fSPetter Reinholdtsen
2116c18ec02fSPetter Reinholdtsen
2117c18ec02fSPetter Reinholdtsen printf(" FRU_PICMG_ADDRESS_TABLE\n");
2118c18ec02fSPetter Reinholdtsen printf(" Type/Len: 0x%02x\n", fru_data[offset++]);
2119c18ec02fSPetter Reinholdtsen printf(" Shelf Addr: ");
2120c18ec02fSPetter Reinholdtsen for (i=0;i<20;i++) {
2121c18ec02fSPetter Reinholdtsen printf("0x%02x ", fru_data[offset++]);
2122c18ec02fSPetter Reinholdtsen }
2123c18ec02fSPetter Reinholdtsen printf("\n");
2124c18ec02fSPetter Reinholdtsen
2125c18ec02fSPetter Reinholdtsen entries = fru_data[offset++];
2126c18ec02fSPetter Reinholdtsen printf(" Addr Table Entries: 0x%02x\n", entries);
2127c18ec02fSPetter Reinholdtsen
2128c18ec02fSPetter Reinholdtsen for (i=0; i<entries; i++) {
2129c18ec02fSPetter Reinholdtsen hwaddr = fru_data[offset];
2130c18ec02fSPetter Reinholdtsen sitenum = fru_data[offset + 1];
2131c18ec02fSPetter Reinholdtsen sitetype = fru_data[offset + 2];
2132c18ec02fSPetter Reinholdtsen printf(
2133c18ec02fSPetter Reinholdtsen " HWAddr: 0x%02x (0x%02x) SiteNum: %d SiteType: 0x%02x %s\n",
2134c18ec02fSPetter Reinholdtsen hwaddr, hwaddr * 2,
2135c18ec02fSPetter Reinholdtsen sitenum, sitetype,
2136c18ec02fSPetter Reinholdtsen (sitetype < 0xa) ?
2137c18ec02fSPetter Reinholdtsen picmg_site_type_strings[sitetype] :
2138c18ec02fSPetter Reinholdtsen "Reserved");
2139c18ec02fSPetter Reinholdtsen offset += 3;
2140c18ec02fSPetter Reinholdtsen }
2141c18ec02fSPetter Reinholdtsen }
2142c18ec02fSPetter Reinholdtsen break;
2143c18ec02fSPetter Reinholdtsen
2144c18ec02fSPetter Reinholdtsen case FRU_PICMG_SHELF_POWER_DIST:
2145c18ec02fSPetter Reinholdtsen {
2146c18ec02fSPetter Reinholdtsen unsigned int entries;
2147c18ec02fSPetter Reinholdtsen unsigned int feeds;
2148c18ec02fSPetter Reinholdtsen unsigned int hwaddr;
2149c18ec02fSPetter Reinholdtsen unsigned int i;
2150c18ec02fSPetter Reinholdtsen unsigned int id;
2151c18ec02fSPetter Reinholdtsen unsigned int j;
2152c18ec02fSPetter Reinholdtsen unsigned int maxext;
2153c18ec02fSPetter Reinholdtsen unsigned int maxint;
2154c18ec02fSPetter Reinholdtsen unsigned int minexp;
2155c18ec02fSPetter Reinholdtsen
2156c18ec02fSPetter Reinholdtsen printf(" FRU_PICMG_SHELF_POWER_DIST\n");
2157c18ec02fSPetter Reinholdtsen
2158c18ec02fSPetter Reinholdtsen feeds = fru_data[offset++];
2159c18ec02fSPetter Reinholdtsen printf(" Number of Power Feeds: 0x%02x\n",
2160c18ec02fSPetter Reinholdtsen feeds);
2161c18ec02fSPetter Reinholdtsen
2162c18ec02fSPetter Reinholdtsen for (i=0; i<feeds; i++) {
2163c18ec02fSPetter Reinholdtsen printf(" Feed %d:\n", i);
2164c18ec02fSPetter Reinholdtsen maxext = fru_data[offset] |
2165c18ec02fSPetter Reinholdtsen (fru_data[offset+1] << 8);
2166c18ec02fSPetter Reinholdtsen offset += 2;
2167c18ec02fSPetter Reinholdtsen maxint = fru_data[offset] |
2168c18ec02fSPetter Reinholdtsen (fru_data[offset+1] << 8);
2169c18ec02fSPetter Reinholdtsen offset += 2;
2170c18ec02fSPetter Reinholdtsen minexp = fru_data[offset];
2171c18ec02fSPetter Reinholdtsen offset += 1;
2172c18ec02fSPetter Reinholdtsen entries = fru_data[offset];
2173c18ec02fSPetter Reinholdtsen offset += 1;
2174c18ec02fSPetter Reinholdtsen
2175c18ec02fSPetter Reinholdtsen printf(
2176c18ec02fSPetter Reinholdtsen " Max External Current: %d.%d Amps (0x%04x)\n",
2177c18ec02fSPetter Reinholdtsen maxext / 10, maxext % 10, maxext);
2178c18ec02fSPetter Reinholdtsen if (maxint < 0xffff) {
2179c18ec02fSPetter Reinholdtsen printf(
2180c18ec02fSPetter Reinholdtsen " Max Internal Current: %d.%d Amps (0x%04x)\n",
2181c18ec02fSPetter Reinholdtsen maxint / 10, maxint % 10,
2182c18ec02fSPetter Reinholdtsen maxint);
2183c18ec02fSPetter Reinholdtsen } else {
2184c18ec02fSPetter Reinholdtsen printf(
2185c18ec02fSPetter Reinholdtsen " Max Internal Current: Not Specified\n");
2186c18ec02fSPetter Reinholdtsen }
2187c18ec02fSPetter Reinholdtsen
2188c18ec02fSPetter Reinholdtsen if (minexp >= 0x48 && minexp <= 0x90) {
2189c18ec02fSPetter Reinholdtsen printf(
2190c18ec02fSPetter Reinholdtsen " Min Expected Voltage: -%02d.%dV\n",
2191c18ec02fSPetter Reinholdtsen minexp / 2, (minexp % 2) * 5);
2192c18ec02fSPetter Reinholdtsen } else {
2193c18ec02fSPetter Reinholdtsen printf(
2194c18ec02fSPetter Reinholdtsen " Min Expected Voltage: -%dV (actual invalid value 0x%x)\n",
2195c18ec02fSPetter Reinholdtsen 36, minexp);
2196c18ec02fSPetter Reinholdtsen }
2197c18ec02fSPetter Reinholdtsen for (j=0; j < entries; j++) {
2198c18ec02fSPetter Reinholdtsen hwaddr = fru_data[offset++];
2199c18ec02fSPetter Reinholdtsen id = fru_data[offset++];
2200c18ec02fSPetter Reinholdtsen printf(
2201c18ec02fSPetter Reinholdtsen " FRU HW Addr: 0x%02x (0x%02x)",
2202c18ec02fSPetter Reinholdtsen hwaddr, hwaddr * 2);
2203c18ec02fSPetter Reinholdtsen printf(
2204c18ec02fSPetter Reinholdtsen " FRU ID: 0x%02x\n",
2205c18ec02fSPetter Reinholdtsen id);
2206c18ec02fSPetter Reinholdtsen }
2207c18ec02fSPetter Reinholdtsen }
2208c18ec02fSPetter Reinholdtsen }
2209c18ec02fSPetter Reinholdtsen break;
2210c18ec02fSPetter Reinholdtsen
2211c18ec02fSPetter Reinholdtsen case FRU_PICMG_SHELF_ACTIVATION:
2212c18ec02fSPetter Reinholdtsen {
2213c18ec02fSPetter Reinholdtsen unsigned int i;
2214c18ec02fSPetter Reinholdtsen unsigned int count = 0;
2215c18ec02fSPetter Reinholdtsen
2216c18ec02fSPetter Reinholdtsen printf(" FRU_PICMG_SHELF_ACTIVATION\n");
2217c18ec02fSPetter Reinholdtsen printf(
2218c18ec02fSPetter Reinholdtsen " Allowance for FRU Act Readiness: 0x%02x\n",
2219c18ec02fSPetter Reinholdtsen fru_data[offset++]);
2220c18ec02fSPetter Reinholdtsen
2221c18ec02fSPetter Reinholdtsen count = fru_data[offset++];
2222c18ec02fSPetter Reinholdtsen printf(
2223c18ec02fSPetter Reinholdtsen " FRU activation and Power Desc Cnt: 0x%02x\n",
2224c18ec02fSPetter Reinholdtsen count);
2225c18ec02fSPetter Reinholdtsen
2226c18ec02fSPetter Reinholdtsen for (i=0; i<count; i++) {
2227c18ec02fSPetter Reinholdtsen printf(" HW Addr: 0x%02x ",
2228c18ec02fSPetter Reinholdtsen fru_data[offset++]);
2229c18ec02fSPetter Reinholdtsen printf(" FRU ID: 0x%02x ",
2230c18ec02fSPetter Reinholdtsen fru_data[offset++]);
2231c18ec02fSPetter Reinholdtsen printf(" Max FRU Power: 0x%04x ",
2232c18ec02fSPetter Reinholdtsen fru_data[offset+0] |
2233c18ec02fSPetter Reinholdtsen (fru_data[offset+1]<<8));
2234c18ec02fSPetter Reinholdtsen offset += 2;
2235c18ec02fSPetter Reinholdtsen printf(" Config: 0x%02x \n",
2236c18ec02fSPetter Reinholdtsen fru_data[offset++]);
2237c18ec02fSPetter Reinholdtsen }
2238c18ec02fSPetter Reinholdtsen }
2239c18ec02fSPetter Reinholdtsen break;
2240c18ec02fSPetter Reinholdtsen
2241c18ec02fSPetter Reinholdtsen case FRU_PICMG_SHMC_IP_CONN:
2242c18ec02fSPetter Reinholdtsen printf(" FRU_PICMG_SHMC_IP_CONN\n");
2243c18ec02fSPetter Reinholdtsen break;
2244c18ec02fSPetter Reinholdtsen
2245c18ec02fSPetter Reinholdtsen case FRU_PICMG_BOARD_P2P:
2246c18ec02fSPetter Reinholdtsen printf(" FRU_PICMG_BOARD_P2P\n");
2247c18ec02fSPetter Reinholdtsen
2248c18ec02fSPetter Reinholdtsen guid_count = fru_data[offset++];
2249c18ec02fSPetter Reinholdtsen printf(" GUID count: %2d\n", guid_count);
2250c18ec02fSPetter Reinholdtsen for (i = 0 ; i < guid_count; i++ ) {
2251c18ec02fSPetter Reinholdtsen int j;
2252c18ec02fSPetter Reinholdtsen printf(" GUID [%2d]: 0x", i);
2253c18ec02fSPetter Reinholdtsen
2254c18ec02fSPetter Reinholdtsen for (j=0; j < sizeof(struct fru_picmgext_guid);
2255c18ec02fSPetter Reinholdtsen j++) {
2256c18ec02fSPetter Reinholdtsen printf("%02x", fru_data[offset+j]);
2257c18ec02fSPetter Reinholdtsen }
2258c18ec02fSPetter Reinholdtsen
2259c18ec02fSPetter Reinholdtsen printf("\n");
2260c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_picmgext_guid);
2261c18ec02fSPetter Reinholdtsen }
2262c18ec02fSPetter Reinholdtsen printf("\n");
2263c18ec02fSPetter Reinholdtsen
2264c18ec02fSPetter Reinholdtsen for (; offset < off + length;
2265c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_picmgext_link_desc)) {
2266c18ec02fSPetter Reinholdtsen
2267c18ec02fSPetter Reinholdtsen /* to solve little endian /big endian problem */
2268c18ec02fSPetter Reinholdtsen struct fru_picmgext_link_desc *d;
2269c18ec02fSPetter Reinholdtsen unsigned int data = (fru_data[offset+0]) |
2270c18ec02fSPetter Reinholdtsen (fru_data[offset+1] << 8) |
2271c18ec02fSPetter Reinholdtsen (fru_data[offset+2] << 16) |
2272c18ec02fSPetter Reinholdtsen (fru_data[offset+3] << 24);
2273c18ec02fSPetter Reinholdtsen d = (struct fru_picmgext_link_desc *) &data;
2274c18ec02fSPetter Reinholdtsen
2275c18ec02fSPetter Reinholdtsen printf(" Link Grouping ID: 0x%02x\n",
2276c18ec02fSPetter Reinholdtsen d->grouping);
2277c18ec02fSPetter Reinholdtsen printf(" Link Type Extension: 0x%02x - ",
2278c18ec02fSPetter Reinholdtsen d->ext);
2279c18ec02fSPetter Reinholdtsen if (d->type == FRU_PICMGEXT_LINK_TYPE_BASE) {
2280c18ec02fSPetter Reinholdtsen switch (d->ext)
2281c18ec02fSPetter Reinholdtsen {
2282c18ec02fSPetter Reinholdtsen case 0:
2283c18ec02fSPetter Reinholdtsen printf("10/100/1000BASE-T Link (four-pair)\n");
2284c18ec02fSPetter Reinholdtsen break;
2285c18ec02fSPetter Reinholdtsen case 1:
2286c18ec02fSPetter Reinholdtsen printf("ShMC Cross-connect (two-pair)\n");
2287c18ec02fSPetter Reinholdtsen break;
2288c18ec02fSPetter Reinholdtsen default:
2289c18ec02fSPetter Reinholdtsen printf("Unknwon\n");
2290c18ec02fSPetter Reinholdtsen break;
2291c18ec02fSPetter Reinholdtsen }
2292c18ec02fSPetter Reinholdtsen } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET) {
2293c18ec02fSPetter Reinholdtsen switch (d->ext)
2294c18ec02fSPetter Reinholdtsen {
2295c18ec02fSPetter Reinholdtsen case 0:
2296c18ec02fSPetter Reinholdtsen printf("Fixed 1000Base-BX\n");
2297c18ec02fSPetter Reinholdtsen break;
2298c18ec02fSPetter Reinholdtsen case 1:
2299c18ec02fSPetter Reinholdtsen printf("Fixed 10GBASE-BX4 [XAUI]\n");
2300c18ec02fSPetter Reinholdtsen break;
2301c18ec02fSPetter Reinholdtsen case 2:
2302c18ec02fSPetter Reinholdtsen printf("FC-PI\n");
2303c18ec02fSPetter Reinholdtsen break;
2304c18ec02fSPetter Reinholdtsen default:
2305c18ec02fSPetter Reinholdtsen printf("Unknwon\n");
2306c18ec02fSPetter Reinholdtsen break;
2307c18ec02fSPetter Reinholdtsen }
2308c18ec02fSPetter Reinholdtsen } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND) {
2309c18ec02fSPetter Reinholdtsen printf("Unknwon\n");
2310c18ec02fSPetter Reinholdtsen } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR) {
2311c18ec02fSPetter Reinholdtsen printf("Unknwon\n");
2312c18ec02fSPetter Reinholdtsen } else if (d->type == FRU_PICMGEXT_LINK_TYPE_PCIE) {
2313c18ec02fSPetter Reinholdtsen printf("Unknwon\n");
2314c18ec02fSPetter Reinholdtsen } else {
2315c18ec02fSPetter Reinholdtsen printf("Unknwon\n");
2316c18ec02fSPetter Reinholdtsen }
2317c18ec02fSPetter Reinholdtsen
2318c18ec02fSPetter Reinholdtsen printf(" Link Type: 0x%02x - ",
2319c18ec02fSPetter Reinholdtsen d->type);
2320c18ec02fSPetter Reinholdtsen if (d->type == 0 || d->type == 0xff) {
2321c18ec02fSPetter Reinholdtsen printf("Reserved\n");
2322c18ec02fSPetter Reinholdtsen }
2323c18ec02fSPetter Reinholdtsen else if (d->type >= 0x06 && d->type <= 0xef) {
2324c18ec02fSPetter Reinholdtsen printf("Reserved\n");
2325c18ec02fSPetter Reinholdtsen }
2326c18ec02fSPetter Reinholdtsen else if (d->type >= 0xf0 && d->type <= 0xfe) {
2327c18ec02fSPetter Reinholdtsen printf("OEM GUID Definition\n");
2328c18ec02fSPetter Reinholdtsen }
2329c18ec02fSPetter Reinholdtsen else {
2330c18ec02fSPetter Reinholdtsen switch (d->type)
2331c18ec02fSPetter Reinholdtsen {
2332c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_LINK_TYPE_BASE:
2333c18ec02fSPetter Reinholdtsen printf("PICMG 3.0 Base Interface 10/100/1000\n");
2334c18ec02fSPetter Reinholdtsen break;
2335c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET:
2336c18ec02fSPetter Reinholdtsen printf("PICMG 3.1 Ethernet Fabric Interface\n");
2337c18ec02fSPetter Reinholdtsen break;
2338c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND:
2339c18ec02fSPetter Reinholdtsen printf("PICMG 3.2 Infiniband Fabric Interface\n");
2340c18ec02fSPetter Reinholdtsen break;
2341c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR:
2342c18ec02fSPetter Reinholdtsen printf("PICMG 3.3 Star Fabric Interface\n");
2343c18ec02fSPetter Reinholdtsen break;
2344c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_LINK_TYPE_PCIE:
2345c18ec02fSPetter Reinholdtsen printf("PICMG 3.4 PCI Express Fabric Interface\n");
2346c18ec02fSPetter Reinholdtsen break;
2347c18ec02fSPetter Reinholdtsen default:
2348c18ec02fSPetter Reinholdtsen printf("Invalid\n");
2349c18ec02fSPetter Reinholdtsen break;
2350c18ec02fSPetter Reinholdtsen }
2351c18ec02fSPetter Reinholdtsen }
2352c18ec02fSPetter Reinholdtsen printf(" Link Designator: \n");
2353c18ec02fSPetter Reinholdtsen printf(" Port Flag: 0x%02x\n",
2354c18ec02fSPetter Reinholdtsen d->desig_port);
2355c18ec02fSPetter Reinholdtsen printf(" Interface: 0x%02x - ",
2356c18ec02fSPetter Reinholdtsen d->desig_if);
2357c18ec02fSPetter Reinholdtsen switch (d->desig_if)
2358c18ec02fSPetter Reinholdtsen {
2359c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_DESIGN_IF_BASE:
2360c18ec02fSPetter Reinholdtsen printf("Base Interface\n");
2361c18ec02fSPetter Reinholdtsen break;
2362c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_DESIGN_IF_FABRIC:
2363c18ec02fSPetter Reinholdtsen printf("Fabric Interface\n");
2364c18ec02fSPetter Reinholdtsen break;
2365c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_DESIGN_IF_UPDATE_CHANNEL:
2366c18ec02fSPetter Reinholdtsen printf("Update Channel\n");
2367c18ec02fSPetter Reinholdtsen break;
2368c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_DESIGN_IF_RESERVED:
2369c18ec02fSPetter Reinholdtsen printf("Reserved\n");
2370c18ec02fSPetter Reinholdtsen break;
2371c18ec02fSPetter Reinholdtsen default:
2372c18ec02fSPetter Reinholdtsen printf("Invalid");
2373c18ec02fSPetter Reinholdtsen break;
2374c18ec02fSPetter Reinholdtsen }
2375c18ec02fSPetter Reinholdtsen printf(" Channel Number: 0x%02x\n",
2376c18ec02fSPetter Reinholdtsen d->desig_channel);
2377c18ec02fSPetter Reinholdtsen printf("\n");
2378c18ec02fSPetter Reinholdtsen }
2379c18ec02fSPetter Reinholdtsen
2380c18ec02fSPetter Reinholdtsen break;
2381c18ec02fSPetter Reinholdtsen
2382c18ec02fSPetter Reinholdtsen case FRU_AMC_CURRENT:
2383c18ec02fSPetter Reinholdtsen {
2384c18ec02fSPetter Reinholdtsen unsigned char current;
2385c18ec02fSPetter Reinholdtsen printf(" FRU_AMC_CURRENT\n");
2386c18ec02fSPetter Reinholdtsen
2387c18ec02fSPetter Reinholdtsen current = fru_data[offset];
2388c18ec02fSPetter Reinholdtsen printf(" Current draw(@12V): %.2f A [ %.2f Watt ]\n",
2389c18ec02fSPetter Reinholdtsen (float)current / 10.0f,
2390c18ec02fSPetter Reinholdtsen (float)current / 10.0f * 12.0f);
2391c18ec02fSPetter Reinholdtsen printf("\n");
2392c18ec02fSPetter Reinholdtsen }
2393c18ec02fSPetter Reinholdtsen break;
2394c18ec02fSPetter Reinholdtsen
2395c18ec02fSPetter Reinholdtsen case FRU_AMC_ACTIVATION:
2396c18ec02fSPetter Reinholdtsen printf(" FRU_AMC_ACTIVATION\n");
2397c18ec02fSPetter Reinholdtsen {
2398c18ec02fSPetter Reinholdtsen uint16_t max_current;
2399c18ec02fSPetter Reinholdtsen
2400c18ec02fSPetter Reinholdtsen max_current = fru_data[offset];
2401c18ec02fSPetter Reinholdtsen max_current |= fru_data[++offset]<<8;
2402c18ec02fSPetter Reinholdtsen printf(" Maximum Internal Current(@12V): %.2f A [ %.2f Watt ]\n",
2403c18ec02fSPetter Reinholdtsen (float)max_current / 10.0f,
2404c18ec02fSPetter Reinholdtsen (float)max_current / 10.0f * 12.0f);
2405c18ec02fSPetter Reinholdtsen
2406c18ec02fSPetter Reinholdtsen printf(" Module Activation Readiness: %i sec.\n", fru_data[++offset]);
2407c18ec02fSPetter Reinholdtsen printf(" Descriptor Count: %i\n", fru_data[++offset]);
2408c18ec02fSPetter Reinholdtsen printf("\n");
2409c18ec02fSPetter Reinholdtsen
2410c18ec02fSPetter Reinholdtsen for(++offset; offset < off + length;
2411c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_picmgext_activation_record))
2412c18ec02fSPetter Reinholdtsen {
2413c18ec02fSPetter Reinholdtsen struct fru_picmgext_activation_record *a;
2414c18ec02fSPetter Reinholdtsen a = (struct fru_picmgext_activation_record *)&fru_data[offset];
2415c18ec02fSPetter Reinholdtsen printf(" IPMB-Address: 0x%x\n",
2416c18ec02fSPetter Reinholdtsen a->ibmb_addr);
2417c18ec02fSPetter Reinholdtsen printf(" Max. Module Current: %.2f A\n",
2418c18ec02fSPetter Reinholdtsen (float)a->max_module_curr / 10.0f);
2419c18ec02fSPetter Reinholdtsen printf("\n");
2420c18ec02fSPetter Reinholdtsen }
2421c18ec02fSPetter Reinholdtsen }
2422c18ec02fSPetter Reinholdtsen break;
2423c18ec02fSPetter Reinholdtsen
2424c18ec02fSPetter Reinholdtsen case FRU_AMC_CARRIER_P2P:
2425c18ec02fSPetter Reinholdtsen {
2426c18ec02fSPetter Reinholdtsen uint16_t index;
2427c18ec02fSPetter Reinholdtsen printf(" FRU_CARRIER_P2P\n");
2428c18ec02fSPetter Reinholdtsen for(; offset < off + length; ) {
2429c18ec02fSPetter Reinholdtsen struct fru_picmgext_carrier_p2p_record * h =
2430c18ec02fSPetter Reinholdtsen (struct fru_picmgext_carrier_p2p_record *)&fru_data[offset];
2431c18ec02fSPetter Reinholdtsen printf("\n");
2432c18ec02fSPetter Reinholdtsen printf(" Resource ID: %i",
2433c18ec02fSPetter Reinholdtsen (h->resource_id & 0x07));
2434c18ec02fSPetter Reinholdtsen printf(" Type: ");
2435c18ec02fSPetter Reinholdtsen if ((h->resource_id>>7) == 1) {
2436c18ec02fSPetter Reinholdtsen printf("AMC\n");
2437c18ec02fSPetter Reinholdtsen } else {
2438c18ec02fSPetter Reinholdtsen printf("Local\n");
2439c18ec02fSPetter Reinholdtsen }
2440c18ec02fSPetter Reinholdtsen printf(" Descriptor Count: %i\n",
2441c18ec02fSPetter Reinholdtsen h->p2p_count);
2442c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_picmgext_carrier_p2p_record);
2443c18ec02fSPetter Reinholdtsen for (index = 0; index < h->p2p_count; index++) {
2444c18ec02fSPetter Reinholdtsen /* to solve little endian /big endian problem */
2445c18ec02fSPetter Reinholdtsen unsigned char data[3];
2446c18ec02fSPetter Reinholdtsen struct fru_picmgext_carrier_p2p_descriptor * desc;
2447c18ec02fSPetter Reinholdtsen # ifndef WORDS_BIGENDIAN
2448c18ec02fSPetter Reinholdtsen data[0] = fru_data[offset+0];
2449c18ec02fSPetter Reinholdtsen data[1] = fru_data[offset+1];
2450c18ec02fSPetter Reinholdtsen data[2] = fru_data[offset+2];
2451c18ec02fSPetter Reinholdtsen # else
2452c18ec02fSPetter Reinholdtsen data[0] = fru_data[offset+2];
2453c18ec02fSPetter Reinholdtsen data[1] = fru_data[offset+1];
2454c18ec02fSPetter Reinholdtsen data[2] = fru_data[offset+0];
2455c18ec02fSPetter Reinholdtsen # endif
2456c18ec02fSPetter Reinholdtsen desc = (struct fru_picmgext_carrier_p2p_descriptor*)&data;
2457c18ec02fSPetter Reinholdtsen printf(" Port: %02d\t-> Remote Port: %02d\t",
2458c18ec02fSPetter Reinholdtsen desc->local_port, desc->remote_port);
2459c18ec02fSPetter Reinholdtsen if ((desc->remote_resource_id >> 7) == 1) {
2460c18ec02fSPetter Reinholdtsen printf("[ AMC ID: %02d ]\n",
2461c18ec02fSPetter Reinholdtsen desc->remote_resource_id & 0x0F);
2462c18ec02fSPetter Reinholdtsen } else {
2463c18ec02fSPetter Reinholdtsen printf("[ local ID: %02d ]\n",
2464c18ec02fSPetter Reinholdtsen desc->remote_resource_id & 0x0F);
2465c18ec02fSPetter Reinholdtsen }
2466c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_picmgext_carrier_p2p_descriptor);
2467c18ec02fSPetter Reinholdtsen }
2468c18ec02fSPetter Reinholdtsen }
2469c18ec02fSPetter Reinholdtsen }
2470c18ec02fSPetter Reinholdtsen break;
2471c18ec02fSPetter Reinholdtsen
2472c18ec02fSPetter Reinholdtsen case FRU_AMC_P2P:
2473c18ec02fSPetter Reinholdtsen {
2474c18ec02fSPetter Reinholdtsen unsigned int index;
2475c18ec02fSPetter Reinholdtsen unsigned char channel_count;
2476c18ec02fSPetter Reinholdtsen struct fru_picmgext_amc_p2p_record * h;
2477c18ec02fSPetter Reinholdtsen printf(" FRU_AMC_P2P\n");
2478c18ec02fSPetter Reinholdtsen guid_count = fru_data[offset];
2479c18ec02fSPetter Reinholdtsen printf(" GUID count: %2d\n", guid_count);
2480c18ec02fSPetter Reinholdtsen for (i = 0 ; i < guid_count; i++) {
2481c18ec02fSPetter Reinholdtsen int j;
2482c18ec02fSPetter Reinholdtsen printf(" GUID %2d: ", i);
2483c18ec02fSPetter Reinholdtsen for (j=0; j < sizeof(struct fru_picmgext_guid);
2484c18ec02fSPetter Reinholdtsen j++) {
2485c18ec02fSPetter Reinholdtsen printf("%02x", fru_data[offset+j]);
2486c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_picmgext_guid);
2487c18ec02fSPetter Reinholdtsen printf("\n");
2488c18ec02fSPetter Reinholdtsen }
2489c18ec02fSPetter Reinholdtsen h = (struct fru_picmgext_amc_p2p_record *)&fru_data[++offset];
2490c18ec02fSPetter Reinholdtsen printf(" %s",
2491c18ec02fSPetter Reinholdtsen (h->record_type ?
2492c18ec02fSPetter Reinholdtsen "AMC Module:" : "On-Carrier Device"));
2493c18ec02fSPetter Reinholdtsen printf(" Resource ID: %i\n", h->resource_id);
2494c18ec02fSPetter Reinholdtsen offset += sizeof(struct fru_picmgext_amc_p2p_record);
2495c18ec02fSPetter Reinholdtsen channel_count = fru_data[offset++];
2496c18ec02fSPetter Reinholdtsen printf(" Descriptor Count: %i\n",
2497c18ec02fSPetter Reinholdtsen channel_count);
2498c18ec02fSPetter Reinholdtsen for (index = 0; index < channel_count; index++) {
2499c18ec02fSPetter Reinholdtsen unsigned int data;
2500c18ec02fSPetter Reinholdtsen struct fru_picmgext_amc_channel_desc_record *d;
2501c18ec02fSPetter Reinholdtsen /* pack the data in little endian format.
2502c18ec02fSPetter Reinholdtsen * Stupid intel...
2503c18ec02fSPetter Reinholdtsen */
2504c18ec02fSPetter Reinholdtsen data = fru_data[offset] |
2505c18ec02fSPetter Reinholdtsen (fru_data[offset + 1] << 8) |
2506c18ec02fSPetter Reinholdtsen (fru_data[offset + 2] << 16);
2507c18ec02fSPetter Reinholdtsen d = (struct fru_picmgext_amc_channel_desc_record *)&data;
2508c18ec02fSPetter Reinholdtsen printf(" Lane 0 Port: %i\n",
2509c18ec02fSPetter Reinholdtsen d->lane0port);
2510c18ec02fSPetter Reinholdtsen printf(" Lane 1 Port: %i\n",
2511c18ec02fSPetter Reinholdtsen d->lane1port);
2512c18ec02fSPetter Reinholdtsen printf(" Lane 2 Port: %i\n",
2513c18ec02fSPetter Reinholdtsen d->lane2port);
2514c18ec02fSPetter Reinholdtsen printf(" Lane 3 Port: %i\n\n",
2515c18ec02fSPetter Reinholdtsen d->lane3port);
2516c18ec02fSPetter Reinholdtsen offset += FRU_PICMGEXT_AMC_CHANNEL_DESC_RECORD_SIZE;
2517c18ec02fSPetter Reinholdtsen }
2518c18ec02fSPetter Reinholdtsen for (; offset < off + length;) {
2519c18ec02fSPetter Reinholdtsen unsigned int data[2];
2520c18ec02fSPetter Reinholdtsen struct fru_picmgext_amc_link_desc_record *l;
2521c18ec02fSPetter Reinholdtsen l = (struct fru_picmgext_amc_link_desc_record *)&data[0];
2522c18ec02fSPetter Reinholdtsen data[0] = fru_data[offset] |
2523c18ec02fSPetter Reinholdtsen (fru_data[offset + 1] << 8) |
2524c18ec02fSPetter Reinholdtsen (fru_data[offset + 2] << 16) |
2525c18ec02fSPetter Reinholdtsen (fru_data[offset + 3] << 24);
2526c18ec02fSPetter Reinholdtsen data[1] = fru_data[offset + 4];
2527c18ec02fSPetter Reinholdtsen printf( " Link Designator: Channel ID: %i\n"
2528c18ec02fSPetter Reinholdtsen " Port Flag 0: %s%s%s%s\n",
2529c18ec02fSPetter Reinholdtsen l->channel_id,
2530c18ec02fSPetter Reinholdtsen (l->port_flag_0)?"o":"-",
2531c18ec02fSPetter Reinholdtsen (l->port_flag_1)?"o":"-",
2532c18ec02fSPetter Reinholdtsen (l->port_flag_2)?"o":"-",
2533c18ec02fSPetter Reinholdtsen (l->port_flag_3)?"o":"-" );
2534c18ec02fSPetter Reinholdtsen switch (l->type) {
2535c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE:
2536c18ec02fSPetter Reinholdtsen /* AMC.1 */
2537c18ec02fSPetter Reinholdtsen printf( " Link Type: %02x - "
2538c18ec02fSPetter Reinholdtsen "AMC.1 PCI Express\n", l->type);
2539c18ec02fSPetter Reinholdtsen switch (l->type_ext) {
2540c18ec02fSPetter Reinholdtsen case AMC_LINK_TYPE_EXT_PCIE_G1_NSSC:
2541c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2542c18ec02fSPetter Reinholdtsen " Gen 1 capable - non SSC\n",
2543c18ec02fSPetter Reinholdtsen l->type_ext);
2544c18ec02fSPetter Reinholdtsen break;
2545c18ec02fSPetter Reinholdtsen case AMC_LINK_TYPE_EXT_PCIE_G1_SSC:
2546c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2547c18ec02fSPetter Reinholdtsen " Gen 1 capable - SSC\n",
2548c18ec02fSPetter Reinholdtsen l->type_ext);
2549c18ec02fSPetter Reinholdtsen break;
2550c18ec02fSPetter Reinholdtsen case AMC_LINK_TYPE_EXT_PCIE_G2_NSSC:
2551c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2552c18ec02fSPetter Reinholdtsen " Gen 2 capable - non SSC\n",
2553c18ec02fSPetter Reinholdtsen l->type_ext);
2554c18ec02fSPetter Reinholdtsen break;
2555c18ec02fSPetter Reinholdtsen case AMC_LINK_TYPE_EXT_PCIE_G2_SSC:
2556c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2557c18ec02fSPetter Reinholdtsen " Gen 2 capable - SSC\n",
2558c18ec02fSPetter Reinholdtsen l->type_ext);
2559c18ec02fSPetter Reinholdtsen break;
2560c18ec02fSPetter Reinholdtsen default:
2561c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2562c18ec02fSPetter Reinholdtsen " Invalid\n",
2563c18ec02fSPetter Reinholdtsen l->type_ext);
2564c18ec02fSPetter Reinholdtsen break;
2565c18ec02fSPetter Reinholdtsen }
2566c18ec02fSPetter Reinholdtsen break;
2567c18ec02fSPetter Reinholdtsen
2568c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS1:
2569c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS2:
2570c18ec02fSPetter Reinholdtsen /* AMC.1 */
2571c18ec02fSPetter Reinholdtsen printf( " Link Type: %02x - "
2572c18ec02fSPetter Reinholdtsen "AMC.1 PCI Express Advanced Switching\n",
2573c18ec02fSPetter Reinholdtsen l->type);
2574c18ec02fSPetter Reinholdtsen printf(" Link Type Ext: %i\n",
2575c18ec02fSPetter Reinholdtsen l->type_ext);
2576c18ec02fSPetter Reinholdtsen break;
2577c18ec02fSPetter Reinholdtsen
2578c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET:
2579c18ec02fSPetter Reinholdtsen /* AMC.2 */
2580c18ec02fSPetter Reinholdtsen printf( " Link Type: %02x - "
2581c18ec02fSPetter Reinholdtsen "AMC.2 Ethernet\n",
2582c18ec02fSPetter Reinholdtsen l->type);
2583c18ec02fSPetter Reinholdtsen switch (l->type_ext) {
2584c18ec02fSPetter Reinholdtsen case AMC_LINK_TYPE_EXT_ETH_1000_BX:
2585c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2586c18ec02fSPetter Reinholdtsen " 1000Base-Bx (SerDES Gigabit) Ethernet Link\n",
2587c18ec02fSPetter Reinholdtsen l->type_ext);
2588c18ec02fSPetter Reinholdtsen break;
2589c18ec02fSPetter Reinholdtsen
2590c18ec02fSPetter Reinholdtsen case AMC_LINK_TYPE_EXT_ETH_10G_XAUI:
2591c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2592c18ec02fSPetter Reinholdtsen " 10Gbit XAUI Ethernet Link\n",
2593c18ec02fSPetter Reinholdtsen l->type_ext);
2594c18ec02fSPetter Reinholdtsen break;
2595c18ec02fSPetter Reinholdtsen
2596c18ec02fSPetter Reinholdtsen default:
2597c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2598c18ec02fSPetter Reinholdtsen " Invalid\n",
2599c18ec02fSPetter Reinholdtsen l->type_ext);
2600c18ec02fSPetter Reinholdtsen break;
2601c18ec02fSPetter Reinholdtsen }
2602c18ec02fSPetter Reinholdtsen break;
2603c18ec02fSPetter Reinholdtsen
2604c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE:
2605c18ec02fSPetter Reinholdtsen /* AMC.3 */
2606c18ec02fSPetter Reinholdtsen printf( " Link Type: %02x - "
2607c18ec02fSPetter Reinholdtsen "AMC.3 Storage\n",
2608c18ec02fSPetter Reinholdtsen l->type);
2609c18ec02fSPetter Reinholdtsen switch (l->type_ext) {
2610c18ec02fSPetter Reinholdtsen case AMC_LINK_TYPE_EXT_STORAGE_FC:
2611c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2612c18ec02fSPetter Reinholdtsen " Fibre Channel\n",
2613c18ec02fSPetter Reinholdtsen l->type_ext);
2614c18ec02fSPetter Reinholdtsen break;
2615c18ec02fSPetter Reinholdtsen
2616c18ec02fSPetter Reinholdtsen case AMC_LINK_TYPE_EXT_STORAGE_SATA:
2617c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2618c18ec02fSPetter Reinholdtsen " Serial ATA\n",
2619c18ec02fSPetter Reinholdtsen l->type_ext);
2620c18ec02fSPetter Reinholdtsen break;
2621c18ec02fSPetter Reinholdtsen
2622c18ec02fSPetter Reinholdtsen case AMC_LINK_TYPE_EXT_STORAGE_SAS:
2623c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2624c18ec02fSPetter Reinholdtsen " Serial Attached SCSI\n",
2625c18ec02fSPetter Reinholdtsen l->type_ext);
2626c18ec02fSPetter Reinholdtsen break;
2627c18ec02fSPetter Reinholdtsen
2628c18ec02fSPetter Reinholdtsen default:
2629c18ec02fSPetter Reinholdtsen printf( " Link Type Ext: %i - "
2630c18ec02fSPetter Reinholdtsen " Invalid\n",
2631c18ec02fSPetter Reinholdtsen l->type_ext);
2632c18ec02fSPetter Reinholdtsen break;
2633c18ec02fSPetter Reinholdtsen }
2634c18ec02fSPetter Reinholdtsen break;
2635c18ec02fSPetter Reinholdtsen
2636c18ec02fSPetter Reinholdtsen case FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO:
2637c18ec02fSPetter Reinholdtsen /* AMC.4 */
2638c18ec02fSPetter Reinholdtsen printf( " Link Type: %02x - "
2639c18ec02fSPetter Reinholdtsen "AMC.4 Serial Rapid IO\n",
2640c18ec02fSPetter Reinholdtsen l->type);
2641c18ec02fSPetter Reinholdtsen printf(" Link Type Ext: %i\n",
2642c18ec02fSPetter Reinholdtsen l->type_ext);
2643c18ec02fSPetter Reinholdtsen break;
2644c18ec02fSPetter Reinholdtsen
2645c18ec02fSPetter Reinholdtsen default:
2646c18ec02fSPetter Reinholdtsen printf( " Link Type: %02x - "
2647c18ec02fSPetter Reinholdtsen "reserved or OEM GUID",
2648c18ec02fSPetter Reinholdtsen l->type);
2649c18ec02fSPetter Reinholdtsen printf(" Link Type Ext: %i\n",
2650c18ec02fSPetter Reinholdtsen l->type_ext);
2651c18ec02fSPetter Reinholdtsen break;
2652c18ec02fSPetter Reinholdtsen }
2653c18ec02fSPetter Reinholdtsen
2654c18ec02fSPetter Reinholdtsen printf(" Link group Id: %i\n",
2655c18ec02fSPetter Reinholdtsen l->group_id);
2656c18ec02fSPetter Reinholdtsen printf(" Link Asym Match: %i\n\n",
2657c18ec02fSPetter Reinholdtsen l->asym_match);
2658c18ec02fSPetter Reinholdtsen offset += FRU_PICMGEXT_AMC_LINK_DESC_RECORD_SIZE;
2659c18ec02fSPetter Reinholdtsen }
2660c18ec02fSPetter Reinholdtsen }
2661c18ec02fSPetter Reinholdtsen }
2662c18ec02fSPetter Reinholdtsen break;
2663c18ec02fSPetter Reinholdtsen
2664c18ec02fSPetter Reinholdtsen case FRU_AMC_CARRIER_INFO:
2665c18ec02fSPetter Reinholdtsen {
2666c18ec02fSPetter Reinholdtsen unsigned char extVersion;
2667c18ec02fSPetter Reinholdtsen unsigned char siteCount;
2668c18ec02fSPetter Reinholdtsen
2669c18ec02fSPetter Reinholdtsen printf(" FRU_CARRIER_INFO\n");
2670c18ec02fSPetter Reinholdtsen
2671c18ec02fSPetter Reinholdtsen extVersion = fru_data[offset++];
2672c18ec02fSPetter Reinholdtsen siteCount = fru_data[offset++];
2673c18ec02fSPetter Reinholdtsen
2674c18ec02fSPetter Reinholdtsen printf(" AMC.0 extension version: R%d.%d\n",
2675c18ec02fSPetter Reinholdtsen (extVersion >> 0)& 0x0F,
2676c18ec02fSPetter Reinholdtsen (extVersion >> 4)& 0x0F );
2677c18ec02fSPetter Reinholdtsen printf(" Carrier Sie Number Cnt: %d\n", siteCount);
2678c18ec02fSPetter Reinholdtsen
2679c18ec02fSPetter Reinholdtsen for (i = 0 ; i < siteCount; i++ ){
2680c18ec02fSPetter Reinholdtsen printf(" Site ID: %i \n", fru_data[offset++]);
2681c18ec02fSPetter Reinholdtsen }
2682c18ec02fSPetter Reinholdtsen printf("\n");
2683c18ec02fSPetter Reinholdtsen }
2684c18ec02fSPetter Reinholdtsen break;
2685c18ec02fSPetter Reinholdtsen case FRU_PICMG_CLK_CARRIER_P2P:
2686c18ec02fSPetter Reinholdtsen {
2687c18ec02fSPetter Reinholdtsen unsigned char desc_count;
2688c18ec02fSPetter Reinholdtsen int i,j;
2689c18ec02fSPetter Reinholdtsen
2690c18ec02fSPetter Reinholdtsen printf(" FRU_PICMG_CLK_CARRIER_P2P\n");
2691c18ec02fSPetter Reinholdtsen
2692c18ec02fSPetter Reinholdtsen desc_count = fru_data[offset++];
2693c18ec02fSPetter Reinholdtsen
2694c18ec02fSPetter Reinholdtsen for(i=0; i<desc_count; i++){
2695c18ec02fSPetter Reinholdtsen unsigned char resource_id;
2696c18ec02fSPetter Reinholdtsen unsigned char channel_count;
2697c18ec02fSPetter Reinholdtsen
2698c18ec02fSPetter Reinholdtsen resource_id = fru_data[offset++];
2699c18ec02fSPetter Reinholdtsen channel_count = fru_data[offset++];
2700c18ec02fSPetter Reinholdtsen
2701c18ec02fSPetter Reinholdtsen printf("\n");
2702c18ec02fSPetter Reinholdtsen printf(" Clock Resource ID: 0x%02x Type: ", resource_id);
2703c18ec02fSPetter Reinholdtsen if((resource_id & 0xC0)>>6 == 0) {printf("On-Carrier-Device\n");}
2704c18ec02fSPetter Reinholdtsen else if((resource_id & 0xC0)>>6 == 1) {printf("AMC slot\n");}
2705c18ec02fSPetter Reinholdtsen else if((resource_id & 0xC0)>>6 == 2) {printf("Backplane\n");}
2706c18ec02fSPetter Reinholdtsen else{ printf("reserved\n");}
2707c18ec02fSPetter Reinholdtsen printf(" Channel Count: 0x%02x\n", channel_count);
2708c18ec02fSPetter Reinholdtsen
2709c18ec02fSPetter Reinholdtsen for(j=0; j<channel_count; j++){
2710c18ec02fSPetter Reinholdtsen unsigned char loc_channel, rem_channel, rem_resource;
2711c18ec02fSPetter Reinholdtsen
2712c18ec02fSPetter Reinholdtsen loc_channel = fru_data[offset++];
2713c18ec02fSPetter Reinholdtsen rem_channel = fru_data[offset++];
2714c18ec02fSPetter Reinholdtsen rem_resource = fru_data[offset++];
2715c18ec02fSPetter Reinholdtsen
2716c18ec02fSPetter Reinholdtsen printf(" CLK-ID: 0x%02x ->", loc_channel);
2717c18ec02fSPetter Reinholdtsen printf(" remote CLKID: 0x%02x ", rem_channel);
2718c18ec02fSPetter Reinholdtsen if((rem_resource & 0xC0)>>6 == 0) {printf("[ Carrier-Dev");}
2719c18ec02fSPetter Reinholdtsen else if((rem_resource & 0xC0)>>6 == 1) {printf("[ AMC slot ");}
2720c18ec02fSPetter Reinholdtsen else if((rem_resource & 0xC0)>>6 == 2) {printf("[ Backplane ");}
2721c18ec02fSPetter Reinholdtsen else{ printf("reserved ");}
2722c18ec02fSPetter Reinholdtsen printf(" 0x%02x ]\n", rem_resource&0xF);
2723c18ec02fSPetter Reinholdtsen }
2724c18ec02fSPetter Reinholdtsen }
2725c18ec02fSPetter Reinholdtsen printf("\n");
2726c18ec02fSPetter Reinholdtsen }
2727c18ec02fSPetter Reinholdtsen break;
2728c18ec02fSPetter Reinholdtsen case FRU_PICMG_CLK_CONFIG:
2729c18ec02fSPetter Reinholdtsen {
2730c18ec02fSPetter Reinholdtsen unsigned char resource_id, descr_count;
2731c18ec02fSPetter Reinholdtsen int i,j;
2732c18ec02fSPetter Reinholdtsen
2733c18ec02fSPetter Reinholdtsen printf(" FRU_PICMG_CLK_CONFIG\n");
2734c18ec02fSPetter Reinholdtsen
2735c18ec02fSPetter Reinholdtsen resource_id = fru_data[offset++];
2736c18ec02fSPetter Reinholdtsen descr_count = fru_data[offset++];
2737c18ec02fSPetter Reinholdtsen
2738c18ec02fSPetter Reinholdtsen printf("\n");
2739c18ec02fSPetter Reinholdtsen printf(" Clock Resource ID: 0x%02x\n", resource_id);
2740c18ec02fSPetter Reinholdtsen printf(" Descr. Count: 0x%02x\n", descr_count);
2741c18ec02fSPetter Reinholdtsen
2742c18ec02fSPetter Reinholdtsen for(i=0; i<descr_count; i++){
2743c18ec02fSPetter Reinholdtsen unsigned char channel_id, control;
2744c18ec02fSPetter Reinholdtsen unsigned char indirect_cnt, direct_cnt;
2745c18ec02fSPetter Reinholdtsen
2746c18ec02fSPetter Reinholdtsen channel_id = fru_data[offset++];
2747c18ec02fSPetter Reinholdtsen control = fru_data[offset++];
2748c18ec02fSPetter Reinholdtsen printf(" CLK-ID: 0x%02x - ", channel_id);
2749c18ec02fSPetter Reinholdtsen printf("CTRL 0x%02x [ %12s ]\n",
2750c18ec02fSPetter Reinholdtsen control,
2751c18ec02fSPetter Reinholdtsen ((control&0x1)==0)?"Carrier IPMC":"Application");
2752c18ec02fSPetter Reinholdtsen
2753c18ec02fSPetter Reinholdtsen indirect_cnt = fru_data[offset++];
2754c18ec02fSPetter Reinholdtsen direct_cnt = fru_data[offset++];
2755c18ec02fSPetter Reinholdtsen printf(" Cnt: Indirect 0x%02x / Direct 0x%02x\n",
2756c18ec02fSPetter Reinholdtsen indirect_cnt,
2757c18ec02fSPetter Reinholdtsen direct_cnt);
2758c18ec02fSPetter Reinholdtsen
2759c18ec02fSPetter Reinholdtsen /* indirect desc */
2760c18ec02fSPetter Reinholdtsen for(j=0; j<indirect_cnt; j++){
2761c18ec02fSPetter Reinholdtsen unsigned char feature;
2762c18ec02fSPetter Reinholdtsen unsigned char dep_chn_id;
2763c18ec02fSPetter Reinholdtsen
2764c18ec02fSPetter Reinholdtsen feature = fru_data[offset++];
2765c18ec02fSPetter Reinholdtsen dep_chn_id = fru_data[offset++];
2766c18ec02fSPetter Reinholdtsen
2767c18ec02fSPetter Reinholdtsen printf(" Feature: 0x%02x [%8s] - ", feature, (feature&0x1)==1?"Source":"Receiver");
2768c18ec02fSPetter Reinholdtsen printf(" Dep. CLK-ID: 0x%02x\n", dep_chn_id);
2769c18ec02fSPetter Reinholdtsen }
2770c18ec02fSPetter Reinholdtsen
2771c18ec02fSPetter Reinholdtsen /* direct desc */
2772c18ec02fSPetter Reinholdtsen for(j=0; j<direct_cnt; j++){
2773c18ec02fSPetter Reinholdtsen unsigned char feature, family, accuracy;
2774c18ec02fSPetter Reinholdtsen unsigned int freq, min_freq, max_freq;
2775c18ec02fSPetter Reinholdtsen
2776c18ec02fSPetter Reinholdtsen feature = fru_data[offset++];
2777c18ec02fSPetter Reinholdtsen family = fru_data[offset++];
2778c18ec02fSPetter Reinholdtsen accuracy = fru_data[offset++];
2779c18ec02fSPetter Reinholdtsen freq = (fru_data[offset+0] << 0 ) | (fru_data[offset+1] << 8 )
2780c18ec02fSPetter Reinholdtsen | (fru_data[offset+2] << 16) | (fru_data[offset+3] << 24);
2781c18ec02fSPetter Reinholdtsen offset += 4;
2782c18ec02fSPetter Reinholdtsen min_freq = (fru_data[offset+0] << 0 ) | (fru_data[offset+1] << 8 )
2783c18ec02fSPetter Reinholdtsen | (fru_data[offset+2] << 16) | (fru_data[offset+3] << 24);
2784c18ec02fSPetter Reinholdtsen offset += 4;
2785c18ec02fSPetter Reinholdtsen max_freq = (fru_data[offset+0] << 0 ) | (fru_data[offset+1] << 8 )
2786c18ec02fSPetter Reinholdtsen | (fru_data[offset+2] << 16) | (fru_data[offset+3] << 24);
2787c18ec02fSPetter Reinholdtsen offset += 4;
2788c18ec02fSPetter Reinholdtsen
2789c18ec02fSPetter Reinholdtsen printf(" - Feature: 0x%02x - PLL: %x / Asym: %s\n",
2790c18ec02fSPetter Reinholdtsen feature,
2791c18ec02fSPetter Reinholdtsen (feature > 1) & 1,
2792c18ec02fSPetter Reinholdtsen (feature&1)?"Source":"Receiver");
2793c18ec02fSPetter Reinholdtsen printf(" Family: 0x%02x - AccLVL: 0x%02x\n", family, accuracy);
2794c18ec02fSPetter Reinholdtsen printf(" FRQ: %-9ld - min: %-9ld - max: %-9ld\n",
2795c18ec02fSPetter Reinholdtsen freq, min_freq, max_freq);
2796c18ec02fSPetter Reinholdtsen }
2797c18ec02fSPetter Reinholdtsen printf("\n");
2798c18ec02fSPetter Reinholdtsen }
2799c18ec02fSPetter Reinholdtsen printf("\n");
2800c18ec02fSPetter Reinholdtsen }
2801c18ec02fSPetter Reinholdtsen break;
2802c18ec02fSPetter Reinholdtsen
2803c18ec02fSPetter Reinholdtsen case FRU_UTCA_FRU_INFO_TABLE:
2804c18ec02fSPetter Reinholdtsen case FRU_UTCA_CARRIER_MNG_IP:
2805c18ec02fSPetter Reinholdtsen case FRU_UTCA_CARRIER_INFO:
2806c18ec02fSPetter Reinholdtsen case FRU_UTCA_CARRIER_LOCATION:
2807c18ec02fSPetter Reinholdtsen case FRU_UTCA_SHMC_IP_LINK:
2808c18ec02fSPetter Reinholdtsen case FRU_UTCA_POWER_POLICY:
2809c18ec02fSPetter Reinholdtsen case FRU_UTCA_ACTIVATION:
2810c18ec02fSPetter Reinholdtsen case FRU_UTCA_PM_CAPABILTY:
2811c18ec02fSPetter Reinholdtsen case FRU_UTCA_FAN_GEOGRAPHY:
2812c18ec02fSPetter Reinholdtsen case FRU_UTCA_CLOCK_MAPPING:
2813c18ec02fSPetter Reinholdtsen case FRU_UTCA_MSG_BRIDGE_POLICY:
2814c18ec02fSPetter Reinholdtsen case FRU_UTCA_OEM_MODULE_DESC:
2815c18ec02fSPetter Reinholdtsen printf(" Not implemented yet. uTCA specific record found!!\n");
2816c18ec02fSPetter Reinholdtsen printf(" - Record ID: 0x%02x\n", h->record_id);
2817c18ec02fSPetter Reinholdtsen break;
2818c18ec02fSPetter Reinholdtsen
2819c18ec02fSPetter Reinholdtsen default:
2820c18ec02fSPetter Reinholdtsen printf(" Unknown OEM Extension Record ID: %x\n", h->record_id);
2821c18ec02fSPetter Reinholdtsen break;
2822c18ec02fSPetter Reinholdtsen
2823c18ec02fSPetter Reinholdtsen }
2824c18ec02fSPetter Reinholdtsen }
2825c18ec02fSPetter Reinholdtsen
2826c18ec02fSPetter Reinholdtsen
2827c18ec02fSPetter Reinholdtsen /* __ipmi_fru_print - Do actual work to print a FRU by its ID
2828c18ec02fSPetter Reinholdtsen *
2829c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
2830c18ec02fSPetter Reinholdtsen * @id: fru id
2831c18ec02fSPetter Reinholdtsen *
2832c18ec02fSPetter Reinholdtsen * returns -1 on error
2833c18ec02fSPetter Reinholdtsen * returns 0 if successful
2834c18ec02fSPetter Reinholdtsen * returns 1 if device not present
2835c18ec02fSPetter Reinholdtsen */
2836c18ec02fSPetter Reinholdtsen static int
__ipmi_fru_print(struct ipmi_intf * intf,uint8_t id)2837c18ec02fSPetter Reinholdtsen __ipmi_fru_print(struct ipmi_intf * intf, uint8_t id)
2838c18ec02fSPetter Reinholdtsen {
2839c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
2840c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
2841c18ec02fSPetter Reinholdtsen struct fru_info fru;
2842c18ec02fSPetter Reinholdtsen struct fru_header header;
2843c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
2844c18ec02fSPetter Reinholdtsen
2845c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(struct fru_info));
2846c18ec02fSPetter Reinholdtsen memset(&header, 0, sizeof(struct fru_header));
2847c18ec02fSPetter Reinholdtsen
2848c18ec02fSPetter Reinholdtsen /*
2849c18ec02fSPetter Reinholdtsen * get info about this FRU
2850c18ec02fSPetter Reinholdtsen */
2851c18ec02fSPetter Reinholdtsen memset(msg_data, 0, 4);
2852c18ec02fSPetter Reinholdtsen msg_data[0] = id;
2853c18ec02fSPetter Reinholdtsen
2854c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
2855c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
2856c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_INFO;
2857c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
2858c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
2859c18ec02fSPetter Reinholdtsen
2860c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
2861c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
2862c18ec02fSPetter Reinholdtsen printf(" Device not present (No Response)\n");
2863c18ec02fSPetter Reinholdtsen return -1;
2864c18ec02fSPetter Reinholdtsen }
2865c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
2866c18ec02fSPetter Reinholdtsen printf(" Device not present (%s)\n",
2867c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
2868c18ec02fSPetter Reinholdtsen return -1;
2869c18ec02fSPetter Reinholdtsen }
2870c18ec02fSPetter Reinholdtsen
2871c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(fru));
2872c18ec02fSPetter Reinholdtsen fru.size = (rsp->data[1] << 8) | rsp->data[0];
2873c18ec02fSPetter Reinholdtsen fru.access = rsp->data[2] & 0x1;
2874c18ec02fSPetter Reinholdtsen
2875c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
2876c18ec02fSPetter Reinholdtsen fru.size, fru.access ? "words" : "bytes");
2877c18ec02fSPetter Reinholdtsen
2878c18ec02fSPetter Reinholdtsen if (fru.size < 1) {
2879c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Invalid FRU size %d", fru.size);
2880c18ec02fSPetter Reinholdtsen return -1;
2881c18ec02fSPetter Reinholdtsen }
2882c18ec02fSPetter Reinholdtsen
2883c18ec02fSPetter Reinholdtsen /*
2884c18ec02fSPetter Reinholdtsen * retrieve the FRU header
2885c18ec02fSPetter Reinholdtsen */
2886c18ec02fSPetter Reinholdtsen msg_data[0] = id;
2887c18ec02fSPetter Reinholdtsen msg_data[1] = 0;
2888c18ec02fSPetter Reinholdtsen msg_data[2] = 0;
2889c18ec02fSPetter Reinholdtsen msg_data[3] = 8;
2890c18ec02fSPetter Reinholdtsen
2891c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
2892c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
2893c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_DATA;
2894c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
2895c18ec02fSPetter Reinholdtsen req.msg.data_len = 4;
2896c18ec02fSPetter Reinholdtsen
2897c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
2898c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
2899c18ec02fSPetter Reinholdtsen printf(" Device not present (No Response)\n");
2900c18ec02fSPetter Reinholdtsen return 1;
2901c18ec02fSPetter Reinholdtsen }
2902c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
2903c18ec02fSPetter Reinholdtsen printf(" Device not present (%s)\n",
2904c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
2905c18ec02fSPetter Reinholdtsen return 1;
2906c18ec02fSPetter Reinholdtsen }
2907c18ec02fSPetter Reinholdtsen
2908c18ec02fSPetter Reinholdtsen if (verbose > 1)
2909c18ec02fSPetter Reinholdtsen printbuf(rsp->data, rsp->data_len, "FRU DATA");
2910c18ec02fSPetter Reinholdtsen
2911c18ec02fSPetter Reinholdtsen memcpy(&header, rsp->data + 1, 8);
2912c18ec02fSPetter Reinholdtsen
2913c18ec02fSPetter Reinholdtsen if (header.version != 1) {
2914c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Unknown FRU header version 0x%02x",
2915c18ec02fSPetter Reinholdtsen header.version);
2916c18ec02fSPetter Reinholdtsen return -1;
2917c18ec02fSPetter Reinholdtsen }
2918c18ec02fSPetter Reinholdtsen
2919c18ec02fSPetter Reinholdtsen /* offsets need converted to bytes
2920c18ec02fSPetter Reinholdtsen * but that conversion is not done to the structure
2921c18ec02fSPetter Reinholdtsen * because we may end up with offset > 255
2922c18ec02fSPetter Reinholdtsen * which would overflow our 1-byte offset field */
2923c18ec02fSPetter Reinholdtsen
2924c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.version: 0x%x",
2925c18ec02fSPetter Reinholdtsen header.version);
2926c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.offset.internal: 0x%x",
2927c18ec02fSPetter Reinholdtsen header.offset.internal * 8);
2928c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.offset.chassis: 0x%x",
2929c18ec02fSPetter Reinholdtsen header.offset.chassis * 8);
2930c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.offset.board: 0x%x",
2931c18ec02fSPetter Reinholdtsen header.offset.board * 8);
2932c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.offset.product: 0x%x",
2933c18ec02fSPetter Reinholdtsen header.offset.product * 8);
2934c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.offset.multi: 0x%x",
2935c18ec02fSPetter Reinholdtsen header.offset.multi * 8);
2936c18ec02fSPetter Reinholdtsen
2937c18ec02fSPetter Reinholdtsen /*
2938c18ec02fSPetter Reinholdtsen * rather than reading the entire part
2939c18ec02fSPetter Reinholdtsen * only read the areas we'll format
2940c18ec02fSPetter Reinholdtsen */
2941c18ec02fSPetter Reinholdtsen /* chassis area */
2942c18ec02fSPetter Reinholdtsen if ((header.offset.chassis*8) >= sizeof(struct fru_header))
2943c18ec02fSPetter Reinholdtsen fru_area_print_chassis(intf, &fru, id, header.offset.chassis*8);
2944c18ec02fSPetter Reinholdtsen
2945c18ec02fSPetter Reinholdtsen /* board area */
2946c18ec02fSPetter Reinholdtsen if ((header.offset.board*8) >= sizeof(struct fru_header))
2947c18ec02fSPetter Reinholdtsen fru_area_print_board(intf, &fru, id, header.offset.board*8);
2948c18ec02fSPetter Reinholdtsen
2949c18ec02fSPetter Reinholdtsen /* product area */
2950c18ec02fSPetter Reinholdtsen if ((header.offset.product*8) >= sizeof(struct fru_header))
2951c18ec02fSPetter Reinholdtsen fru_area_print_product(intf, &fru, id, header.offset.product*8);
2952c18ec02fSPetter Reinholdtsen
2953c18ec02fSPetter Reinholdtsen /* multirecord area */
2954c18ec02fSPetter Reinholdtsen if( verbose==0 ) /* scipp parsing multirecord */
2955c18ec02fSPetter Reinholdtsen return 0;
2956c18ec02fSPetter Reinholdtsen
2957c18ec02fSPetter Reinholdtsen if ((header.offset.multi*8) >= sizeof(struct fru_header))
2958c18ec02fSPetter Reinholdtsen fru_area_print_multirec(intf, &fru, id, header.offset.multi*8);
2959c18ec02fSPetter Reinholdtsen
2960c18ec02fSPetter Reinholdtsen return 0;
2961c18ec02fSPetter Reinholdtsen }
2962c18ec02fSPetter Reinholdtsen
2963c18ec02fSPetter Reinholdtsen /* ipmi_fru_print - Print a FRU from its SDR locator record
2964c18ec02fSPetter Reinholdtsen *
2965c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
2966c18ec02fSPetter Reinholdtsen * @fru: SDR FRU Locator Record
2967c18ec02fSPetter Reinholdtsen *
2968c18ec02fSPetter Reinholdtsen * returns -1 on error
2969c18ec02fSPetter Reinholdtsen */
2970c18ec02fSPetter Reinholdtsen int
ipmi_fru_print(struct ipmi_intf * intf,struct sdr_record_fru_locator * fru)2971c18ec02fSPetter Reinholdtsen ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
2972c18ec02fSPetter Reinholdtsen {
2973c18ec02fSPetter Reinholdtsen char desc[17];
2974c18ec02fSPetter Reinholdtsen uint8_t bridged_request = 0;
2975c18ec02fSPetter Reinholdtsen uint32_t save_addr;
2976c18ec02fSPetter Reinholdtsen uint32_t save_channel;
2977c18ec02fSPetter Reinholdtsen int rc = 0;
2978c18ec02fSPetter Reinholdtsen
2979c18ec02fSPetter Reinholdtsen if (fru == NULL)
2980c18ec02fSPetter Reinholdtsen return __ipmi_fru_print(intf, 0);
2981c18ec02fSPetter Reinholdtsen
2982c18ec02fSPetter Reinholdtsen /* Logical FRU Device
2983c18ec02fSPetter Reinholdtsen * dev_type == 0x10
2984c18ec02fSPetter Reinholdtsen * modifier
2985c18ec02fSPetter Reinholdtsen * 0x00 = IPMI FRU Inventory
2986c18ec02fSPetter Reinholdtsen * 0x01 = DIMM Memory ID
2987c18ec02fSPetter Reinholdtsen * 0x02 = IPMI FRU Inventory
2988c18ec02fSPetter Reinholdtsen * 0x03 = System Processor FRU
2989c18ec02fSPetter Reinholdtsen * 0xff = unspecified
2990c18ec02fSPetter Reinholdtsen *
2991c18ec02fSPetter Reinholdtsen * EEPROM 24C01 or equivalent
2992c18ec02fSPetter Reinholdtsen * dev_type >= 0x08 && dev_type <= 0x0f
2993c18ec02fSPetter Reinholdtsen * modifier
2994c18ec02fSPetter Reinholdtsen * 0x00 = unspecified
2995c18ec02fSPetter Reinholdtsen * 0x01 = DIMM Memory ID
2996c18ec02fSPetter Reinholdtsen * 0x02 = IPMI FRU Inventory
2997c18ec02fSPetter Reinholdtsen * 0x03 = System Processor Cartridge
2998c18ec02fSPetter Reinholdtsen */
2999c18ec02fSPetter Reinholdtsen if (fru->dev_type != 0x10 &&
3000c18ec02fSPetter Reinholdtsen (fru->dev_type_modifier != 0x02 ||
3001c18ec02fSPetter Reinholdtsen fru->dev_type < 0x08 || fru->dev_type > 0x0f))
3002c18ec02fSPetter Reinholdtsen return -1;
3003c18ec02fSPetter Reinholdtsen
3004c18ec02fSPetter Reinholdtsen if (fru->dev_slave_addr == IPMI_BMC_SLAVE_ADDR &&
3005c18ec02fSPetter Reinholdtsen fru->device_id == 0)
3006c18ec02fSPetter Reinholdtsen return 0;
3007c18ec02fSPetter Reinholdtsen
3008c18ec02fSPetter Reinholdtsen memset(desc, 0, sizeof(desc));
3009c18ec02fSPetter Reinholdtsen memcpy(desc, fru->id_string, fru->id_code & 0x01f);
3010c18ec02fSPetter Reinholdtsen desc[fru->id_code & 0x01f] = 0;
3011c18ec02fSPetter Reinholdtsen printf("FRU Device Description : %s (ID %d)\n", desc, fru->device_id);
3012c18ec02fSPetter Reinholdtsen
3013c18ec02fSPetter Reinholdtsen switch (fru->dev_type_modifier) {
3014c18ec02fSPetter Reinholdtsen case 0x00:
3015c18ec02fSPetter Reinholdtsen case 0x02:
3016c18ec02fSPetter Reinholdtsen if (BRIDGE_TO_SENSOR(intf, fru->dev_slave_addr,
3017c18ec02fSPetter Reinholdtsen fru->channel_num)) {
3018c18ec02fSPetter Reinholdtsen bridged_request = 1;
3019c18ec02fSPetter Reinholdtsen save_addr = intf->target_addr;
3020c18ec02fSPetter Reinholdtsen intf->target_addr = fru->dev_slave_addr;
3021c18ec02fSPetter Reinholdtsen save_channel = intf->target_channel;
3022c18ec02fSPetter Reinholdtsen intf->target_channel = fru->channel_num;
3023c18ec02fSPetter Reinholdtsen }
3024c18ec02fSPetter Reinholdtsen /* print FRU */
3025c18ec02fSPetter Reinholdtsen rc = __ipmi_fru_print(intf, fru->device_id);
3026c18ec02fSPetter Reinholdtsen if (bridged_request) {
3027c18ec02fSPetter Reinholdtsen intf->target_addr = save_addr;
3028c18ec02fSPetter Reinholdtsen intf->target_channel = save_channel;
3029c18ec02fSPetter Reinholdtsen }
3030c18ec02fSPetter Reinholdtsen break;
3031c18ec02fSPetter Reinholdtsen case 0x01:
3032c18ec02fSPetter Reinholdtsen rc = ipmi_spd_print_fru(intf, fru->device_id);
3033c18ec02fSPetter Reinholdtsen break;
3034c18ec02fSPetter Reinholdtsen default:
3035c18ec02fSPetter Reinholdtsen if (verbose)
3036c18ec02fSPetter Reinholdtsen printf(" Unsupported device 0x%02x "
3037c18ec02fSPetter Reinholdtsen "type 0x%02x with modifier 0x%02x\n",
3038c18ec02fSPetter Reinholdtsen fru->device_id, fru->dev_type,
3039c18ec02fSPetter Reinholdtsen fru->dev_type_modifier);
3040c18ec02fSPetter Reinholdtsen else
3041c18ec02fSPetter Reinholdtsen printf(" Unsupported device\n");
3042c18ec02fSPetter Reinholdtsen }
3043c18ec02fSPetter Reinholdtsen printf("\n");
3044c18ec02fSPetter Reinholdtsen
3045c18ec02fSPetter Reinholdtsen return rc;
3046c18ec02fSPetter Reinholdtsen }
3047c18ec02fSPetter Reinholdtsen
3048c18ec02fSPetter Reinholdtsen /* ipmi_fru_print_all - Print builtin FRU + SDR FRU Locator records
3049c18ec02fSPetter Reinholdtsen *
3050c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
3051c18ec02fSPetter Reinholdtsen *
3052c18ec02fSPetter Reinholdtsen * returns -1 on error
3053c18ec02fSPetter Reinholdtsen */
3054c18ec02fSPetter Reinholdtsen static int
ipmi_fru_print_all(struct ipmi_intf * intf)3055c18ec02fSPetter Reinholdtsen ipmi_fru_print_all(struct ipmi_intf * intf)
3056c18ec02fSPetter Reinholdtsen {
3057c18ec02fSPetter Reinholdtsen struct ipmi_sdr_iterator * itr;
3058c18ec02fSPetter Reinholdtsen struct sdr_get_rs * header;
3059c18ec02fSPetter Reinholdtsen struct sdr_record_fru_locator * fru;
3060c18ec02fSPetter Reinholdtsen int rc;
3061c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
3062c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
3063c18ec02fSPetter Reinholdtsen struct ipm_devid_rsp *devid;
3064c18ec02fSPetter Reinholdtsen struct sdr_record_mc_locator * mc;
3065c18ec02fSPetter Reinholdtsen uint32_t save_addr;
3066c18ec02fSPetter Reinholdtsen
3067c18ec02fSPetter Reinholdtsen printf("FRU Device Description : Builtin FRU Device (ID 0)\n");
3068c18ec02fSPetter Reinholdtsen /* TODO: Figure out if FRU device 0 may show up in SDR records. */
3069c18ec02fSPetter Reinholdtsen
3070c18ec02fSPetter Reinholdtsen /* Do a Get Device ID command to determine device support */
3071c18ec02fSPetter Reinholdtsen memset (&req, 0, sizeof(req));
3072c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_APP;
3073c18ec02fSPetter Reinholdtsen req.msg.cmd = BMC_GET_DEVICE_ID;
3074c18ec02fSPetter Reinholdtsen req.msg.data_len = 0;
3075c18ec02fSPetter Reinholdtsen
3076c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
3077c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
3078c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Get Device ID command failed");
3079c18ec02fSPetter Reinholdtsen return -1;
3080c18ec02fSPetter Reinholdtsen }
3081c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
3082c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Get Device ID command failed: %s",
3083c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
3084c18ec02fSPetter Reinholdtsen return -1;
3085c18ec02fSPetter Reinholdtsen }
3086c18ec02fSPetter Reinholdtsen
3087c18ec02fSPetter Reinholdtsen devid = (struct ipm_devid_rsp *) rsp->data;
3088c18ec02fSPetter Reinholdtsen
3089c18ec02fSPetter Reinholdtsen /* Check the FRU inventory device bit to decide whether various */
3090c18ec02fSPetter Reinholdtsen /* FRU commands can be issued to FRU device #0 LUN 0 */
3091c18ec02fSPetter Reinholdtsen
3092c18ec02fSPetter Reinholdtsen if (devid->adtl_device_support & 0x08) { /* FRU Inventory Device bit? */
3093c18ec02fSPetter Reinholdtsen rc = ipmi_fru_print(intf, NULL);
3094c18ec02fSPetter Reinholdtsen printf("\n");
3095c18ec02fSPetter Reinholdtsen }
3096c18ec02fSPetter Reinholdtsen
3097c18ec02fSPetter Reinholdtsen if ((itr = ipmi_sdr_start(intf, 0)) == NULL)
3098c18ec02fSPetter Reinholdtsen return -1;
3099c18ec02fSPetter Reinholdtsen
3100c18ec02fSPetter Reinholdtsen /* Walk the SDRs looking for FRU Devices and Management Controller Devices. */
3101c18ec02fSPetter Reinholdtsen /* For FRU devices, print the FRU from the SDR locator record. */
3102c18ec02fSPetter Reinholdtsen /* For MC devices, issue FRU commands to the satellite controller to print */
3103c18ec02fSPetter Reinholdtsen /* FRU data. */
3104c18ec02fSPetter Reinholdtsen while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL)
3105c18ec02fSPetter Reinholdtsen {
3106c18ec02fSPetter Reinholdtsen if (header->type == SDR_RECORD_TYPE_MC_DEVICE_LOCATOR ) {
3107c18ec02fSPetter Reinholdtsen /* Check the capabilities of the Management Controller Device */
3108c18ec02fSPetter Reinholdtsen mc = (struct sdr_record_mc_locator *)
3109c18ec02fSPetter Reinholdtsen ipmi_sdr_get_record(intf, header, itr);
3110c18ec02fSPetter Reinholdtsen /* Does this MC device support FRU inventory device? */
31113b15a7c0SZdenek Styblik if (mc && (mc->dev_support & 0x08) && /* FRU inventory device? */
31123b15a7c0SZdenek Styblik intf->target_addr != mc->dev_slave_addr) {
3113c18ec02fSPetter Reinholdtsen /* Yes. Prepare to issue FRU commands to FRU device #0 LUN 0 */
3114c18ec02fSPetter Reinholdtsen /* using the slave address specified in the MC record. */
3115c18ec02fSPetter Reinholdtsen
3116c18ec02fSPetter Reinholdtsen /* save current target address */
3117c18ec02fSPetter Reinholdtsen save_addr = intf->target_addr;
3118c18ec02fSPetter Reinholdtsen
3119c18ec02fSPetter Reinholdtsen /* set new target address to satellite controller */
3120c18ec02fSPetter Reinholdtsen intf->target_addr = mc->dev_slave_addr;
3121c18ec02fSPetter Reinholdtsen
3122c18ec02fSPetter Reinholdtsen printf("FRU Device Description : %-16s\n", mc->id_string);
3123c18ec02fSPetter Reinholdtsen
3124c18ec02fSPetter Reinholdtsen /* print the FRU by issuing FRU commands to the satellite */
3125c18ec02fSPetter Reinholdtsen /* controller. */
3126c18ec02fSPetter Reinholdtsen rc = __ipmi_fru_print(intf, 0);
3127c18ec02fSPetter Reinholdtsen
3128c18ec02fSPetter Reinholdtsen printf("\n");
3129c18ec02fSPetter Reinholdtsen
3130c18ec02fSPetter Reinholdtsen /* restore previous target */
3131c18ec02fSPetter Reinholdtsen intf->target_addr = save_addr;
3132c18ec02fSPetter Reinholdtsen }
3133c18ec02fSPetter Reinholdtsen
3134c18ec02fSPetter Reinholdtsen if (mc) {
3135c18ec02fSPetter Reinholdtsen free(mc);
3136c18ec02fSPetter Reinholdtsen mc = NULL;
3137c18ec02fSPetter Reinholdtsen }
3138c18ec02fSPetter Reinholdtsen
3139c18ec02fSPetter Reinholdtsen continue;
3140c18ec02fSPetter Reinholdtsen }
3141c18ec02fSPetter Reinholdtsen
3142c18ec02fSPetter Reinholdtsen if (header->type != SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR)
3143c18ec02fSPetter Reinholdtsen continue;
3144c18ec02fSPetter Reinholdtsen
3145c18ec02fSPetter Reinholdtsen /* Print the FRU from the SDR locator record. */
3146c18ec02fSPetter Reinholdtsen fru = (struct sdr_record_fru_locator *)
3147c18ec02fSPetter Reinholdtsen ipmi_sdr_get_record(intf, header, itr);
3148c18ec02fSPetter Reinholdtsen if (fru == NULL || !fru->logical) {
3149c18ec02fSPetter Reinholdtsen if (fru) {
3150c18ec02fSPetter Reinholdtsen free(fru);
3151c18ec02fSPetter Reinholdtsen fru = NULL;
3152c18ec02fSPetter Reinholdtsen }
3153c18ec02fSPetter Reinholdtsen continue;
3154c18ec02fSPetter Reinholdtsen }
3155c18ec02fSPetter Reinholdtsen rc = ipmi_fru_print(intf, fru);
3156c18ec02fSPetter Reinholdtsen free(fru);
3157c18ec02fSPetter Reinholdtsen fru = NULL;
3158c18ec02fSPetter Reinholdtsen }
3159c18ec02fSPetter Reinholdtsen
3160c18ec02fSPetter Reinholdtsen ipmi_sdr_end(intf, itr);
3161c18ec02fSPetter Reinholdtsen
3162c18ec02fSPetter Reinholdtsen return rc;
3163c18ec02fSPetter Reinholdtsen }
3164c18ec02fSPetter Reinholdtsen
3165c18ec02fSPetter Reinholdtsen /* ipmi_fru_read_help() - print help text for 'read'
3166c18ec02fSPetter Reinholdtsen *
3167c18ec02fSPetter Reinholdtsen * returns void
3168c18ec02fSPetter Reinholdtsen */
3169c18ec02fSPetter Reinholdtsen void
ipmi_fru_read_help()3170c18ec02fSPetter Reinholdtsen ipmi_fru_read_help()
3171c18ec02fSPetter Reinholdtsen {
3172c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "fru read <fru id> <fru file>");
3173c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "Note: FRU ID and file(incl. full path) must be specified.");
3174c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "Example: ipmitool fru read 0 /root/fru.bin");
3175c18ec02fSPetter Reinholdtsen } /* ipmi_fru_read_help() */
3176c18ec02fSPetter Reinholdtsen
3177c18ec02fSPetter Reinholdtsen static void
ipmi_fru_read_to_bin(struct ipmi_intf * intf,char * pFileName,uint8_t fruId)3178c18ec02fSPetter Reinholdtsen ipmi_fru_read_to_bin(struct ipmi_intf * intf,
3179c18ec02fSPetter Reinholdtsen char * pFileName,
3180c18ec02fSPetter Reinholdtsen uint8_t fruId)
3181c18ec02fSPetter Reinholdtsen {
3182c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
3183c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
3184c18ec02fSPetter Reinholdtsen struct fru_info fru;
3185c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
3186c18ec02fSPetter Reinholdtsen uint8_t * pFruBuf;
3187c18ec02fSPetter Reinholdtsen
3188c18ec02fSPetter Reinholdtsen msg_data[0] = fruId;
3189c18ec02fSPetter Reinholdtsen
3190c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
3191c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
3192c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_INFO;
3193c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
3194c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
3195c18ec02fSPetter Reinholdtsen
3196c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
3197c18ec02fSPetter Reinholdtsen if (!rsp)
3198c18ec02fSPetter Reinholdtsen return;
3199c18ec02fSPetter Reinholdtsen
3200c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
3201c18ec02fSPetter Reinholdtsen if (rsp->ccode == 0xc3)
3202c18ec02fSPetter Reinholdtsen printf (" Timeout accessing FRU info. (Device not present?)\n");
3203c18ec02fSPetter Reinholdtsen return;
3204c18ec02fSPetter Reinholdtsen }
3205c18ec02fSPetter Reinholdtsen
3206c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(fru));
3207c18ec02fSPetter Reinholdtsen fru.size = (rsp->data[1] << 8) | rsp->data[0];
3208c18ec02fSPetter Reinholdtsen fru.access = rsp->data[2] & 0x1;
3209c18ec02fSPetter Reinholdtsen
3210c18ec02fSPetter Reinholdtsen if (verbose) {
3211c18ec02fSPetter Reinholdtsen printf("Fru Size = %d bytes\n",fru.size);
3212c18ec02fSPetter Reinholdtsen printf("Fru Access = %xh\n", fru.access);
3213c18ec02fSPetter Reinholdtsen }
3214c18ec02fSPetter Reinholdtsen
3215c18ec02fSPetter Reinholdtsen pFruBuf = malloc(fru.size);
3216c18ec02fSPetter Reinholdtsen if (pFruBuf != NULL) {
3217c18ec02fSPetter Reinholdtsen printf("Fru Size : %d bytes\n",fru.size);
3218c18ec02fSPetter Reinholdtsen read_fru_area(intf, &fru, fruId, 0, fru.size, pFruBuf);
3219c18ec02fSPetter Reinholdtsen } else {
3220c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Cannot allocate %d bytes\n", fru.size);
3221c18ec02fSPetter Reinholdtsen return;
3222c18ec02fSPetter Reinholdtsen }
3223c18ec02fSPetter Reinholdtsen
3224c18ec02fSPetter Reinholdtsen if(pFruBuf != NULL)
3225c18ec02fSPetter Reinholdtsen {
3226c18ec02fSPetter Reinholdtsen FILE * pFile;
3227c18ec02fSPetter Reinholdtsen pFile = fopen(pFileName,"wb");
3228c18ec02fSPetter Reinholdtsen if (pFile) {
3229c18ec02fSPetter Reinholdtsen fwrite(pFruBuf, fru.size, 1, pFile);
3230c18ec02fSPetter Reinholdtsen printf("Done\n");
3231c18ec02fSPetter Reinholdtsen } else {
3232c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error opening file %s\n", pFileName);
3233c18ec02fSPetter Reinholdtsen free(pFruBuf);
3234c18ec02fSPetter Reinholdtsen pFruBuf = NULL;
3235c18ec02fSPetter Reinholdtsen return;
3236c18ec02fSPetter Reinholdtsen }
3237c18ec02fSPetter Reinholdtsen fclose(pFile);
3238c18ec02fSPetter Reinholdtsen }
3239c18ec02fSPetter Reinholdtsen free(pFruBuf);
3240c18ec02fSPetter Reinholdtsen pFruBuf = NULL;
3241c18ec02fSPetter Reinholdtsen }
3242c18ec02fSPetter Reinholdtsen
3243c18ec02fSPetter Reinholdtsen static void
ipmi_fru_write_from_bin(struct ipmi_intf * intf,char * pFileName,uint8_t fruId)3244c18ec02fSPetter Reinholdtsen ipmi_fru_write_from_bin(struct ipmi_intf * intf,
3245c18ec02fSPetter Reinholdtsen char * pFileName,
3246c18ec02fSPetter Reinholdtsen uint8_t fruId)
3247c18ec02fSPetter Reinholdtsen {
3248c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
3249c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
3250c18ec02fSPetter Reinholdtsen struct fru_info fru;
3251c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
3252c18ec02fSPetter Reinholdtsen uint8_t *pFruBuf;
3253c18ec02fSPetter Reinholdtsen uint16_t len = 0;
3254c18ec02fSPetter Reinholdtsen FILE *pFile;
3255c18ec02fSPetter Reinholdtsen
3256c18ec02fSPetter Reinholdtsen msg_data[0] = fruId;
3257c18ec02fSPetter Reinholdtsen
3258c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof (req));
3259c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
3260c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_INFO;
3261c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
3262c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
3263c18ec02fSPetter Reinholdtsen
3264c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
3265c18ec02fSPetter Reinholdtsen if (!rsp)
3266c18ec02fSPetter Reinholdtsen return;
3267c18ec02fSPetter Reinholdtsen
3268c18ec02fSPetter Reinholdtsen if (rsp->ccode) {
3269c18ec02fSPetter Reinholdtsen if (rsp->ccode == 0xc3)
3270c18ec02fSPetter Reinholdtsen printf(" Timeout accessing FRU info. (Device not present?)\n");
3271c18ec02fSPetter Reinholdtsen return;
3272c18ec02fSPetter Reinholdtsen }
3273c18ec02fSPetter Reinholdtsen
3274c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(fru));
3275c18ec02fSPetter Reinholdtsen fru.size = (rsp->data[1] << 8) | rsp->data[0];
3276c18ec02fSPetter Reinholdtsen fru.access = rsp->data[2] & 0x1;
3277c18ec02fSPetter Reinholdtsen
3278c18ec02fSPetter Reinholdtsen if (verbose) {
3279c18ec02fSPetter Reinholdtsen printf("Fru Size = %d bytes\n", fru.size);
3280c18ec02fSPetter Reinholdtsen printf("Fru Access = %xh\n", fru.access);
3281c18ec02fSPetter Reinholdtsen }
3282c18ec02fSPetter Reinholdtsen
3283c18ec02fSPetter Reinholdtsen pFruBuf = malloc(fru.size);
3284c18ec02fSPetter Reinholdtsen if (pFruBuf == NULL) {
3285c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Cannot allocate %d bytes\n", fru.size);
3286c18ec02fSPetter Reinholdtsen return;
3287c18ec02fSPetter Reinholdtsen }
3288c18ec02fSPetter Reinholdtsen
3289c18ec02fSPetter Reinholdtsen pFile = fopen(pFileName, "rb");
3290c18ec02fSPetter Reinholdtsen if (pFile != NULL) {
3291c18ec02fSPetter Reinholdtsen len = fread(pFruBuf, 1, fru.size, pFile);
3292c18ec02fSPetter Reinholdtsen printf("Fru Size : %d bytes\n", fru.size);
3293c18ec02fSPetter Reinholdtsen printf("Size to Write : %d bytes\n", len);
3294c18ec02fSPetter Reinholdtsen fclose(pFile);
3295c18ec02fSPetter Reinholdtsen } else {
3296c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error opening file %s\n", pFileName);
3297c18ec02fSPetter Reinholdtsen }
3298c18ec02fSPetter Reinholdtsen
3299c18ec02fSPetter Reinholdtsen if (len != 0) {
3300c18ec02fSPetter Reinholdtsen write_fru_area(intf, &fru, fruId,0, 0, len, pFruBuf);
3301c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO,"Done");
3302c18ec02fSPetter Reinholdtsen }
3303c18ec02fSPetter Reinholdtsen
3304c18ec02fSPetter Reinholdtsen free(pFruBuf);
3305c18ec02fSPetter Reinholdtsen pFruBuf = NULL;
3306c18ec02fSPetter Reinholdtsen }
3307c18ec02fSPetter Reinholdtsen
3308c18ec02fSPetter Reinholdtsen /* ipmi_fru_write_help() - print help text for 'write'
3309c18ec02fSPetter Reinholdtsen *
3310c18ec02fSPetter Reinholdtsen * retruns void
3311c18ec02fSPetter Reinholdtsen */
3312c18ec02fSPetter Reinholdtsen void
ipmi_fru_write_help()3313c18ec02fSPetter Reinholdtsen ipmi_fru_write_help()
3314c18ec02fSPetter Reinholdtsen {
3315c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "fru write <fru id> <fru file>");
3316c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "Note: FRU ID and file(incl. full path) must be specified.");
3317c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "Example: ipmitool fru write 0 /root/fru.bin");
3318c18ec02fSPetter Reinholdtsen } /* ipmi_fru_write_help() */
3319c18ec02fSPetter Reinholdtsen
3320c18ec02fSPetter Reinholdtsen /* ipmi_fru_edit_help - print help text for 'fru edit' command
3321c18ec02fSPetter Reinholdtsen *
3322c18ec02fSPetter Reinholdtsen * returns void
3323c18ec02fSPetter Reinholdtsen */
3324c18ec02fSPetter Reinholdtsen void
ipmi_fru_edit_help()3325c18ec02fSPetter Reinholdtsen ipmi_fru_edit_help()
3326c18ec02fSPetter Reinholdtsen {
3327c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE,
3328c18ec02fSPetter Reinholdtsen "fru edit <fruid> field <section> <index> <string> - edit FRU string");
3329c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE,
3330c18ec02fSPetter Reinholdtsen "fru edit <fruid> oem iana <record> <format> <args> - limited OEM support");
3331c18ec02fSPetter Reinholdtsen } /* ipmi_fru_edit_help() */
3332c18ec02fSPetter Reinholdtsen
3333c18ec02fSPetter Reinholdtsen /* ipmi_fru_edit_multirec - Query new values to replace original FRU content
3334c18ec02fSPetter Reinholdtsen *
3335c18ec02fSPetter Reinholdtsen * @intf: interface to use
3336c18ec02fSPetter Reinholdtsen * @id: FRU id to work on
3337c18ec02fSPetter Reinholdtsen *
3338c18ec02fSPetter Reinholdtsen * returns: nothing
3339c18ec02fSPetter Reinholdtsen */
3340c18ec02fSPetter Reinholdtsen /* Work in progress, copy paste most of the stuff for other functions in this
3341c18ec02fSPetter Reinholdtsen file ... not elegant yet */
3342c18ec02fSPetter Reinholdtsen static int
ipmi_fru_edit_multirec(struct ipmi_intf * intf,uint8_t id,int argc,char ** argv)3343c18ec02fSPetter Reinholdtsen ipmi_fru_edit_multirec(struct ipmi_intf * intf, uint8_t id ,
3344c18ec02fSPetter Reinholdtsen int argc, char ** argv)
3345c18ec02fSPetter Reinholdtsen {
3346c18ec02fSPetter Reinholdtsen
3347c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
3348c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
3349c18ec02fSPetter Reinholdtsen struct fru_info fru;
3350c18ec02fSPetter Reinholdtsen struct fru_header header;
3351c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
3352c18ec02fSPetter Reinholdtsen
3353c18ec02fSPetter Reinholdtsen uint16_t retStatus = 0;
3354c18ec02fSPetter Reinholdtsen uint32_t offFruMultiRec;
3355c18ec02fSPetter Reinholdtsen uint32_t fruMultiRecSize = 0;
3356c18ec02fSPetter Reinholdtsen struct fru_info fruInfo;
3357c18ec02fSPetter Reinholdtsen retStatus = ipmi_fru_get_multirec_location_from_fru(intf, id, &fruInfo,
3358c18ec02fSPetter Reinholdtsen &offFruMultiRec,
3359c18ec02fSPetter Reinholdtsen &fruMultiRecSize);
3360c18ec02fSPetter Reinholdtsen
3361c18ec02fSPetter Reinholdtsen
3362c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "FRU Size : %lu\n", fruMultiRecSize);
3363c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Multi Rec offset: %lu\n", offFruMultiRec);
3364c18ec02fSPetter Reinholdtsen
3365c18ec02fSPetter Reinholdtsen {
3366c18ec02fSPetter Reinholdtsen
3367c18ec02fSPetter Reinholdtsen
3368c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(struct fru_info));
3369c18ec02fSPetter Reinholdtsen memset(&header, 0, sizeof(struct fru_header));
3370c18ec02fSPetter Reinholdtsen
3371c18ec02fSPetter Reinholdtsen /*
3372c18ec02fSPetter Reinholdtsen * get info about this FRU
3373c18ec02fSPetter Reinholdtsen */
3374c18ec02fSPetter Reinholdtsen memset(msg_data, 0, 4);
3375c18ec02fSPetter Reinholdtsen msg_data[0] = id;
3376c18ec02fSPetter Reinholdtsen
3377c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
3378c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
3379c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_INFO;
3380c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
3381c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
3382c18ec02fSPetter Reinholdtsen
3383c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
3384c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
3385c18ec02fSPetter Reinholdtsen printf(" Device not present (No Response)\n");
3386c18ec02fSPetter Reinholdtsen return -1;
3387c18ec02fSPetter Reinholdtsen }
3388c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
3389c18ec02fSPetter Reinholdtsen printf(" Device not present (%s)\n",
3390c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
3391c18ec02fSPetter Reinholdtsen return -1;
3392c18ec02fSPetter Reinholdtsen }
3393c18ec02fSPetter Reinholdtsen
3394c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(fru));
3395c18ec02fSPetter Reinholdtsen fru.size = (rsp->data[1] << 8) | rsp->data[0];
3396c18ec02fSPetter Reinholdtsen fru.access = rsp->data[2] & 0x1;
3397c18ec02fSPetter Reinholdtsen
3398c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
3399c18ec02fSPetter Reinholdtsen fru.size, fru.access ? "words" : "bytes");
3400c18ec02fSPetter Reinholdtsen
3401c18ec02fSPetter Reinholdtsen if (fru.size < 1) {
3402c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Invalid FRU size %d", fru.size);
3403c18ec02fSPetter Reinholdtsen return -1;
3404c18ec02fSPetter Reinholdtsen }
3405c18ec02fSPetter Reinholdtsen }
3406c18ec02fSPetter Reinholdtsen
3407c18ec02fSPetter Reinholdtsen {
3408c18ec02fSPetter Reinholdtsen uint8_t * fru_data;
3409c18ec02fSPetter Reinholdtsen uint32_t fru_len, i;
3410c18ec02fSPetter Reinholdtsen uint32_t offset= offFruMultiRec;
3411c18ec02fSPetter Reinholdtsen struct fru_multirec_header * h;
3412c18ec02fSPetter Reinholdtsen uint32_t last_off, len;
3413c18ec02fSPetter Reinholdtsen uint8_t error=0;
3414c18ec02fSPetter Reinholdtsen
3415c18ec02fSPetter Reinholdtsen i = last_off = offset;
3416c18ec02fSPetter Reinholdtsen fru_len = 0;
3417c18ec02fSPetter Reinholdtsen
3418c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(fru));
3419c18ec02fSPetter Reinholdtsen fru_data = malloc(fru.size + 1);
3420c18ec02fSPetter Reinholdtsen if (fru_data == NULL) {
3421c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Out of memory!");
3422c18ec02fSPetter Reinholdtsen return -1;
3423c18ec02fSPetter Reinholdtsen }
3424c18ec02fSPetter Reinholdtsen memset(fru_data, 0, fru.size + 1);
3425c18ec02fSPetter Reinholdtsen
3426c18ec02fSPetter Reinholdtsen do {
3427c18ec02fSPetter Reinholdtsen h = (struct fru_multirec_header *) (fru_data + i);
3428c18ec02fSPetter Reinholdtsen
3429c18ec02fSPetter Reinholdtsen /* read area in (at most) FRU_MULTIREC_CHUNK_SIZE bytes at a time */
3430c18ec02fSPetter Reinholdtsen if ((last_off < (i + sizeof(*h))) || (last_off < (i + h->len)))
3431c18ec02fSPetter Reinholdtsen {
3432c18ec02fSPetter Reinholdtsen len = fru.size - last_off;
3433c18ec02fSPetter Reinholdtsen if (len > FRU_MULTIREC_CHUNK_SIZE)
3434c18ec02fSPetter Reinholdtsen len = FRU_MULTIREC_CHUNK_SIZE;
3435c18ec02fSPetter Reinholdtsen
3436c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, &fru, id, last_off, len, fru_data) < 0)
3437c18ec02fSPetter Reinholdtsen break;
3438c18ec02fSPetter Reinholdtsen
3439c18ec02fSPetter Reinholdtsen last_off += len;
3440c18ec02fSPetter Reinholdtsen }
3441c18ec02fSPetter Reinholdtsen if( h->type == FRU_RECORD_TYPE_OEM_EXTENSION ){
3442c18ec02fSPetter Reinholdtsen
3443c18ec02fSPetter Reinholdtsen struct fru_multirec_oem_header *oh=(struct fru_multirec_oem_header *)
3444c18ec02fSPetter Reinholdtsen &fru_data[i + sizeof(struct fru_multirec_header)];
3445c18ec02fSPetter Reinholdtsen uint32_t iana = oh->mfg_id[0] | oh->mfg_id[1]<<8 | oh->mfg_id[2]<<16;
3446c18ec02fSPetter Reinholdtsen
3447c18ec02fSPetter Reinholdtsen uint32_t suppliedIana = 0 ;
3448c18ec02fSPetter Reinholdtsen /* Now makes sure this is really PICMG record */
3449c18ec02fSPetter Reinholdtsen
3450c18ec02fSPetter Reinholdtsen /* Default to PICMG for backward compatibility */
3451c18ec02fSPetter Reinholdtsen if( argc <=2 ) {
3452c18ec02fSPetter Reinholdtsen suppliedIana = IPMI_OEM_PICMG;
3453c18ec02fSPetter Reinholdtsen } else {
3454c18ec02fSPetter Reinholdtsen if( !strncmp( argv[2] , "oem" , 3 )) {
3455c18ec02fSPetter Reinholdtsen /* Expect IANA number next */
3456c18ec02fSPetter Reinholdtsen if( argc <= 3 ) {
3457c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "oem iana <record> <format> [<args>]");
3458c18ec02fSPetter Reinholdtsen error = 1;
3459c18ec02fSPetter Reinholdtsen } else {
3460c18ec02fSPetter Reinholdtsen if (str2uint(argv[3], &suppliedIana) == 0) {
3461c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,
3462c18ec02fSPetter Reinholdtsen "using iana: %d",
3463c18ec02fSPetter Reinholdtsen suppliedIana);
3464c18ec02fSPetter Reinholdtsen } else {
3465c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
3466c18ec02fSPetter Reinholdtsen "Given IANA '%s' is invalid.",
3467c18ec02fSPetter Reinholdtsen argv[3]);
3468c18ec02fSPetter Reinholdtsen error = 1;
3469c18ec02fSPetter Reinholdtsen }
3470c18ec02fSPetter Reinholdtsen }
3471c18ec02fSPetter Reinholdtsen }
3472c18ec02fSPetter Reinholdtsen }
3473c18ec02fSPetter Reinholdtsen
3474c18ec02fSPetter Reinholdtsen if( suppliedIana == iana ) {
3475c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Matching record found" );
3476c18ec02fSPetter Reinholdtsen
3477c18ec02fSPetter Reinholdtsen if( iana == IPMI_OEM_PICMG ){
3478c18ec02fSPetter Reinholdtsen if( ipmi_fru_picmg_ext_edit(fru_data,
3479c18ec02fSPetter Reinholdtsen i + sizeof(struct fru_multirec_header),
3480c18ec02fSPetter Reinholdtsen h->len, h, oh )){
3481c18ec02fSPetter Reinholdtsen /* The fru changed */
3482c18ec02fSPetter Reinholdtsen write_fru_area(intf,&fru,id, i,i,
3483c18ec02fSPetter Reinholdtsen h->len+ sizeof(struct fru_multirec_header), fru_data);
3484c18ec02fSPetter Reinholdtsen }
3485c18ec02fSPetter Reinholdtsen }
3486c18ec02fSPetter Reinholdtsen else if( iana == IPMI_OEM_KONTRON ) {
3487c18ec02fSPetter Reinholdtsen if( ipmi_fru_oemkontron_edit( argc,argv,fru_data,
3488c18ec02fSPetter Reinholdtsen i + sizeof(struct fru_multirec_header),
3489c18ec02fSPetter Reinholdtsen h->len, h, oh )){
3490c18ec02fSPetter Reinholdtsen /* The fru changed */
3491c18ec02fSPetter Reinholdtsen write_fru_area(intf,&fru,id, i,i,
3492c18ec02fSPetter Reinholdtsen h->len+ sizeof(struct fru_multirec_header), fru_data);
3493c18ec02fSPetter Reinholdtsen }
3494c18ec02fSPetter Reinholdtsen }
3495c18ec02fSPetter Reinholdtsen /* FIXME: Add OEM record support here */
3496c18ec02fSPetter Reinholdtsen else{
3497c18ec02fSPetter Reinholdtsen printf(" OEM IANA (%s) Record not support in this mode\n",
3498c18ec02fSPetter Reinholdtsen val2str( iana, ipmi_oem_info));
3499c18ec02fSPetter Reinholdtsen error = 1;
3500c18ec02fSPetter Reinholdtsen }
3501c18ec02fSPetter Reinholdtsen }
3502c18ec02fSPetter Reinholdtsen }
3503c18ec02fSPetter Reinholdtsen i += h->len + sizeof (struct fru_multirec_header);
3504c18ec02fSPetter Reinholdtsen } while (!(h->format & 0x80) && (error != 1));
3505c18ec02fSPetter Reinholdtsen
3506c18ec02fSPetter Reinholdtsen free(fru_data);
3507c18ec02fSPetter Reinholdtsen fru_data = NULL;
3508c18ec02fSPetter Reinholdtsen }
3509c18ec02fSPetter Reinholdtsen return 0;
3510c18ec02fSPetter Reinholdtsen }
3511c18ec02fSPetter Reinholdtsen
3512c18ec02fSPetter Reinholdtsen /* ipmi_fru_get_help - print help text for 'fru get'
3513c18ec02fSPetter Reinholdtsen *
3514c18ec02fSPetter Reinholdtsen * returns void
3515c18ec02fSPetter Reinholdtsen */
3516c18ec02fSPetter Reinholdtsen void
ipmi_fru_get_help()3517c18ec02fSPetter Reinholdtsen ipmi_fru_get_help()
3518c18ec02fSPetter Reinholdtsen {
3519c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE,
3520c18ec02fSPetter Reinholdtsen "fru get <fruid> oem iana <record> <format> <args> - limited OEM support");
3521c18ec02fSPetter Reinholdtsen } /* ipmi_fru_get_help() */
3522c18ec02fSPetter Reinholdtsen
3523c18ec02fSPetter Reinholdtsen void
ipmi_fru_internaluse_help()3524c18ec02fSPetter Reinholdtsen ipmi_fru_internaluse_help()
3525c18ec02fSPetter Reinholdtsen {
3526c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE,
3527c18ec02fSPetter Reinholdtsen "fru internaluse <fru id> info - get internal use area size");
3528c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE,
3529c18ec02fSPetter Reinholdtsen "fru internaluse <fru id> print - print internal use area in hex");
3530c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE,
3531c18ec02fSPetter Reinholdtsen "fru internaluse <fru id> read <fru file> - read internal use area to file");
3532c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE,
3533c18ec02fSPetter Reinholdtsen "fru internaluse <fru id> write <fru file> - write internal use area from file");
3534c18ec02fSPetter Reinholdtsen } /* void ipmi_fru_internaluse_help() */
3535c18ec02fSPetter Reinholdtsen
3536c18ec02fSPetter Reinholdtsen /* ipmi_fru_get_multirec - Query new values to replace original FRU content
3537c18ec02fSPetter Reinholdtsen *
3538c18ec02fSPetter Reinholdtsen * @intf: interface to use
3539c18ec02fSPetter Reinholdtsen * @id: FRU id to work on
3540c18ec02fSPetter Reinholdtsen *
3541c18ec02fSPetter Reinholdtsen * returns: nothing
3542c18ec02fSPetter Reinholdtsen */
3543c18ec02fSPetter Reinholdtsen /* Work in progress, copy paste most of the stuff for other functions in this
3544c18ec02fSPetter Reinholdtsen file ... not elegant yet */
3545c18ec02fSPetter Reinholdtsen static int
ipmi_fru_get_multirec(struct ipmi_intf * intf,uint8_t id,int argc,char ** argv)3546c18ec02fSPetter Reinholdtsen ipmi_fru_get_multirec(struct ipmi_intf * intf, uint8_t id ,
3547c18ec02fSPetter Reinholdtsen int argc, char ** argv)
3548c18ec02fSPetter Reinholdtsen {
3549c18ec02fSPetter Reinholdtsen
3550c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
3551c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
3552c18ec02fSPetter Reinholdtsen struct fru_info fru;
3553c18ec02fSPetter Reinholdtsen struct fru_header header;
3554c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
3555c18ec02fSPetter Reinholdtsen
3556c18ec02fSPetter Reinholdtsen uint16_t retStatus = 0;
3557c18ec02fSPetter Reinholdtsen uint32_t offFruMultiRec;
3558c18ec02fSPetter Reinholdtsen uint32_t fruMultiRecSize = 0;
3559c18ec02fSPetter Reinholdtsen struct fru_info fruInfo;
3560c18ec02fSPetter Reinholdtsen retStatus = ipmi_fru_get_multirec_location_from_fru(intf, id, &fruInfo,
3561c18ec02fSPetter Reinholdtsen &offFruMultiRec,
3562c18ec02fSPetter Reinholdtsen &fruMultiRecSize);
3563c18ec02fSPetter Reinholdtsen
3564c18ec02fSPetter Reinholdtsen
3565c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "FRU Size : %lu\n", fruMultiRecSize);
3566c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Multi Rec offset: %lu\n", offFruMultiRec);
3567c18ec02fSPetter Reinholdtsen
3568c18ec02fSPetter Reinholdtsen {
3569c18ec02fSPetter Reinholdtsen
3570c18ec02fSPetter Reinholdtsen
3571c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(struct fru_info));
3572c18ec02fSPetter Reinholdtsen memset(&header, 0, sizeof(struct fru_header));
3573c18ec02fSPetter Reinholdtsen
3574c18ec02fSPetter Reinholdtsen /*
3575c18ec02fSPetter Reinholdtsen * get info about this FRU
3576c18ec02fSPetter Reinholdtsen */
3577c18ec02fSPetter Reinholdtsen memset(msg_data, 0, 4);
3578c18ec02fSPetter Reinholdtsen msg_data[0] = id;
3579c18ec02fSPetter Reinholdtsen
3580c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
3581c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
3582c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_INFO;
3583c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
3584c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
3585c18ec02fSPetter Reinholdtsen
3586c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
3587c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
3588c18ec02fSPetter Reinholdtsen printf(" Device not present (No Response)\n");
3589c18ec02fSPetter Reinholdtsen return -1;
3590c18ec02fSPetter Reinholdtsen }
3591c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
3592c18ec02fSPetter Reinholdtsen printf(" Device not present (%s)\n",
3593c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
3594c18ec02fSPetter Reinholdtsen return -1;
3595c18ec02fSPetter Reinholdtsen }
3596c18ec02fSPetter Reinholdtsen
3597c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(fru));
3598c18ec02fSPetter Reinholdtsen fru.size = (rsp->data[1] << 8) | rsp->data[0];
3599c18ec02fSPetter Reinholdtsen fru.access = rsp->data[2] & 0x1;
3600c18ec02fSPetter Reinholdtsen
3601c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
3602c18ec02fSPetter Reinholdtsen fru.size, fru.access ? "words" : "bytes");
3603c18ec02fSPetter Reinholdtsen
3604c18ec02fSPetter Reinholdtsen if (fru.size < 1) {
3605c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Invalid FRU size %d", fru.size);
3606c18ec02fSPetter Reinholdtsen return -1;
3607c18ec02fSPetter Reinholdtsen }
3608c18ec02fSPetter Reinholdtsen }
3609c18ec02fSPetter Reinholdtsen
3610c18ec02fSPetter Reinholdtsen {
3611c18ec02fSPetter Reinholdtsen uint8_t * fru_data;
3612c18ec02fSPetter Reinholdtsen uint32_t fru_len, i;
3613c18ec02fSPetter Reinholdtsen uint32_t offset= offFruMultiRec;
3614c18ec02fSPetter Reinholdtsen struct fru_multirec_header * h;
3615c18ec02fSPetter Reinholdtsen uint32_t last_off, len;
3616c18ec02fSPetter Reinholdtsen uint8_t error=0;
3617c18ec02fSPetter Reinholdtsen
3618c18ec02fSPetter Reinholdtsen i = last_off = offset;
3619c18ec02fSPetter Reinholdtsen fru_len = 0;
3620c18ec02fSPetter Reinholdtsen
3621c18ec02fSPetter Reinholdtsen fru_data = malloc(fru.size + 1);
3622c18ec02fSPetter Reinholdtsen if (fru_data == NULL) {
3623c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Out of memory!");
3624c18ec02fSPetter Reinholdtsen return -1;
3625c18ec02fSPetter Reinholdtsen }
3626c18ec02fSPetter Reinholdtsen memset(fru_data, 0, fru.size + 1);
3627c18ec02fSPetter Reinholdtsen
3628c18ec02fSPetter Reinholdtsen do {
3629c18ec02fSPetter Reinholdtsen h = (struct fru_multirec_header *) (fru_data + i);
3630c18ec02fSPetter Reinholdtsen
3631c18ec02fSPetter Reinholdtsen /* read area in (at most) FRU_MULTIREC_CHUNK_SIZE bytes at a time */
3632c18ec02fSPetter Reinholdtsen if ((last_off < (i + sizeof(*h))) || (last_off < (i + h->len)))
3633c18ec02fSPetter Reinholdtsen {
3634c18ec02fSPetter Reinholdtsen len = fru.size - last_off;
3635c18ec02fSPetter Reinholdtsen if (len > FRU_MULTIREC_CHUNK_SIZE)
3636c18ec02fSPetter Reinholdtsen len = FRU_MULTIREC_CHUNK_SIZE;
3637c18ec02fSPetter Reinholdtsen
3638c18ec02fSPetter Reinholdtsen if (read_fru_area(intf, &fru, id, last_off, len, fru_data) < 0)
3639c18ec02fSPetter Reinholdtsen break;
3640c18ec02fSPetter Reinholdtsen
3641c18ec02fSPetter Reinholdtsen last_off += len;
3642c18ec02fSPetter Reinholdtsen }
3643c18ec02fSPetter Reinholdtsen if( h->type == FRU_RECORD_TYPE_OEM_EXTENSION ){
3644c18ec02fSPetter Reinholdtsen
3645c18ec02fSPetter Reinholdtsen struct fru_multirec_oem_header *oh=(struct fru_multirec_oem_header *)
3646c18ec02fSPetter Reinholdtsen &fru_data[i + sizeof(struct fru_multirec_header)];
3647c18ec02fSPetter Reinholdtsen uint32_t iana = oh->mfg_id[0] | oh->mfg_id[1]<<8 | oh->mfg_id[2]<<16;
3648c18ec02fSPetter Reinholdtsen
3649c18ec02fSPetter Reinholdtsen uint32_t suppliedIana = 0 ;
3650c18ec02fSPetter Reinholdtsen /* Now makes sure this is really PICMG record */
3651c18ec02fSPetter Reinholdtsen if( !strncmp( argv[2] , "oem" , 3 )) {
3652c18ec02fSPetter Reinholdtsen /* Expect IANA number next */
3653c18ec02fSPetter Reinholdtsen if( argc <= 3 ) {
3654c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "oem iana <record> <format>");
3655c18ec02fSPetter Reinholdtsen error = 1;
3656c18ec02fSPetter Reinholdtsen } else {
3657c18ec02fSPetter Reinholdtsen if (str2uint(argv[3], &suppliedIana) == 0) {
3658c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,
3659c18ec02fSPetter Reinholdtsen "using iana: %d",
3660c18ec02fSPetter Reinholdtsen suppliedIana);
3661c18ec02fSPetter Reinholdtsen } else {
3662c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
3663c18ec02fSPetter Reinholdtsen "Given IANA '%s' is invalid.",
3664c18ec02fSPetter Reinholdtsen argv[3]);
3665c18ec02fSPetter Reinholdtsen error = 1;
3666c18ec02fSPetter Reinholdtsen }
3667c18ec02fSPetter Reinholdtsen }
3668c18ec02fSPetter Reinholdtsen }
3669c18ec02fSPetter Reinholdtsen
3670c18ec02fSPetter Reinholdtsen if( suppliedIana == iana ) {
3671c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Matching record found" );
3672c18ec02fSPetter Reinholdtsen
3673c18ec02fSPetter Reinholdtsen if( iana == IPMI_OEM_KONTRON ) {
3674c18ec02fSPetter Reinholdtsen ipmi_fru_oemkontron_get( argc,argv,fru_data,
3675c18ec02fSPetter Reinholdtsen i + sizeof(struct fru_multirec_header),
3676c18ec02fSPetter Reinholdtsen h->len, h, oh );
3677c18ec02fSPetter Reinholdtsen }
3678c18ec02fSPetter Reinholdtsen /* FIXME: Add OEM record support here */
3679c18ec02fSPetter Reinholdtsen else{
3680c18ec02fSPetter Reinholdtsen printf(" OEM IANA (%s) Record not supported in this mode\n",
3681c18ec02fSPetter Reinholdtsen val2str( iana, ipmi_oem_info));
3682c18ec02fSPetter Reinholdtsen error = 1;
3683c18ec02fSPetter Reinholdtsen }
3684c18ec02fSPetter Reinholdtsen }
3685c18ec02fSPetter Reinholdtsen }
3686c18ec02fSPetter Reinholdtsen i += h->len + sizeof (struct fru_multirec_header);
3687c18ec02fSPetter Reinholdtsen } while (!(h->format & 0x80) && (error != 1));
3688c18ec02fSPetter Reinholdtsen
3689c18ec02fSPetter Reinholdtsen free(fru_data);
3690c18ec02fSPetter Reinholdtsen fru_data = NULL;
3691c18ec02fSPetter Reinholdtsen }
3692c18ec02fSPetter Reinholdtsen return 0;
3693c18ec02fSPetter Reinholdtsen }
3694c18ec02fSPetter Reinholdtsen
3695c18ec02fSPetter Reinholdtsen static int
ipmi_fru_upg_ekeying(struct ipmi_intf * intf,char * pFileName,uint8_t fruId)3696c18ec02fSPetter Reinholdtsen ipmi_fru_upg_ekeying(struct ipmi_intf * intf,
3697c18ec02fSPetter Reinholdtsen char * pFileName,
3698c18ec02fSPetter Reinholdtsen uint8_t fruId)
3699c18ec02fSPetter Reinholdtsen {
3700312f9593SZdenek Styblik struct fru_info fruInfo = {0};
3701c18ec02fSPetter Reinholdtsen uint8_t *buf = NULL;
3702c18ec02fSPetter Reinholdtsen uint32_t offFruMultiRec = 0;
3703c18ec02fSPetter Reinholdtsen uint32_t fruMultiRecSize = 0;
3704c18ec02fSPetter Reinholdtsen uint32_t offFileMultiRec = 0;
3705c18ec02fSPetter Reinholdtsen uint32_t fileMultiRecSize = 0;
3706c18ec02fSPetter Reinholdtsen if (pFileName == NULL) {
3707c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "File expected, but none given.");
3708c18ec02fSPetter Reinholdtsen return (-1);
3709c18ec02fSPetter Reinholdtsen }
3710c18ec02fSPetter Reinholdtsen if (ipmi_fru_get_multirec_location_from_fru(intf, fruId, &fruInfo,
3711c18ec02fSPetter Reinholdtsen &offFruMultiRec, &fruMultiRecSize) != 0) {
3712c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Failed to get multirec location from FRU.");
3713c18ec02fSPetter Reinholdtsen return (-1);
3714c18ec02fSPetter Reinholdtsen }
3715c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "FRU Size : %lu\n", fruMultiRecSize);
3716c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Multi Rec offset: %lu\n", offFruMultiRec);
3717c18ec02fSPetter Reinholdtsen if (ipmi_fru_get_multirec_size_from_file(pFileName, &fileMultiRecSize,
3718c18ec02fSPetter Reinholdtsen &offFileMultiRec) != 0) {
3719c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Failed to get multirec size from file '%s'.", pFileName);
3720c18ec02fSPetter Reinholdtsen return (-1);
3721c18ec02fSPetter Reinholdtsen }
3722c18ec02fSPetter Reinholdtsen buf = malloc(fileMultiRecSize);
3723c18ec02fSPetter Reinholdtsen if (buf == NULL) {
3724c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure");
3725c18ec02fSPetter Reinholdtsen return (-1);
3726c18ec02fSPetter Reinholdtsen }
3727c18ec02fSPetter Reinholdtsen if (ipmi_fru_get_multirec_from_file(pFileName, buf, fileMultiRecSize,
3728c18ec02fSPetter Reinholdtsen offFileMultiRec) != 0) {
3729c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Failed to get multirec from file '%s'.", pFileName);
3730c18ec02fSPetter Reinholdtsen if (buf != NULL) {
3731c18ec02fSPetter Reinholdtsen free(buf);
3732c18ec02fSPetter Reinholdtsen buf = NULL;
3733c18ec02fSPetter Reinholdtsen }
3734c18ec02fSPetter Reinholdtsen return (-1);
3735c18ec02fSPetter Reinholdtsen }
3736c18ec02fSPetter Reinholdtsen if (ipmi_fru_get_adjust_size_from_buffer(buf, &fileMultiRecSize) != 0) {
3737c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Failed to adjust size from buffer.");
3738c18ec02fSPetter Reinholdtsen if (buf != NULL) {
3739c18ec02fSPetter Reinholdtsen free(buf);
3740c18ec02fSPetter Reinholdtsen buf = NULL;
3741c18ec02fSPetter Reinholdtsen }
3742c18ec02fSPetter Reinholdtsen return (-1);
3743c18ec02fSPetter Reinholdtsen }
3744c18ec02fSPetter Reinholdtsen if (write_fru_area(intf, &fruInfo, fruId, 0, offFruMultiRec,
3745c18ec02fSPetter Reinholdtsen fileMultiRecSize, buf) != 0) {
3746c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Failed to write FRU area.");
3747c18ec02fSPetter Reinholdtsen if (buf != NULL) {
3748c18ec02fSPetter Reinholdtsen free(buf);
3749c18ec02fSPetter Reinholdtsen buf = NULL;
3750c18ec02fSPetter Reinholdtsen }
3751c18ec02fSPetter Reinholdtsen return (-1);
3752c18ec02fSPetter Reinholdtsen }
3753c18ec02fSPetter Reinholdtsen if (buf != NULL) {
3754c18ec02fSPetter Reinholdtsen free(buf);
3755c18ec02fSPetter Reinholdtsen buf = NULL;
3756c18ec02fSPetter Reinholdtsen }
3757c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "Done upgrading Ekey.");
3758c18ec02fSPetter Reinholdtsen return 0;
3759c18ec02fSPetter Reinholdtsen }
3760c18ec02fSPetter Reinholdtsen
3761c18ec02fSPetter Reinholdtsen /* ipmi_fru_upgekey_help - print help text for 'upgEkey'
3762c18ec02fSPetter Reinholdtsen *
3763c18ec02fSPetter Reinholdtsen * returns void
3764c18ec02fSPetter Reinholdtsen */
3765c18ec02fSPetter Reinholdtsen void
ipmi_fru_upgekey_help()3766c18ec02fSPetter Reinholdtsen ipmi_fru_upgekey_help()
3767c18ec02fSPetter Reinholdtsen {
3768c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "fru upgEkey <fru id> <fru file>");
3769c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "Note: FRU ID and file(incl. full path) must be specified.");
3770c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "Example: ipmitool fru upgEkey 0 /root/fru.bin");
3771c18ec02fSPetter Reinholdtsen } /* ipmi_fru_upgekey_help() */
3772c18ec02fSPetter Reinholdtsen
3773c18ec02fSPetter Reinholdtsen static int
ipmi_fru_get_multirec_size_from_file(char * pFileName,uint32_t * pSize,uint32_t * pOffset)3774c18ec02fSPetter Reinholdtsen ipmi_fru_get_multirec_size_from_file(char * pFileName,
3775c18ec02fSPetter Reinholdtsen uint32_t * pSize,
3776c18ec02fSPetter Reinholdtsen uint32_t * pOffset)
3777c18ec02fSPetter Reinholdtsen {
3778c18ec02fSPetter Reinholdtsen struct fru_header header;
3779c18ec02fSPetter Reinholdtsen FILE * pFile;
3780c18ec02fSPetter Reinholdtsen uint8_t len = 0;
3781c18ec02fSPetter Reinholdtsen uint32_t end = 0;
3782c18ec02fSPetter Reinholdtsen *pSize = 0;
3783c18ec02fSPetter Reinholdtsen
3784c18ec02fSPetter Reinholdtsen pFile = fopen(pFileName,"rb");
3785c18ec02fSPetter Reinholdtsen if (pFile) {
3786c18ec02fSPetter Reinholdtsen rewind(pFile);
3787c18ec02fSPetter Reinholdtsen len = fread(&header, 1, 8, pFile);
3788c18ec02fSPetter Reinholdtsen fseek(pFile, 0, SEEK_END);
3789c18ec02fSPetter Reinholdtsen end = ftell(pFile);
3790c18ec02fSPetter Reinholdtsen fclose(pFile);
3791c18ec02fSPetter Reinholdtsen }
3792c18ec02fSPetter Reinholdtsen
3793c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "File Size = %lu\n", end);
3794c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Len = %u\n", len);
3795c18ec02fSPetter Reinholdtsen
3796c18ec02fSPetter Reinholdtsen if (len != 8) {
3797c18ec02fSPetter Reinholdtsen printf("Error with file %s in getting size\n", pFileName);
3798c18ec02fSPetter Reinholdtsen return -1;
3799c18ec02fSPetter Reinholdtsen }
3800c18ec02fSPetter Reinholdtsen
3801c18ec02fSPetter Reinholdtsen if (header.version != 0x01) {
3802c18ec02fSPetter Reinholdtsen printf ("Unknown FRU header version %02x.\n", header.version);
3803c18ec02fSPetter Reinholdtsen return -1;
3804c18ec02fSPetter Reinholdtsen }
3805c18ec02fSPetter Reinholdtsen
3806c18ec02fSPetter Reinholdtsen /* Retreive length */
3807c18ec02fSPetter Reinholdtsen if (((header.offset.internal * 8) > (header.offset.internal * 8)) &&
3808c18ec02fSPetter Reinholdtsen ((header.offset.internal * 8) < end))
3809c18ec02fSPetter Reinholdtsen end = (header.offset.internal * 8);
3810c18ec02fSPetter Reinholdtsen
3811c18ec02fSPetter Reinholdtsen if (((header.offset.chassis * 8) > (header.offset.chassis * 8)) &&
3812c18ec02fSPetter Reinholdtsen ((header.offset.chassis * 8) < end))
3813c18ec02fSPetter Reinholdtsen end = (header.offset.chassis * 8);
3814c18ec02fSPetter Reinholdtsen
3815c18ec02fSPetter Reinholdtsen if (((header.offset.board * 8) > (header.offset.board * 8)) &&
3816c18ec02fSPetter Reinholdtsen ((header.offset.board * 8) < end))
3817c18ec02fSPetter Reinholdtsen end = (header.offset.board * 8);
3818c18ec02fSPetter Reinholdtsen
3819c18ec02fSPetter Reinholdtsen if (((header.offset.product * 8) > (header.offset.product * 8)) &&
3820c18ec02fSPetter Reinholdtsen ((header.offset.product * 8) < end))
3821c18ec02fSPetter Reinholdtsen end = (header.offset.product * 8);
3822c18ec02fSPetter Reinholdtsen
3823c18ec02fSPetter Reinholdtsen *pSize = end - (header.offset.multi * 8);
3824c18ec02fSPetter Reinholdtsen *pOffset = (header.offset.multi * 8);
3825c18ec02fSPetter Reinholdtsen
3826c18ec02fSPetter Reinholdtsen return 0;
3827c18ec02fSPetter Reinholdtsen }
3828c18ec02fSPetter Reinholdtsen
3829c18ec02fSPetter Reinholdtsen int
ipmi_fru_get_adjust_size_from_buffer(uint8_t * fru_data,uint32_t * pSize)3830c18ec02fSPetter Reinholdtsen ipmi_fru_get_adjust_size_from_buffer(uint8_t * fru_data, uint32_t *pSize)
3831c18ec02fSPetter Reinholdtsen {
3832c18ec02fSPetter Reinholdtsen struct fru_multirec_header * head;
3833c18ec02fSPetter Reinholdtsen int status = 0;
3834c18ec02fSPetter Reinholdtsen uint8_t checksum = 0;
3835c18ec02fSPetter Reinholdtsen uint8_t counter = 0;
3836c18ec02fSPetter Reinholdtsen uint16_t count = 0;
3837c18ec02fSPetter Reinholdtsen do {
3838c18ec02fSPetter Reinholdtsen checksum = 0;
3839c18ec02fSPetter Reinholdtsen head = (struct fru_multirec_header *) (fru_data + count);
3840c18ec02fSPetter Reinholdtsen if (verbose) {
3841c18ec02fSPetter Reinholdtsen printf("Adding (");
3842c18ec02fSPetter Reinholdtsen }
3843c18ec02fSPetter Reinholdtsen for (counter = 0; counter < sizeof(struct fru_multirec_header); counter++) {
3844c18ec02fSPetter Reinholdtsen if (verbose) {
3845c18ec02fSPetter Reinholdtsen printf(" %02X", *(fru_data + count + counter));
3846c18ec02fSPetter Reinholdtsen }
3847c18ec02fSPetter Reinholdtsen checksum += *(fru_data + count + counter);
3848c18ec02fSPetter Reinholdtsen }
3849c18ec02fSPetter Reinholdtsen if (verbose) {
3850c18ec02fSPetter Reinholdtsen printf(")");
3851c18ec02fSPetter Reinholdtsen }
3852c18ec02fSPetter Reinholdtsen if (checksum != 0) {
3853c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Bad checksum in Multi Records");
3854c18ec02fSPetter Reinholdtsen status = (-1);
3855c18ec02fSPetter Reinholdtsen if (verbose) {
3856c18ec02fSPetter Reinholdtsen printf("--> FAIL");
3857c18ec02fSPetter Reinholdtsen }
3858c18ec02fSPetter Reinholdtsen } else if (verbose) {
3859c18ec02fSPetter Reinholdtsen printf("--> OK");
3860c18ec02fSPetter Reinholdtsen }
3861c18ec02fSPetter Reinholdtsen if (verbose > 1 && checksum == 0) {
3862c18ec02fSPetter Reinholdtsen for (counter = 0; counter < head->len; counter++) {
3863c18ec02fSPetter Reinholdtsen printf(" %02X", *(fru_data + count + counter
3864c18ec02fSPetter Reinholdtsen + sizeof(struct fru_multirec_header)));
3865c18ec02fSPetter Reinholdtsen }
3866c18ec02fSPetter Reinholdtsen }
3867c18ec02fSPetter Reinholdtsen if (verbose) {
3868c18ec02fSPetter Reinholdtsen printf("\n");
3869c18ec02fSPetter Reinholdtsen }
3870c18ec02fSPetter Reinholdtsen count += head->len + sizeof (struct fru_multirec_header);
3871c18ec02fSPetter Reinholdtsen } while ((!(head->format & 0x80)) && (status == 0));
3872c18ec02fSPetter Reinholdtsen
3873c18ec02fSPetter Reinholdtsen *pSize = count;
3874c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Size of multirec: %lu\n", *pSize);
3875c18ec02fSPetter Reinholdtsen return status;
3876c18ec02fSPetter Reinholdtsen }
3877c18ec02fSPetter Reinholdtsen
3878c18ec02fSPetter Reinholdtsen static int
ipmi_fru_get_multirec_from_file(char * pFileName,uint8_t * pBufArea,uint32_t size,uint32_t offset)3879c18ec02fSPetter Reinholdtsen ipmi_fru_get_multirec_from_file(char * pFileName, uint8_t * pBufArea,
3880c18ec02fSPetter Reinholdtsen uint32_t size, uint32_t offset)
3881c18ec02fSPetter Reinholdtsen {
3882c18ec02fSPetter Reinholdtsen FILE * pFile;
3883c18ec02fSPetter Reinholdtsen uint32_t len = 0;
3884c18ec02fSPetter Reinholdtsen if (pFileName == NULL) {
3885c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Invalid file name given.");
3886c18ec02fSPetter Reinholdtsen return (-1);
3887c18ec02fSPetter Reinholdtsen }
3888c18ec02fSPetter Reinholdtsen
3889c18ec02fSPetter Reinholdtsen errno = 0;
3890c18ec02fSPetter Reinholdtsen pFile = fopen(pFileName, "rb");
3891c18ec02fSPetter Reinholdtsen if (!pFile) {
3892c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error opening file '%s': %i -> %s.", pFileName, errno,
3893c18ec02fSPetter Reinholdtsen strerror(errno));
3894c18ec02fSPetter Reinholdtsen return (-1);
3895c18ec02fSPetter Reinholdtsen }
3896c18ec02fSPetter Reinholdtsen errno = 0;
3897c18ec02fSPetter Reinholdtsen if (fseek(pFile, offset, SEEK_SET) != 0) {
3898c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Failed to seek in file '%s': %i -> %s.", pFileName, errno,
3899c18ec02fSPetter Reinholdtsen strerror(errno));
3900c18ec02fSPetter Reinholdtsen fclose(pFile);
3901c18ec02fSPetter Reinholdtsen return (-1);
3902c18ec02fSPetter Reinholdtsen }
3903c18ec02fSPetter Reinholdtsen len = fread(pBufArea, size, 1, pFile);
3904c18ec02fSPetter Reinholdtsen fclose(pFile);
3905c18ec02fSPetter Reinholdtsen
3906c18ec02fSPetter Reinholdtsen if (len != 1) {
3907c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error in file '%s'.", pFileName);
3908c18ec02fSPetter Reinholdtsen return (-1);
3909c18ec02fSPetter Reinholdtsen }
3910c18ec02fSPetter Reinholdtsen return 0;
3911c18ec02fSPetter Reinholdtsen }
3912c18ec02fSPetter Reinholdtsen
3913c18ec02fSPetter Reinholdtsen static int
ipmi_fru_get_multirec_location_from_fru(struct ipmi_intf * intf,uint8_t fruId,struct fru_info * pFruInfo,uint32_t * pRetLocation,uint32_t * pRetSize)3914c18ec02fSPetter Reinholdtsen ipmi_fru_get_multirec_location_from_fru(struct ipmi_intf * intf,
3915c18ec02fSPetter Reinholdtsen uint8_t fruId,
3916c18ec02fSPetter Reinholdtsen struct fru_info *pFruInfo,
3917c18ec02fSPetter Reinholdtsen uint32_t * pRetLocation,
3918c18ec02fSPetter Reinholdtsen uint32_t * pRetSize)
3919c18ec02fSPetter Reinholdtsen {
3920c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
3921c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
3922c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
3923c18ec02fSPetter Reinholdtsen uint32_t end;
3924c18ec02fSPetter Reinholdtsen struct fru_header header;
3925c18ec02fSPetter Reinholdtsen
3926c18ec02fSPetter Reinholdtsen *pRetLocation = 0;
3927c18ec02fSPetter Reinholdtsen
3928c18ec02fSPetter Reinholdtsen msg_data[0] = fruId;
3929c18ec02fSPetter Reinholdtsen
3930c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
3931c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
3932c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_INFO;
3933c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
3934c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
3935c18ec02fSPetter Reinholdtsen
3936c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
3937c18ec02fSPetter Reinholdtsen if (!rsp) {
3938c18ec02fSPetter Reinholdtsen if (verbose > 1)
3939c18ec02fSPetter Reinholdtsen printf("no response\n");
3940c18ec02fSPetter Reinholdtsen return -1;
3941c18ec02fSPetter Reinholdtsen }
3942c18ec02fSPetter Reinholdtsen
3943c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
3944c18ec02fSPetter Reinholdtsen if (rsp->ccode == 0xc3)
3945c18ec02fSPetter Reinholdtsen printf (" Timeout accessing FRU info. (Device not present?)\n");
3946c18ec02fSPetter Reinholdtsen else
3947c18ec02fSPetter Reinholdtsen printf (" CCODE = 0x%02x\n", rsp->ccode);
3948c18ec02fSPetter Reinholdtsen return -1;
3949c18ec02fSPetter Reinholdtsen }
3950c18ec02fSPetter Reinholdtsen pFruInfo->size = (rsp->data[1] << 8) | rsp->data[0];
3951c18ec02fSPetter Reinholdtsen pFruInfo->access = rsp->data[2] & 0x1;
3952c18ec02fSPetter Reinholdtsen
3953c18ec02fSPetter Reinholdtsen if (verbose > 1)
3954c18ec02fSPetter Reinholdtsen printf("pFruInfo->size = %d bytes (accessed by %s)\n",
3955c18ec02fSPetter Reinholdtsen pFruInfo->size, pFruInfo->access ? "words" : "bytes");
3956c18ec02fSPetter Reinholdtsen
3957c18ec02fSPetter Reinholdtsen if (!pFruInfo->size)
3958c18ec02fSPetter Reinholdtsen return -1;
3959c18ec02fSPetter Reinholdtsen
3960c18ec02fSPetter Reinholdtsen msg_data[0] = fruId;
3961c18ec02fSPetter Reinholdtsen msg_data[1] = 0;
3962c18ec02fSPetter Reinholdtsen msg_data[2] = 0;
3963c18ec02fSPetter Reinholdtsen msg_data[3] = 8;
3964c18ec02fSPetter Reinholdtsen
3965c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
3966c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
3967c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_DATA;
3968c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
3969c18ec02fSPetter Reinholdtsen req.msg.data_len = 4;
3970c18ec02fSPetter Reinholdtsen
3971c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
3972c18ec02fSPetter Reinholdtsen
3973c18ec02fSPetter Reinholdtsen if (!rsp)
3974c18ec02fSPetter Reinholdtsen return -1;
3975c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
3976c18ec02fSPetter Reinholdtsen if (rsp->ccode == 0xc3)
3977c18ec02fSPetter Reinholdtsen printf (" Timeout while reading FRU data. (Device not present?)\n");
3978c18ec02fSPetter Reinholdtsen return -1;
3979c18ec02fSPetter Reinholdtsen }
3980c18ec02fSPetter Reinholdtsen
3981c18ec02fSPetter Reinholdtsen if (verbose > 1)
3982c18ec02fSPetter Reinholdtsen printbuf(rsp->data, rsp->data_len, "FRU DATA");
3983c18ec02fSPetter Reinholdtsen
3984c18ec02fSPetter Reinholdtsen memcpy(&header, rsp->data + 1, 8);
3985c18ec02fSPetter Reinholdtsen
3986c18ec02fSPetter Reinholdtsen if (header.version != 0x01) {
3987c18ec02fSPetter Reinholdtsen printf (" Unknown FRU header version %02x.\n", header.version);
3988c18ec02fSPetter Reinholdtsen return -1;
3989c18ec02fSPetter Reinholdtsen }
3990c18ec02fSPetter Reinholdtsen
3991c18ec02fSPetter Reinholdtsen end = pFruInfo->size;
3992c18ec02fSPetter Reinholdtsen
3993c18ec02fSPetter Reinholdtsen /* Retreive length */
3994c18ec02fSPetter Reinholdtsen if (((header.offset.internal * 8) > (header.offset.internal * 8)) &&
3995c18ec02fSPetter Reinholdtsen ((header.offset.internal * 8) < end))
3996c18ec02fSPetter Reinholdtsen end = (header.offset.internal * 8);
3997c18ec02fSPetter Reinholdtsen
3998c18ec02fSPetter Reinholdtsen if (((header.offset.chassis * 8) > (header.offset.chassis * 8)) &&
3999c18ec02fSPetter Reinholdtsen ((header.offset.chassis * 8) < end))
4000c18ec02fSPetter Reinholdtsen end = (header.offset.chassis * 8);
4001c18ec02fSPetter Reinholdtsen
4002c18ec02fSPetter Reinholdtsen if (((header.offset.board * 8) > (header.offset.board * 8)) &&
4003c18ec02fSPetter Reinholdtsen ((header.offset.board * 8) < end))
4004c18ec02fSPetter Reinholdtsen end = (header.offset.board * 8);
4005c18ec02fSPetter Reinholdtsen
4006c18ec02fSPetter Reinholdtsen if (((header.offset.product * 8) > (header.offset.product * 8)) &&
4007c18ec02fSPetter Reinholdtsen ((header.offset.product * 8) < end))
4008c18ec02fSPetter Reinholdtsen end = (header.offset.product * 8);
4009c18ec02fSPetter Reinholdtsen
4010c18ec02fSPetter Reinholdtsen *pRetSize = end;
4011c18ec02fSPetter Reinholdtsen *pRetLocation = 8 * header.offset.multi;
4012c18ec02fSPetter Reinholdtsen
4013c18ec02fSPetter Reinholdtsen return 0;
4014c18ec02fSPetter Reinholdtsen }
4015c18ec02fSPetter Reinholdtsen
4016c18ec02fSPetter Reinholdtsen /* ipmi_fru_get_internal_use_offset - Retreive internal use offset
4017c18ec02fSPetter Reinholdtsen *
4018c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
4019c18ec02fSPetter Reinholdtsen * @id: fru id
4020c18ec02fSPetter Reinholdtsen *
4021c18ec02fSPetter Reinholdtsen * returns -1 on error
4022c18ec02fSPetter Reinholdtsen * returns 0 if successful
4023c18ec02fSPetter Reinholdtsen * returns 1 if device not present
4024c18ec02fSPetter Reinholdtsen */
4025c18ec02fSPetter Reinholdtsen static int
ipmi_fru_get_internal_use_info(struct ipmi_intf * intf,uint8_t id,struct fru_info * fru,uint16_t * size,uint16_t * offset)4026c18ec02fSPetter Reinholdtsen ipmi_fru_get_internal_use_info( struct ipmi_intf * intf,
4027c18ec02fSPetter Reinholdtsen uint8_t id,
4028c18ec02fSPetter Reinholdtsen struct fru_info * fru,
4029c18ec02fSPetter Reinholdtsen uint16_t * size,
4030c18ec02fSPetter Reinholdtsen uint16_t * offset)
4031c18ec02fSPetter Reinholdtsen {
4032c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp;
4033c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
4034c18ec02fSPetter Reinholdtsen struct fru_header header;
4035c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
4036c18ec02fSPetter Reinholdtsen
4037c18ec02fSPetter Reinholdtsen // Init output value
4038c18ec02fSPetter Reinholdtsen * offset = 0;
4039c18ec02fSPetter Reinholdtsen * size = 0;
4040c18ec02fSPetter Reinholdtsen
4041c18ec02fSPetter Reinholdtsen memset(fru, 0, sizeof(struct fru_info));
4042c18ec02fSPetter Reinholdtsen memset(&header, 0, sizeof(struct fru_header));
4043c18ec02fSPetter Reinholdtsen
4044c18ec02fSPetter Reinholdtsen /*
4045c18ec02fSPetter Reinholdtsen * get info about this FRU
4046c18ec02fSPetter Reinholdtsen */
4047c18ec02fSPetter Reinholdtsen memset(msg_data, 0, 4);
4048c18ec02fSPetter Reinholdtsen msg_data[0] = id;
4049c18ec02fSPetter Reinholdtsen
4050c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
4051c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
4052c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_INFO;
4053c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
4054c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
4055c18ec02fSPetter Reinholdtsen
4056c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
4057c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
4058c18ec02fSPetter Reinholdtsen printf(" Device not present (No Response)\n");
4059c18ec02fSPetter Reinholdtsen return -1;
4060c18ec02fSPetter Reinholdtsen }
4061c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
4062c18ec02fSPetter Reinholdtsen printf(" Device not present (%s)\n",
4063c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
4064c18ec02fSPetter Reinholdtsen return -1;
4065c18ec02fSPetter Reinholdtsen }
4066c18ec02fSPetter Reinholdtsen
4067c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(fru));
4068c18ec02fSPetter Reinholdtsen fru->size = (rsp->data[1] << 8) | rsp->data[0];
4069c18ec02fSPetter Reinholdtsen fru->access = rsp->data[2] & 0x1;
4070c18ec02fSPetter Reinholdtsen
4071c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
4072c18ec02fSPetter Reinholdtsen fru->size, fru->access ? "words" : "bytes");
4073c18ec02fSPetter Reinholdtsen
4074c18ec02fSPetter Reinholdtsen if (fru->size < 1) {
4075c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Invalid FRU size %d", fru->size);
4076c18ec02fSPetter Reinholdtsen return -1;
4077c18ec02fSPetter Reinholdtsen }
4078c18ec02fSPetter Reinholdtsen
4079c18ec02fSPetter Reinholdtsen /*
4080c18ec02fSPetter Reinholdtsen * retrieve the FRU header
4081c18ec02fSPetter Reinholdtsen */
4082c18ec02fSPetter Reinholdtsen msg_data[0] = id;
4083c18ec02fSPetter Reinholdtsen msg_data[1] = 0;
4084c18ec02fSPetter Reinholdtsen msg_data[2] = 0;
4085c18ec02fSPetter Reinholdtsen msg_data[3] = 8;
4086c18ec02fSPetter Reinholdtsen
4087c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
4088c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
4089c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_DATA;
4090c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
4091c18ec02fSPetter Reinholdtsen req.msg.data_len = 4;
4092c18ec02fSPetter Reinholdtsen
4093c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
4094c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
4095c18ec02fSPetter Reinholdtsen printf(" Device not present (No Response)\n");
4096c18ec02fSPetter Reinholdtsen return 1;
4097c18ec02fSPetter Reinholdtsen }
4098c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
4099c18ec02fSPetter Reinholdtsen printf(" Device not present (%s)\n",
4100c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
4101c18ec02fSPetter Reinholdtsen return 1;
4102c18ec02fSPetter Reinholdtsen }
4103c18ec02fSPetter Reinholdtsen
4104c18ec02fSPetter Reinholdtsen if (verbose > 1)
4105c18ec02fSPetter Reinholdtsen printbuf(rsp->data, rsp->data_len, "FRU DATA");
4106c18ec02fSPetter Reinholdtsen
4107c18ec02fSPetter Reinholdtsen memcpy(&header, rsp->data + 1, 8);
4108c18ec02fSPetter Reinholdtsen
4109c18ec02fSPetter Reinholdtsen if (header.version != 1) {
4110c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, " Unknown FRU header version 0x%02x",
4111c18ec02fSPetter Reinholdtsen header.version);
4112c18ec02fSPetter Reinholdtsen return -1;
4113c18ec02fSPetter Reinholdtsen }
4114c18ec02fSPetter Reinholdtsen
4115c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.version: 0x%x",
4116c18ec02fSPetter Reinholdtsen header.version);
4117c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.offset.internal: 0x%x",
4118c18ec02fSPetter Reinholdtsen header.offset.internal * 8);
4119c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.offset.chassis: 0x%x",
4120c18ec02fSPetter Reinholdtsen header.offset.chassis * 8);
4121c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.offset.board: 0x%x",
4122c18ec02fSPetter Reinholdtsen header.offset.board * 8);
4123c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.offset.product: 0x%x",
4124c18ec02fSPetter Reinholdtsen header.offset.product * 8);
4125c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "fru.header.offset.multi: 0x%x",
4126c18ec02fSPetter Reinholdtsen header.offset.multi * 8);
4127c18ec02fSPetter Reinholdtsen
4128c18ec02fSPetter Reinholdtsen if((header.offset.internal*8) == 0)
4129c18ec02fSPetter Reinholdtsen {
4130c18ec02fSPetter Reinholdtsen * size = 0;
4131c18ec02fSPetter Reinholdtsen * offset = 0;
4132c18ec02fSPetter Reinholdtsen }
4133c18ec02fSPetter Reinholdtsen else
4134c18ec02fSPetter Reinholdtsen {
4135c18ec02fSPetter Reinholdtsen (* offset) = (header.offset.internal*8);
4136c18ec02fSPetter Reinholdtsen
4137c18ec02fSPetter Reinholdtsen if(header.offset.chassis != 0)
4138c18ec02fSPetter Reinholdtsen {
4139c18ec02fSPetter Reinholdtsen (* size) = ((header.offset.chassis*8)-(* offset));
4140c18ec02fSPetter Reinholdtsen }
4141c18ec02fSPetter Reinholdtsen else if(header.offset.board != 0)
4142c18ec02fSPetter Reinholdtsen {
4143c18ec02fSPetter Reinholdtsen (* size) = ((header.offset.board*8)-(* offset));
4144c18ec02fSPetter Reinholdtsen }
4145c18ec02fSPetter Reinholdtsen else if(header.offset.product != 0)
4146c18ec02fSPetter Reinholdtsen {
4147c18ec02fSPetter Reinholdtsen (* size) = ((header.offset.product*8)-(* offset));
4148c18ec02fSPetter Reinholdtsen }
4149c18ec02fSPetter Reinholdtsen else if(header.offset.multi != 0)
4150c18ec02fSPetter Reinholdtsen {
4151c18ec02fSPetter Reinholdtsen (* size) = ((header.offset.multi*8)-(* offset));
4152c18ec02fSPetter Reinholdtsen }
4153c18ec02fSPetter Reinholdtsen else
4154c18ec02fSPetter Reinholdtsen {
4155c18ec02fSPetter Reinholdtsen (* size) = (fru->size - (* offset));
4156c18ec02fSPetter Reinholdtsen }
4157c18ec02fSPetter Reinholdtsen }
4158c18ec02fSPetter Reinholdtsen return 0;
4159c18ec02fSPetter Reinholdtsen }
4160c18ec02fSPetter Reinholdtsen
4161c18ec02fSPetter Reinholdtsen /* ipmi_fru_info_internal_use - print internal use info
4162c18ec02fSPetter Reinholdtsen *
4163c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
4164c18ec02fSPetter Reinholdtsen * @id: fru id
4165c18ec02fSPetter Reinholdtsen *
4166c18ec02fSPetter Reinholdtsen * returns -1 on error
4167c18ec02fSPetter Reinholdtsen * returns 0 if successful
4168c18ec02fSPetter Reinholdtsen * returns 1 if device not present
4169c18ec02fSPetter Reinholdtsen */
4170c18ec02fSPetter Reinholdtsen static int
ipmi_fru_info_internal_use(struct ipmi_intf * intf,uint8_t id)4171c18ec02fSPetter Reinholdtsen ipmi_fru_info_internal_use(struct ipmi_intf * intf, uint8_t id)
4172c18ec02fSPetter Reinholdtsen {
4173c18ec02fSPetter Reinholdtsen struct fru_info fru;
4174c18ec02fSPetter Reinholdtsen uint16_t size;
4175c18ec02fSPetter Reinholdtsen uint16_t offset;
4176c18ec02fSPetter Reinholdtsen int rc = 0;
4177c18ec02fSPetter Reinholdtsen
4178c18ec02fSPetter Reinholdtsen rc = ipmi_fru_get_internal_use_info(intf, id, &fru, &size, &offset);
4179c18ec02fSPetter Reinholdtsen
4180c18ec02fSPetter Reinholdtsen if(rc == 0)
4181c18ec02fSPetter Reinholdtsen {
4182c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Internal Use Area Offset: %i", offset);
4183c18ec02fSPetter Reinholdtsen printf( "Internal Use Area Size : %i\n", size);
4184c18ec02fSPetter Reinholdtsen }
4185c18ec02fSPetter Reinholdtsen else
4186c18ec02fSPetter Reinholdtsen {
4187c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Cannot access internal use area");
4188c18ec02fSPetter Reinholdtsen return -1;
4189c18ec02fSPetter Reinholdtsen }
4190c18ec02fSPetter Reinholdtsen return 0;
4191c18ec02fSPetter Reinholdtsen }
4192c18ec02fSPetter Reinholdtsen
4193c18ec02fSPetter Reinholdtsen /* ipmi_fru_help - print help text for FRU subcommand
4194c18ec02fSPetter Reinholdtsen *
4195c18ec02fSPetter Reinholdtsen * returns void
4196c18ec02fSPetter Reinholdtsen */
4197c18ec02fSPetter Reinholdtsen void
ipmi_fru_help()4198c18ec02fSPetter Reinholdtsen ipmi_fru_help()
4199c18ec02fSPetter Reinholdtsen {
4200c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE,
4201c18ec02fSPetter Reinholdtsen "FRU Commands: print read write upgEkey edit internaluse get");
4202c18ec02fSPetter Reinholdtsen } /* ipmi_fru_help() */
4203c18ec02fSPetter Reinholdtsen
4204c18ec02fSPetter Reinholdtsen /* ipmi_fru_read_internal_use - print internal use are in hex or file
4205c18ec02fSPetter Reinholdtsen *
4206c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
4207c18ec02fSPetter Reinholdtsen * @id: fru id
4208c18ec02fSPetter Reinholdtsen *
4209c18ec02fSPetter Reinholdtsen * returns -1 on error
4210c18ec02fSPetter Reinholdtsen * returns 0 if successful
4211c18ec02fSPetter Reinholdtsen * returns 1 if device not present
4212c18ec02fSPetter Reinholdtsen */
4213c18ec02fSPetter Reinholdtsen static int
ipmi_fru_read_internal_use(struct ipmi_intf * intf,uint8_t id,char * pFileName)4214c18ec02fSPetter Reinholdtsen ipmi_fru_read_internal_use(struct ipmi_intf * intf, uint8_t id, char * pFileName)
4215c18ec02fSPetter Reinholdtsen {
4216c18ec02fSPetter Reinholdtsen struct fru_info fru;
4217c18ec02fSPetter Reinholdtsen uint16_t size;
4218c18ec02fSPetter Reinholdtsen uint16_t offset;
4219c18ec02fSPetter Reinholdtsen int rc = 0;
4220c18ec02fSPetter Reinholdtsen
4221c18ec02fSPetter Reinholdtsen rc = ipmi_fru_get_internal_use_info(intf, id, &fru, &size, &offset);
4222c18ec02fSPetter Reinholdtsen
4223c18ec02fSPetter Reinholdtsen if(rc == 0)
4224c18ec02fSPetter Reinholdtsen {
4225c18ec02fSPetter Reinholdtsen uint8_t * frubuf;
4226c18ec02fSPetter Reinholdtsen
4227c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Internal Use Area Offset: %i", offset);
4228c18ec02fSPetter Reinholdtsen printf( "Internal Use Area Size : %i\n", size);
4229c18ec02fSPetter Reinholdtsen
4230c18ec02fSPetter Reinholdtsen frubuf = malloc( size );
4231c18ec02fSPetter Reinholdtsen if(frubuf)
4232c18ec02fSPetter Reinholdtsen {
4233c18ec02fSPetter Reinholdtsen rc = read_fru_area_section(intf, &fru, id, offset, size, frubuf);
4234c18ec02fSPetter Reinholdtsen
4235c18ec02fSPetter Reinholdtsen if(rc == 0)
4236c18ec02fSPetter Reinholdtsen {
4237c18ec02fSPetter Reinholdtsen if(pFileName == NULL)
4238c18ec02fSPetter Reinholdtsen {
4239c18ec02fSPetter Reinholdtsen uint16_t counter;
4240c18ec02fSPetter Reinholdtsen for(counter = 0; counter < size; counter ++)
4241c18ec02fSPetter Reinholdtsen {
4242c18ec02fSPetter Reinholdtsen if((counter % 16) == 0)
4243c18ec02fSPetter Reinholdtsen printf("\n%02i- ", (counter / 16));
4244c18ec02fSPetter Reinholdtsen printf("%02X ", frubuf[counter]);
4245c18ec02fSPetter Reinholdtsen }
4246c18ec02fSPetter Reinholdtsen }
4247c18ec02fSPetter Reinholdtsen else
4248c18ec02fSPetter Reinholdtsen {
4249c18ec02fSPetter Reinholdtsen FILE * pFile;
4250c18ec02fSPetter Reinholdtsen pFile = fopen(pFileName,"wb");
4251c18ec02fSPetter Reinholdtsen if (pFile)
4252c18ec02fSPetter Reinholdtsen {
4253c18ec02fSPetter Reinholdtsen fwrite(frubuf, size, 1, pFile);
4254c18ec02fSPetter Reinholdtsen printf("Done\n");
4255c18ec02fSPetter Reinholdtsen }
4256c18ec02fSPetter Reinholdtsen else
4257c18ec02fSPetter Reinholdtsen {
4258c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error opening file %s\n", pFileName);
4259c18ec02fSPetter Reinholdtsen free(frubuf);
4260c18ec02fSPetter Reinholdtsen frubuf = NULL;
4261c18ec02fSPetter Reinholdtsen return -1;
4262c18ec02fSPetter Reinholdtsen }
4263c18ec02fSPetter Reinholdtsen fclose(pFile);
4264c18ec02fSPetter Reinholdtsen }
4265c18ec02fSPetter Reinholdtsen }
4266c18ec02fSPetter Reinholdtsen printf("\n");
4267c18ec02fSPetter Reinholdtsen
4268c18ec02fSPetter Reinholdtsen free(frubuf);
4269c18ec02fSPetter Reinholdtsen frubuf = NULL;
4270c18ec02fSPetter Reinholdtsen }
4271c18ec02fSPetter Reinholdtsen
4272c18ec02fSPetter Reinholdtsen }
4273c18ec02fSPetter Reinholdtsen else
4274c18ec02fSPetter Reinholdtsen {
4275c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Cannot access internal use area");
4276c18ec02fSPetter Reinholdtsen }
4277c18ec02fSPetter Reinholdtsen return 0;
4278c18ec02fSPetter Reinholdtsen }
4279c18ec02fSPetter Reinholdtsen
4280c18ec02fSPetter Reinholdtsen /* ipmi_fru_write_internal_use - print internal use are in hex or file
4281c18ec02fSPetter Reinholdtsen *
4282c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
4283c18ec02fSPetter Reinholdtsen * @id: fru id
4284c18ec02fSPetter Reinholdtsen *
4285c18ec02fSPetter Reinholdtsen * returns -1 on error
4286c18ec02fSPetter Reinholdtsen * returns 0 if successful
4287c18ec02fSPetter Reinholdtsen * returns 1 if device not present
4288c18ec02fSPetter Reinholdtsen */
4289c18ec02fSPetter Reinholdtsen static int
ipmi_fru_write_internal_use(struct ipmi_intf * intf,uint8_t id,char * pFileName)4290c18ec02fSPetter Reinholdtsen ipmi_fru_write_internal_use(struct ipmi_intf * intf, uint8_t id, char * pFileName)
4291c18ec02fSPetter Reinholdtsen {
4292c18ec02fSPetter Reinholdtsen struct fru_info fru;
4293c18ec02fSPetter Reinholdtsen uint16_t size;
4294c18ec02fSPetter Reinholdtsen uint16_t offset;
4295c18ec02fSPetter Reinholdtsen int rc = 0;
4296c18ec02fSPetter Reinholdtsen
4297c18ec02fSPetter Reinholdtsen rc = ipmi_fru_get_internal_use_info(intf, id, &fru, &size, &offset);
4298c18ec02fSPetter Reinholdtsen
4299c18ec02fSPetter Reinholdtsen if(rc == 0)
4300c18ec02fSPetter Reinholdtsen {
4301c18ec02fSPetter Reinholdtsen uint8_t * frubuf;
4302c18ec02fSPetter Reinholdtsen FILE * fp;
4303c18ec02fSPetter Reinholdtsen uint32_t fileLength = 0;
4304c18ec02fSPetter Reinholdtsen
4305c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Internal Use Area Offset: %i", offset);
4306c18ec02fSPetter Reinholdtsen printf( "Internal Use Area Size : %i\n", size);
4307c18ec02fSPetter Reinholdtsen
4308c18ec02fSPetter Reinholdtsen fp = fopen(pFileName, "r");
4309c18ec02fSPetter Reinholdtsen
4310c18ec02fSPetter Reinholdtsen if(fp)
4311c18ec02fSPetter Reinholdtsen {
4312c18ec02fSPetter Reinholdtsen /* Retreive file length, check if it's fits the Eeprom Size */
4313c18ec02fSPetter Reinholdtsen fseek(fp, 0 ,SEEK_END);
4314c18ec02fSPetter Reinholdtsen fileLength = ftell(fp);
4315c18ec02fSPetter Reinholdtsen
4316c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "File Size: %i", fileLength);
4317c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Area Size: %i", size);
4318c18ec02fSPetter Reinholdtsen if(fileLength != size)
4319c18ec02fSPetter Reinholdtsen {
4320c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "File size does not fit Eeprom Size");
4321c18ec02fSPetter Reinholdtsen fclose(fp);
4322c18ec02fSPetter Reinholdtsen fp = NULL;
4323c18ec02fSPetter Reinholdtsen }
4324c18ec02fSPetter Reinholdtsen else
4325c18ec02fSPetter Reinholdtsen {
4326c18ec02fSPetter Reinholdtsen fseek(fp, 0 ,SEEK_SET);
4327c18ec02fSPetter Reinholdtsen }
4328c18ec02fSPetter Reinholdtsen }
4329c18ec02fSPetter Reinholdtsen
4330c18ec02fSPetter Reinholdtsen if(fp)
4331c18ec02fSPetter Reinholdtsen {
4332c18ec02fSPetter Reinholdtsen frubuf = malloc( size );
4333c18ec02fSPetter Reinholdtsen if(frubuf)
4334c18ec02fSPetter Reinholdtsen {
4335c18ec02fSPetter Reinholdtsen uint16_t fru_read_size;
4336c18ec02fSPetter Reinholdtsen fru_read_size = fread(frubuf, 1, size, fp);
4337c18ec02fSPetter Reinholdtsen
4338c18ec02fSPetter Reinholdtsen if(fru_read_size == size)
4339c18ec02fSPetter Reinholdtsen {
4340c18ec02fSPetter Reinholdtsen rc = write_fru_area(intf, &fru, id, 0, offset, size, frubuf);
4341c18ec02fSPetter Reinholdtsen
4342c18ec02fSPetter Reinholdtsen if(rc == 0)
4343c18ec02fSPetter Reinholdtsen {
4344c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "Done\n");
4345c18ec02fSPetter Reinholdtsen }
4346c18ec02fSPetter Reinholdtsen }
4347c18ec02fSPetter Reinholdtsen else
4348c18ec02fSPetter Reinholdtsen {
4349c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Unable to read file: %i\n", fru_read_size);
4350c18ec02fSPetter Reinholdtsen }
4351c18ec02fSPetter Reinholdtsen
4352c18ec02fSPetter Reinholdtsen free(frubuf);
4353c18ec02fSPetter Reinholdtsen frubuf = NULL;
4354c18ec02fSPetter Reinholdtsen }
4355c18ec02fSPetter Reinholdtsen fclose(fp);
4356c18ec02fSPetter Reinholdtsen fp = NULL;
4357c18ec02fSPetter Reinholdtsen }
4358c18ec02fSPetter Reinholdtsen }
4359c18ec02fSPetter Reinholdtsen else
4360c18ec02fSPetter Reinholdtsen {
4361c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Cannot access internal use area");
4362c18ec02fSPetter Reinholdtsen }
4363c18ec02fSPetter Reinholdtsen return 0;
4364c18ec02fSPetter Reinholdtsen }
4365c18ec02fSPetter Reinholdtsen
4366c18ec02fSPetter Reinholdtsen int
ipmi_fru_main(struct ipmi_intf * intf,int argc,char ** argv)4367c18ec02fSPetter Reinholdtsen ipmi_fru_main(struct ipmi_intf * intf, int argc, char ** argv)
4368c18ec02fSPetter Reinholdtsen {
4369c18ec02fSPetter Reinholdtsen int rc = 0;
4370c18ec02fSPetter Reinholdtsen uint8_t fru_id = 0;
4371c18ec02fSPetter Reinholdtsen
4372c18ec02fSPetter Reinholdtsen if (argc < 1) {
4373c18ec02fSPetter Reinholdtsen rc = ipmi_fru_print_all(intf);
4374c18ec02fSPetter Reinholdtsen }
4375c18ec02fSPetter Reinholdtsen else if (strncmp(argv[0], "help", 4) == 0) {
4376c18ec02fSPetter Reinholdtsen ipmi_fru_help();
4377c18ec02fSPetter Reinholdtsen return 0;
4378c18ec02fSPetter Reinholdtsen }
4379c18ec02fSPetter Reinholdtsen else if (strncmp(argv[0], "print", 5) == 0 ||
4380c18ec02fSPetter Reinholdtsen strncmp(argv[0], "list", 4) == 0) {
4381c18ec02fSPetter Reinholdtsen if (argc > 1) {
4382c18ec02fSPetter Reinholdtsen if (strcmp(argv[1], "help") == 0) {
4383c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "fru print [fru id] - print information about FRU(s)");
4384c18ec02fSPetter Reinholdtsen return 0;
4385c18ec02fSPetter Reinholdtsen }
4386c18ec02fSPetter Reinholdtsen
4387c18ec02fSPetter Reinholdtsen if (is_fru_id(argv[1], &fru_id) != 0)
4388c18ec02fSPetter Reinholdtsen return (-1);
4389c18ec02fSPetter Reinholdtsen
4390c18ec02fSPetter Reinholdtsen rc = __ipmi_fru_print(intf, fru_id);
4391c18ec02fSPetter Reinholdtsen } else {
4392c18ec02fSPetter Reinholdtsen rc = ipmi_fru_print_all(intf);
4393c18ec02fSPetter Reinholdtsen }
4394c18ec02fSPetter Reinholdtsen }
4395c18ec02fSPetter Reinholdtsen else if (!strncmp(argv[0], "read", 5)) {
4396c18ec02fSPetter Reinholdtsen if (argc > 1 && strcmp(argv[1], "help") == 0) {
4397c18ec02fSPetter Reinholdtsen ipmi_fru_read_help();
4398c18ec02fSPetter Reinholdtsen return 0;
4399c18ec02fSPetter Reinholdtsen } else if (argc < 3) {
4400c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Not enough parameters given.");
4401c18ec02fSPetter Reinholdtsen ipmi_fru_read_help();
4402c18ec02fSPetter Reinholdtsen return (-1);
4403c18ec02fSPetter Reinholdtsen }
4404c18ec02fSPetter Reinholdtsen
4405c18ec02fSPetter Reinholdtsen if (is_fru_id(argv[1], &fru_id) != 0)
4406c18ec02fSPetter Reinholdtsen return (-1);
4407c18ec02fSPetter Reinholdtsen
4408c18ec02fSPetter Reinholdtsen /* There is a file name in the parameters */
4409c18ec02fSPetter Reinholdtsen if (is_valid_filename(argv[2]) != 0)
4410c18ec02fSPetter Reinholdtsen return (-1);
4411c18ec02fSPetter Reinholdtsen
4412c18ec02fSPetter Reinholdtsen if (verbose) {
4413c18ec02fSPetter Reinholdtsen printf("FRU ID : %d\n", fru_id);
4414c18ec02fSPetter Reinholdtsen printf("FRU File : %s\n", argv[2]);
4415c18ec02fSPetter Reinholdtsen }
4416c18ec02fSPetter Reinholdtsen /* TODO - rc is missing */
4417c18ec02fSPetter Reinholdtsen ipmi_fru_read_to_bin(intf, argv[2], fru_id);
4418c18ec02fSPetter Reinholdtsen }
4419c18ec02fSPetter Reinholdtsen else if (!strncmp(argv[0], "write", 5)) {
4420c18ec02fSPetter Reinholdtsen if (argc > 1 && strcmp(argv[1], "help") == 0) {
4421c18ec02fSPetter Reinholdtsen ipmi_fru_write_help();
4422c18ec02fSPetter Reinholdtsen return 0;
4423c18ec02fSPetter Reinholdtsen } else if (argc < 3) {
4424c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Not enough parameters given.");
4425c18ec02fSPetter Reinholdtsen ipmi_fru_write_help();
4426c18ec02fSPetter Reinholdtsen return (-1);
4427c18ec02fSPetter Reinholdtsen }
4428c18ec02fSPetter Reinholdtsen
4429c18ec02fSPetter Reinholdtsen if (is_fru_id(argv[1], &fru_id) != 0)
4430c18ec02fSPetter Reinholdtsen return (-1);
4431c18ec02fSPetter Reinholdtsen
4432c18ec02fSPetter Reinholdtsen /* There is a file name in the parameters */
4433c18ec02fSPetter Reinholdtsen if (is_valid_filename(argv[2]) != 0)
4434c18ec02fSPetter Reinholdtsen return (-1);
4435c18ec02fSPetter Reinholdtsen
4436c18ec02fSPetter Reinholdtsen if (verbose) {
4437c18ec02fSPetter Reinholdtsen printf("FRU ID : %d\n", fru_id);
4438c18ec02fSPetter Reinholdtsen printf("FRU File : %s\n", argv[2]);
4439c18ec02fSPetter Reinholdtsen }
4440c18ec02fSPetter Reinholdtsen /* TODO - rc is missing */
4441c18ec02fSPetter Reinholdtsen ipmi_fru_write_from_bin(intf, argv[2], fru_id);
4442c18ec02fSPetter Reinholdtsen }
4443c18ec02fSPetter Reinholdtsen else if (!strncmp(argv[0], "upgEkey", 7)) {
4444c18ec02fSPetter Reinholdtsen if (argc > 1 && strcmp(argv[1], "help") == 0) {
4445c18ec02fSPetter Reinholdtsen ipmi_fru_upgekey_help();
4446c18ec02fSPetter Reinholdtsen return 0;
4447c18ec02fSPetter Reinholdtsen } else if (argc < 3) {
4448c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Not enough parameters given.");
4449c18ec02fSPetter Reinholdtsen ipmi_fru_upgekey_help();
4450c18ec02fSPetter Reinholdtsen return (-1);
4451c18ec02fSPetter Reinholdtsen }
4452c18ec02fSPetter Reinholdtsen
4453c18ec02fSPetter Reinholdtsen if (is_fru_id(argv[1], &fru_id) != 0)
4454c18ec02fSPetter Reinholdtsen return (-1);
4455c18ec02fSPetter Reinholdtsen
4456c18ec02fSPetter Reinholdtsen /* There is a file name in the parameters */
4457c18ec02fSPetter Reinholdtsen if (is_valid_filename(argv[2]) != 0)
4458c18ec02fSPetter Reinholdtsen return (-1);
4459c18ec02fSPetter Reinholdtsen
4460c18ec02fSPetter Reinholdtsen rc = ipmi_fru_upg_ekeying(intf, argv[2], fru_id);
4461c18ec02fSPetter Reinholdtsen }
4462c18ec02fSPetter Reinholdtsen else if (!strncmp(argv[0], "internaluse", 11)) {
4463c18ec02fSPetter Reinholdtsen if (argc > 1 && strcmp(argv[1], "help") == 0) {
4464c18ec02fSPetter Reinholdtsen ipmi_fru_internaluse_help();
4465c18ec02fSPetter Reinholdtsen return 0;
4466c18ec02fSPetter Reinholdtsen }
4467c18ec02fSPetter Reinholdtsen
4468c18ec02fSPetter Reinholdtsen if ( (argc >= 3) && (!strncmp(argv[2], "info", 4)) ) {
4469c18ec02fSPetter Reinholdtsen
4470c18ec02fSPetter Reinholdtsen if (is_fru_id(argv[1], &fru_id) != 0)
4471c18ec02fSPetter Reinholdtsen return (-1);
4472c18ec02fSPetter Reinholdtsen
4473c18ec02fSPetter Reinholdtsen rc = ipmi_fru_info_internal_use(intf, fru_id);
4474c18ec02fSPetter Reinholdtsen }
4475c18ec02fSPetter Reinholdtsen else if ( (argc >= 3) && (!strncmp(argv[2], "print", 5)) ) {
4476c18ec02fSPetter Reinholdtsen
4477c18ec02fSPetter Reinholdtsen if (is_fru_id(argv[1], &fru_id) != 0)
4478c18ec02fSPetter Reinholdtsen return (-1);
4479c18ec02fSPetter Reinholdtsen
4480c18ec02fSPetter Reinholdtsen rc = ipmi_fru_read_internal_use(intf, fru_id, NULL);
4481c18ec02fSPetter Reinholdtsen }
4482c18ec02fSPetter Reinholdtsen else if ( (argc >= 4) && (!strncmp(argv[2], "read", 4)) ) {
4483c18ec02fSPetter Reinholdtsen
4484c18ec02fSPetter Reinholdtsen if (is_fru_id(argv[1], &fru_id) != 0)
4485c18ec02fSPetter Reinholdtsen return (-1);
4486c18ec02fSPetter Reinholdtsen
4487c18ec02fSPetter Reinholdtsen /* There is a file name in the parameters */
4488c18ec02fSPetter Reinholdtsen if (is_valid_filename(argv[3]) != 0)
4489c18ec02fSPetter Reinholdtsen return (-1);
4490c18ec02fSPetter Reinholdtsen
4491c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "FRU ID : %d", fru_id);
4492c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "FRU File : %s", argv[3]);
4493c18ec02fSPetter Reinholdtsen
4494c18ec02fSPetter Reinholdtsen rc = ipmi_fru_read_internal_use(intf, fru_id, argv[3]);
4495c18ec02fSPetter Reinholdtsen }
4496c18ec02fSPetter Reinholdtsen else if ( (argc >= 4) && (!strncmp(argv[2], "write", 5)) ) {
4497c18ec02fSPetter Reinholdtsen
4498c18ec02fSPetter Reinholdtsen if (is_fru_id(argv[1], &fru_id) != 0)
4499c18ec02fSPetter Reinholdtsen return (-1);
4500c18ec02fSPetter Reinholdtsen
4501c18ec02fSPetter Reinholdtsen /* There is a file name in the parameters */
4502c18ec02fSPetter Reinholdtsen if (is_valid_filename(argv[3]) != 0)
4503c18ec02fSPetter Reinholdtsen return (-1);
4504c18ec02fSPetter Reinholdtsen
4505c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "FRU ID : %d", fru_id);
4506c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "FRU File : %s", argv[3]);
4507c18ec02fSPetter Reinholdtsen
4508c18ec02fSPetter Reinholdtsen rc = ipmi_fru_write_internal_use(intf, fru_id, argv[3]);
4509c18ec02fSPetter Reinholdtsen } else {
4510c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
4511c18ec02fSPetter Reinholdtsen "Either unknown command or not enough parameters given.");
4512c18ec02fSPetter Reinholdtsen ipmi_fru_internaluse_help();
4513c18ec02fSPetter Reinholdtsen return (-1);
4514c18ec02fSPetter Reinholdtsen }
4515c18ec02fSPetter Reinholdtsen }
4516c18ec02fSPetter Reinholdtsen else if (!strncmp(argv[0], "edit", 4)) {
4517c18ec02fSPetter Reinholdtsen if (argc > 1 && strcmp(argv[1], "help") == 0) {
4518c18ec02fSPetter Reinholdtsen ipmi_fru_edit_help();
4519c18ec02fSPetter Reinholdtsen return 0;
4520c18ec02fSPetter Reinholdtsen } else if (argc < 2) {
4521c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Not enough parameters given.");
4522c18ec02fSPetter Reinholdtsen ipmi_fru_edit_help();
4523c18ec02fSPetter Reinholdtsen return (-1);
4524c18ec02fSPetter Reinholdtsen }
4525c18ec02fSPetter Reinholdtsen
4526c18ec02fSPetter Reinholdtsen if (argc >= 2) {
4527c18ec02fSPetter Reinholdtsen if (is_fru_id(argv[1], &fru_id) != 0)
4528c18ec02fSPetter Reinholdtsen return (-1);
4529c18ec02fSPetter Reinholdtsen
4530c18ec02fSPetter Reinholdtsen if (verbose) {
4531c18ec02fSPetter Reinholdtsen printf("FRU ID : %d\n", fru_id);
4532c18ec02fSPetter Reinholdtsen }
4533c18ec02fSPetter Reinholdtsen } else {
4534c18ec02fSPetter Reinholdtsen printf("Using default FRU ID: %d\n", fru_id);
4535c18ec02fSPetter Reinholdtsen }
4536c18ec02fSPetter Reinholdtsen
4537c18ec02fSPetter Reinholdtsen if (argc >= 3) {
4538c18ec02fSPetter Reinholdtsen if (!strncmp(argv[2], "field", 5)) {
4539c18ec02fSPetter Reinholdtsen if (argc != 6) {
4540c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Not enough parameters given.");
4541c18ec02fSPetter Reinholdtsen ipmi_fru_edit_help();
4542c18ec02fSPetter Reinholdtsen return (-1);
4543c18ec02fSPetter Reinholdtsen }
4544c18ec02fSPetter Reinholdtsen rc = ipmi_fru_set_field_string(intf, fru_id, *argv[3], *argv[4],
4545c18ec02fSPetter Reinholdtsen (char *) argv[5]);
4546c18ec02fSPetter Reinholdtsen } else if (!strncmp(argv[2], "oem", 3)) {
4547c18ec02fSPetter Reinholdtsen rc = ipmi_fru_edit_multirec(intf, fru_id, argc, argv);
4548c18ec02fSPetter Reinholdtsen } else {
4549c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Invalid command: %s", argv[2]);
4550c18ec02fSPetter Reinholdtsen ipmi_fru_edit_help();
4551c18ec02fSPetter Reinholdtsen return (-1);
4552c18ec02fSPetter Reinholdtsen }
4553c18ec02fSPetter Reinholdtsen } else {
4554c18ec02fSPetter Reinholdtsen rc = ipmi_fru_edit_multirec(intf, fru_id, argc, argv);
4555c18ec02fSPetter Reinholdtsen }
4556c18ec02fSPetter Reinholdtsen }
4557c18ec02fSPetter Reinholdtsen else if (!strncmp(argv[0], "get", 4)) {
4558c18ec02fSPetter Reinholdtsen if (argc > 1 && (strncmp(argv[1], "help", 4) == 0)) {
4559c18ec02fSPetter Reinholdtsen ipmi_fru_get_help();
4560c18ec02fSPetter Reinholdtsen return 0;
4561c18ec02fSPetter Reinholdtsen } else if (argc < 2) {
4562c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Not enough parameters given.");
4563c18ec02fSPetter Reinholdtsen ipmi_fru_get_help();
4564c18ec02fSPetter Reinholdtsen return (-1);
4565c18ec02fSPetter Reinholdtsen }
4566c18ec02fSPetter Reinholdtsen
4567c18ec02fSPetter Reinholdtsen if (argc >= 2) {
4568c18ec02fSPetter Reinholdtsen if (is_fru_id(argv[1], &fru_id) != 0)
4569c18ec02fSPetter Reinholdtsen return (-1);
4570c18ec02fSPetter Reinholdtsen
4571c18ec02fSPetter Reinholdtsen if (verbose) {
4572c18ec02fSPetter Reinholdtsen printf("FRU ID : %d\n", fru_id);
4573c18ec02fSPetter Reinholdtsen }
4574c18ec02fSPetter Reinholdtsen } else {
4575c18ec02fSPetter Reinholdtsen printf("Using default FRU ID: %d\n", fru_id);
4576c18ec02fSPetter Reinholdtsen }
4577c18ec02fSPetter Reinholdtsen
4578c18ec02fSPetter Reinholdtsen if (argc >= 3) {
4579c18ec02fSPetter Reinholdtsen if (!strncmp(argv[2], "oem", 3)) {
4580c18ec02fSPetter Reinholdtsen rc = ipmi_fru_get_multirec(intf, fru_id, argc, argv);
4581c18ec02fSPetter Reinholdtsen } else {
4582c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Invalid command: %s", argv[2]);
4583c18ec02fSPetter Reinholdtsen ipmi_fru_get_help();
4584c18ec02fSPetter Reinholdtsen return (-1);
4585c18ec02fSPetter Reinholdtsen }
4586c18ec02fSPetter Reinholdtsen } else {
4587c18ec02fSPetter Reinholdtsen rc = ipmi_fru_get_multirec(intf, fru_id, argc, argv);
4588c18ec02fSPetter Reinholdtsen }
4589c18ec02fSPetter Reinholdtsen }
4590c18ec02fSPetter Reinholdtsen else {
4591c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Invalid FRU command: %s", argv[0]);
4592c18ec02fSPetter Reinholdtsen ipmi_fru_help();
4593c18ec02fSPetter Reinholdtsen return (-1);
4594c18ec02fSPetter Reinholdtsen }
4595c18ec02fSPetter Reinholdtsen
4596c18ec02fSPetter Reinholdtsen return rc;
4597c18ec02fSPetter Reinholdtsen }
4598c18ec02fSPetter Reinholdtsen
4599c18ec02fSPetter Reinholdtsen /* ipmi_fru_set_field_string - Set a field string to a new value, Need to be the same size. If
4600c18ec02fSPetter Reinholdtsen * size if not equal, the function ipmi_fru_set_field_string_rebuild
4601c18ec02fSPetter Reinholdtsen * will be called.
4602c18ec02fSPetter Reinholdtsen *
4603c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
4604c18ec02fSPetter Reinholdtsen * @id: fru id
4605c18ec02fSPetter Reinholdtsen * @f_type: Type of the Field : c=Chassis b=Board p=Product
4606c18ec02fSPetter Reinholdtsen * @f_index: findex of the field, zero indexed.
4607c18ec02fSPetter Reinholdtsen * @f_string: NULL terminated string
4608c18ec02fSPetter Reinholdtsen *
4609c18ec02fSPetter Reinholdtsen * returns -1 on error
4610c18ec02fSPetter Reinholdtsen * returns 1 if successful
4611c18ec02fSPetter Reinholdtsen */
4612c18ec02fSPetter Reinholdtsen static int
ipmi_fru_set_field_string(struct ipmi_intf * intf,uint8_t fruId,uint8_t f_type,uint8_t f_index,char * f_string)4613c18ec02fSPetter Reinholdtsen ipmi_fru_set_field_string(struct ipmi_intf * intf, uint8_t fruId, uint8_t
4614c18ec02fSPetter Reinholdtsen f_type, uint8_t f_index, char *f_string)
4615c18ec02fSPetter Reinholdtsen {
4616c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
4617c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
4618c18ec02fSPetter Reinholdtsen
4619c18ec02fSPetter Reinholdtsen struct fru_info fru;
4620c18ec02fSPetter Reinholdtsen struct fru_header header;
4621c18ec02fSPetter Reinholdtsen uint8_t msg_data[4];
4622c18ec02fSPetter Reinholdtsen uint8_t checksum;
4623c18ec02fSPetter Reinholdtsen int i = 0;
4624c18ec02fSPetter Reinholdtsen int rc = 1;
4625c18ec02fSPetter Reinholdtsen uint8_t *fru_data = NULL;
4626c18ec02fSPetter Reinholdtsen uint8_t *fru_area = NULL;
4627c18ec02fSPetter Reinholdtsen uint32_t fru_field_offset, fru_field_offset_tmp;
4628c18ec02fSPetter Reinholdtsen uint32_t fru_section_len, header_offset;
4629c18ec02fSPetter Reinholdtsen
4630c18ec02fSPetter Reinholdtsen memset(msg_data, 0, 4);
4631c18ec02fSPetter Reinholdtsen msg_data[0] = fruId;
4632c18ec02fSPetter Reinholdtsen
4633c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
4634c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
4635c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_INFO;
4636c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
4637c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
4638c18ec02fSPetter Reinholdtsen
4639c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
4640c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
4641c18ec02fSPetter Reinholdtsen printf(" Device not present (No Response)\n");
4642c18ec02fSPetter Reinholdtsen rc = (-1);
4643c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4644c18ec02fSPetter Reinholdtsen }
4645c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) {
4646c18ec02fSPetter Reinholdtsen printf(" Device not present (%s)\n",
4647c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
4648c18ec02fSPetter Reinholdtsen rc = (-1);
4649c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4650c18ec02fSPetter Reinholdtsen }
4651c18ec02fSPetter Reinholdtsen
4652c18ec02fSPetter Reinholdtsen memset(&fru, 0, sizeof(fru));
4653c18ec02fSPetter Reinholdtsen fru.size = (rsp->data[1] << 8) | rsp->data[0];
4654c18ec02fSPetter Reinholdtsen fru.access = rsp->data[2] & 0x1;
4655c18ec02fSPetter Reinholdtsen
4656c18ec02fSPetter Reinholdtsen if (fru.size < 1) {
4657c18ec02fSPetter Reinholdtsen printf(" Invalid FRU size %d", fru.size);
4658c18ec02fSPetter Reinholdtsen rc = (-1);
4659c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4660c18ec02fSPetter Reinholdtsen }
4661c18ec02fSPetter Reinholdtsen /*
4662c18ec02fSPetter Reinholdtsen * retrieve the FRU header
4663c18ec02fSPetter Reinholdtsen */
4664c18ec02fSPetter Reinholdtsen msg_data[0] = fruId;
4665c18ec02fSPetter Reinholdtsen msg_data[1] = 0;
4666c18ec02fSPetter Reinholdtsen msg_data[2] = 0;
4667c18ec02fSPetter Reinholdtsen msg_data[3] = 8;
4668c18ec02fSPetter Reinholdtsen
4669c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
4670c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_STORAGE;
4671c18ec02fSPetter Reinholdtsen req.msg.cmd = GET_FRU_DATA;
4672c18ec02fSPetter Reinholdtsen req.msg.data = msg_data;
4673c18ec02fSPetter Reinholdtsen req.msg.data_len = 4;
4674c18ec02fSPetter Reinholdtsen
4675c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
4676c18ec02fSPetter Reinholdtsen if (rsp == NULL)
4677c18ec02fSPetter Reinholdtsen {
4678c18ec02fSPetter Reinholdtsen printf(" Device not present (No Response)\n");
4679c18ec02fSPetter Reinholdtsen rc = (-1);
4680c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4681c18ec02fSPetter Reinholdtsen }
4682c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0)
4683c18ec02fSPetter Reinholdtsen {
4684c18ec02fSPetter Reinholdtsen printf(" Device not present (%s)\n",
4685c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals));
4686c18ec02fSPetter Reinholdtsen rc = (-1);
4687c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4688c18ec02fSPetter Reinholdtsen }
4689c18ec02fSPetter Reinholdtsen
4690c18ec02fSPetter Reinholdtsen if (verbose > 1)
4691c18ec02fSPetter Reinholdtsen printbuf(rsp->data, rsp->data_len, "FRU DATA");
4692c18ec02fSPetter Reinholdtsen
4693c18ec02fSPetter Reinholdtsen memcpy(&header, rsp->data + 1, 8);
4694c18ec02fSPetter Reinholdtsen
4695c18ec02fSPetter Reinholdtsen if (header.version != 1)
4696c18ec02fSPetter Reinholdtsen {
4697c18ec02fSPetter Reinholdtsen printf(" Unknown FRU header version 0x%02x",
4698c18ec02fSPetter Reinholdtsen header.version);
4699c18ec02fSPetter Reinholdtsen rc = (-1);
4700c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4701c18ec02fSPetter Reinholdtsen }
4702c18ec02fSPetter Reinholdtsen
4703c18ec02fSPetter Reinholdtsen fru_data = malloc( fru.size );
4704c18ec02fSPetter Reinholdtsen
4705c18ec02fSPetter Reinholdtsen if( fru_data == NULL )
4706c18ec02fSPetter Reinholdtsen {
4707c18ec02fSPetter Reinholdtsen printf("Out of memory!\n");
4708c18ec02fSPetter Reinholdtsen rc = (-1);
4709c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4710c18ec02fSPetter Reinholdtsen }
4711c18ec02fSPetter Reinholdtsen
4712c18ec02fSPetter Reinholdtsen /* Setup offset from the field type */
4713c18ec02fSPetter Reinholdtsen
4714c18ec02fSPetter Reinholdtsen /* Chassis type field */
4715c18ec02fSPetter Reinholdtsen if (f_type == 'c' ) {
4716c18ec02fSPetter Reinholdtsen header_offset = (header.offset.chassis * 8);
4717c18ec02fSPetter Reinholdtsen read_fru_area(intf ,&fru, fruId, header_offset , 3 , fru_data);
4718166ae1daSZdenek Styblik fru_field_offset = 3;
4719166ae1daSZdenek Styblik fru_section_len = *(fru_data + 1) * 8;
4720c18ec02fSPetter Reinholdtsen }
4721c18ec02fSPetter Reinholdtsen /* Board type field */
4722c18ec02fSPetter Reinholdtsen else if (f_type == 'b' ) {
4723c18ec02fSPetter Reinholdtsen header_offset = (header.offset.board * 8);
4724c18ec02fSPetter Reinholdtsen read_fru_area(intf ,&fru, fruId, header_offset , 3 , fru_data);
4725166ae1daSZdenek Styblik fru_field_offset = 6;
4726166ae1daSZdenek Styblik fru_section_len = *(fru_data + 1) * 8;
4727c18ec02fSPetter Reinholdtsen }
4728c18ec02fSPetter Reinholdtsen /* Product type field */
4729c18ec02fSPetter Reinholdtsen else if (f_type == 'p' ) {
4730c18ec02fSPetter Reinholdtsen header_offset = (header.offset.product * 8);
4731c18ec02fSPetter Reinholdtsen read_fru_area(intf ,&fru, fruId, header_offset , 3 , fru_data);
4732166ae1daSZdenek Styblik fru_field_offset = 3;
4733166ae1daSZdenek Styblik fru_section_len = *(fru_data + 1) * 8;
4734c18ec02fSPetter Reinholdtsen }
4735c18ec02fSPetter Reinholdtsen else
4736c18ec02fSPetter Reinholdtsen {
4737c18ec02fSPetter Reinholdtsen printf("Wrong field type.");
4738c18ec02fSPetter Reinholdtsen rc = (-1);
4739c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4740c18ec02fSPetter Reinholdtsen }
4741c18ec02fSPetter Reinholdtsen memset(fru_data, 0, fru.size);
4742c18ec02fSPetter Reinholdtsen if( read_fru_area(intf ,&fru, fruId, header_offset ,
4743c18ec02fSPetter Reinholdtsen fru_section_len , fru_data) < 0 )
4744c18ec02fSPetter Reinholdtsen {
4745c18ec02fSPetter Reinholdtsen rc = (-1);
4746c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4747c18ec02fSPetter Reinholdtsen }
4748c18ec02fSPetter Reinholdtsen /* Convert index from character to decimal */
4749c18ec02fSPetter Reinholdtsen f_index= f_index - 0x30;
4750c18ec02fSPetter Reinholdtsen
4751c18ec02fSPetter Reinholdtsen /*Seek to field index */
4752c18ec02fSPetter Reinholdtsen for (i=0; i <= f_index; i++) {
4753c18ec02fSPetter Reinholdtsen fru_field_offset_tmp = fru_field_offset;
4754c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
4755c18ec02fSPetter Reinholdtsen free(fru_area);
4756c18ec02fSPetter Reinholdtsen fru_area = NULL;
4757c18ec02fSPetter Reinholdtsen }
4758c18ec02fSPetter Reinholdtsen fru_area = (uint8_t *) get_fru_area_str(fru_data, &fru_field_offset);
4759c18ec02fSPetter Reinholdtsen }
4760c18ec02fSPetter Reinholdtsen
4761c18ec02fSPetter Reinholdtsen if( (fru_area == NULL ) || strlen((const char *)fru_area) == 0 ) {
4762c18ec02fSPetter Reinholdtsen printf("Field not found !\n");
4763c18ec02fSPetter Reinholdtsen rc = (-1);
4764c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4765c18ec02fSPetter Reinholdtsen }
4766c18ec02fSPetter Reinholdtsen
4767c18ec02fSPetter Reinholdtsen if ( strlen((const char *)fru_area) == strlen((const char *)f_string) )
4768c18ec02fSPetter Reinholdtsen {
4769c18ec02fSPetter Reinholdtsen printf("Updating Field '%s' with '%s' ...\n", fru_area, f_string );
4770c18ec02fSPetter Reinholdtsen memcpy(fru_data + fru_field_offset_tmp + 1,
4771c18ec02fSPetter Reinholdtsen f_string, strlen(f_string));
4772c18ec02fSPetter Reinholdtsen
4773c18ec02fSPetter Reinholdtsen checksum = 0;
4774c18ec02fSPetter Reinholdtsen /* Calculate Header Checksum */
4775c18ec02fSPetter Reinholdtsen for( i = header_offset; i < header_offset
4776c18ec02fSPetter Reinholdtsen + fru_section_len - 1; i ++ )
4777c18ec02fSPetter Reinholdtsen {
4778c18ec02fSPetter Reinholdtsen checksum += fru_data[i];
4779c18ec02fSPetter Reinholdtsen }
4780c18ec02fSPetter Reinholdtsen checksum = (~checksum) + 1;
4781c18ec02fSPetter Reinholdtsen fru_data[header_offset + fru_section_len - 1] = checksum;
4782c18ec02fSPetter Reinholdtsen
4783eeeb973eSZdenek Styblik /* Write the updated section to the FRU data; source offset => 0 */
4784166ae1daSZdenek Styblik if( write_fru_area(intf, &fru, fruId, 0,
4785c18ec02fSPetter Reinholdtsen header_offset, fru_section_len, fru_data) < 0 )
4786c18ec02fSPetter Reinholdtsen {
4787c18ec02fSPetter Reinholdtsen printf("Write to FRU data failed.\n");
4788c18ec02fSPetter Reinholdtsen rc = (-1);
4789c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4790c18ec02fSPetter Reinholdtsen }
4791c18ec02fSPetter Reinholdtsen }
4792c18ec02fSPetter Reinholdtsen else {
4793c18ec02fSPetter Reinholdtsen printf("String size are not equal, resizing fru to fit new string\n");
4794c18ec02fSPetter Reinholdtsen if(
4795c18ec02fSPetter Reinholdtsen ipmi_fru_set_field_string_rebuild(intf,fruId,fru,header,f_type,f_index,f_string)
4796c18ec02fSPetter Reinholdtsen )
4797c18ec02fSPetter Reinholdtsen {
4798c18ec02fSPetter Reinholdtsen rc = (-1);
4799c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_out;
4800c18ec02fSPetter Reinholdtsen }
4801c18ec02fSPetter Reinholdtsen }
4802c18ec02fSPetter Reinholdtsen
4803c18ec02fSPetter Reinholdtsen ipmi_fru_set_field_string_out:
4804c18ec02fSPetter Reinholdtsen if (fru_data != NULL) {
4805c18ec02fSPetter Reinholdtsen free(fru_data);
4806c18ec02fSPetter Reinholdtsen fru_data = NULL;
4807c18ec02fSPetter Reinholdtsen }
4808c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
4809c18ec02fSPetter Reinholdtsen free(fru_area);
4810c18ec02fSPetter Reinholdtsen fru_area = NULL;
4811c18ec02fSPetter Reinholdtsen }
4812c18ec02fSPetter Reinholdtsen
4813c18ec02fSPetter Reinholdtsen return rc;
4814c18ec02fSPetter Reinholdtsen }
4815c18ec02fSPetter Reinholdtsen
4816c18ec02fSPetter Reinholdtsen /*
4817c18ec02fSPetter Reinholdtsen This function can update a string within of the following section when the size is not equal:
4818c18ec02fSPetter Reinholdtsen
4819c18ec02fSPetter Reinholdtsen Chassis
4820c18ec02fSPetter Reinholdtsen Product
4821c18ec02fSPetter Reinholdtsen Board
4822c18ec02fSPetter Reinholdtsen */
4823c18ec02fSPetter Reinholdtsen /* ipmi_fru_set_field_string_rebuild - Set a field string to a new value, When size are not
4824c18ec02fSPetter Reinholdtsen * the same size.
4825c18ec02fSPetter Reinholdtsen *
4826c18ec02fSPetter Reinholdtsen * This function can update a string within of the following section when the size is not equal:
4827c18ec02fSPetter Reinholdtsen *
4828c18ec02fSPetter Reinholdtsen * - Chassis
4829c18ec02fSPetter Reinholdtsen * - Product
4830c18ec02fSPetter Reinholdtsen * - Board
4831c18ec02fSPetter Reinholdtsen *
4832c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
4833c18ec02fSPetter Reinholdtsen * @fruId: fru id
4834c18ec02fSPetter Reinholdtsen * @fru: info about fru
4835c18ec02fSPetter Reinholdtsen * @header: contain the header of the FRU
4836c18ec02fSPetter Reinholdtsen * @f_type: Type of the Field : c=Chassis b=Board p=Product
4837c18ec02fSPetter Reinholdtsen * @f_index: findex of the field, zero indexed.
4838c18ec02fSPetter Reinholdtsen * @f_string: NULL terminated string
4839c18ec02fSPetter Reinholdtsen *
4840c18ec02fSPetter Reinholdtsen * returns -1 on error
4841c18ec02fSPetter Reinholdtsen * returns 1 if successful
4842c18ec02fSPetter Reinholdtsen */
4843c18ec02fSPetter Reinholdtsen
4844c18ec02fSPetter Reinholdtsen #define DBG_RESIZE_FRU
4845c18ec02fSPetter Reinholdtsen static int
ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf,uint8_t fruId,struct fru_info fru,struct fru_header header,uint8_t f_type,uint8_t f_index,char * f_string)4846c18ec02fSPetter Reinholdtsen ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
4847c18ec02fSPetter Reinholdtsen struct fru_info fru, struct fru_header header,
4848c18ec02fSPetter Reinholdtsen uint8_t f_type, uint8_t f_index, char *f_string)
4849c18ec02fSPetter Reinholdtsen {
4850c18ec02fSPetter Reinholdtsen int i = 0;
4851c18ec02fSPetter Reinholdtsen uint8_t *fru_data_old = NULL;
4852c18ec02fSPetter Reinholdtsen uint8_t *fru_data_new = NULL;
4853c18ec02fSPetter Reinholdtsen uint8_t *fru_area = NULL;
4854c18ec02fSPetter Reinholdtsen uint32_t fru_field_offset, fru_field_offset_tmp;
4855c18ec02fSPetter Reinholdtsen uint32_t fru_section_len, old_section_len, header_offset;
4856c18ec02fSPetter Reinholdtsen uint32_t chassis_offset, board_offset, product_offset;
4857c18ec02fSPetter Reinholdtsen uint32_t chassis_len, board_len, product_len, product_len_new;
4858c18ec02fSPetter Reinholdtsen int num_byte_change = 0, padding_len = 0;
4859c18ec02fSPetter Reinholdtsen uint32_t counter;
4860c18ec02fSPetter Reinholdtsen unsigned char cksum;
4861c18ec02fSPetter Reinholdtsen int rc = 1;
4862c18ec02fSPetter Reinholdtsen
4863c18ec02fSPetter Reinholdtsen fru_data_old = calloc( fru.size, sizeof(uint8_t) );
4864c18ec02fSPetter Reinholdtsen
4865c18ec02fSPetter Reinholdtsen fru_data_new = malloc( fru.size );
4866c18ec02fSPetter Reinholdtsen
4867c18ec02fSPetter Reinholdtsen if( fru_data_old == NULL || fru_data_new == NULL )
4868c18ec02fSPetter Reinholdtsen {
4869c18ec02fSPetter Reinholdtsen printf("Out of memory!\n");
4870c18ec02fSPetter Reinholdtsen rc = (-1);
4871c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_rebuild_out;
4872c18ec02fSPetter Reinholdtsen }
4873c18ec02fSPetter Reinholdtsen
4874c18ec02fSPetter Reinholdtsen /*************************
4875c18ec02fSPetter Reinholdtsen 1) Read ALL FRU */
4876c18ec02fSPetter Reinholdtsen printf("Read All FRU area\n");
4877c18ec02fSPetter Reinholdtsen printf("Fru Size : %u bytes\n", fru.size);
4878c18ec02fSPetter Reinholdtsen
4879c18ec02fSPetter Reinholdtsen /* Read current fru data */
4880c18ec02fSPetter Reinholdtsen read_fru_area(intf ,&fru, fruId, 0, fru.size , fru_data_old);
4881c18ec02fSPetter Reinholdtsen
4882c18ec02fSPetter Reinholdtsen #ifdef DBG_RESIZE_FRU
4883c18ec02fSPetter Reinholdtsen printf("Copy to new FRU\n");
4884c18ec02fSPetter Reinholdtsen #endif
4885c18ec02fSPetter Reinholdtsen
4886c18ec02fSPetter Reinholdtsen /*************************
4887c18ec02fSPetter Reinholdtsen 2) Copy all FRU to new FRU */
4888c18ec02fSPetter Reinholdtsen memcpy(fru_data_new, fru_data_old, fru.size);
4889c18ec02fSPetter Reinholdtsen
4890c18ec02fSPetter Reinholdtsen /* Build location of all modifiable components */
4891c18ec02fSPetter Reinholdtsen chassis_offset = (header.offset.chassis * 8);
4892c18ec02fSPetter Reinholdtsen board_offset = (header.offset.board * 8);
4893c18ec02fSPetter Reinholdtsen product_offset = (header.offset.product * 8);
4894c18ec02fSPetter Reinholdtsen
4895c18ec02fSPetter Reinholdtsen /* Retrieve length of all modifiable components */
4896c18ec02fSPetter Reinholdtsen chassis_len = *(fru_data_old + chassis_offset + 1) * 8;
4897c18ec02fSPetter Reinholdtsen board_len = *(fru_data_old + board_offset + 1) * 8;
4898c18ec02fSPetter Reinholdtsen product_len = *(fru_data_old + product_offset + 1) * 8;
4899c18ec02fSPetter Reinholdtsen product_len_new = product_len;
4900c18ec02fSPetter Reinholdtsen
4901c18ec02fSPetter Reinholdtsen /* Chassis type field */
4902c18ec02fSPetter Reinholdtsen if (f_type == 'c' )
4903c18ec02fSPetter Reinholdtsen {
4904c18ec02fSPetter Reinholdtsen header_offset = chassis_offset;
4905c18ec02fSPetter Reinholdtsen fru_field_offset = chassis_offset + 3;
4906c18ec02fSPetter Reinholdtsen fru_section_len = chassis_len;
4907c18ec02fSPetter Reinholdtsen }
4908c18ec02fSPetter Reinholdtsen /* Board type field */
4909c18ec02fSPetter Reinholdtsen else if (f_type == 'b' )
4910c18ec02fSPetter Reinholdtsen {
4911c18ec02fSPetter Reinholdtsen header_offset = board_offset;
4912c18ec02fSPetter Reinholdtsen fru_field_offset = board_offset + 6;
4913c18ec02fSPetter Reinholdtsen fru_section_len = board_len;
4914c18ec02fSPetter Reinholdtsen }
4915c18ec02fSPetter Reinholdtsen /* Product type field */
4916c18ec02fSPetter Reinholdtsen else if (f_type == 'p' )
4917c18ec02fSPetter Reinholdtsen {
4918c18ec02fSPetter Reinholdtsen header_offset = product_offset;
4919c18ec02fSPetter Reinholdtsen fru_field_offset = product_offset + 3;
4920c18ec02fSPetter Reinholdtsen fru_section_len = product_len;
4921c18ec02fSPetter Reinholdtsen }
4922c18ec02fSPetter Reinholdtsen else
4923c18ec02fSPetter Reinholdtsen {
4924c18ec02fSPetter Reinholdtsen printf("Wrong field type.");
4925c18ec02fSPetter Reinholdtsen rc = (-1);
4926c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_rebuild_out;
4927c18ec02fSPetter Reinholdtsen }
4928c18ec02fSPetter Reinholdtsen
4929c18ec02fSPetter Reinholdtsen /* Keep length for future old section display */
4930c18ec02fSPetter Reinholdtsen old_section_len = fru_section_len;
4931c18ec02fSPetter Reinholdtsen
4932c18ec02fSPetter Reinholdtsen /*************************
4933c18ec02fSPetter Reinholdtsen 3) Seek to field index */
4934c18ec02fSPetter Reinholdtsen for (i = 0;i <= f_index; i++) {
4935c18ec02fSPetter Reinholdtsen fru_field_offset_tmp = fru_field_offset;
4936c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
4937c18ec02fSPetter Reinholdtsen free(fru_area);
4938c18ec02fSPetter Reinholdtsen fru_area = NULL;
4939c18ec02fSPetter Reinholdtsen }
4940c18ec02fSPetter Reinholdtsen fru_area = (uint8_t *) get_fru_area_str(fru_data_old, &fru_field_offset);
4941c18ec02fSPetter Reinholdtsen }
4942c18ec02fSPetter Reinholdtsen
4943c18ec02fSPetter Reinholdtsen if( (fru_area == NULL ) || strlen((const char *)fru_area) == 0 ) {
4944c18ec02fSPetter Reinholdtsen printf("Field not found (1)!\n");
4945c18ec02fSPetter Reinholdtsen rc = (-1);
4946c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_rebuild_out;
4947c18ec02fSPetter Reinholdtsen }
4948c18ec02fSPetter Reinholdtsen
4949c18ec02fSPetter Reinholdtsen #ifdef DBG_RESIZE_FRU
4950c18ec02fSPetter Reinholdtsen printf("Section Length: %u\n", fru_section_len);
4951c18ec02fSPetter Reinholdtsen #endif
4952c18ec02fSPetter Reinholdtsen
4953c18ec02fSPetter Reinholdtsen /*************************
4954c18ec02fSPetter Reinholdtsen 4) Check number of padding bytes and bytes changed */
4955c18ec02fSPetter Reinholdtsen for(counter = 2; counter < fru_section_len; counter ++)
4956c18ec02fSPetter Reinholdtsen {
4957c18ec02fSPetter Reinholdtsen if(*(fru_data_old + (header_offset + fru_section_len - counter)) == 0)
4958c18ec02fSPetter Reinholdtsen padding_len ++;
4959c18ec02fSPetter Reinholdtsen else
4960c18ec02fSPetter Reinholdtsen break;
4961c18ec02fSPetter Reinholdtsen }
4962c18ec02fSPetter Reinholdtsen num_byte_change = strlen(f_string) - strlen(fru_area);
4963c18ec02fSPetter Reinholdtsen
4964c18ec02fSPetter Reinholdtsen #ifdef DBG_RESIZE_FRU
4965c18ec02fSPetter Reinholdtsen printf("Padding Length: %u\n", padding_len);
4966c18ec02fSPetter Reinholdtsen printf("NumByte Change: %i\n", num_byte_change);
4967c18ec02fSPetter Reinholdtsen printf("Start SecChnge: %x\n", *(fru_data_old + fru_field_offset_tmp));
4968c18ec02fSPetter Reinholdtsen printf("End SecChnge : %x\n", *(fru_data_old + fru_field_offset_tmp + strlen(f_string) + 1));
4969c18ec02fSPetter Reinholdtsen
4970c18ec02fSPetter Reinholdtsen printf("Start Section : %x\n", *(fru_data_old + header_offset));
4971c18ec02fSPetter Reinholdtsen printf("End Sec wo Pad: %x\n", *(fru_data_old + header_offset + fru_section_len - 2 - padding_len));
4972c18ec02fSPetter Reinholdtsen printf("End Section : %x\n", *(fru_data_old + header_offset + fru_section_len - 1));
4973c18ec02fSPetter Reinholdtsen #endif
4974c18ec02fSPetter Reinholdtsen
4975c18ec02fSPetter Reinholdtsen /* Calculate New Padding Length */
4976c18ec02fSPetter Reinholdtsen padding_len -= num_byte_change;
4977c18ec02fSPetter Reinholdtsen
4978c18ec02fSPetter Reinholdtsen #ifdef DBG_RESIZE_FRU
4979c18ec02fSPetter Reinholdtsen printf("New Padding Length: %i\n", padding_len);
4980c18ec02fSPetter Reinholdtsen #endif
4981c18ec02fSPetter Reinholdtsen
4982c18ec02fSPetter Reinholdtsen /*************************
4983c18ec02fSPetter Reinholdtsen 5) Check if section must be resize. This occur when padding length is not between 0 and 7 */
4984c18ec02fSPetter Reinholdtsen if( (padding_len < 0) || (padding_len >= 8))
4985c18ec02fSPetter Reinholdtsen {
4986c18ec02fSPetter Reinholdtsen uint32_t remaining_offset = ((header.offset.product * 8) + product_len);
4987c18ec02fSPetter Reinholdtsen int change_size_by_8;
4988c18ec02fSPetter Reinholdtsen
4989c18ec02fSPetter Reinholdtsen if(padding_len >= 8)
4990c18ec02fSPetter Reinholdtsen {
4991c18ec02fSPetter Reinholdtsen /* Section must be set smaller */
4992c18ec02fSPetter Reinholdtsen change_size_by_8 = ((padding_len) / 8) * (-1);
4993c18ec02fSPetter Reinholdtsen }
4994c18ec02fSPetter Reinholdtsen else
4995c18ec02fSPetter Reinholdtsen {
4996c18ec02fSPetter Reinholdtsen /* Section must be set bigger */
4997c18ec02fSPetter Reinholdtsen change_size_by_8 = 1 + (((padding_len+1) / 8) * (-1));
4998c18ec02fSPetter Reinholdtsen }
4999c18ec02fSPetter Reinholdtsen
5000c18ec02fSPetter Reinholdtsen /* Recalculate padding and section length base on the section changes */
5001c18ec02fSPetter Reinholdtsen fru_section_len += (change_size_by_8 * 8);
5002c18ec02fSPetter Reinholdtsen padding_len += (change_size_by_8 * 8);
5003c18ec02fSPetter Reinholdtsen
5004c18ec02fSPetter Reinholdtsen #ifdef DBG_RESIZE_FRU
5005c18ec02fSPetter Reinholdtsen printf("change_size_by_8: %i\n", change_size_by_8);
5006c18ec02fSPetter Reinholdtsen printf("New Padding Length: %i\n", padding_len);
5007c18ec02fSPetter Reinholdtsen printf("change_size_by_8: %i\n", change_size_by_8);
5008c18ec02fSPetter Reinholdtsen printf("header.offset.board: %i\n", header.offset.board);
5009c18ec02fSPetter Reinholdtsen #endif
5010c18ec02fSPetter Reinholdtsen
5011c18ec02fSPetter Reinholdtsen /* Must move sections */
5012c18ec02fSPetter Reinholdtsen /* Section that can be modified are as follow
5013c18ec02fSPetter Reinholdtsen Chassis
5014c18ec02fSPetter Reinholdtsen Board
5015c18ec02fSPetter Reinholdtsen product */
5016c18ec02fSPetter Reinholdtsen
5017c18ec02fSPetter Reinholdtsen /* Chassis type field */
5018c18ec02fSPetter Reinholdtsen if (f_type == 'c' )
5019c18ec02fSPetter Reinholdtsen {
5020c18ec02fSPetter Reinholdtsen printf("Moving Section Chassis, from %i to %i\n",
5021c18ec02fSPetter Reinholdtsen ((header.offset.board) * 8),
5022c18ec02fSPetter Reinholdtsen ((header.offset.board + change_size_by_8) * 8)
5023c18ec02fSPetter Reinholdtsen );
5024c18ec02fSPetter Reinholdtsen memcpy(
5025c18ec02fSPetter Reinholdtsen (fru_data_new + ((header.offset.board + change_size_by_8) * 8)),
5026c18ec02fSPetter Reinholdtsen (fru_data_old + (header.offset.board) * 8),
5027c18ec02fSPetter Reinholdtsen board_len
5028c18ec02fSPetter Reinholdtsen );
5029c18ec02fSPetter Reinholdtsen header.offset.board += change_size_by_8;
5030c18ec02fSPetter Reinholdtsen }
5031c18ec02fSPetter Reinholdtsen /* Board type field */
5032c18ec02fSPetter Reinholdtsen if ((f_type == 'c' ) || (f_type == 'b' ))
5033c18ec02fSPetter Reinholdtsen {
5034c18ec02fSPetter Reinholdtsen printf("Moving Section Product, from %i to %i\n",
5035c18ec02fSPetter Reinholdtsen ((header.offset.product) * 8),
5036c18ec02fSPetter Reinholdtsen ((header.offset.product + change_size_by_8) * 8)
5037c18ec02fSPetter Reinholdtsen );
5038c18ec02fSPetter Reinholdtsen memcpy(
5039c18ec02fSPetter Reinholdtsen (fru_data_new + ((header.offset.product + change_size_by_8) * 8)),
5040c18ec02fSPetter Reinholdtsen (fru_data_old + (header.offset.product) * 8),
5041c18ec02fSPetter Reinholdtsen product_len
5042c18ec02fSPetter Reinholdtsen );
5043c18ec02fSPetter Reinholdtsen header.offset.product += change_size_by_8;
5044c18ec02fSPetter Reinholdtsen }
5045c18ec02fSPetter Reinholdtsen
5046c18ec02fSPetter Reinholdtsen /* Adjust length of the section */
5047c18ec02fSPetter Reinholdtsen if (f_type == 'c')
5048c18ec02fSPetter Reinholdtsen {
5049c18ec02fSPetter Reinholdtsen *(fru_data_new + chassis_offset + 1) += change_size_by_8;
5050c18ec02fSPetter Reinholdtsen }
5051c18ec02fSPetter Reinholdtsen else if( f_type == 'b')
5052c18ec02fSPetter Reinholdtsen {
5053c18ec02fSPetter Reinholdtsen *(fru_data_new + board_offset + 1) += change_size_by_8;
5054c18ec02fSPetter Reinholdtsen }
5055c18ec02fSPetter Reinholdtsen else if( f_type == 'p')
5056c18ec02fSPetter Reinholdtsen {
5057c18ec02fSPetter Reinholdtsen *(fru_data_new + product_offset + 1) += change_size_by_8;
5058c18ec02fSPetter Reinholdtsen product_len_new = *(fru_data_new + product_offset + 1) * 8;
5059c18ec02fSPetter Reinholdtsen }
5060c18ec02fSPetter Reinholdtsen
5061c18ec02fSPetter Reinholdtsen /* Rebuild Header checksum */
5062c18ec02fSPetter Reinholdtsen {
5063c18ec02fSPetter Reinholdtsen unsigned char * pfru_header = (unsigned char *) &header;
5064c18ec02fSPetter Reinholdtsen header.checksum = 0;
5065c18ec02fSPetter Reinholdtsen for(counter = 0; counter < (sizeof(struct fru_header) -1); counter ++)
5066c18ec02fSPetter Reinholdtsen {
5067c18ec02fSPetter Reinholdtsen header.checksum += pfru_header[counter];
5068c18ec02fSPetter Reinholdtsen }
5069c18ec02fSPetter Reinholdtsen header.checksum = (0 - header.checksum);
5070c18ec02fSPetter Reinholdtsen memcpy(fru_data_new, pfru_header, sizeof(struct fru_header));
5071c18ec02fSPetter Reinholdtsen }
5072c18ec02fSPetter Reinholdtsen
5073c18ec02fSPetter Reinholdtsen /* Move remaining sections in 1 copy */
5074c18ec02fSPetter Reinholdtsen printf("Moving Remaining Bytes (Multi-Rec , etc..), from %i to %i\n",
5075c18ec02fSPetter Reinholdtsen remaining_offset,
5076c18ec02fSPetter Reinholdtsen ((header.offset.product) * 8) + product_len_new
5077c18ec02fSPetter Reinholdtsen );
5078c18ec02fSPetter Reinholdtsen if(((header.offset.product * 8) + product_len_new - remaining_offset) < 0)
5079c18ec02fSPetter Reinholdtsen {
5080c18ec02fSPetter Reinholdtsen memcpy(
5081c18ec02fSPetter Reinholdtsen fru_data_new + (header.offset.product * 8) + product_len_new,
5082c18ec02fSPetter Reinholdtsen fru_data_old + remaining_offset,
5083c18ec02fSPetter Reinholdtsen fru.size - remaining_offset
5084c18ec02fSPetter Reinholdtsen );
5085c18ec02fSPetter Reinholdtsen }
5086c18ec02fSPetter Reinholdtsen else
5087c18ec02fSPetter Reinholdtsen {
5088c18ec02fSPetter Reinholdtsen memcpy(
5089c18ec02fSPetter Reinholdtsen fru_data_new + (header.offset.product * 8) + product_len_new,
5090c18ec02fSPetter Reinholdtsen fru_data_old + remaining_offset,
5091c18ec02fSPetter Reinholdtsen fru.size - ((header.offset.product * 8) + product_len_new)
5092c18ec02fSPetter Reinholdtsen );
5093c18ec02fSPetter Reinholdtsen }
5094c18ec02fSPetter Reinholdtsen }
5095c18ec02fSPetter Reinholdtsen
5096c18ec02fSPetter Reinholdtsen /* Update only if it's fits padding length as defined in the spec, otherwise, it's an internal
5097c18ec02fSPetter Reinholdtsen error */
5098c18ec02fSPetter Reinholdtsen /*************************
5099c18ec02fSPetter Reinholdtsen 6) Update Field and sections */
5100c18ec02fSPetter Reinholdtsen if( (padding_len >=0) && (padding_len < 8))
5101c18ec02fSPetter Reinholdtsen {
5102c18ec02fSPetter Reinholdtsen /* Do not requires any change in other section */
5103c18ec02fSPetter Reinholdtsen
5104c18ec02fSPetter Reinholdtsen /* Change field length */
5105c18ec02fSPetter Reinholdtsen printf(
5106c18ec02fSPetter Reinholdtsen "Updating Field : '%s' with '%s' ... (Length from '%d' to '%d')\n",
5107c18ec02fSPetter Reinholdtsen fru_area, f_string,
5108c18ec02fSPetter Reinholdtsen (int)*(fru_data_old + fru_field_offset_tmp),
5109c18ec02fSPetter Reinholdtsen (int)(0xc0 + strlen(f_string)));
5110c18ec02fSPetter Reinholdtsen *(fru_data_new + fru_field_offset_tmp) = (0xc0 + strlen(f_string));
5111c18ec02fSPetter Reinholdtsen memcpy(fru_data_new + fru_field_offset_tmp + 1, f_string, strlen(f_string));
5112c18ec02fSPetter Reinholdtsen
5113c18ec02fSPetter Reinholdtsen /* Copy remaing bytes in section */
5114c18ec02fSPetter Reinholdtsen #ifdef DBG_RESIZE_FRU
5115c18ec02fSPetter Reinholdtsen printf("Copying remaining of sections: %d \n",
5116c18ec02fSPetter Reinholdtsen (int)((fru_data_old + header_offset + fru_section_len - 1) -
5117c18ec02fSPetter Reinholdtsen (fru_data_old + fru_field_offset_tmp + strlen(f_string) + 1)));
5118c18ec02fSPetter Reinholdtsen #endif
5119c18ec02fSPetter Reinholdtsen
5120c18ec02fSPetter Reinholdtsen memcpy((fru_data_new + fru_field_offset_tmp + 1 +
5121c18ec02fSPetter Reinholdtsen strlen(f_string)),
5122c18ec02fSPetter Reinholdtsen (fru_data_old + fru_field_offset_tmp + 1 +
5123c18ec02fSPetter Reinholdtsen strlen(fru_area)),
5124c18ec02fSPetter Reinholdtsen ((fru_data_old + header_offset + fru_section_len - 1) -
5125c18ec02fSPetter Reinholdtsen (fru_data_old + fru_field_offset_tmp + strlen(f_string) + 1)));
5126c18ec02fSPetter Reinholdtsen
5127c18ec02fSPetter Reinholdtsen /* Add Padding if required */
5128c18ec02fSPetter Reinholdtsen for(counter = 0; counter < padding_len; counter ++)
5129c18ec02fSPetter Reinholdtsen {
5130c18ec02fSPetter Reinholdtsen *(fru_data_new + header_offset + fru_section_len - 1 -
5131c18ec02fSPetter Reinholdtsen padding_len + counter) = 0;
5132c18ec02fSPetter Reinholdtsen }
5133c18ec02fSPetter Reinholdtsen
5134c18ec02fSPetter Reinholdtsen /* Calculate New Checksum */
5135c18ec02fSPetter Reinholdtsen cksum = 0;
5136c18ec02fSPetter Reinholdtsen for( counter = 0; counter <fru_section_len-1; counter ++ )
5137c18ec02fSPetter Reinholdtsen {
5138c18ec02fSPetter Reinholdtsen cksum += *(fru_data_new + header_offset + counter);
5139c18ec02fSPetter Reinholdtsen }
5140c18ec02fSPetter Reinholdtsen *(fru_data_new + header_offset + fru_section_len - 1) = (0 - cksum);
5141c18ec02fSPetter Reinholdtsen
5142c18ec02fSPetter Reinholdtsen #ifdef DBG_RESIZE_FRU
5143c18ec02fSPetter Reinholdtsen printf("Calculate New Checksum: %x\n", (0 - cksum));
5144c18ec02fSPetter Reinholdtsen #endif
5145c18ec02fSPetter Reinholdtsen
5146c18ec02fSPetter Reinholdtsen /****** ENABLE to show section modified before and after ********/
5147c18ec02fSPetter Reinholdtsen #if 0
5148c18ec02fSPetter Reinholdtsen printf("Section: ");
5149c18ec02fSPetter Reinholdtsen for( counter = 0; counter <old_section_len; counter ++ )
5150c18ec02fSPetter Reinholdtsen {
5151c18ec02fSPetter Reinholdtsen if((counter %16) == 0)
5152c18ec02fSPetter Reinholdtsen {
5153c18ec02fSPetter Reinholdtsen printf("\n");
5154c18ec02fSPetter Reinholdtsen }
5155c18ec02fSPetter Reinholdtsen printf( "%02X ", *(fru_data_old + header_offset + counter) );
5156c18ec02fSPetter Reinholdtsen }
5157c18ec02fSPetter Reinholdtsen printf("\n");
5158c18ec02fSPetter Reinholdtsen
5159c18ec02fSPetter Reinholdtsen printf("Section: ");
5160c18ec02fSPetter Reinholdtsen for( counter = 0; counter <fru_section_len; counter ++ )
5161c18ec02fSPetter Reinholdtsen {
5162c18ec02fSPetter Reinholdtsen if((counter %16) == 0)
5163c18ec02fSPetter Reinholdtsen {
5164c18ec02fSPetter Reinholdtsen printf("\n");
5165c18ec02fSPetter Reinholdtsen }
5166c18ec02fSPetter Reinholdtsen printf( "%02X ", *(fru_data_new + header_offset + counter) );
5167c18ec02fSPetter Reinholdtsen }
5168c18ec02fSPetter Reinholdtsen printf("\n");
5169c18ec02fSPetter Reinholdtsen #endif
5170c18ec02fSPetter Reinholdtsen }
5171c18ec02fSPetter Reinholdtsen else
5172c18ec02fSPetter Reinholdtsen {
5173c18ec02fSPetter Reinholdtsen printf( "Internal error, padding length %i (must be from 0 to 7) ", padding_len );
5174c18ec02fSPetter Reinholdtsen rc = (-1);
5175c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_rebuild_out;
5176c18ec02fSPetter Reinholdtsen }
5177c18ec02fSPetter Reinholdtsen
5178c18ec02fSPetter Reinholdtsen /*************************
5179c18ec02fSPetter Reinholdtsen 7) Finally, write new FRU */
5180c18ec02fSPetter Reinholdtsen printf("Writing new FRU.\n");
5181c18ec02fSPetter Reinholdtsen if( write_fru_area( intf, &fru, fruId, 0, 0, fru.size, fru_data_new ) < 0 )
5182c18ec02fSPetter Reinholdtsen {
5183c18ec02fSPetter Reinholdtsen printf("Write to FRU data failed.\n");
5184c18ec02fSPetter Reinholdtsen rc = (-1);
5185c18ec02fSPetter Reinholdtsen goto ipmi_fru_set_field_string_rebuild_out;
5186c18ec02fSPetter Reinholdtsen }
5187c18ec02fSPetter Reinholdtsen
5188c18ec02fSPetter Reinholdtsen printf("Done.\n");
5189c18ec02fSPetter Reinholdtsen
5190c18ec02fSPetter Reinholdtsen ipmi_fru_set_field_string_rebuild_out:
5191c18ec02fSPetter Reinholdtsen if (fru_area != NULL) {
5192c18ec02fSPetter Reinholdtsen free(fru_area);
5193c18ec02fSPetter Reinholdtsen fru_area = NULL;
5194c18ec02fSPetter Reinholdtsen }
5195c18ec02fSPetter Reinholdtsen if (fru_data_new != NULL) {
5196c18ec02fSPetter Reinholdtsen free(fru_data_new);
5197c18ec02fSPetter Reinholdtsen fru_data_new = NULL;
5198c18ec02fSPetter Reinholdtsen }
5199c18ec02fSPetter Reinholdtsen if (fru_data_old != NULL) {
5200c18ec02fSPetter Reinholdtsen free(fru_data_old);
5201c18ec02fSPetter Reinholdtsen fru_data_old = NULL;
5202c18ec02fSPetter Reinholdtsen }
5203c18ec02fSPetter Reinholdtsen
5204c18ec02fSPetter Reinholdtsen return rc;
5205c18ec02fSPetter Reinholdtsen }
5206