blob: 7bdf35fb1f6e1c6571731ef85e2e3069b3bccd41 [file] [log] [blame]
Hariharasubramanian R44473092015-10-15 08:25:28 -05001/*
2 * Copyright (C) 2003-2014 FreeIPMI Core Team
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05003 *
Hariharasubramanian R44473092015-10-15 08:25:28 -05004 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Hariharasubramanian Ra032c772015-10-20 07:28:19 -050016 *
Hariharasubramanian R44473092015-10-15 08:25:28 -050017 */
18/*****************************************************************************\
19 * Copyright (C) 2007-2014 Lawrence Livermore National Security, LLC.
20 * Copyright (C) 2007 The Regents of the University of California.
21 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
22 * Written by Albert Chu <chu11@llnl.gov>
23 * UCRL-CODE-232183
24 *
25 * This file is part of Ipmi-fru, a tool used for retrieving
26 * motherboard field replaceable unit (FRU) information. For details,
27 * see http://www.llnl.gov/linux/.
28 *
29 * Ipmi-fru is free software; you can redistribute it and/or modify
30 * it under the terms of the GNU General Public License as published by the
31 * Free Software Foundation; either version 3 of the License, or (at your
32 * option) any later version.
33 *
34 * Ipmi-fru is distributed in the hope that it will be useful, but
35 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
36 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37 * for more details.
38 *
39 * You should have received a copy of the GNU General Public License along
40 * with Ipmi-fru. If not, see <http://www.gnu.org/licenses/>.
41\*****************************************************************************/
42#include <stdio.h>
43#include <unistd.h>
44#include <string.h>
45#include <time.h>
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050046#include <systemd/sd-bus.h>
Hariharasubramanian Ra032c772015-10-20 07:28:19 -050047#include <ctype.h>
Hariharasubramanian R44473092015-10-15 08:25:28 -050048
49#define uint8_t unsigned char
50#define uint32_t unsigned int
51
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050052#define TEXTSTR(a) #a
53# define ASSERT(x) \
54do { \
55if (0 == (x)) { \
56fprintf(stderr, \
57"Assertion failed: %s, " \
58"%d at \'%s\'\n", \
59__FILE__, \
60__LINE__, \
61TEXTSTR(a)); \
62return -1; \
63} \
64} while (0)
Hariharasubramanian R44473092015-10-15 08:25:28 -050065
66#define IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX 512
67#define IPMI_FRU_SENTINEL_VALUE 0xC1
68#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK 0xC0
69#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT 0x06
70#define IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK 0x3F
71#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE 0x03
72
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050073/* OpenBMC defines for Parser */
74#define IPMI_FRU_AREA_INTERNAL_USE 0x00
75#define IPMI_FRU_AREA_CHASSIS_INFO 0x01
76#define IPMI_FRU_AREA_BOARD_INFO 0x02
77#define IPMI_FRU_AREA_PRODUCT_INFO 0x03
78#define IPMI_FRU_AREA_MULTI_RECORD 0x04
79#define IPMI_FRU_AREA_TYPE_MAX 0x05
80
81#define OPENBMC_VPD_KEY_LEN 64
82#define OPENBMC_VPD_VAL_LEN 512
Hariharasubramanian R44473092015-10-15 08:25:28 -050083
84struct ipmi_fru_field
85{
86 uint8_t type_length_field[IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX];
87 /* store length of data stored in buffer */
88 unsigned int type_length_field_length;
89};
90
91typedef struct ipmi_fru_field ipmi_fru_field_t;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -050092/*
93 * FRU Parser
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050094 */
Hariharasubramanian R44473092015-10-15 08:25:28 -050095
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050096typedef struct ipmi_fru_area_info
97{
98 uint8_t off;
99 uint8_t len;
100} ipmi_fru_area_info_t;
101
102typedef struct ipmi_fru_common_hdr
103{
104 uint8_t fmtver;
105 uint8_t internal;
106 uint8_t chassis;
107 uint8_t board;
108 uint8_t product;
109 uint8_t multirec;
110} __attribute__((packed)) ipmi_fru_common_hdr_t;
111
112enum openbmc_vpd_key_id
113{
114 OPENBMC_VPD_KEY_CHASSIS_TYPE = 1, /* not a type/len */
115 OPENBMC_VPD_KEY_CHASSIS_PART_NUM,
116 OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500117 OPENBMC_VPD_KEY_CHASSIS_CUSTOM1,
118 OPENBMC_VPD_KEY_CHASSIS_CUSTOM2,
119 OPENBMC_VPD_KEY_CHASSIS_CUSTOM3,
120 OPENBMC_VPD_KEY_CHASSIS_CUSTOM4,
121 OPENBMC_VPD_KEY_CHASSIS_CUSTOM5,
122 OPENBMC_VPD_KEY_CHASSIS_CUSTOM6,
123 OPENBMC_VPD_KEY_CHASSIS_CUSTOM7,
124 OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,
125 OPENBMC_VPD_KEY_CHASSIS_MAX = OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500126 /* TODO: chassis_custom_fields */
127
128 OPENBMC_VPD_KEY_BOARD_MFG_DATE, /* not a type/len */
129 OPENBMC_VPD_KEY_BOARD_MFR,
130 OPENBMC_VPD_KEY_BOARD_NAME,
131 OPENBMC_VPD_KEY_BOARD_SERIAL_NUM,
132 OPENBMC_VPD_KEY_BOARD_PART_NUM,
133 OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID,
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500134 OPENBMC_VPD_KEY_BOARD_CUSTOM1,
135 OPENBMC_VPD_KEY_BOARD_CUSTOM2,
136 OPENBMC_VPD_KEY_BOARD_CUSTOM3,
137 OPENBMC_VPD_KEY_BOARD_CUSTOM4,
138 OPENBMC_VPD_KEY_BOARD_CUSTOM5,
139 OPENBMC_VPD_KEY_BOARD_CUSTOM6,
140 OPENBMC_VPD_KEY_BOARD_CUSTOM7,
141 OPENBMC_VPD_KEY_BOARD_CUSTOM8,
142 OPENBMC_VPD_KEY_BOARD_MAX = OPENBMC_VPD_KEY_BOARD_CUSTOM8,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500143 /* TODO: board_custom_fields */
144
145 OPENBMC_VPD_KEY_PRODUCT_MFR,
146 OPENBMC_VPD_KEY_PRODUCT_NAME,
147 OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM,
148 OPENBMC_VPD_KEY_PRODUCT_VER,
149 OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM,
150 OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG,
151 OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID,
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500152 OPENBMC_VPD_KEY_PRODUCT_CUSTOM1,
153 OPENBMC_VPD_KEY_PRODUCT_CUSTOM2,
154 OPENBMC_VPD_KEY_PRODUCT_CUSTOM3,
155 OPENBMC_VPD_KEY_PRODUCT_CUSTOM4,
156 OPENBMC_VPD_KEY_PRODUCT_CUSTOM5,
157 OPENBMC_VPD_KEY_PRODUCT_CUSTOM6,
158 OPENBMC_VPD_KEY_PRODUCT_CUSTOM7,
159 OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,
160 OPENBMC_VPD_KEY_PRODUCT_MAX = OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500161
162 OPENBMC_VPD_KEY_MAX,
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500163 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX=8,
164
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500165};
166
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500167const char* vpd_key_names [] =
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500168{
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500169 "Key Names Table Start",
170 "Type", /*OPENBMC_VPD_KEY_CHASSIS_TYPE*/
171 "Part Number", /*OPENBMC_VPD_KEY_CHASSIS_PART_NUM,*/
172 "Serial Number", /*OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,*/
173 "Custom Field 1", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM1,*/
174 "Custom Field 2", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM2,*/
175 "Custom Field 3", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM3,*/
176 "Custom Field 4", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM4,*/
177 "Custom Field 5", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM5,*/
178 "Custom Field 6", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM6,*/
179 "Custom Field 7", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM7,*/
180 "Custom Field 8", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500181
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500182 "Mfg Date", /* OPENBMC_VPD_KEY_BOARD_MFG_DATE, */ /* not a type/len */
183 "Manufacturer", /* OPENBMC_VPD_KEY_BOARD_MFR, */
184 "Name", /* OPENBMC_VPD_KEY_BOARD_NAME, */
185 "Serial Number", /* OPENBMC_VPD_KEY_BOARD_SERIAL_NUM, */
186 "Part Number", /* OPENBMC_VPD_KEY_BOARD_PART_NUM, */
187 "FRU File ID", /* OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID, */
188 "Custom Field 1", /*OPENBMC_VPD_KEY_BOARD_CUSTOM1,*/
189 "Custom Field 2", /*OPENBMC_VPD_KEY_BOARD_CUSTOM2,*/
190 "Custom Field 3", /*OPENBMC_VPD_KEY_BOARD_CUSTOM3,*/
191 "Custom Field 4", /*OPENBMC_VPD_KEY_BOARD_CUSTOM4,*/
192 "Custom Field 5", /*OPENBMC_VPD_KEY_BOARD_CUSTOM5,*/
193 "Custom Field 6", /*OPENBMC_VPD_KEY_BOARD_CUSTOM6,*/
194 "Custom Field 7", /*OPENBMC_VPD_KEY_BOARD_CUSTOM7,*/
195 "Custom Field 8", /*OPENBMC_VPD_KEY_BOARD_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500196
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500197 "Manufacturer", /* OPENBMC_VPD_KEY_PRODUCT_MFR, */
198 "Name", /* OPENBMC_VPD_KEY_PRODUCT_NAME, */
199 "Model Number", /* OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM, */
200 "Version", /* OPENBMC_VPD_KEY_PRODUCT_VER, */
201 "Serial Number", /* OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM, */
202 "Asset Tag", /* OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG, */
203 "FRU File ID", /* OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID, */
204 "Custom Field 1", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM1,*/
205 "Custom Field 2", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM2,*/
206 "Custom Field 3", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM3,*/
207 "Custom Field 4", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM4,*/
208 "Custom Field 5", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM5,*/
209 "Custom Field 6", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM6,*/
210 "Custom Field 7", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM7,*/
211 "Custom Field 8", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500212
213 "Key Names Table End" /*OPENBMC_VPD_KEY_MAX,*/
214};
215
216
217/*
218 * --------------------------------------------------------------------
219 *
220 * --------------------------------------------------------------------
221 */
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500222
223static size_t _to_time_str (uint32_t mfg_date_time, char* timestr, uint32_t len)
224{
225 struct tm tm;
226 time_t t;
227 size_t s;
228
229 ASSERT (timestr);
230 ASSERT (len);
231
232 memset (&tm, '\0', sizeof (struct tm));
233
234 t = mfg_date_time;
235 gmtime_r (&t, &tm);
236 s = strftime (timestr, len, "%F - %H:%M:%S", &tm);
237
238 return s;
239}
240
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500241/* private method to parse type/length */
Hariharasubramanian R44473092015-10-15 08:25:28 -0500242static int
243_parse_type_length (const void *areabuf,
244 unsigned int areabuflen,
245 unsigned int current_area_offset,
246 uint8_t *number_of_data_bytes,
247 ipmi_fru_field_t *field)
248{
249 const uint8_t *areabufptr = (const uint8_t*) areabuf;
250 uint8_t type_length;
251 uint8_t type_code;
252
253 ASSERT (areabuf);
254 ASSERT (areabuflen);
255 ASSERT (number_of_data_bytes);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500256
Hariharasubramanian R44473092015-10-15 08:25:28 -0500257 type_length = areabufptr[current_area_offset];
258
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500259 /* ipmi workaround
Hariharasubramanian R44473092015-10-15 08:25:28 -0500260 *
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500261 * dell p weredge r610
Hariharasubramanian R44473092015-10-15 08:25:28 -0500262 *
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500263 * my reading of the fru spec is that all non-custom fields are
264 * required to be listed by the vendor. however, on this
Hariharasubramanian R44473092015-10-15 08:25:28 -0500265 * motherboard, some areas list this, indicating that there is
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500266 * no more data to be parsed. so now, for "required" fields, i
Hariharasubramanian R44473092015-10-15 08:25:28 -0500267 * check to see if the type-length field is a sentinel before
268 * calling this function.
269 */
270
271 ASSERT (type_length != IPMI_FRU_SENTINEL_VALUE);
272
273 type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >> IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
274 (*number_of_data_bytes) = type_length & IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
275
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500276 /* special case: this shouldn't be a length of 0x01 (see type/length
277 * byte format in fru information storage definition).
Hariharasubramanian R44473092015-10-15 08:25:28 -0500278 */
279 if (type_code == IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE
280 && (*number_of_data_bytes) == 0x01)
281 {
282 return (-1);
283 }
284
285 if ((current_area_offset + 1 + (*number_of_data_bytes)) > areabuflen)
286 {
287 return (-1);
288 }
289
290 if (field)
291 {
292 memset (field->type_length_field,
293 '\0',
294 IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
295 memcpy (field->type_length_field,
296 &areabufptr[current_area_offset],
297 1 + (*number_of_data_bytes));
298 field->type_length_field_length = 1 + (*number_of_data_bytes);
299 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500300
Hariharasubramanian R44473092015-10-15 08:25:28 -0500301 return (0);
302}
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500303
Hariharasubramanian R44473092015-10-15 08:25:28 -0500304int
305ipmi_fru_chassis_info_area (const void *areabuf,
306 unsigned int areabuflen,
307 uint8_t *chassis_type,
308 ipmi_fru_field_t *chassis_part_number,
309 ipmi_fru_field_t *chassis_serial_number,
310 ipmi_fru_field_t *chassis_custom_fields,
311 unsigned int chassis_custom_fields_len)
312{
313 const uint8_t *areabufptr = (const uint8_t*) areabuf;
314 unsigned int area_offset = 0;
315 unsigned int custom_fields_index = 0;
316 uint8_t number_of_data_bytes;
317 int rv = -1;
318
319 if (!areabuf || !areabuflen)
320 {
321 return (-1);
322 }
323
324 if (chassis_part_number)
325 memset (chassis_part_number,
326 '\0',
327 sizeof (ipmi_fru_field_t));
328 if (chassis_serial_number)
329 memset (chassis_serial_number,
330 '\0',
331 sizeof (ipmi_fru_field_t));
332 if (chassis_custom_fields && chassis_custom_fields_len)
333 memset (chassis_custom_fields,
334 '\0',
335 sizeof (ipmi_fru_field_t) * chassis_custom_fields_len);
336
337 if (chassis_type)
338 (*chassis_type) = areabufptr[area_offset];
339 area_offset++;
340
341 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
342 goto out;
343
344 if (_parse_type_length (areabufptr,
345 areabuflen,
346 area_offset,
347 &number_of_data_bytes,
348 chassis_part_number) < 0)
349 goto cleanup;
350 area_offset += 1; /* type/length byte */
351 area_offset += number_of_data_bytes;
352
353 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
354 goto out;
355
356 if (_parse_type_length (areabufptr,
357 areabuflen,
358 area_offset,
359 &number_of_data_bytes,
360 chassis_serial_number) < 0)
361 goto cleanup;
362 area_offset += 1; /* type/length byte */
363 area_offset += number_of_data_bytes;
364
365 while (area_offset < areabuflen
366 && areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
367 {
368 ipmi_fru_field_t *field_ptr = NULL;
369
370 if (chassis_custom_fields && chassis_custom_fields_len)
371 {
372 if (custom_fields_index < chassis_custom_fields_len)
373 field_ptr = &chassis_custom_fields[custom_fields_index];
374 else
375 {
376 goto cleanup;
377 }
378 }
379
380 if (_parse_type_length (areabufptr,
381 areabuflen,
382 area_offset,
383 &number_of_data_bytes,
384 field_ptr) < 0)
385 goto cleanup;
386
387 area_offset += 1; /* type/length byte */
388 area_offset += number_of_data_bytes;
389 custom_fields_index++;
390 }
391
392
393 out:
394 rv = 0;
395 cleanup:
396 return (rv);
397}
398
399int
400ipmi_fru_board_info_area (const void *areabuf,
401 unsigned int areabuflen,
402 uint8_t *language_code,
403 uint32_t *mfg_date_time,
404 ipmi_fru_field_t *board_manufacturer,
405 ipmi_fru_field_t *board_product_name,
406 ipmi_fru_field_t *board_serial_number,
407 ipmi_fru_field_t *board_part_number,
408 ipmi_fru_field_t *board_fru_file_id,
409 ipmi_fru_field_t *board_custom_fields,
410 unsigned int board_custom_fields_len)
411{
412 const uint8_t *areabufptr = (const uint8_t*) areabuf;
413 uint32_t mfg_date_time_tmp = 0;
414 unsigned int area_offset = 0;
415 unsigned int custom_fields_index = 0;
416 uint8_t number_of_data_bytes;
417 int rv = -1;
418
419 if (!areabuf || !areabuflen)
420 {
421 return (-1);
422 }
423
424 if (board_manufacturer)
425 memset (board_manufacturer,
426 '\0',
427 sizeof (ipmi_fru_field_t));
428 if (board_product_name)
429 memset (board_product_name,
430 '\0',
431 sizeof (ipmi_fru_field_t));
432 if (board_serial_number)
433 memset (board_serial_number,
434 '\0',
435 sizeof (ipmi_fru_field_t));
436 if (board_part_number)
437 memset (board_part_number,
438 '\0',
439 sizeof (ipmi_fru_field_t));
440 if (board_fru_file_id)
441 memset (board_fru_file_id,
442 '\0',
443 sizeof (ipmi_fru_field_t));
444 if (board_custom_fields && board_custom_fields_len)
445 memset (board_custom_fields,
446 '\0',
447 sizeof (ipmi_fru_field_t) * board_custom_fields_len);
448
449 if (language_code)
450 (*language_code) = areabufptr[area_offset];
451 area_offset++;
452
453 if (mfg_date_time)
454 {
455 struct tm tm;
456 time_t t;
457
458 /* mfg_date_time is little endian - see spec */
459 mfg_date_time_tmp |= areabufptr[area_offset];
460 area_offset++;
461 mfg_date_time_tmp |= (areabufptr[area_offset] << 8);
462 area_offset++;
463 mfg_date_time_tmp |= (areabufptr[area_offset] << 16);
464 area_offset++;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500465
Hariharasubramanian R44473092015-10-15 08:25:28 -0500466 /* mfg_date_time is in minutes, so multiple by 60 to get seconds */
467 mfg_date_time_tmp *= 60;
468
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500469 /* posix says individual calls need not clear/set all portions of
Hariharasubramanian R44473092015-10-15 08:25:28 -0500470 * 'struct tm', thus passing 'struct tm' between functions could
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500471 * have issues. so we need to memset.
Hariharasubramanian R44473092015-10-15 08:25:28 -0500472 */
473 memset (&tm, '\0', sizeof(struct tm));
474
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500475 /* in fru, epoch is 0:00 hrs 1/1/96
Hariharasubramanian R44473092015-10-15 08:25:28 -0500476 *
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500477 * so convert into ansi epoch
Hariharasubramanian R44473092015-10-15 08:25:28 -0500478 */
479
480 tm.tm_year = 96; /* years since 1900 */
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500481 tm.tm_mon = 0; /* months since january */
Hariharasubramanian R44473092015-10-15 08:25:28 -0500482 tm.tm_mday = 1; /* 1-31 */
483 tm.tm_hour = 0;
484 tm.tm_min = 0;
485 tm.tm_sec = 0;
486 tm.tm_isdst = -1;
487
488 if ((t = mktime (&tm)) == (time_t)-1)
489 {
490 goto cleanup;
491 }
492
493 mfg_date_time_tmp += (uint32_t)t;
494 (*mfg_date_time) = mfg_date_time_tmp;
495 }
496 else
497 area_offset += 3;
498
499 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
500 goto out;
501
502 if (_parse_type_length (areabufptr,
503 areabuflen,
504 area_offset,
505 &number_of_data_bytes,
506 board_manufacturer) < 0)
507 goto cleanup;
508 area_offset += 1; /* type/length byte */
509 area_offset += number_of_data_bytes;
510
511 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
512 goto out;
513
514 if (_parse_type_length (areabufptr,
515 areabuflen,
516 area_offset,
517 &number_of_data_bytes,
518 board_product_name) < 0)
519 goto cleanup;
520 area_offset += 1; /* type/length byte */
521 area_offset += number_of_data_bytes;
522
523 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
524 goto out;
525
526 if (_parse_type_length (areabufptr,
527 areabuflen,
528 area_offset,
529 &number_of_data_bytes,
530 board_serial_number) < 0)
531 goto cleanup;
532 area_offset += 1; /* type/length byte */
533 area_offset += number_of_data_bytes;
534
535 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
536 goto out;
537
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500538 if (_parse_type_length (areabufptr,
Hariharasubramanian R44473092015-10-15 08:25:28 -0500539 areabuflen,
540 area_offset,
541 &number_of_data_bytes,
542 board_part_number) < 0)
543 goto cleanup;
544 area_offset += 1; /* type/length byte */
545 area_offset += number_of_data_bytes;
546
547 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
548 goto out;
549
550 if (_parse_type_length (areabufptr,
551 areabuflen,
552 area_offset,
553 &number_of_data_bytes,
554 board_fru_file_id) < 0)
555 goto cleanup;
556 area_offset += 1; /* type/length byte */
557 area_offset += number_of_data_bytes;
558
559 while (area_offset < areabuflen
560 && areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
561 {
562 ipmi_fru_field_t *field_ptr = NULL;
563
564 if (board_custom_fields && board_custom_fields_len)
565 {
566 if (custom_fields_index < board_custom_fields_len)
567 field_ptr = &board_custom_fields[custom_fields_index];
568 else
569 {
570 goto cleanup;
571 }
572 }
573
574 if (_parse_type_length (areabufptr,
575 areabuflen,
576 area_offset,
577 &number_of_data_bytes,
578 field_ptr) < 0)
579 goto cleanup;
580
581 area_offset += 1; /* type/length byte */
582 area_offset += number_of_data_bytes;
583 custom_fields_index++;
584 }
585
586 out:
587 rv = 0;
588 cleanup:
589 return (rv);
590}
591
592int
593ipmi_fru_product_info_area (const void *areabuf,
594 unsigned int areabuflen,
595 uint8_t *language_code,
596 ipmi_fru_field_t *product_manufacturer_name,
597 ipmi_fru_field_t *product_name,
598 ipmi_fru_field_t *product_part_model_number,
599 ipmi_fru_field_t *product_version,
600 ipmi_fru_field_t *product_serial_number,
601 ipmi_fru_field_t *product_asset_tag,
602 ipmi_fru_field_t *product_fru_file_id,
603 ipmi_fru_field_t *product_custom_fields,
604 unsigned int product_custom_fields_len)
605{
606 const uint8_t *areabufptr = (const uint8_t*) areabuf;
607 unsigned int area_offset = 0;
608 unsigned int custom_fields_index = 0;
609 uint8_t number_of_data_bytes;
610 int rv = -1;
611
612 if (!areabuf || !areabuflen)
613 {
614 return (-1);
615 }
616
617 if (product_manufacturer_name)
618 memset (product_manufacturer_name,
619 '\0',
620 sizeof (ipmi_fru_field_t));
621 if (product_name)
622 memset (product_name,
623 '\0',
624 sizeof (ipmi_fru_field_t));
625 if (product_part_model_number)
626 memset (product_part_model_number,
627 '\0',
628 sizeof (ipmi_fru_field_t));
629 if (product_version)
630 memset (product_version,
631 '\0',
632 sizeof (ipmi_fru_field_t));
633 if (product_serial_number)
634 memset (product_serial_number,
635 '\0',
636 sizeof (ipmi_fru_field_t));
637 if (product_asset_tag)
638 memset (product_asset_tag,
639 '\0',
640 sizeof (ipmi_fru_field_t));
641 if (product_fru_file_id)
642 memset (product_fru_file_id,
643 '\0',
644 sizeof (ipmi_fru_field_t));
645 if (product_custom_fields && product_custom_fields_len)
646 memset (product_custom_fields,
647 '\0',
648 sizeof (ipmi_fru_field_t) * product_custom_fields_len);
649
650 if (language_code)
651 (*language_code) = areabufptr[area_offset];
652 area_offset++;
653
654 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
655 goto out;
656
657 if (_parse_type_length (areabufptr,
658 areabuflen,
659 area_offset,
660 &number_of_data_bytes,
661 product_manufacturer_name) < 0)
662 goto cleanup;
663 area_offset += 1; /* type/length byte */
664 area_offset += number_of_data_bytes;
665
666 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
667 goto out;
668
669 if (_parse_type_length (areabufptr,
670 areabuflen,
671 area_offset,
672 &number_of_data_bytes,
673 product_name) < 0)
674 goto cleanup;
675 area_offset += 1; /* type/length byte */
676 area_offset += number_of_data_bytes;
677
678 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
679 goto out;
680
681 if (_parse_type_length (areabufptr,
682 areabuflen,
683 area_offset,
684 &number_of_data_bytes,
685 product_part_model_number) < 0)
686 goto cleanup;
687 area_offset += 1; /* type/length byte */
688 area_offset += number_of_data_bytes;
689
690 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
691 goto out;
692
693 if (_parse_type_length (areabufptr,
694 areabuflen,
695 area_offset,
696 &number_of_data_bytes,
697 product_version) < 0)
698 goto cleanup;
699 area_offset += 1; /* type/length byte */
700 area_offset += number_of_data_bytes;
701
702 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
703 goto out;
704
705 if (_parse_type_length (areabufptr,
706 areabuflen,
707 area_offset,
708 &number_of_data_bytes,
709 product_serial_number) < 0)
710 goto cleanup;
711 area_offset += 1; /* type/length byte */
712 area_offset += number_of_data_bytes;
713
714 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
715 goto out;
716
717 if (_parse_type_length (areabufptr,
718 areabuflen,
719 area_offset,
720 &number_of_data_bytes,
721 product_asset_tag) < 0)
722 goto cleanup;
723 area_offset += 1; /* type/length byte */
724 area_offset += number_of_data_bytes;
725
726 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
727 goto out;
728
729 if (_parse_type_length (areabufptr,
730 areabuflen,
731 area_offset,
732 &number_of_data_bytes,
733 product_fru_file_id) < 0)
734 goto cleanup;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500735
Hariharasubramanian R44473092015-10-15 08:25:28 -0500736 area_offset += 1; /* type/length byte */
737 area_offset += number_of_data_bytes;
738
739 while (area_offset < areabuflen
740 && areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
741 {
742 ipmi_fru_field_t *field_ptr = NULL;
743
744 if (product_custom_fields && product_custom_fields_len)
745 {
746 if (custom_fields_index < product_custom_fields_len)
747 field_ptr = &product_custom_fields[custom_fields_index];
748 else
749 {
750 goto cleanup;
751 }
752 }
753
754 if (_parse_type_length (areabufptr,
755 areabuflen,
756 area_offset,
757 &number_of_data_bytes,
758 field_ptr) < 0)
759 goto cleanup;
760
761 area_offset += 1; /* type/length byte */
762 area_offset += number_of_data_bytes;
763 custom_fields_index++;
764 }
765
766
767 out:
768 rv = 0;
769 cleanup:
770 return (rv);
771}
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500772
773
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500774int _append_to_dict (uint8_t vpd_key_id, uint8_t* vpd_key_val, sd_bus_message* vpdtbl)
775{
776 int type_length = vpd_key_val[0];
777 int type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >> IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
778 int vpd_val_len = type_length & IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
779 int sdr=0;
780
781 switch (type_code)
782 {
783 case 0:
784 printf ("_append_to_dict: VPD Key = [%s] : Type Code = [BINARY] : Len = [%d] : Val = [%s]\n", vpd_key_names [vpd_key_id], vpd_val_len, &vpd_key_val[1]);
785 sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "ay", vpd_val_len, &vpd_key_val[1]);
786 /*sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "s", &vpd_key_val[1]);*/
787 break;
788 case 3:
789 printf ("_append_to_dict: VPD Key = [%s] : Type Code = [ASCII+Latin] : Len = [%d] : Val = [%s]\n", vpd_key_names [vpd_key_id], vpd_val_len, &vpd_key_val[1]);
790 sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "s", &vpd_key_val[1]);
791 break;
792 }
793
794 if (sdr < 0)
795 {
796#if IPMI_FRU_PARSER_DEBUG
797 printf ("_append_to_dict : sd_bus_message_append Failed [ %d ] for [%s]\n", sdr, vpd_key_names[vpd_key_id]);
798#endif
799 }
800}
801
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500802int
803parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
804{
805 int ret = 0;
806 int rv = -1;
807 int i = 0;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500808 int j = 0;
809 int isprintable = 0;
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500810 ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
811 ipmi_fru_common_hdr_t* chdr = NULL;
812 uint8_t* hdr = NULL;
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500813 char timestr [ OPENBMC_VPD_VAL_LEN ];
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500814
815
816 ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500817 uint8_t* ipmi_fru_field_str;
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500818
819 /* Chassis */
820 uint8_t chassis_type;
821
822 /* Board */
823 uint32_t mfg_date_time;
824
825 /* Product */
826 unsigned int product_custom_fields_len;
827
828 ASSERT (msgbuf);
829 ASSERT (vpdtbl);
830
831 for (i=0; i<OPENBMC_VPD_KEY_MAX; i++)
832 {
833 memset (vpd_info[i].type_length_field, '\0', IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
834 vpd_info[i].type_length_field_length = 0;
835 }
836
837 for (i=0; i<IPMI_FRU_AREA_TYPE_MAX; i++)
838 {
839 fru_area_info [ i ].off = 0;
840 fru_area_info [ i ].len = 0;
841 }
842
843 chdr = (ipmi_fru_common_hdr_t*) msgbuf;
844 hdr = (uint8_t*) msgbuf;
845
846 fru_area_info [ IPMI_FRU_AREA_INTERNAL_USE ].off = chdr->internal;
847 fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].off = chdr->chassis;
848 fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].off = chdr->board;
849 fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].off = chdr->product;
850 fru_area_info [ IPMI_FRU_AREA_MULTI_RECORD ].off = chdr->multirec;
851
852 if (chdr->internal)
853 {
854 fru_area_info [ IPMI_FRU_AREA_INTERNAL_USE ].len = 8*(*(hdr+8*chdr->internal+1));
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500855
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500856 /* TODO: Parse internal use area */
857 }
858
859 if (chdr->chassis)
860 {
861 fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].len = 8*(*(hdr+8*chdr->chassis+1));
862 ipmi_fru_chassis_info_area (hdr+8*chdr->chassis+2,
863 fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].len,
864 &chassis_type,
865 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
866 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500867 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_CUSTOM1],
868 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500869 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500870
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500871 if (chdr->board)
872 {
873 fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].len = 8*(*(hdr+8*chdr->board+1));
874 ipmi_fru_board_info_area (hdr+8*chdr->board+2,
875 fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].len,
876 NULL,
877 &mfg_date_time,
878 &vpd_info [OPENBMC_VPD_KEY_BOARD_MFR],
879 &vpd_info [OPENBMC_VPD_KEY_BOARD_NAME],
880 &vpd_info [OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
881 &vpd_info [OPENBMC_VPD_KEY_BOARD_PART_NUM],
882 &vpd_info [OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500883 &vpd_info [OPENBMC_VPD_KEY_BOARD_CUSTOM1],
884 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500885 }
886
887 if (chdr->product)
888 {
889 fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].len = 8*(*(hdr+8*chdr->product+1));
890 ipmi_fru_product_info_area (hdr+8*chdr->product+2,
891 fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].len,
892 NULL,
893 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_MFR],
894 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_NAME],
895 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM],
896 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_VER],
897 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
898 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
899 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500900 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_CUSTOM1],
901 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500902 }
903
904 if (chdr->multirec)
905 {
906 fru_area_info [ IPMI_FRU_AREA_MULTI_RECORD ].len = 8*(*(hdr+8*chdr->multirec+1));
907 /* TODO: Parse multi record area */
908 }
909
910 for (i=0; i<IPMI_FRU_AREA_TYPE_MAX; i++)
911 {
912#if IPMI_FRU_PARSER_DEBUG
913 printf ("IPMI_FRU_AREA_TYPE=[%d] : Offset=[%d] : Len=[%d]\n", i, fru_area_info [i].off, fru_area_info[i].len);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500914#endif
915 }
916
917 /* Populate VPD Table */
918 for (i=1; i<OPENBMC_VPD_KEY_MAX; i++)
919 {
920 if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
921 {
922 sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "y", chassis_type);
923#if IPMI_FRU_PARSER_DEBUG
924 printf ("[%s] = [%d]\n", vpd_key_names[i], chassis_type);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500925#endif
926 continue;
927 }
928
929 if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
930 {
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500931 _to_time_str (mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN);
932 sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", timestr);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500933#if IPMI_FRU_PARSER_DEBUG
934 printf ("[%s] = [%d]\n", vpd_key_names[i], mfg_date_time);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500935#endif
936 continue;
937 }
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500938
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500939 /* Append TypeLen Field to Dictionary */
940 _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
941
942 /*ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;*/
943 /*sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str); */
944 }
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500945 out:
946 rv = 0;
947 cleanup:
948 return (rv);
949}
950
951int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, sd_bus_message* vpdtbl)
952{
953 int ret = 0;
954 int rv = -1;
955 int i = 0;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500956 int j = 0;
957 int sdr = 0;
958 int isprintable = 0;
959
960 /* Chassis */
961 uint8_t chassis_type;
962 /* Board */
963 uint32_t mfg_date_time;
964 /* Product */
965 unsigned int product_custom_fields_len;
966
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500967 ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500968 ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500969 char timestr [ OPENBMC_VPD_VAL_LEN ];
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500970
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500971 uint8_t* ipmi_fru_field_str=NULL;
972 ipmi_fru_common_hdr_t* chdr = NULL;
973 uint8_t* hdr = NULL;
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500974
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500975 ASSERT (msgbuf);
976 ASSERT (vpdtbl);
977
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500978 for (i=0; i<OPENBMC_VPD_KEY_MAX; i++)
979 {
980 memset (vpd_info[i].type_length_field, '\0', IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
981 vpd_info[i].type_length_field_length = 0;
982 }
983
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500984 switch (area)
985 {
986 case IPMI_FRU_AREA_CHASSIS_INFO:
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500987#if IPMI_FRU_PARSER_DEBUG
988 printf ("Chassis : Buf len = [%d]\n", len);
989#endif
990 ipmi_fru_chassis_info_area ((uint8_t*)msgbuf+2,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500991 len,
992 &chassis_type,
993 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
994 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500995 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_CUSTOM1],
996 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500997
998 /* Populate VPD Table */
999 for (i=1; i<=OPENBMC_VPD_KEY_CHASSIS_MAX; i++)
1000 {
1001 if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
1002 {
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001003#if IPMI_FRU_PARSER_DEBUG
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001004 printf ("Chassis : Appending [%s] = [%d]\n", vpd_key_names[i], chassis_type);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001005#endif
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001006 sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "y", chassis_type);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001007 continue;
1008 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001009
1010 _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
1011/*
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001012 ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001013 sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
1014*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001015 }
1016 break;
1017 case IPMI_FRU_AREA_BOARD_INFO:
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001018#if IPMI_FRU_PARSER_DEBUG
1019 printf ("Board : Buf len = [%d]\n", len);
1020#endif
1021 ipmi_fru_board_info_area ((uint8_t*)msgbuf+2,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001022 len,
1023 NULL,
1024 &mfg_date_time,
1025 &vpd_info [OPENBMC_VPD_KEY_BOARD_MFR],
1026 &vpd_info [OPENBMC_VPD_KEY_BOARD_NAME],
1027 &vpd_info [OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
1028 &vpd_info [OPENBMC_VPD_KEY_BOARD_PART_NUM],
1029 &vpd_info [OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001030 &vpd_info [OPENBMC_VPD_KEY_BOARD_CUSTOM1],
1031 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001032
1033 /* Populate VPD Table */
1034 for (i=OPENBMC_VPD_KEY_BOARD_MFR; i<=OPENBMC_VPD_KEY_BOARD_MAX; i++)
1035 {
1036 if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
1037 {
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -05001038 _to_time_str (mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001039#if IPMI_FRU_PARSER_DEBUG
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001040 printf ("Board : Appending [%s] = [%d]\n", vpd_key_names[i], timestr);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001041#endif
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001042 sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", timestr);
1043 if (sdr < 0)
1044 {
1045#if IPMI_FRU_PARSER_DEBUG
1046 printf ("ipmi_fru_board_info_area : sd_bus_message_append Failed [ %d ] for [%s]\n", sdr, vpd_key_names[i]);
1047#endif
1048 }
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001049 continue;
1050 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001051
1052 _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
1053/*
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001054 ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001055 sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
1056*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001057 }
1058 break;
1059 case IPMI_FRU_AREA_PRODUCT_INFO:
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001060#if IPMI_FRU_PARSER_DEBUG
1061 printf ("Product : Buf len = [%d]\n", len);
1062#endif
1063 ipmi_fru_product_info_area ((uint8_t*)msgbuf+2,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001064 len,
1065 NULL,
1066 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_MFR],
1067 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_NAME],
1068 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM],
1069 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_VER],
1070 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
1071 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
1072 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001073 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_CUSTOM1],
1074 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
1075
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001076 for (i=OPENBMC_VPD_KEY_PRODUCT_MFR; i<=OPENBMC_VPD_KEY_PRODUCT_MAX; i++)
1077 {
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001078 _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001079 }
1080 break;
1081 defualt:
1082 /* TODO: Parse Multi Rec / Internal use area */
1083 break;
1084 }
1085
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001086#if IPMI_FRU_PARSER_DEBUG
1087 printf ("parse_fru_area : Dictionary Packing Complete\n");
1088#endif
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001089 out:
1090 rv = 0;
1091 cleanup:
1092 return (rv);
1093}