blob: 1740f108f683ea3dbd6b9145274fe521d48dbf26 [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>
Matthew Barth619db932016-08-29 14:19:38 -050043#include <stdlib.h>
Hariharasubramanian R44473092015-10-15 08:25:28 -050044#include <unistd.h>
45#include <string.h>
46#include <time.h>
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050047#include <systemd/sd-bus.h>
Hariharasubramanian Ra032c772015-10-20 07:28:19 -050048#include <ctype.h>
Hariharasubramanian R44473092015-10-15 08:25:28 -050049
50#define uint8_t unsigned char
51#define uint32_t unsigned int
52
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050053#define TEXTSTR(a) #a
54# define ASSERT(x) \
55do { \
56if (0 == (x)) { \
57fprintf(stderr, \
58"Assertion failed: %s, " \
59"%d at \'%s\'\n", \
60__FILE__, \
61__LINE__, \
62TEXTSTR(a)); \
63return -1; \
64} \
65} while (0)
Hariharasubramanian R44473092015-10-15 08:25:28 -050066
67#define IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX 512
68#define IPMI_FRU_SENTINEL_VALUE 0xC1
69#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK 0xC0
70#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT 0x06
71#define IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK 0x3F
72#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE 0x03
73
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050074/* OpenBMC defines for Parser */
75#define IPMI_FRU_AREA_INTERNAL_USE 0x00
76#define IPMI_FRU_AREA_CHASSIS_INFO 0x01
77#define IPMI_FRU_AREA_BOARD_INFO 0x02
78#define IPMI_FRU_AREA_PRODUCT_INFO 0x03
79#define IPMI_FRU_AREA_MULTI_RECORD 0x04
80#define IPMI_FRU_AREA_TYPE_MAX 0x05
81
82#define OPENBMC_VPD_KEY_LEN 64
83#define OPENBMC_VPD_VAL_LEN 512
Hariharasubramanian R44473092015-10-15 08:25:28 -050084
85struct ipmi_fru_field
86{
87 uint8_t type_length_field[IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX];
88 /* store length of data stored in buffer */
89 unsigned int type_length_field_length;
90};
91
92typedef struct ipmi_fru_field ipmi_fru_field_t;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -050093/*
94 * FRU Parser
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050095 */
Hariharasubramanian R44473092015-10-15 08:25:28 -050096
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050097typedef struct ipmi_fru_area_info
98{
99 uint8_t off;
100 uint8_t len;
101} ipmi_fru_area_info_t;
102
103typedef struct ipmi_fru_common_hdr
104{
105 uint8_t fmtver;
106 uint8_t internal;
107 uint8_t chassis;
108 uint8_t board;
109 uint8_t product;
110 uint8_t multirec;
111} __attribute__((packed)) ipmi_fru_common_hdr_t;
112
113enum openbmc_vpd_key_id
114{
115 OPENBMC_VPD_KEY_CHASSIS_TYPE = 1, /* not a type/len */
116 OPENBMC_VPD_KEY_CHASSIS_PART_NUM,
117 OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500118 OPENBMC_VPD_KEY_CHASSIS_CUSTOM1,
119 OPENBMC_VPD_KEY_CHASSIS_CUSTOM2,
120 OPENBMC_VPD_KEY_CHASSIS_CUSTOM3,
121 OPENBMC_VPD_KEY_CHASSIS_CUSTOM4,
122 OPENBMC_VPD_KEY_CHASSIS_CUSTOM5,
123 OPENBMC_VPD_KEY_CHASSIS_CUSTOM6,
124 OPENBMC_VPD_KEY_CHASSIS_CUSTOM7,
125 OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,
126 OPENBMC_VPD_KEY_CHASSIS_MAX = OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500127 /* TODO: chassis_custom_fields */
128
129 OPENBMC_VPD_KEY_BOARD_MFG_DATE, /* not a type/len */
130 OPENBMC_VPD_KEY_BOARD_MFR,
131 OPENBMC_VPD_KEY_BOARD_NAME,
132 OPENBMC_VPD_KEY_BOARD_SERIAL_NUM,
133 OPENBMC_VPD_KEY_BOARD_PART_NUM,
134 OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID,
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500135 OPENBMC_VPD_KEY_BOARD_CUSTOM1,
136 OPENBMC_VPD_KEY_BOARD_CUSTOM2,
137 OPENBMC_VPD_KEY_BOARD_CUSTOM3,
138 OPENBMC_VPD_KEY_BOARD_CUSTOM4,
139 OPENBMC_VPD_KEY_BOARD_CUSTOM5,
140 OPENBMC_VPD_KEY_BOARD_CUSTOM6,
141 OPENBMC_VPD_KEY_BOARD_CUSTOM7,
142 OPENBMC_VPD_KEY_BOARD_CUSTOM8,
143 OPENBMC_VPD_KEY_BOARD_MAX = OPENBMC_VPD_KEY_BOARD_CUSTOM8,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500144 /* TODO: board_custom_fields */
145
146 OPENBMC_VPD_KEY_PRODUCT_MFR,
147 OPENBMC_VPD_KEY_PRODUCT_NAME,
148 OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM,
149 OPENBMC_VPD_KEY_PRODUCT_VER,
150 OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM,
151 OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG,
152 OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID,
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500153 OPENBMC_VPD_KEY_PRODUCT_CUSTOM1,
154 OPENBMC_VPD_KEY_PRODUCT_CUSTOM2,
155 OPENBMC_VPD_KEY_PRODUCT_CUSTOM3,
156 OPENBMC_VPD_KEY_PRODUCT_CUSTOM4,
157 OPENBMC_VPD_KEY_PRODUCT_CUSTOM5,
158 OPENBMC_VPD_KEY_PRODUCT_CUSTOM6,
159 OPENBMC_VPD_KEY_PRODUCT_CUSTOM7,
160 OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,
161 OPENBMC_VPD_KEY_PRODUCT_MAX = OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500162
163 OPENBMC_VPD_KEY_MAX,
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500164 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX=8,
165
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500166};
167
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500168const char* vpd_key_names [] =
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500169{
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500170 "Key Names Table Start",
171 "Type", /*OPENBMC_VPD_KEY_CHASSIS_TYPE*/
172 "Part Number", /*OPENBMC_VPD_KEY_CHASSIS_PART_NUM,*/
173 "Serial Number", /*OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,*/
174 "Custom Field 1", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM1,*/
175 "Custom Field 2", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM2,*/
176 "Custom Field 3", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM3,*/
177 "Custom Field 4", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM4,*/
178 "Custom Field 5", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM5,*/
179 "Custom Field 6", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM6,*/
180 "Custom Field 7", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM7,*/
181 "Custom Field 8", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500182
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500183 "Mfg Date", /* OPENBMC_VPD_KEY_BOARD_MFG_DATE, */ /* not a type/len */
184 "Manufacturer", /* OPENBMC_VPD_KEY_BOARD_MFR, */
185 "Name", /* OPENBMC_VPD_KEY_BOARD_NAME, */
186 "Serial Number", /* OPENBMC_VPD_KEY_BOARD_SERIAL_NUM, */
187 "Part Number", /* OPENBMC_VPD_KEY_BOARD_PART_NUM, */
188 "FRU File ID", /* OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID, */
189 "Custom Field 1", /*OPENBMC_VPD_KEY_BOARD_CUSTOM1,*/
190 "Custom Field 2", /*OPENBMC_VPD_KEY_BOARD_CUSTOM2,*/
191 "Custom Field 3", /*OPENBMC_VPD_KEY_BOARD_CUSTOM3,*/
192 "Custom Field 4", /*OPENBMC_VPD_KEY_BOARD_CUSTOM4,*/
193 "Custom Field 5", /*OPENBMC_VPD_KEY_BOARD_CUSTOM5,*/
194 "Custom Field 6", /*OPENBMC_VPD_KEY_BOARD_CUSTOM6,*/
195 "Custom Field 7", /*OPENBMC_VPD_KEY_BOARD_CUSTOM7,*/
196 "Custom Field 8", /*OPENBMC_VPD_KEY_BOARD_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500197
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500198 "Manufacturer", /* OPENBMC_VPD_KEY_PRODUCT_MFR, */
199 "Name", /* OPENBMC_VPD_KEY_PRODUCT_NAME, */
200 "Model Number", /* OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM, */
201 "Version", /* OPENBMC_VPD_KEY_PRODUCT_VER, */
202 "Serial Number", /* OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM, */
203 "Asset Tag", /* OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG, */
204 "FRU File ID", /* OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID, */
205 "Custom Field 1", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM1,*/
206 "Custom Field 2", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM2,*/
207 "Custom Field 3", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM3,*/
208 "Custom Field 4", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM4,*/
209 "Custom Field 5", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM5,*/
210 "Custom Field 6", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM6,*/
211 "Custom Field 7", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM7,*/
212 "Custom Field 8", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500213
214 "Key Names Table End" /*OPENBMC_VPD_KEY_MAX,*/
215};
216
217
218/*
219 * --------------------------------------------------------------------
220 *
221 * --------------------------------------------------------------------
222 */
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500223
224static size_t _to_time_str (uint32_t mfg_date_time, char* timestr, uint32_t len)
225{
226 struct tm tm;
227 time_t t;
228 size_t s;
229
230 ASSERT (timestr);
231 ASSERT (len);
232
233 memset (&tm, '\0', sizeof (struct tm));
234
235 t = mfg_date_time;
236 gmtime_r (&t, &tm);
237 s = strftime (timestr, len, "%F - %H:%M:%S", &tm);
238
239 return s;
240}
241
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500242/* private method to parse type/length */
Hariharasubramanian R44473092015-10-15 08:25:28 -0500243static int
244_parse_type_length (const void *areabuf,
245 unsigned int areabuflen,
246 unsigned int current_area_offset,
247 uint8_t *number_of_data_bytes,
248 ipmi_fru_field_t *field)
249{
250 const uint8_t *areabufptr = (const uint8_t*) areabuf;
251 uint8_t type_length;
252 uint8_t type_code;
253
254 ASSERT (areabuf);
255 ASSERT (areabuflen);
256 ASSERT (number_of_data_bytes);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500257
Hariharasubramanian R44473092015-10-15 08:25:28 -0500258 type_length = areabufptr[current_area_offset];
259
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500260 /* ipmi workaround
Hariharasubramanian R44473092015-10-15 08:25:28 -0500261 *
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500262 * dell p weredge r610
Hariharasubramanian R44473092015-10-15 08:25:28 -0500263 *
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500264 * my reading of the fru spec is that all non-custom fields are
265 * required to be listed by the vendor. however, on this
Hariharasubramanian R44473092015-10-15 08:25:28 -0500266 * motherboard, some areas list this, indicating that there is
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500267 * no more data to be parsed. so now, for "required" fields, i
Hariharasubramanian R44473092015-10-15 08:25:28 -0500268 * check to see if the type-length field is a sentinel before
269 * calling this function.
270 */
271
272 ASSERT (type_length != IPMI_FRU_SENTINEL_VALUE);
273
274 type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >> IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
275 (*number_of_data_bytes) = type_length & IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
276
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500277 /* special case: this shouldn't be a length of 0x01 (see type/length
278 * byte format in fru information storage definition).
Hariharasubramanian R44473092015-10-15 08:25:28 -0500279 */
280 if (type_code == IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE
281 && (*number_of_data_bytes) == 0x01)
282 {
283 return (-1);
284 }
285
286 if ((current_area_offset + 1 + (*number_of_data_bytes)) > areabuflen)
287 {
288 return (-1);
289 }
290
291 if (field)
292 {
293 memset (field->type_length_field,
294 '\0',
295 IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
296 memcpy (field->type_length_field,
297 &areabufptr[current_area_offset],
298 1 + (*number_of_data_bytes));
299 field->type_length_field_length = 1 + (*number_of_data_bytes);
300 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500301
Hariharasubramanian R44473092015-10-15 08:25:28 -0500302 return (0);
303}
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500304
Hariharasubramanian R44473092015-10-15 08:25:28 -0500305int
306ipmi_fru_chassis_info_area (const void *areabuf,
307 unsigned int areabuflen,
308 uint8_t *chassis_type,
309 ipmi_fru_field_t *chassis_part_number,
310 ipmi_fru_field_t *chassis_serial_number,
311 ipmi_fru_field_t *chassis_custom_fields,
312 unsigned int chassis_custom_fields_len)
313{
314 const uint8_t *areabufptr = (const uint8_t*) areabuf;
315 unsigned int area_offset = 0;
316 unsigned int custom_fields_index = 0;
317 uint8_t number_of_data_bytes;
318 int rv = -1;
319
320 if (!areabuf || !areabuflen)
321 {
322 return (-1);
323 }
324
325 if (chassis_part_number)
326 memset (chassis_part_number,
327 '\0',
328 sizeof (ipmi_fru_field_t));
329 if (chassis_serial_number)
330 memset (chassis_serial_number,
331 '\0',
332 sizeof (ipmi_fru_field_t));
333 if (chassis_custom_fields && chassis_custom_fields_len)
334 memset (chassis_custom_fields,
335 '\0',
336 sizeof (ipmi_fru_field_t) * chassis_custom_fields_len);
337
338 if (chassis_type)
339 (*chassis_type) = areabufptr[area_offset];
340 area_offset++;
341
342 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
343 goto out;
344
345 if (_parse_type_length (areabufptr,
346 areabuflen,
347 area_offset,
348 &number_of_data_bytes,
349 chassis_part_number) < 0)
350 goto cleanup;
351 area_offset += 1; /* type/length byte */
352 area_offset += number_of_data_bytes;
353
354 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
355 goto out;
356
357 if (_parse_type_length (areabufptr,
358 areabuflen,
359 area_offset,
360 &number_of_data_bytes,
361 chassis_serial_number) < 0)
362 goto cleanup;
363 area_offset += 1; /* type/length byte */
364 area_offset += number_of_data_bytes;
365
366 while (area_offset < areabuflen
367 && areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
368 {
369 ipmi_fru_field_t *field_ptr = NULL;
370
371 if (chassis_custom_fields && chassis_custom_fields_len)
372 {
373 if (custom_fields_index < chassis_custom_fields_len)
374 field_ptr = &chassis_custom_fields[custom_fields_index];
375 else
376 {
377 goto cleanup;
378 }
379 }
380
381 if (_parse_type_length (areabufptr,
382 areabuflen,
383 area_offset,
384 &number_of_data_bytes,
385 field_ptr) < 0)
386 goto cleanup;
387
388 area_offset += 1; /* type/length byte */
389 area_offset += number_of_data_bytes;
390 custom_fields_index++;
391 }
392
393
394 out:
395 rv = 0;
396 cleanup:
397 return (rv);
398}
399
400int
401ipmi_fru_board_info_area (const void *areabuf,
402 unsigned int areabuflen,
403 uint8_t *language_code,
404 uint32_t *mfg_date_time,
405 ipmi_fru_field_t *board_manufacturer,
406 ipmi_fru_field_t *board_product_name,
407 ipmi_fru_field_t *board_serial_number,
408 ipmi_fru_field_t *board_part_number,
409 ipmi_fru_field_t *board_fru_file_id,
410 ipmi_fru_field_t *board_custom_fields,
411 unsigned int board_custom_fields_len)
412{
413 const uint8_t *areabufptr = (const uint8_t*) areabuf;
414 uint32_t mfg_date_time_tmp = 0;
415 unsigned int area_offset = 0;
416 unsigned int custom_fields_index = 0;
417 uint8_t number_of_data_bytes;
418 int rv = -1;
419
420 if (!areabuf || !areabuflen)
421 {
422 return (-1);
423 }
424
425 if (board_manufacturer)
426 memset (board_manufacturer,
427 '\0',
428 sizeof (ipmi_fru_field_t));
429 if (board_product_name)
430 memset (board_product_name,
431 '\0',
432 sizeof (ipmi_fru_field_t));
433 if (board_serial_number)
434 memset (board_serial_number,
435 '\0',
436 sizeof (ipmi_fru_field_t));
437 if (board_part_number)
438 memset (board_part_number,
439 '\0',
440 sizeof (ipmi_fru_field_t));
441 if (board_fru_file_id)
442 memset (board_fru_file_id,
443 '\0',
444 sizeof (ipmi_fru_field_t));
445 if (board_custom_fields && board_custom_fields_len)
446 memset (board_custom_fields,
447 '\0',
448 sizeof (ipmi_fru_field_t) * board_custom_fields_len);
449
450 if (language_code)
451 (*language_code) = areabufptr[area_offset];
452 area_offset++;
453
454 if (mfg_date_time)
455 {
456 struct tm tm;
457 time_t t;
458
459 /* mfg_date_time is little endian - see spec */
460 mfg_date_time_tmp |= areabufptr[area_offset];
461 area_offset++;
462 mfg_date_time_tmp |= (areabufptr[area_offset] << 8);
463 area_offset++;
464 mfg_date_time_tmp |= (areabufptr[area_offset] << 16);
465 area_offset++;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500466
Hariharasubramanian R44473092015-10-15 08:25:28 -0500467 /* mfg_date_time is in minutes, so multiple by 60 to get seconds */
468 mfg_date_time_tmp *= 60;
469
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500470 /* posix says individual calls need not clear/set all portions of
Hariharasubramanian R44473092015-10-15 08:25:28 -0500471 * 'struct tm', thus passing 'struct tm' between functions could
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500472 * have issues. so we need to memset.
Hariharasubramanian R44473092015-10-15 08:25:28 -0500473 */
474 memset (&tm, '\0', sizeof(struct tm));
475
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500476 /* in fru, epoch is 0:00 hrs 1/1/96
Hariharasubramanian R44473092015-10-15 08:25:28 -0500477 *
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500478 * so convert into ansi epoch
Hariharasubramanian R44473092015-10-15 08:25:28 -0500479 */
480
481 tm.tm_year = 96; /* years since 1900 */
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500482 tm.tm_mon = 0; /* months since january */
Hariharasubramanian R44473092015-10-15 08:25:28 -0500483 tm.tm_mday = 1; /* 1-31 */
484 tm.tm_hour = 0;
485 tm.tm_min = 0;
486 tm.tm_sec = 0;
487 tm.tm_isdst = -1;
488
489 if ((t = mktime (&tm)) == (time_t)-1)
490 {
491 goto cleanup;
492 }
493
494 mfg_date_time_tmp += (uint32_t)t;
495 (*mfg_date_time) = mfg_date_time_tmp;
496 }
497 else
498 area_offset += 3;
499
500 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
501 goto out;
502
503 if (_parse_type_length (areabufptr,
504 areabuflen,
505 area_offset,
506 &number_of_data_bytes,
507 board_manufacturer) < 0)
508 goto cleanup;
509 area_offset += 1; /* type/length byte */
510 area_offset += number_of_data_bytes;
511
512 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
513 goto out;
514
515 if (_parse_type_length (areabufptr,
516 areabuflen,
517 area_offset,
518 &number_of_data_bytes,
519 board_product_name) < 0)
520 goto cleanup;
521 area_offset += 1; /* type/length byte */
522 area_offset += number_of_data_bytes;
523
524 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
525 goto out;
526
527 if (_parse_type_length (areabufptr,
528 areabuflen,
529 area_offset,
530 &number_of_data_bytes,
531 board_serial_number) < 0)
532 goto cleanup;
533 area_offset += 1; /* type/length byte */
534 area_offset += number_of_data_bytes;
535
536 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
537 goto out;
538
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500539 if (_parse_type_length (areabufptr,
Hariharasubramanian R44473092015-10-15 08:25:28 -0500540 areabuflen,
541 area_offset,
542 &number_of_data_bytes,
543 board_part_number) < 0)
544 goto cleanup;
545 area_offset += 1; /* type/length byte */
546 area_offset += number_of_data_bytes;
547
548 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
549 goto out;
550
551 if (_parse_type_length (areabufptr,
552 areabuflen,
553 area_offset,
554 &number_of_data_bytes,
555 board_fru_file_id) < 0)
556 goto cleanup;
557 area_offset += 1; /* type/length byte */
558 area_offset += number_of_data_bytes;
559
560 while (area_offset < areabuflen
561 && areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
562 {
563 ipmi_fru_field_t *field_ptr = NULL;
564
565 if (board_custom_fields && board_custom_fields_len)
566 {
567 if (custom_fields_index < board_custom_fields_len)
568 field_ptr = &board_custom_fields[custom_fields_index];
569 else
570 {
571 goto cleanup;
572 }
573 }
574
575 if (_parse_type_length (areabufptr,
576 areabuflen,
577 area_offset,
578 &number_of_data_bytes,
579 field_ptr) < 0)
580 goto cleanup;
581
582 area_offset += 1; /* type/length byte */
583 area_offset += number_of_data_bytes;
584 custom_fields_index++;
585 }
586
587 out:
588 rv = 0;
589 cleanup:
590 return (rv);
591}
592
593int
594ipmi_fru_product_info_area (const void *areabuf,
595 unsigned int areabuflen,
596 uint8_t *language_code,
597 ipmi_fru_field_t *product_manufacturer_name,
598 ipmi_fru_field_t *product_name,
599 ipmi_fru_field_t *product_part_model_number,
600 ipmi_fru_field_t *product_version,
601 ipmi_fru_field_t *product_serial_number,
602 ipmi_fru_field_t *product_asset_tag,
603 ipmi_fru_field_t *product_fru_file_id,
604 ipmi_fru_field_t *product_custom_fields,
605 unsigned int product_custom_fields_len)
606{
607 const uint8_t *areabufptr = (const uint8_t*) areabuf;
608 unsigned int area_offset = 0;
609 unsigned int custom_fields_index = 0;
610 uint8_t number_of_data_bytes;
611 int rv = -1;
612
613 if (!areabuf || !areabuflen)
614 {
615 return (-1);
616 }
617
618 if (product_manufacturer_name)
619 memset (product_manufacturer_name,
620 '\0',
621 sizeof (ipmi_fru_field_t));
622 if (product_name)
623 memset (product_name,
624 '\0',
625 sizeof (ipmi_fru_field_t));
626 if (product_part_model_number)
627 memset (product_part_model_number,
628 '\0',
629 sizeof (ipmi_fru_field_t));
630 if (product_version)
631 memset (product_version,
632 '\0',
633 sizeof (ipmi_fru_field_t));
634 if (product_serial_number)
635 memset (product_serial_number,
636 '\0',
637 sizeof (ipmi_fru_field_t));
638 if (product_asset_tag)
639 memset (product_asset_tag,
640 '\0',
641 sizeof (ipmi_fru_field_t));
642 if (product_fru_file_id)
643 memset (product_fru_file_id,
644 '\0',
645 sizeof (ipmi_fru_field_t));
646 if (product_custom_fields && product_custom_fields_len)
647 memset (product_custom_fields,
648 '\0',
649 sizeof (ipmi_fru_field_t) * product_custom_fields_len);
650
651 if (language_code)
652 (*language_code) = areabufptr[area_offset];
653 area_offset++;
654
655 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
656 goto out;
657
658 if (_parse_type_length (areabufptr,
659 areabuflen,
660 area_offset,
661 &number_of_data_bytes,
662 product_manufacturer_name) < 0)
663 goto cleanup;
664 area_offset += 1; /* type/length byte */
665 area_offset += number_of_data_bytes;
666
667 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
668 goto out;
669
670 if (_parse_type_length (areabufptr,
671 areabuflen,
672 area_offset,
673 &number_of_data_bytes,
674 product_name) < 0)
675 goto cleanup;
676 area_offset += 1; /* type/length byte */
677 area_offset += number_of_data_bytes;
678
679 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
680 goto out;
681
682 if (_parse_type_length (areabufptr,
683 areabuflen,
684 area_offset,
685 &number_of_data_bytes,
686 product_part_model_number) < 0)
687 goto cleanup;
688 area_offset += 1; /* type/length byte */
689 area_offset += number_of_data_bytes;
690
691 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
692 goto out;
693
694 if (_parse_type_length (areabufptr,
695 areabuflen,
696 area_offset,
697 &number_of_data_bytes,
698 product_version) < 0)
699 goto cleanup;
700 area_offset += 1; /* type/length byte */
701 area_offset += number_of_data_bytes;
702
703 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
704 goto out;
705
706 if (_parse_type_length (areabufptr,
707 areabuflen,
708 area_offset,
709 &number_of_data_bytes,
710 product_serial_number) < 0)
711 goto cleanup;
712 area_offset += 1; /* type/length byte */
713 area_offset += number_of_data_bytes;
714
715 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
716 goto out;
717
718 if (_parse_type_length (areabufptr,
719 areabuflen,
720 area_offset,
721 &number_of_data_bytes,
722 product_asset_tag) < 0)
723 goto cleanup;
724 area_offset += 1; /* type/length byte */
725 area_offset += number_of_data_bytes;
726
727 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
728 goto out;
729
730 if (_parse_type_length (areabufptr,
731 areabuflen,
732 area_offset,
733 &number_of_data_bytes,
734 product_fru_file_id) < 0)
735 goto cleanup;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500736
Hariharasubramanian R44473092015-10-15 08:25:28 -0500737 area_offset += 1; /* type/length byte */
738 area_offset += number_of_data_bytes;
739
740 while (area_offset < areabuflen
741 && areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
742 {
743 ipmi_fru_field_t *field_ptr = NULL;
744
745 if (product_custom_fields && product_custom_fields_len)
746 {
747 if (custom_fields_index < product_custom_fields_len)
748 field_ptr = &product_custom_fields[custom_fields_index];
749 else
750 {
751 goto cleanup;
752 }
753 }
754
755 if (_parse_type_length (areabufptr,
756 areabuflen,
757 area_offset,
758 &number_of_data_bytes,
759 field_ptr) < 0)
760 goto cleanup;
761
762 area_offset += 1; /* type/length byte */
763 area_offset += number_of_data_bytes;
764 custom_fields_index++;
765 }
766
767
768 out:
769 rv = 0;
770 cleanup:
771 return (rv);
772}
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500773
Matthew Barth619db932016-08-29 14:19:38 -0500774void _append_to_dict (uint8_t vpd_key_id, uint8_t* vpd_key_val, sd_bus_message* vpdtbl)
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500775{
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
vishwa24afbb92016-06-10 06:08:56 -0500781 /* Needed to convert each uint8_t byte to a ascii */
782 char bin_byte[3] = {0};
783
784 /*
785 * Max number of characters needed to represent 1 unsigned byte in string
786 * is number of bytes multipled by 2. Extra 3 for 0x and a ending '\0';
787 */
788 char bin_in_ascii_len = vpd_val_len * 2 + 3;
789
790 /* Binary converted to ascii in array */
791 char *bin_in_ascii = (char *)malloc(bin_in_ascii_len);
792
793 /* For reading byte from the area */
794 size_t val = 0;
795
796 char *bin_copy = &((char *)bin_in_ascii)[2];
797
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500798 switch (type_code)
799 {
800 case 0:
vishwa24afbb92016-06-10 06:08:56 -0500801 memset(bin_in_ascii, 0x0, bin_in_ascii_len);
802
803 /* Offset 1 is where actual data starts */
804 for(val = 1; val <= vpd_val_len ; val++)
805 {
806 /* 2 bytes for data and 1 for terminating '\0' */
807 snprintf(bin_byte, 3, "%02x", vpd_key_val[val]);
808
809 /* Its a running string so strip off the '\0' */
810 strncat(bin_copy, bin_byte, 2);
811 }
812
813 /* We need the data represented as 0x...... */
814 if(vpd_val_len > 0)
815 {
816 strncpy(bin_in_ascii, "0x", 2);
817 }
818
819 printf ("_append_to_dict: VPD Key = [%s] : Type Code = [BINARY] : Len = [%d] : Val = [%s]\n",
820 vpd_key_names [vpd_key_id], vpd_val_len, bin_in_ascii);
821 sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "s", bin_in_ascii);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500822 break;
vishwa24afbb92016-06-10 06:08:56 -0500823
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500824 case 3:
825 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]);
826 sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "s", &vpd_key_val[1]);
827 break;
828 }
829
vishwa24afbb92016-06-10 06:08:56 -0500830 if(bin_in_ascii)
831 {
832 free(bin_in_ascii);
833 bin_in_ascii = NULL;
834 }
835
836
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500837 if (sdr < 0)
838 {
839#if IPMI_FRU_PARSER_DEBUG
840 printf ("_append_to_dict : sd_bus_message_append Failed [ %d ] for [%s]\n", sdr, vpd_key_names[vpd_key_id]);
841#endif
842 }
843}
844
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500845int
846parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
847{
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500848 int rv = -1;
849 int i = 0;
850 ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
851 ipmi_fru_common_hdr_t* chdr = NULL;
852 uint8_t* hdr = NULL;
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500853 char timestr [ OPENBMC_VPD_VAL_LEN ];
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500854
855
856 ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
Matthew Barth619db932016-08-29 14:19:38 -0500857 //uint8_t* ipmi_fru_field_str;
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500858
859 /* Chassis */
860 uint8_t chassis_type;
861
862 /* Board */
863 uint32_t mfg_date_time;
864
865 /* Product */
Matthew Barth619db932016-08-29 14:19:38 -0500866 //unsigned int product_custom_fields_len;
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500867
868 ASSERT (msgbuf);
869 ASSERT (vpdtbl);
870
871 for (i=0; i<OPENBMC_VPD_KEY_MAX; i++)
872 {
873 memset (vpd_info[i].type_length_field, '\0', IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
874 vpd_info[i].type_length_field_length = 0;
875 }
876
877 for (i=0; i<IPMI_FRU_AREA_TYPE_MAX; i++)
878 {
879 fru_area_info [ i ].off = 0;
880 fru_area_info [ i ].len = 0;
881 }
882
883 chdr = (ipmi_fru_common_hdr_t*) msgbuf;
884 hdr = (uint8_t*) msgbuf;
885
886 fru_area_info [ IPMI_FRU_AREA_INTERNAL_USE ].off = chdr->internal;
887 fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].off = chdr->chassis;
888 fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].off = chdr->board;
889 fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].off = chdr->product;
890 fru_area_info [ IPMI_FRU_AREA_MULTI_RECORD ].off = chdr->multirec;
891
892 if (chdr->internal)
893 {
894 fru_area_info [ IPMI_FRU_AREA_INTERNAL_USE ].len = 8*(*(hdr+8*chdr->internal+1));
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500895
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500896 /* TODO: Parse internal use area */
897 }
898
899 if (chdr->chassis)
900 {
901 fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].len = 8*(*(hdr+8*chdr->chassis+1));
902 ipmi_fru_chassis_info_area (hdr+8*chdr->chassis+2,
903 fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].len,
904 &chassis_type,
905 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
906 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500907 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_CUSTOM1],
908 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500909 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500910
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500911 if (chdr->board)
912 {
913 fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].len = 8*(*(hdr+8*chdr->board+1));
914 ipmi_fru_board_info_area (hdr+8*chdr->board+2,
915 fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].len,
916 NULL,
917 &mfg_date_time,
918 &vpd_info [OPENBMC_VPD_KEY_BOARD_MFR],
919 &vpd_info [OPENBMC_VPD_KEY_BOARD_NAME],
920 &vpd_info [OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
921 &vpd_info [OPENBMC_VPD_KEY_BOARD_PART_NUM],
922 &vpd_info [OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500923 &vpd_info [OPENBMC_VPD_KEY_BOARD_CUSTOM1],
924 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500925 }
926
927 if (chdr->product)
928 {
929 fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].len = 8*(*(hdr+8*chdr->product+1));
930 ipmi_fru_product_info_area (hdr+8*chdr->product+2,
931 fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].len,
932 NULL,
933 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_MFR],
934 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_NAME],
935 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM],
936 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_VER],
937 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
938 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
939 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500940 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_CUSTOM1],
941 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500942 }
943
944 if (chdr->multirec)
945 {
946 fru_area_info [ IPMI_FRU_AREA_MULTI_RECORD ].len = 8*(*(hdr+8*chdr->multirec+1));
947 /* TODO: Parse multi record area */
948 }
949
950 for (i=0; i<IPMI_FRU_AREA_TYPE_MAX; i++)
951 {
952#if IPMI_FRU_PARSER_DEBUG
953 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 -0500954#endif
955 }
956
957 /* Populate VPD Table */
958 for (i=1; i<OPENBMC_VPD_KEY_MAX; i++)
959 {
960 if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
961 {
962 sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "y", chassis_type);
963#if IPMI_FRU_PARSER_DEBUG
964 printf ("[%s] = [%d]\n", vpd_key_names[i], chassis_type);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500965#endif
966 continue;
967 }
968
969 if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
970 {
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500971 _to_time_str (mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN);
972 sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", timestr);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500973#if IPMI_FRU_PARSER_DEBUG
974 printf ("[%s] = [%d]\n", vpd_key_names[i], mfg_date_time);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500975#endif
976 continue;
977 }
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500978
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500979 /* Append TypeLen Field to Dictionary */
980 _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
981
982 /*ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;*/
983 /*sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str); */
984 }
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500985 rv = 0;
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500986 return (rv);
987}
988
Adriana Kobylak81aecc62016-05-12 13:52:47 -0500989int parse_fru_area (const uint8_t area, const void* msgbuf, const size_t len, sd_bus_message* vpdtbl)
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500990{
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500991 int rv = -1;
992 int i = 0;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500993 int sdr = 0;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500994
995 /* Chassis */
996 uint8_t chassis_type;
997 /* Board */
998 uint32_t mfg_date_time;
999 /* Product */
Matthew Barth619db932016-08-29 14:19:38 -05001000 //unsigned int product_custom_fields_len;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001001
Matthew Barth619db932016-08-29 14:19:38 -05001002 //ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001003 ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -05001004 char timestr [ OPENBMC_VPD_VAL_LEN ];
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001005
Matthew Barth619db932016-08-29 14:19:38 -05001006 //uint8_t* ipmi_fru_field_str=NULL;
1007 //ipmi_fru_common_hdr_t* chdr = NULL;
1008 //uint8_t* hdr = NULL;
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001009
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001010 ASSERT (msgbuf);
1011 ASSERT (vpdtbl);
1012
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001013 for (i=0; i<OPENBMC_VPD_KEY_MAX; i++)
1014 {
1015 memset (vpd_info[i].type_length_field, '\0', IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
1016 vpd_info[i].type_length_field_length = 0;
1017 }
1018
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001019 switch (area)
1020 {
1021 case IPMI_FRU_AREA_CHASSIS_INFO:
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001022#if IPMI_FRU_PARSER_DEBUG
1023 printf ("Chassis : Buf len = [%d]\n", len);
1024#endif
1025 ipmi_fru_chassis_info_area ((uint8_t*)msgbuf+2,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001026 len,
1027 &chassis_type,
1028 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
1029 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001030 &vpd_info [OPENBMC_VPD_KEY_CHASSIS_CUSTOM1],
1031 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001032
1033 /* Populate VPD Table */
1034 for (i=1; i<=OPENBMC_VPD_KEY_CHASSIS_MAX; i++)
1035 {
1036 if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
1037 {
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001038#if IPMI_FRU_PARSER_DEBUG
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001039 printf ("Chassis : Appending [%s] = [%d]\n", vpd_key_names[i], chassis_type);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001040#endif
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001041 sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "y", chassis_type);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001042 continue;
1043 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001044
1045 _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
1046/*
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001047 ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001048 sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
1049*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001050 }
1051 break;
1052 case IPMI_FRU_AREA_BOARD_INFO:
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001053#if IPMI_FRU_PARSER_DEBUG
1054 printf ("Board : Buf len = [%d]\n", len);
1055#endif
1056 ipmi_fru_board_info_area ((uint8_t*)msgbuf+2,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001057 len,
1058 NULL,
1059 &mfg_date_time,
1060 &vpd_info [OPENBMC_VPD_KEY_BOARD_MFR],
1061 &vpd_info [OPENBMC_VPD_KEY_BOARD_NAME],
1062 &vpd_info [OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
1063 &vpd_info [OPENBMC_VPD_KEY_BOARD_PART_NUM],
1064 &vpd_info [OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001065 &vpd_info [OPENBMC_VPD_KEY_BOARD_CUSTOM1],
1066 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001067
1068 /* Populate VPD Table */
1069 for (i=OPENBMC_VPD_KEY_BOARD_MFR; i<=OPENBMC_VPD_KEY_BOARD_MAX; i++)
1070 {
1071 if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
1072 {
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -05001073 _to_time_str (mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001074#if IPMI_FRU_PARSER_DEBUG
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001075 printf ("Board : Appending [%s] = [%d]\n", vpd_key_names[i], timestr);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001076#endif
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001077 sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", timestr);
1078 if (sdr < 0)
1079 {
1080#if IPMI_FRU_PARSER_DEBUG
1081 printf ("ipmi_fru_board_info_area : sd_bus_message_append Failed [ %d ] for [%s]\n", sdr, vpd_key_names[i]);
1082#endif
1083 }
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001084 continue;
1085 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001086
1087 _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
1088/*
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001089 ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001090 sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
1091*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001092 }
1093 break;
1094 case IPMI_FRU_AREA_PRODUCT_INFO:
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001095#if IPMI_FRU_PARSER_DEBUG
1096 printf ("Product : Buf len = [%d]\n", len);
1097#endif
1098 ipmi_fru_product_info_area ((uint8_t*)msgbuf+2,
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001099 len,
1100 NULL,
1101 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_MFR],
1102 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_NAME],
1103 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM],
1104 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_VER],
1105 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
1106 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
1107 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001108 &vpd_info [OPENBMC_VPD_KEY_PRODUCT_CUSTOM1],
1109 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
1110
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001111 for (i=OPENBMC_VPD_KEY_PRODUCT_MFR; i<=OPENBMC_VPD_KEY_PRODUCT_MAX; i++)
1112 {
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001113 _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001114 }
1115 break;
Matthew Barth619db932016-08-29 14:19:38 -05001116 default:
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001117 /* TODO: Parse Multi Rec / Internal use area */
1118 break;
1119 }
1120
Hariharasubramanian Ra032c772015-10-20 07:28:19 -05001121#if IPMI_FRU_PARSER_DEBUG
1122 printf ("parse_fru_area : Dictionary Packing Complete\n");
1123#endif
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001124 rv = 0;
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -05001125 return (rv);
1126}