xref: /openbmc/ipmi-fru-parser/frup.cpp (revision 6f47bee5)
182ab3e19SRatan Gupta /*
282ab3e19SRatan Gupta  * Copyright (C) 2003-2014 FreeIPMI Core Team
382ab3e19SRatan Gupta  *
482ab3e19SRatan Gupta  * This program is free software: you can redistribute it and/or modify
582ab3e19SRatan Gupta  * it under the terms of the GNU General Public License as published by
682ab3e19SRatan Gupta  * the Free Software Foundation, either version 3 of the License, or
782ab3e19SRatan Gupta  * (at your option) any later version.
882ab3e19SRatan Gupta  *
982ab3e19SRatan Gupta  * This program is distributed in the hope that it will be useful,
1082ab3e19SRatan Gupta  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1182ab3e19SRatan Gupta  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1282ab3e19SRatan Gupta  * GNU General Public License for more details.
1382ab3e19SRatan Gupta  *
1482ab3e19SRatan Gupta  * You should have received a copy of the GNU General Public License
1582ab3e19SRatan Gupta  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1682ab3e19SRatan Gupta  *
1782ab3e19SRatan Gupta  */
1882ab3e19SRatan Gupta /*****************************************************************************\
1982ab3e19SRatan Gupta  *  Copyright (C) 2007-2014 Lawrence Livermore National Security, LLC.
2082ab3e19SRatan Gupta  *  Copyright (C) 2007 The Regents of the University of California.
2182ab3e19SRatan Gupta  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
2282ab3e19SRatan Gupta  *  Written by Albert Chu <chu11@llnl.gov>
2382ab3e19SRatan Gupta  *  UCRL-CODE-232183
2482ab3e19SRatan Gupta  *
2582ab3e19SRatan Gupta  *  This file is part of Ipmi-fru, a tool used for retrieving
2682ab3e19SRatan Gupta  *  motherboard field replaceable unit (FRU) information. For details,
2782ab3e19SRatan Gupta  *  see http://www.llnl.gov/linux/.
2882ab3e19SRatan Gupta  *
2982ab3e19SRatan Gupta  *  Ipmi-fru is free software; you can redistribute it and/or modify
3082ab3e19SRatan Gupta  *  it under the terms of the GNU General Public License as published by the
3182ab3e19SRatan Gupta  *  Free Software Foundation; either version 3 of the License, or (at your
3282ab3e19SRatan Gupta  *  option) any later version.
3382ab3e19SRatan Gupta  *
3482ab3e19SRatan Gupta  *  Ipmi-fru is distributed in the hope that it will be useful, but
3582ab3e19SRatan Gupta  *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
3682ab3e19SRatan Gupta  *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
3782ab3e19SRatan Gupta  *  for more details.
3882ab3e19SRatan Gupta  *
3982ab3e19SRatan Gupta  *  You should have received a copy of the GNU General Public License along
4082ab3e19SRatan Gupta  *  with Ipmi-fru.  If not, see <http://www.gnu.org/licenses/>.
4182ab3e19SRatan Gupta \*****************************************************************************/
42c9508db8SPatrick Venture #include "frup.hpp"
43c9508db8SPatrick Venture 
44c9508db8SPatrick Venture #include <ctype.h>
4582ab3e19SRatan Gupta #include <stdio.h>
4682ab3e19SRatan Gupta #include <stdlib.h>
4782ab3e19SRatan Gupta #include <string.h>
4882ab3e19SRatan Gupta #include <systemd/sd-bus.h>
49c9508db8SPatrick Venture #include <time.h>
50c9508db8SPatrick Venture #include <unistd.h>
5182ab3e19SRatan Gupta 
5282ab3e19SRatan Gupta #define TEXTSTR(a) #a
5382ab3e19SRatan Gupta #define ASSERT(x)                                                              \
54c9508db8SPatrick Venture     do                                                                         \
55c9508db8SPatrick Venture     {                                                                          \
56c9508db8SPatrick Venture         if (0 == (x))                                                          \
57c9508db8SPatrick Venture         {                                                                      \
5882ab3e19SRatan Gupta             fprintf(stderr,                                                    \
5982ab3e19SRatan Gupta                     "Assertion failed: %s, "                                   \
6082ab3e19SRatan Gupta                     "%d at \'%s\'\n",                                          \
61c9508db8SPatrick Venture                     __FILE__, __LINE__, TEXTSTR(a));                           \
6282ab3e19SRatan Gupta             return -1;                                                         \
6382ab3e19SRatan Gupta         }                                                                      \
6482ab3e19SRatan Gupta     } while (0)
6582ab3e19SRatan Gupta 
6682ab3e19SRatan Gupta #define IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX 512
6782ab3e19SRatan Gupta #define IPMI_FRU_SENTINEL_VALUE 0xC1
6882ab3e19SRatan Gupta #define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK 0xC0
6982ab3e19SRatan Gupta #define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT 0x06
7082ab3e19SRatan Gupta #define IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK 0x3F
7182ab3e19SRatan Gupta #define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE 0x03
7282ab3e19SRatan Gupta 
7382ab3e19SRatan Gupta /* OpenBMC defines for Parser */
7482ab3e19SRatan Gupta #define IPMI_FRU_AREA_INTERNAL_USE 0x00
7582ab3e19SRatan Gupta #define IPMI_FRU_AREA_CHASSIS_INFO 0x01
7682ab3e19SRatan Gupta #define IPMI_FRU_AREA_BOARD_INFO 0x02
7782ab3e19SRatan Gupta #define IPMI_FRU_AREA_PRODUCT_INFO 0x03
7882ab3e19SRatan Gupta #define IPMI_FRU_AREA_MULTI_RECORD 0x04
7982ab3e19SRatan Gupta #define IPMI_FRU_AREA_TYPE_MAX 0x05
8082ab3e19SRatan Gupta 
8182ab3e19SRatan Gupta #define OPENBMC_VPD_KEY_LEN 64
8282ab3e19SRatan Gupta #define OPENBMC_VPD_VAL_LEN 512
8382ab3e19SRatan Gupta 
849084f520SWilly Tu constexpr long fruEpochMinutes = 820454400;
859084f520SWilly Tu 
8682ab3e19SRatan Gupta struct ipmi_fru_field
8782ab3e19SRatan Gupta {
8882ab3e19SRatan Gupta     uint8_t type_length_field[IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX];
8982ab3e19SRatan Gupta     /* store length of data stored in buffer */
9082ab3e19SRatan Gupta     unsigned int type_length_field_length;
9182ab3e19SRatan Gupta };
9282ab3e19SRatan Gupta 
9382ab3e19SRatan Gupta typedef struct ipmi_fru_field ipmi_fru_field_t;
9482ab3e19SRatan Gupta /*
9582ab3e19SRatan Gupta  * FRU Parser
9682ab3e19SRatan Gupta  */
9782ab3e19SRatan Gupta 
9882ab3e19SRatan Gupta typedef struct ipmi_fru_area_info
9982ab3e19SRatan Gupta {
10082ab3e19SRatan Gupta     uint8_t off;
10182ab3e19SRatan Gupta     uint8_t len;
10282ab3e19SRatan Gupta } ipmi_fru_area_info_t;
10382ab3e19SRatan Gupta 
10482ab3e19SRatan Gupta typedef struct ipmi_fru_common_hdr
10582ab3e19SRatan Gupta {
10682ab3e19SRatan Gupta     uint8_t fmtver;
10782ab3e19SRatan Gupta     uint8_t internal;
10882ab3e19SRatan Gupta     uint8_t chassis;
10982ab3e19SRatan Gupta     uint8_t board;
11082ab3e19SRatan Gupta     uint8_t product;
11182ab3e19SRatan Gupta     uint8_t multirec;
11282ab3e19SRatan Gupta } __attribute__((packed)) ipmi_fru_common_hdr_t;
11382ab3e19SRatan Gupta 
114c9508db8SPatrick Venture const char* vpd_key_names[] = {
11582ab3e19SRatan Gupta     "Key Names Table Start",
11682ab3e19SRatan Gupta     "Type",           /*OPENBMC_VPD_KEY_CHASSIS_TYPE*/
11782ab3e19SRatan Gupta     "Part Number",    /*OPENBMC_VPD_KEY_CHASSIS_PART_NUM,*/
11882ab3e19SRatan Gupta     "Serial Number",  /*OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,*/
11982ab3e19SRatan Gupta     "Custom Field 1", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM1,*/
12082ab3e19SRatan Gupta     "Custom Field 2", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM2,*/
12182ab3e19SRatan Gupta     "Custom Field 3", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM3,*/
12282ab3e19SRatan Gupta     "Custom Field 4", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM4,*/
12382ab3e19SRatan Gupta     "Custom Field 5", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM5,*/
12482ab3e19SRatan Gupta     "Custom Field 6", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM6,*/
12582ab3e19SRatan Gupta     "Custom Field 7", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM7,*/
12682ab3e19SRatan Gupta     "Custom Field 8", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,*/
12782ab3e19SRatan Gupta 
128c9508db8SPatrick Venture     "Mfg Date",
129c9508db8SPatrick Venture     /* OPENBMC_VPD_KEY_BOARD_MFG_DATE, */ /* not a type/len */
13082ab3e19SRatan Gupta     "Manufacturer",                       /* OPENBMC_VPD_KEY_BOARD_MFR, */
13182ab3e19SRatan Gupta     "Name",                               /* OPENBMC_VPD_KEY_BOARD_NAME, */
13282ab3e19SRatan Gupta     "Serial Number",      /* OPENBMC_VPD_KEY_BOARD_SERIAL_NUM, */
13382ab3e19SRatan Gupta     "Part Number",        /* OPENBMC_VPD_KEY_BOARD_PART_NUM, */
13482ab3e19SRatan Gupta     "FRU File ID",        /* OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID, */
13582ab3e19SRatan Gupta     "Custom Field 1",     /*OPENBMC_VPD_KEY_BOARD_CUSTOM1,*/
13682ab3e19SRatan Gupta     "Custom Field 2",     /*OPENBMC_VPD_KEY_BOARD_CUSTOM2,*/
13782ab3e19SRatan Gupta     "Custom Field 3",     /*OPENBMC_VPD_KEY_BOARD_CUSTOM3,*/
13882ab3e19SRatan Gupta     "Custom Field 4",     /*OPENBMC_VPD_KEY_BOARD_CUSTOM4,*/
13982ab3e19SRatan Gupta     "Custom Field 5",     /*OPENBMC_VPD_KEY_BOARD_CUSTOM5,*/
14082ab3e19SRatan Gupta     "Custom Field 6",     /*OPENBMC_VPD_KEY_BOARD_CUSTOM6,*/
14182ab3e19SRatan Gupta     "Custom Field 7",     /*OPENBMC_VPD_KEY_BOARD_CUSTOM7,*/
14282ab3e19SRatan Gupta     "Custom Field 8",     /*OPENBMC_VPD_KEY_BOARD_CUSTOM8,*/
14382ab3e19SRatan Gupta 
14482ab3e19SRatan Gupta     "Manufacturer",       /* OPENBMC_VPD_KEY_PRODUCT_MFR, */
14582ab3e19SRatan Gupta     "Name",               /* OPENBMC_VPD_KEY_PRODUCT_NAME, */
14682ab3e19SRatan Gupta     "Model Number",       /* OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM, */
14782ab3e19SRatan Gupta     "Version",            /* OPENBMC_VPD_KEY_PRODUCT_VER, */
14882ab3e19SRatan Gupta     "Serial Number",      /* OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM, */
14982ab3e19SRatan Gupta     "Asset Tag",          /* OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG, */
15082ab3e19SRatan Gupta     "FRU File ID",        /* OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID, */
15182ab3e19SRatan Gupta     "Custom Field 1",     /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM1,*/
15282ab3e19SRatan Gupta     "Custom Field 2",     /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM2,*/
15382ab3e19SRatan Gupta     "Custom Field 3",     /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM3,*/
15482ab3e19SRatan Gupta     "Custom Field 4",     /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM4,*/
15582ab3e19SRatan Gupta     "Custom Field 5",     /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM5,*/
15682ab3e19SRatan Gupta     "Custom Field 6",     /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM6,*/
15782ab3e19SRatan Gupta     "Custom Field 7",     /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM7,*/
15882ab3e19SRatan Gupta     "Custom Field 8",     /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,*/
15982ab3e19SRatan Gupta 
16082ab3e19SRatan Gupta     "Key Names Table End" /*OPENBMC_VPD_KEY_MAX,*/
16182ab3e19SRatan Gupta };
16282ab3e19SRatan Gupta 
16382ab3e19SRatan Gupta /*
16482ab3e19SRatan Gupta  * --------------------------------------------------------------------
16582ab3e19SRatan Gupta  *
16682ab3e19SRatan Gupta  * --------------------------------------------------------------------
16782ab3e19SRatan Gupta  */
16882ab3e19SRatan Gupta 
_to_time_str(uint32_t mfg_date_time,char * timestr,uint32_t len)16982ab3e19SRatan Gupta static size_t _to_time_str(uint32_t mfg_date_time, char* timestr, uint32_t len)
17082ab3e19SRatan Gupta {
17182ab3e19SRatan Gupta     struct tm tm;
17282ab3e19SRatan Gupta     time_t t;
17382ab3e19SRatan Gupta     size_t s;
17482ab3e19SRatan Gupta 
17582ab3e19SRatan Gupta     ASSERT(timestr);
17682ab3e19SRatan Gupta     ASSERT(len);
17782ab3e19SRatan Gupta 
17882ab3e19SRatan Gupta     memset(&tm, '\0', sizeof(struct tm));
17982ab3e19SRatan Gupta 
18082ab3e19SRatan Gupta     t = mfg_date_time;
18182ab3e19SRatan Gupta     gmtime_r(&t, &tm);
1829084f520SWilly Tu     s = strftime(timestr, len, "%F - %H:%M:%S UTC", &tm);
18382ab3e19SRatan Gupta 
18482ab3e19SRatan Gupta     return s;
18582ab3e19SRatan Gupta }
18682ab3e19SRatan Gupta 
18782ab3e19SRatan Gupta /* private method to parse type/length */
_parse_type_length(const void * areabuf,unsigned int areabuflen,unsigned int current_area_offset,uint8_t * number_of_data_bytes,ipmi_fru_field_t * field)188c9508db8SPatrick Venture static int _parse_type_length(const void* areabuf, unsigned int areabuflen,
18982ab3e19SRatan Gupta                               unsigned int current_area_offset,
19082ab3e19SRatan Gupta                               uint8_t* number_of_data_bytes,
19182ab3e19SRatan Gupta                               ipmi_fru_field_t* field)
19282ab3e19SRatan Gupta {
19382ab3e19SRatan Gupta     const uint8_t* areabufptr = (const uint8_t*)areabuf;
19482ab3e19SRatan Gupta     uint8_t type_length;
19582ab3e19SRatan Gupta     uint8_t type_code;
19682ab3e19SRatan Gupta 
19782ab3e19SRatan Gupta     ASSERT(areabuf);
19882ab3e19SRatan Gupta     ASSERT(areabuflen);
19982ab3e19SRatan Gupta     ASSERT(number_of_data_bytes);
20082ab3e19SRatan Gupta 
20182ab3e19SRatan Gupta     type_length = areabufptr[current_area_offset];
20282ab3e19SRatan Gupta 
20382ab3e19SRatan Gupta     /* ipmi workaround
20482ab3e19SRatan Gupta      *
20582ab3e19SRatan Gupta      * dell p weredge r610
20682ab3e19SRatan Gupta      *
20782ab3e19SRatan Gupta      * my reading of the fru spec is that all non-custom fields are
20882ab3e19SRatan Gupta      * required to be listed by the vendor.  however, on this
20982ab3e19SRatan Gupta      * motherboard, some areas list this, indicating that there is
21082ab3e19SRatan Gupta      * no more data to be parsed.  so now, for "required" fields, i
21182ab3e19SRatan Gupta      * check to see if the type-length field is a sentinel before
21282ab3e19SRatan Gupta      * calling this function.
21382ab3e19SRatan Gupta      */
21482ab3e19SRatan Gupta 
21582ab3e19SRatan Gupta     ASSERT(type_length != IPMI_FRU_SENTINEL_VALUE);
21682ab3e19SRatan Gupta 
217c9508db8SPatrick Venture     type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >>
218c9508db8SPatrick Venture                 IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
219cfa96afaSPatrick Williams     (*number_of_data_bytes) = type_length &
220cfa96afaSPatrick Williams                               IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
22182ab3e19SRatan Gupta 
22282ab3e19SRatan Gupta     /* special case: this shouldn't be a length of 0x01 (see type/length
22382ab3e19SRatan Gupta      * byte format in fru information storage definition).
22482ab3e19SRatan Gupta      */
225c9508db8SPatrick Venture     if (type_code == IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE &&
226c9508db8SPatrick Venture         (*number_of_data_bytes) == 0x01)
22782ab3e19SRatan Gupta     {
22882ab3e19SRatan Gupta         return (-1);
22982ab3e19SRatan Gupta     }
23082ab3e19SRatan Gupta 
23182ab3e19SRatan Gupta     if ((current_area_offset + 1 + (*number_of_data_bytes)) > areabuflen)
23282ab3e19SRatan Gupta     {
23382ab3e19SRatan Gupta         return (-1);
23482ab3e19SRatan Gupta     }
23582ab3e19SRatan Gupta 
23682ab3e19SRatan Gupta     if (field)
23782ab3e19SRatan Gupta     {
238c9508db8SPatrick Venture         memset(field->type_length_field, '\0',
23982ab3e19SRatan Gupta                IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
240c9508db8SPatrick Venture         memcpy(field->type_length_field, &areabufptr[current_area_offset],
24182ab3e19SRatan Gupta                1 + (*number_of_data_bytes));
24282ab3e19SRatan Gupta         field->type_length_field_length = 1 + (*number_of_data_bytes);
24382ab3e19SRatan Gupta     }
24482ab3e19SRatan Gupta 
24582ab3e19SRatan Gupta     return (0);
24682ab3e19SRatan Gupta }
24782ab3e19SRatan Gupta 
ipmi_fru_chassis_info_area(const void * areabuf,unsigned int areabuflen,uint8_t * chassis_type,ipmi_fru_field_t * chassis_part_number,ipmi_fru_field_t * chassis_serial_number,ipmi_fru_field_t * chassis_custom_fields,unsigned int chassis_custom_fields_len)248c9508db8SPatrick Venture int ipmi_fru_chassis_info_area(const void* areabuf, unsigned int areabuflen,
24982ab3e19SRatan Gupta                                uint8_t* chassis_type,
25082ab3e19SRatan Gupta                                ipmi_fru_field_t* chassis_part_number,
25182ab3e19SRatan Gupta                                ipmi_fru_field_t* chassis_serial_number,
25282ab3e19SRatan Gupta                                ipmi_fru_field_t* chassis_custom_fields,
25382ab3e19SRatan Gupta                                unsigned int chassis_custom_fields_len)
25482ab3e19SRatan Gupta {
25582ab3e19SRatan Gupta     const uint8_t* areabufptr = (const uint8_t*)areabuf;
25682ab3e19SRatan Gupta     unsigned int area_offset = 0;
25782ab3e19SRatan Gupta     unsigned int custom_fields_index = 0;
25882ab3e19SRatan Gupta     uint8_t number_of_data_bytes;
25982ab3e19SRatan Gupta     int rv = -1;
26082ab3e19SRatan Gupta 
26182ab3e19SRatan Gupta     if (!areabuf || !areabuflen)
26282ab3e19SRatan Gupta     {
26382ab3e19SRatan Gupta         return (-1);
26482ab3e19SRatan Gupta     }
26582ab3e19SRatan Gupta 
26682ab3e19SRatan Gupta     if (chassis_part_number)
267c9508db8SPatrick Venture         memset(chassis_part_number, '\0', sizeof(ipmi_fru_field_t));
26882ab3e19SRatan Gupta     if (chassis_serial_number)
269c9508db8SPatrick Venture         memset(chassis_serial_number, '\0', sizeof(ipmi_fru_field_t));
27082ab3e19SRatan Gupta     if (chassis_custom_fields && chassis_custom_fields_len)
271c9508db8SPatrick Venture         memset(chassis_custom_fields, '\0',
27282ab3e19SRatan Gupta                sizeof(ipmi_fru_field_t) * chassis_custom_fields_len);
27382ab3e19SRatan Gupta 
27482ab3e19SRatan Gupta     if (chassis_type)
27582ab3e19SRatan Gupta         (*chassis_type) = areabufptr[area_offset];
27682ab3e19SRatan Gupta     area_offset++;
27782ab3e19SRatan Gupta 
27882ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
27982ab3e19SRatan Gupta         goto out;
28082ab3e19SRatan Gupta 
281c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
282c9508db8SPatrick Venture                            &number_of_data_bytes, chassis_part_number) < 0)
28382ab3e19SRatan Gupta         goto cleanup;
28482ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
28582ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
28682ab3e19SRatan Gupta 
28782ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
28882ab3e19SRatan Gupta         goto out;
28982ab3e19SRatan Gupta 
290c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
291c9508db8SPatrick Venture                            &number_of_data_bytes, chassis_serial_number) < 0)
29282ab3e19SRatan Gupta         goto cleanup;
29382ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
29482ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
29582ab3e19SRatan Gupta 
296c9508db8SPatrick Venture     while (area_offset < areabuflen &&
297c9508db8SPatrick Venture            areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
29882ab3e19SRatan Gupta     {
29982ab3e19SRatan Gupta         ipmi_fru_field_t* field_ptr = NULL;
30082ab3e19SRatan Gupta 
30182ab3e19SRatan Gupta         if (chassis_custom_fields && chassis_custom_fields_len)
30282ab3e19SRatan Gupta         {
30382ab3e19SRatan Gupta             if (custom_fields_index < chassis_custom_fields_len)
30482ab3e19SRatan Gupta                 field_ptr = &chassis_custom_fields[custom_fields_index];
30582ab3e19SRatan Gupta             else
30682ab3e19SRatan Gupta             {
30782ab3e19SRatan Gupta                 goto cleanup;
30882ab3e19SRatan Gupta             }
30982ab3e19SRatan Gupta         }
31082ab3e19SRatan Gupta 
311c9508db8SPatrick Venture         if (_parse_type_length(areabufptr, areabuflen, area_offset,
312c9508db8SPatrick Venture                                &number_of_data_bytes, field_ptr) < 0)
31382ab3e19SRatan Gupta             goto cleanup;
31482ab3e19SRatan Gupta 
31582ab3e19SRatan Gupta         area_offset += 1; /* type/length byte */
31682ab3e19SRatan Gupta         area_offset += number_of_data_bytes;
31782ab3e19SRatan Gupta         custom_fields_index++;
31882ab3e19SRatan Gupta     }
31982ab3e19SRatan Gupta 
32082ab3e19SRatan Gupta out:
32182ab3e19SRatan Gupta     rv = 0;
32282ab3e19SRatan Gupta cleanup:
32382ab3e19SRatan Gupta     return (rv);
32482ab3e19SRatan Gupta }
32582ab3e19SRatan Gupta 
ipmi_fru_board_info_area(const void * areabuf,unsigned int areabuflen,uint8_t * language_code,uint32_t * mfg_date_time,ipmi_fru_field_t * board_manufacturer,ipmi_fru_field_t * board_product_name,ipmi_fru_field_t * board_serial_number,ipmi_fru_field_t * board_part_number,ipmi_fru_field_t * board_fru_file_id,ipmi_fru_field_t * board_custom_fields,unsigned int board_custom_fields_len)326c9508db8SPatrick Venture int ipmi_fru_board_info_area(
327c9508db8SPatrick Venture     const void* areabuf, unsigned int areabuflen, uint8_t* language_code,
328c9508db8SPatrick Venture     uint32_t* mfg_date_time, ipmi_fru_field_t* board_manufacturer,
329c9508db8SPatrick Venture     ipmi_fru_field_t* board_product_name, ipmi_fru_field_t* board_serial_number,
330c9508db8SPatrick Venture     ipmi_fru_field_t* board_part_number, ipmi_fru_field_t* board_fru_file_id,
331c9508db8SPatrick Venture     ipmi_fru_field_t* board_custom_fields, unsigned int board_custom_fields_len)
33282ab3e19SRatan Gupta {
33382ab3e19SRatan Gupta     const uint8_t* areabufptr = (const uint8_t*)areabuf;
33482ab3e19SRatan Gupta     unsigned int area_offset = 0;
33582ab3e19SRatan Gupta     unsigned int custom_fields_index = 0;
33682ab3e19SRatan Gupta     uint8_t number_of_data_bytes;
33782ab3e19SRatan Gupta     int rv = -1;
33882ab3e19SRatan Gupta 
33982ab3e19SRatan Gupta     if (!areabuf || !areabuflen)
34082ab3e19SRatan Gupta     {
34182ab3e19SRatan Gupta         return (-1);
34282ab3e19SRatan Gupta     }
34382ab3e19SRatan Gupta 
34482ab3e19SRatan Gupta     if (board_manufacturer)
345c9508db8SPatrick Venture         memset(board_manufacturer, '\0', sizeof(ipmi_fru_field_t));
34682ab3e19SRatan Gupta     if (board_product_name)
347c9508db8SPatrick Venture         memset(board_product_name, '\0', sizeof(ipmi_fru_field_t));
34882ab3e19SRatan Gupta     if (board_serial_number)
349c9508db8SPatrick Venture         memset(board_serial_number, '\0', sizeof(ipmi_fru_field_t));
35082ab3e19SRatan Gupta     if (board_part_number)
351c9508db8SPatrick Venture         memset(board_part_number, '\0', sizeof(ipmi_fru_field_t));
35282ab3e19SRatan Gupta     if (board_fru_file_id)
353c9508db8SPatrick Venture         memset(board_fru_file_id, '\0', sizeof(ipmi_fru_field_t));
35482ab3e19SRatan Gupta     if (board_custom_fields && board_custom_fields_len)
355c9508db8SPatrick Venture         memset(board_custom_fields, '\0',
35682ab3e19SRatan Gupta                sizeof(ipmi_fru_field_t) * board_custom_fields_len);
35782ab3e19SRatan Gupta 
35882ab3e19SRatan Gupta     if (language_code)
35982ab3e19SRatan Gupta         (*language_code) = areabufptr[area_offset];
36082ab3e19SRatan Gupta     area_offset++;
36182ab3e19SRatan Gupta 
36282ab3e19SRatan Gupta     if (mfg_date_time)
36382ab3e19SRatan Gupta     {
3649084f520SWilly Tu         unsigned int minutes = areabufptr[area_offset];
36582ab3e19SRatan Gupta         area_offset++;
3669084f520SWilly Tu         minutes |= (areabufptr[area_offset] << 8);
36782ab3e19SRatan Gupta         area_offset++;
3689084f520SWilly Tu         minutes |= (areabufptr[area_offset] << 16);
36982ab3e19SRatan Gupta         area_offset++;
37082ab3e19SRatan Gupta 
3719084f520SWilly Tu         /* In fru, epoch is 0:00 hrs 1/1/96 == 820454400
3729084f520SWilly Tu          * Remove it directly and remove the time conversion.
37382ab3e19SRatan Gupta          */
3749084f520SWilly Tu         (*mfg_date_time) = fruEpochMinutes + static_cast<long>(minutes) * 60;
37582ab3e19SRatan Gupta     }
37682ab3e19SRatan Gupta     else
37782ab3e19SRatan Gupta         area_offset += 3;
37882ab3e19SRatan Gupta 
37982ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
38082ab3e19SRatan Gupta         goto out;
38182ab3e19SRatan Gupta 
382c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
383c9508db8SPatrick Venture                            &number_of_data_bytes, board_manufacturer) < 0)
38482ab3e19SRatan Gupta         goto cleanup;
38582ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
38682ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
38782ab3e19SRatan Gupta 
38882ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
38982ab3e19SRatan Gupta         goto out;
39082ab3e19SRatan Gupta 
391c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
392c9508db8SPatrick Venture                            &number_of_data_bytes, board_product_name) < 0)
39382ab3e19SRatan Gupta         goto cleanup;
39482ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
39582ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
39682ab3e19SRatan Gupta 
39782ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
39882ab3e19SRatan Gupta         goto out;
39982ab3e19SRatan Gupta 
400c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
401c9508db8SPatrick Venture                            &number_of_data_bytes, board_serial_number) < 0)
40282ab3e19SRatan Gupta         goto cleanup;
40382ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
40482ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
40582ab3e19SRatan Gupta 
40682ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
40782ab3e19SRatan Gupta         goto out;
40882ab3e19SRatan Gupta 
409c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
410c9508db8SPatrick Venture                            &number_of_data_bytes, board_part_number) < 0)
41182ab3e19SRatan Gupta         goto cleanup;
41282ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
41382ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
41482ab3e19SRatan Gupta 
41582ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
41682ab3e19SRatan Gupta         goto out;
41782ab3e19SRatan Gupta 
418c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
419c9508db8SPatrick Venture                            &number_of_data_bytes, board_fru_file_id) < 0)
42082ab3e19SRatan Gupta         goto cleanup;
42182ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
42282ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
42382ab3e19SRatan Gupta 
424c9508db8SPatrick Venture     while (area_offset < areabuflen &&
425c9508db8SPatrick Venture            areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
42682ab3e19SRatan Gupta     {
42782ab3e19SRatan Gupta         ipmi_fru_field_t* field_ptr = NULL;
42882ab3e19SRatan Gupta 
42982ab3e19SRatan Gupta         if (board_custom_fields && board_custom_fields_len)
43082ab3e19SRatan Gupta         {
43182ab3e19SRatan Gupta             if (custom_fields_index < board_custom_fields_len)
43282ab3e19SRatan Gupta                 field_ptr = &board_custom_fields[custom_fields_index];
43382ab3e19SRatan Gupta             else
43482ab3e19SRatan Gupta             {
43582ab3e19SRatan Gupta                 goto cleanup;
43682ab3e19SRatan Gupta             }
43782ab3e19SRatan Gupta         }
43882ab3e19SRatan Gupta 
439c9508db8SPatrick Venture         if (_parse_type_length(areabufptr, areabuflen, area_offset,
440c9508db8SPatrick Venture                                &number_of_data_bytes, field_ptr) < 0)
44182ab3e19SRatan Gupta             goto cleanup;
44282ab3e19SRatan Gupta 
44382ab3e19SRatan Gupta         area_offset += 1; /* type/length byte */
44482ab3e19SRatan Gupta         area_offset += number_of_data_bytes;
44582ab3e19SRatan Gupta         custom_fields_index++;
44682ab3e19SRatan Gupta     }
44782ab3e19SRatan Gupta 
44882ab3e19SRatan Gupta out:
44982ab3e19SRatan Gupta     rv = 0;
45082ab3e19SRatan Gupta cleanup:
45182ab3e19SRatan Gupta     return (rv);
45282ab3e19SRatan Gupta }
45382ab3e19SRatan Gupta 
ipmi_fru_product_info_area(const void * areabuf,unsigned int areabuflen,uint8_t * language_code,ipmi_fru_field_t * product_manufacturer_name,ipmi_fru_field_t * product_name,ipmi_fru_field_t * product_part_model_number,ipmi_fru_field_t * product_version,ipmi_fru_field_t * product_serial_number,ipmi_fru_field_t * product_asset_tag,ipmi_fru_field_t * product_fru_file_id,ipmi_fru_field_t * product_custom_fields,unsigned int product_custom_fields_len)454c9508db8SPatrick Venture int ipmi_fru_product_info_area(
455c9508db8SPatrick Venture     const void* areabuf, unsigned int areabuflen, uint8_t* language_code,
456c9508db8SPatrick Venture     ipmi_fru_field_t* product_manufacturer_name, ipmi_fru_field_t* product_name,
45782ab3e19SRatan Gupta     ipmi_fru_field_t* product_part_model_number,
458c9508db8SPatrick Venture     ipmi_fru_field_t* product_version, ipmi_fru_field_t* product_serial_number,
459c9508db8SPatrick Venture     ipmi_fru_field_t* product_asset_tag, ipmi_fru_field_t* product_fru_file_id,
46082ab3e19SRatan Gupta     ipmi_fru_field_t* product_custom_fields,
46182ab3e19SRatan Gupta     unsigned int product_custom_fields_len)
46282ab3e19SRatan Gupta {
46382ab3e19SRatan Gupta     const uint8_t* areabufptr = (const uint8_t*)areabuf;
46482ab3e19SRatan Gupta     unsigned int area_offset = 0;
46582ab3e19SRatan Gupta     unsigned int custom_fields_index = 0;
46682ab3e19SRatan Gupta     uint8_t number_of_data_bytes;
46782ab3e19SRatan Gupta     int rv = -1;
46882ab3e19SRatan Gupta 
46982ab3e19SRatan Gupta     if (!areabuf || !areabuflen)
47082ab3e19SRatan Gupta     {
47182ab3e19SRatan Gupta         return (-1);
47282ab3e19SRatan Gupta     }
47382ab3e19SRatan Gupta 
47482ab3e19SRatan Gupta     if (product_manufacturer_name)
475c9508db8SPatrick Venture         memset(product_manufacturer_name, '\0', sizeof(ipmi_fru_field_t));
47682ab3e19SRatan Gupta     if (product_name)
477c9508db8SPatrick Venture         memset(product_name, '\0', sizeof(ipmi_fru_field_t));
47882ab3e19SRatan Gupta     if (product_part_model_number)
479c9508db8SPatrick Venture         memset(product_part_model_number, '\0', sizeof(ipmi_fru_field_t));
48082ab3e19SRatan Gupta     if (product_version)
481c9508db8SPatrick Venture         memset(product_version, '\0', sizeof(ipmi_fru_field_t));
48282ab3e19SRatan Gupta     if (product_serial_number)
483c9508db8SPatrick Venture         memset(product_serial_number, '\0', sizeof(ipmi_fru_field_t));
48482ab3e19SRatan Gupta     if (product_asset_tag)
485c9508db8SPatrick Venture         memset(product_asset_tag, '\0', sizeof(ipmi_fru_field_t));
48682ab3e19SRatan Gupta     if (product_fru_file_id)
487c9508db8SPatrick Venture         memset(product_fru_file_id, '\0', sizeof(ipmi_fru_field_t));
48882ab3e19SRatan Gupta     if (product_custom_fields && product_custom_fields_len)
489c9508db8SPatrick Venture         memset(product_custom_fields, '\0',
49082ab3e19SRatan Gupta                sizeof(ipmi_fru_field_t) * product_custom_fields_len);
49182ab3e19SRatan Gupta 
49282ab3e19SRatan Gupta     if (language_code)
49382ab3e19SRatan Gupta         (*language_code) = areabufptr[area_offset];
49482ab3e19SRatan Gupta     area_offset++;
49582ab3e19SRatan Gupta 
49682ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
49782ab3e19SRatan Gupta         goto out;
49882ab3e19SRatan Gupta 
499c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
50082ab3e19SRatan Gupta                            &number_of_data_bytes,
50182ab3e19SRatan Gupta                            product_manufacturer_name) < 0)
50282ab3e19SRatan Gupta         goto cleanup;
50382ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
50482ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
50582ab3e19SRatan Gupta 
50682ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
50782ab3e19SRatan Gupta         goto out;
50882ab3e19SRatan Gupta 
509c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
510c9508db8SPatrick Venture                            &number_of_data_bytes, product_name) < 0)
51182ab3e19SRatan Gupta         goto cleanup;
51282ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
51382ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
51482ab3e19SRatan Gupta 
51582ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
51682ab3e19SRatan Gupta         goto out;
51782ab3e19SRatan Gupta 
518c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
51982ab3e19SRatan Gupta                            &number_of_data_bytes,
52082ab3e19SRatan Gupta                            product_part_model_number) < 0)
52182ab3e19SRatan Gupta         goto cleanup;
52282ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
52382ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
52482ab3e19SRatan Gupta 
52582ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
52682ab3e19SRatan Gupta         goto out;
52782ab3e19SRatan Gupta 
528c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
529c9508db8SPatrick Venture                            &number_of_data_bytes, product_version) < 0)
53082ab3e19SRatan Gupta         goto cleanup;
53182ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
53282ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
53382ab3e19SRatan Gupta 
53482ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
53582ab3e19SRatan Gupta         goto out;
53682ab3e19SRatan Gupta 
537c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
538c9508db8SPatrick Venture                            &number_of_data_bytes, product_serial_number) < 0)
53982ab3e19SRatan Gupta         goto cleanup;
54082ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
54182ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
54282ab3e19SRatan Gupta 
54382ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
54482ab3e19SRatan Gupta         goto out;
54582ab3e19SRatan Gupta 
546c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
547c9508db8SPatrick Venture                            &number_of_data_bytes, product_asset_tag) < 0)
54882ab3e19SRatan Gupta         goto cleanup;
54982ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
55082ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
55182ab3e19SRatan Gupta 
55282ab3e19SRatan Gupta     if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
55382ab3e19SRatan Gupta         goto out;
55482ab3e19SRatan Gupta 
555c9508db8SPatrick Venture     if (_parse_type_length(areabufptr, areabuflen, area_offset,
556c9508db8SPatrick Venture                            &number_of_data_bytes, product_fru_file_id) < 0)
55782ab3e19SRatan Gupta         goto cleanup;
55882ab3e19SRatan Gupta 
55982ab3e19SRatan Gupta     area_offset += 1; /* type/length byte */
56082ab3e19SRatan Gupta     area_offset += number_of_data_bytes;
56182ab3e19SRatan Gupta 
562c9508db8SPatrick Venture     while (area_offset < areabuflen &&
563c9508db8SPatrick Venture            areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
56482ab3e19SRatan Gupta     {
56582ab3e19SRatan Gupta         ipmi_fru_field_t* field_ptr = NULL;
56682ab3e19SRatan Gupta 
56782ab3e19SRatan Gupta         if (product_custom_fields && product_custom_fields_len)
56882ab3e19SRatan Gupta         {
56982ab3e19SRatan Gupta             if (custom_fields_index < product_custom_fields_len)
57082ab3e19SRatan Gupta                 field_ptr = &product_custom_fields[custom_fields_index];
57182ab3e19SRatan Gupta             else
57282ab3e19SRatan Gupta             {
57382ab3e19SRatan Gupta                 goto cleanup;
57482ab3e19SRatan Gupta             }
57582ab3e19SRatan Gupta         }
57682ab3e19SRatan Gupta 
577c9508db8SPatrick Venture         if (_parse_type_length(areabufptr, areabuflen, area_offset,
578c9508db8SPatrick Venture                                &number_of_data_bytes, field_ptr) < 0)
57982ab3e19SRatan Gupta             goto cleanup;
58082ab3e19SRatan Gupta 
58182ab3e19SRatan Gupta         area_offset += 1; /* type/length byte */
58282ab3e19SRatan Gupta         area_offset += number_of_data_bytes;
58382ab3e19SRatan Gupta         custom_fields_index++;
58482ab3e19SRatan Gupta     }
58582ab3e19SRatan Gupta 
58682ab3e19SRatan Gupta out:
58782ab3e19SRatan Gupta     rv = 0;
58882ab3e19SRatan Gupta cleanup:
58982ab3e19SRatan Gupta     return (rv);
59082ab3e19SRatan Gupta }
59182ab3e19SRatan Gupta 
_append_to_dict(uint8_t vpd_key_id,uint8_t * vpd_key_val,IPMIFruInfo & info)592c9508db8SPatrick Venture void _append_to_dict(uint8_t vpd_key_id, uint8_t* vpd_key_val,
5938a2a675eSDeepak Kodihalli                      IPMIFruInfo& info)
59482ab3e19SRatan Gupta {
59582ab3e19SRatan Gupta     int type_length = vpd_key_val[0];
5968a2a675eSDeepak Kodihalli     int type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >>
5978a2a675eSDeepak Kodihalli                     IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
598cfa96afaSPatrick Williams     int vpd_val_len = type_length &
599cfa96afaSPatrick Williams                       IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
60082ab3e19SRatan Gupta 
60182ab3e19SRatan Gupta     /* Needed to convert each uint8_t byte to a ascii */
60282ab3e19SRatan Gupta     char bin_byte[3] = {0};
60382ab3e19SRatan Gupta 
60482ab3e19SRatan Gupta     /*
60582ab3e19SRatan Gupta      * Max number of characters needed to represent 1 unsigned byte in string
606c19b813eSGunnar Mills      * is number of bytes multiplied by 2. Extra 3 for 0x and a ending '\0';
60782ab3e19SRatan Gupta      */
60882ab3e19SRatan Gupta     char bin_in_ascii_len = vpd_val_len * 2 + 3;
60982ab3e19SRatan Gupta 
61082ab3e19SRatan Gupta     /* Binary converted to ascii in array */
61182ab3e19SRatan Gupta     char* bin_in_ascii = (char*)malloc(bin_in_ascii_len);
61282ab3e19SRatan Gupta 
61382ab3e19SRatan Gupta     /* For reading byte from the area */
614cb0d4e5eSRatan Gupta     int val = 0;
61582ab3e19SRatan Gupta 
61682ab3e19SRatan Gupta     char* bin_copy = &((char*)bin_in_ascii)[2];
61782ab3e19SRatan Gupta 
61882ab3e19SRatan Gupta     switch (type_code)
61982ab3e19SRatan Gupta     {
62082ab3e19SRatan Gupta         case 0:
62182ab3e19SRatan Gupta             memset(bin_in_ascii, 0x0, bin_in_ascii_len);
62282ab3e19SRatan Gupta 
62382ab3e19SRatan Gupta             /* Offset 1 is where actual data starts */
62482ab3e19SRatan Gupta             for (val = 1; val <= vpd_val_len; val++)
62582ab3e19SRatan Gupta             {
62682ab3e19SRatan Gupta                 /* 2 bytes for data and 1 for terminating '\0' */
62782ab3e19SRatan Gupta                 snprintf(bin_byte, 3, "%02x", vpd_key_val[val]);
62882ab3e19SRatan Gupta 
629*6f47bee5SPatrick Williams #pragma GCC diagnostic push
630*6f47bee5SPatrick Williams #pragma GCC diagnostic ignored "-Wstringop-truncation"
63182ab3e19SRatan Gupta                 /* Its a running string so strip off the '\0' */
63282ab3e19SRatan Gupta                 strncat(bin_copy, bin_byte, 2);
633*6f47bee5SPatrick Williams #pragma GCC diagnostic pop
63482ab3e19SRatan Gupta             }
63582ab3e19SRatan Gupta 
63682ab3e19SRatan Gupta             /* We need the data represented as 0x...... */
63782ab3e19SRatan Gupta             if (vpd_val_len > 0)
63882ab3e19SRatan Gupta             {
639ec73c958SBrad Bishop                 memcpy(bin_in_ascii, "0x", 2);
64082ab3e19SRatan Gupta             }
6414e41166cSAndrew Geissler #if IPMI_FRU_PARSER_DEBUG
6428a2a675eSDeepak Kodihalli             printf("_append_to_dict: VPD Key = [%s] : Type Code = [BINARY] :"
6438a2a675eSDeepak Kodihalli                    " Len = [%d] : Val = [%s]\n",
64482ab3e19SRatan Gupta                    vpd_key_names[vpd_key_id], vpd_val_len, bin_in_ascii);
6454e41166cSAndrew Geissler #endif
646cfa96afaSPatrick Williams             info[vpd_key_id] = std::make_pair(vpd_key_names[vpd_key_id],
647cfa96afaSPatrick Williams                                               bin_in_ascii);
64882ab3e19SRatan Gupta             break;
64982ab3e19SRatan Gupta 
65082ab3e19SRatan Gupta         case 3:
6514e41166cSAndrew Geissler #if IPMI_FRU_PARSER_DEBUG
6528a2a675eSDeepak Kodihalli             printf("_append_to_dict: VPD Key = [%s] : Type Code=[ASCII+Latin]"
6538a2a675eSDeepak Kodihalli                    " : Len = [%d] : Val = [%s]\n",
6548a2a675eSDeepak Kodihalli                    vpd_key_names[vpd_key_id], vpd_val_len, &vpd_key_val[1]);
6554e41166cSAndrew Geissler #endif
6568a2a675eSDeepak Kodihalli             info[vpd_key_id] = std::make_pair(
6578a2a675eSDeepak Kodihalli                 vpd_key_names[vpd_key_id],
658c9508db8SPatrick Venture                 std::string(vpd_key_val + 1, vpd_key_val + 1 + type_length));
65982ab3e19SRatan Gupta             break;
66082ab3e19SRatan Gupta     }
66182ab3e19SRatan Gupta 
66282ab3e19SRatan Gupta     if (bin_in_ascii)
66382ab3e19SRatan Gupta     {
66482ab3e19SRatan Gupta         free(bin_in_ascii);
66582ab3e19SRatan Gupta         bin_in_ascii = NULL;
66682ab3e19SRatan Gupta     }
66782ab3e19SRatan Gupta }
66882ab3e19SRatan Gupta 
parse_fru_area(const uint8_t area,const void * msgbuf,const size_t len,IPMIFruInfo & info)669c9508db8SPatrick Venture int parse_fru_area(const uint8_t area, const void* msgbuf, const size_t len,
670c9508db8SPatrick Venture                    IPMIFruInfo& info)
67182ab3e19SRatan Gupta {
67282ab3e19SRatan Gupta     int rv = -1;
67382ab3e19SRatan Gupta     int i = 0;
67482ab3e19SRatan Gupta 
67582ab3e19SRatan Gupta     /* Chassis */
67682ab3e19SRatan Gupta     uint8_t chassis_type;
67782ab3e19SRatan Gupta     /* Board */
67882ab3e19SRatan Gupta     uint32_t mfg_date_time;
67982ab3e19SRatan Gupta     /* Product */
68082ab3e19SRatan Gupta     // unsigned int product_custom_fields_len;
68182ab3e19SRatan Gupta 
68282ab3e19SRatan Gupta     // ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
68382ab3e19SRatan Gupta     ipmi_fru_field_t vpd_info[OPENBMC_VPD_KEY_MAX];
68482ab3e19SRatan Gupta     char timestr[OPENBMC_VPD_VAL_LEN];
68582ab3e19SRatan Gupta 
68682ab3e19SRatan Gupta     // uint8_t* ipmi_fru_field_str=NULL;
68782ab3e19SRatan Gupta     // ipmi_fru_common_hdr_t* chdr = NULL;
68882ab3e19SRatan Gupta     // uint8_t* hdr = NULL;
68982ab3e19SRatan Gupta 
69082ab3e19SRatan Gupta     ASSERT(msgbuf);
69182ab3e19SRatan Gupta 
69282ab3e19SRatan Gupta     for (i = 0; i < OPENBMC_VPD_KEY_MAX; i++)
69382ab3e19SRatan Gupta     {
6948a2a675eSDeepak Kodihalli         memset(vpd_info[i].type_length_field, '\0',
6958a2a675eSDeepak Kodihalli                IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
69682ab3e19SRatan Gupta         vpd_info[i].type_length_field_length = 0;
69782ab3e19SRatan Gupta     }
69882ab3e19SRatan Gupta 
69982ab3e19SRatan Gupta     switch (area)
70082ab3e19SRatan Gupta     {
70182ab3e19SRatan Gupta         case IPMI_FRU_AREA_CHASSIS_INFO:
70282ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG
70382ab3e19SRatan Gupta             printf("Chassis : Buf len = [%d]\n", len);
70482ab3e19SRatan Gupta #endif
705c9508db8SPatrick Venture             ipmi_fru_chassis_info_area(
706c9508db8SPatrick Venture                 (uint8_t*)msgbuf + 2, len, &chassis_type,
70782ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
70882ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
70982ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_CHASSIS_CUSTOM1],
71082ab3e19SRatan Gupta                 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
71182ab3e19SRatan Gupta 
71282ab3e19SRatan Gupta             /* Populate VPD Table */
71382ab3e19SRatan Gupta             for (i = 1; i <= OPENBMC_VPD_KEY_CHASSIS_MAX; i++)
71482ab3e19SRatan Gupta             {
71582ab3e19SRatan Gupta                 if (i == OPENBMC_VPD_KEY_CHASSIS_TYPE)
71682ab3e19SRatan Gupta                 {
71782ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG
7188a2a675eSDeepak Kodihalli                     printf("Chassis : Appending [%s] = [%d]\n",
7198a2a675eSDeepak Kodihalli                            vpd_key_names[i], chassis_type);
72082ab3e19SRatan Gupta #endif
721cb0d4e5eSRatan Gupta                     info[i] = std::make_pair(vpd_key_names[i],
722cb0d4e5eSRatan Gupta                                              std::to_string(chassis_type));
72382ab3e19SRatan Gupta                     continue;
72482ab3e19SRatan Gupta                 }
72510b7ea76SRatan Gupta                 _append_to_dict(i, vpd_info[i].type_length_field, info);
72682ab3e19SRatan Gupta             }
72782ab3e19SRatan Gupta             break;
72882ab3e19SRatan Gupta         case IPMI_FRU_AREA_BOARD_INFO:
72982ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG
73082ab3e19SRatan Gupta             printf("Board : Buf len = [%d]\n", len);
73182ab3e19SRatan Gupta #endif
732c9508db8SPatrick Venture             ipmi_fru_board_info_area(
733c9508db8SPatrick Venture                 (uint8_t*)msgbuf + 2, len, NULL, &mfg_date_time,
73482ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_BOARD_MFR],
73582ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_BOARD_NAME],
73682ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
73782ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_BOARD_PART_NUM],
73882ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
73982ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_BOARD_CUSTOM1],
74082ab3e19SRatan Gupta                 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
74182ab3e19SRatan Gupta 
74282ab3e19SRatan Gupta             /* Populate VPD Table */
7432796bf90STom Joseph             for (i = OPENBMC_VPD_KEY_BOARD_MFG_DATE;
7442796bf90STom Joseph                  i <= OPENBMC_VPD_KEY_BOARD_MAX; i++)
74582ab3e19SRatan Gupta             {
74682ab3e19SRatan Gupta                 if (i == OPENBMC_VPD_KEY_BOARD_MFG_DATE)
74782ab3e19SRatan Gupta                 {
74882ab3e19SRatan Gupta                     _to_time_str(mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN);
74982ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG
750c9508db8SPatrick Venture                     printf("Board : Appending [%s] = [%s]\n", vpd_key_names[i],
751c9508db8SPatrick Venture                            timestr);
75282ab3e19SRatan Gupta #endif
753cfa96afaSPatrick Williams                     info[i] = std::make_pair(vpd_key_names[i],
754cfa96afaSPatrick Williams                                              std::string(timestr));
75582ab3e19SRatan Gupta                     continue;
75682ab3e19SRatan Gupta                 }
7578a2a675eSDeepak Kodihalli                 _append_to_dict(i, vpd_info[i].type_length_field, info);
75882ab3e19SRatan Gupta             }
75982ab3e19SRatan Gupta             break;
76082ab3e19SRatan Gupta         case IPMI_FRU_AREA_PRODUCT_INFO:
76182ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG
76282ab3e19SRatan Gupta             printf("Product : Buf len = [%d]\n", len);
76382ab3e19SRatan Gupta #endif
764c9508db8SPatrick Venture             ipmi_fru_product_info_area(
765c9508db8SPatrick Venture                 (uint8_t*)msgbuf + 2, len, NULL,
76682ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_MFR],
76782ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_NAME],
76882ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM],
76982ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_VER],
77082ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
77182ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
77282ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
77382ab3e19SRatan Gupta                 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_CUSTOM1],
77482ab3e19SRatan Gupta                 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
77582ab3e19SRatan Gupta 
7768a2a675eSDeepak Kodihalli             for (i = OPENBMC_VPD_KEY_PRODUCT_MFR;
777c9508db8SPatrick Venture                  i <= OPENBMC_VPD_KEY_PRODUCT_MAX; ++i)
77882ab3e19SRatan Gupta             {
7798a2a675eSDeepak Kodihalli                 _append_to_dict(i, vpd_info[i].type_length_field, info);
78082ab3e19SRatan Gupta             }
78182ab3e19SRatan Gupta             break;
78282ab3e19SRatan Gupta         default:
78382ab3e19SRatan Gupta             /* TODO: Parse Multi Rec / Internal use area */
78482ab3e19SRatan Gupta             break;
78582ab3e19SRatan Gupta     }
78682ab3e19SRatan Gupta 
78782ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG
78882ab3e19SRatan Gupta     printf("parse_fru_area : Dictionary Packing Complete\n");
78982ab3e19SRatan Gupta #endif
79082ab3e19SRatan Gupta     rv = 0;
79182ab3e19SRatan Gupta     return (rv);
79282ab3e19SRatan Gupta }
793