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 84*9084f520SWilly Tu constexpr long fruEpochMinutes = 820454400; 85*9084f520SWilly 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 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); 182*9084f520SWilly 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 */ 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 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 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 { 364*9084f520SWilly Tu unsigned int minutes = areabufptr[area_offset]; 36582ab3e19SRatan Gupta area_offset++; 366*9084f520SWilly Tu minutes |= (areabufptr[area_offset] << 8); 36782ab3e19SRatan Gupta area_offset++; 368*9084f520SWilly Tu minutes |= (areabufptr[area_offset] << 16); 36982ab3e19SRatan Gupta area_offset++; 37082ab3e19SRatan Gupta 371*9084f520SWilly Tu /* In fru, epoch is 0:00 hrs 1/1/96 == 820454400 372*9084f520SWilly Tu * Remove it directly and remove the time conversion. 37382ab3e19SRatan Gupta */ 374*9084f520SWilly 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 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 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 62982ab3e19SRatan Gupta /* Its a running string so strip off the '\0' */ 63082ab3e19SRatan Gupta strncat(bin_copy, bin_byte, 2); 63182ab3e19SRatan Gupta } 63282ab3e19SRatan Gupta 63382ab3e19SRatan Gupta /* We need the data represented as 0x...... */ 63482ab3e19SRatan Gupta if (vpd_val_len > 0) 63582ab3e19SRatan Gupta { 636ec73c958SBrad Bishop memcpy(bin_in_ascii, "0x", 2); 63782ab3e19SRatan Gupta } 6384e41166cSAndrew Geissler #if IPMI_FRU_PARSER_DEBUG 6398a2a675eSDeepak Kodihalli printf("_append_to_dict: VPD Key = [%s] : Type Code = [BINARY] :" 6408a2a675eSDeepak Kodihalli " Len = [%d] : Val = [%s]\n", 64182ab3e19SRatan Gupta vpd_key_names[vpd_key_id], vpd_val_len, bin_in_ascii); 6424e41166cSAndrew Geissler #endif 643cfa96afaSPatrick Williams info[vpd_key_id] = std::make_pair(vpd_key_names[vpd_key_id], 644cfa96afaSPatrick Williams bin_in_ascii); 64582ab3e19SRatan Gupta break; 64682ab3e19SRatan Gupta 64782ab3e19SRatan Gupta case 3: 6484e41166cSAndrew Geissler #if IPMI_FRU_PARSER_DEBUG 6498a2a675eSDeepak Kodihalli printf("_append_to_dict: VPD Key = [%s] : Type Code=[ASCII+Latin]" 6508a2a675eSDeepak Kodihalli " : Len = [%d] : Val = [%s]\n", 6518a2a675eSDeepak Kodihalli vpd_key_names[vpd_key_id], vpd_val_len, &vpd_key_val[1]); 6524e41166cSAndrew Geissler #endif 6538a2a675eSDeepak Kodihalli info[vpd_key_id] = std::make_pair( 6548a2a675eSDeepak Kodihalli vpd_key_names[vpd_key_id], 655c9508db8SPatrick Venture std::string(vpd_key_val + 1, vpd_key_val + 1 + type_length)); 65682ab3e19SRatan Gupta break; 65782ab3e19SRatan Gupta } 65882ab3e19SRatan Gupta 65982ab3e19SRatan Gupta if (bin_in_ascii) 66082ab3e19SRatan Gupta { 66182ab3e19SRatan Gupta free(bin_in_ascii); 66282ab3e19SRatan Gupta bin_in_ascii = NULL; 66382ab3e19SRatan Gupta } 66482ab3e19SRatan Gupta } 66582ab3e19SRatan Gupta 666c9508db8SPatrick Venture int parse_fru_area(const uint8_t area, const void* msgbuf, const size_t len, 667c9508db8SPatrick Venture IPMIFruInfo& info) 66882ab3e19SRatan Gupta { 66982ab3e19SRatan Gupta int rv = -1; 67082ab3e19SRatan Gupta int i = 0; 67182ab3e19SRatan Gupta 67282ab3e19SRatan Gupta /* Chassis */ 67382ab3e19SRatan Gupta uint8_t chassis_type; 67482ab3e19SRatan Gupta /* Board */ 67582ab3e19SRatan Gupta uint32_t mfg_date_time; 67682ab3e19SRatan Gupta /* Product */ 67782ab3e19SRatan Gupta // unsigned int product_custom_fields_len; 67882ab3e19SRatan Gupta 67982ab3e19SRatan Gupta // ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ]; 68082ab3e19SRatan Gupta ipmi_fru_field_t vpd_info[OPENBMC_VPD_KEY_MAX]; 68182ab3e19SRatan Gupta char timestr[OPENBMC_VPD_VAL_LEN]; 68282ab3e19SRatan Gupta 68382ab3e19SRatan Gupta // uint8_t* ipmi_fru_field_str=NULL; 68482ab3e19SRatan Gupta // ipmi_fru_common_hdr_t* chdr = NULL; 68582ab3e19SRatan Gupta // uint8_t* hdr = NULL; 68682ab3e19SRatan Gupta 68782ab3e19SRatan Gupta ASSERT(msgbuf); 68882ab3e19SRatan Gupta 68982ab3e19SRatan Gupta for (i = 0; i < OPENBMC_VPD_KEY_MAX; i++) 69082ab3e19SRatan Gupta { 6918a2a675eSDeepak Kodihalli memset(vpd_info[i].type_length_field, '\0', 6928a2a675eSDeepak Kodihalli IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX); 69382ab3e19SRatan Gupta vpd_info[i].type_length_field_length = 0; 69482ab3e19SRatan Gupta } 69582ab3e19SRatan Gupta 69682ab3e19SRatan Gupta switch (area) 69782ab3e19SRatan Gupta { 69882ab3e19SRatan Gupta case IPMI_FRU_AREA_CHASSIS_INFO: 69982ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG 70082ab3e19SRatan Gupta printf("Chassis : Buf len = [%d]\n", len); 70182ab3e19SRatan Gupta #endif 702c9508db8SPatrick Venture ipmi_fru_chassis_info_area( 703c9508db8SPatrick Venture (uint8_t*)msgbuf + 2, len, &chassis_type, 70482ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_CHASSIS_PART_NUM], 70582ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM], 70682ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_CHASSIS_CUSTOM1], 70782ab3e19SRatan Gupta OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX); 70882ab3e19SRatan Gupta 70982ab3e19SRatan Gupta /* Populate VPD Table */ 71082ab3e19SRatan Gupta for (i = 1; i <= OPENBMC_VPD_KEY_CHASSIS_MAX; i++) 71182ab3e19SRatan Gupta { 71282ab3e19SRatan Gupta if (i == OPENBMC_VPD_KEY_CHASSIS_TYPE) 71382ab3e19SRatan Gupta { 71482ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG 7158a2a675eSDeepak Kodihalli printf("Chassis : Appending [%s] = [%d]\n", 7168a2a675eSDeepak Kodihalli vpd_key_names[i], chassis_type); 71782ab3e19SRatan Gupta #endif 718cb0d4e5eSRatan Gupta info[i] = std::make_pair(vpd_key_names[i], 719cb0d4e5eSRatan Gupta std::to_string(chassis_type)); 72082ab3e19SRatan Gupta continue; 72182ab3e19SRatan Gupta } 72210b7ea76SRatan Gupta _append_to_dict(i, vpd_info[i].type_length_field, info); 72382ab3e19SRatan Gupta } 72482ab3e19SRatan Gupta break; 72582ab3e19SRatan Gupta case IPMI_FRU_AREA_BOARD_INFO: 72682ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG 72782ab3e19SRatan Gupta printf("Board : Buf len = [%d]\n", len); 72882ab3e19SRatan Gupta #endif 729c9508db8SPatrick Venture ipmi_fru_board_info_area( 730c9508db8SPatrick Venture (uint8_t*)msgbuf + 2, len, NULL, &mfg_date_time, 73182ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_BOARD_MFR], 73282ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_BOARD_NAME], 73382ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_BOARD_SERIAL_NUM], 73482ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_BOARD_PART_NUM], 73582ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID], 73682ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_BOARD_CUSTOM1], 73782ab3e19SRatan Gupta OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX); 73882ab3e19SRatan Gupta 73982ab3e19SRatan Gupta /* Populate VPD Table */ 7402796bf90STom Joseph for (i = OPENBMC_VPD_KEY_BOARD_MFG_DATE; 7412796bf90STom Joseph i <= OPENBMC_VPD_KEY_BOARD_MAX; i++) 74282ab3e19SRatan Gupta { 74382ab3e19SRatan Gupta if (i == OPENBMC_VPD_KEY_BOARD_MFG_DATE) 74482ab3e19SRatan Gupta { 74582ab3e19SRatan Gupta _to_time_str(mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN); 74682ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG 747c9508db8SPatrick Venture printf("Board : Appending [%s] = [%s]\n", vpd_key_names[i], 748c9508db8SPatrick Venture timestr); 74982ab3e19SRatan Gupta #endif 750cfa96afaSPatrick Williams info[i] = std::make_pair(vpd_key_names[i], 751cfa96afaSPatrick Williams std::string(timestr)); 75282ab3e19SRatan Gupta continue; 75382ab3e19SRatan Gupta } 7548a2a675eSDeepak Kodihalli _append_to_dict(i, vpd_info[i].type_length_field, info); 75582ab3e19SRatan Gupta } 75682ab3e19SRatan Gupta break; 75782ab3e19SRatan Gupta case IPMI_FRU_AREA_PRODUCT_INFO: 75882ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG 75982ab3e19SRatan Gupta printf("Product : Buf len = [%d]\n", len); 76082ab3e19SRatan Gupta #endif 761c9508db8SPatrick Venture ipmi_fru_product_info_area( 762c9508db8SPatrick Venture (uint8_t*)msgbuf + 2, len, NULL, 76382ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_PRODUCT_MFR], 76482ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_PRODUCT_NAME], 76582ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM], 76682ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_PRODUCT_VER], 76782ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM], 76882ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG], 76982ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID], 77082ab3e19SRatan Gupta &vpd_info[OPENBMC_VPD_KEY_PRODUCT_CUSTOM1], 77182ab3e19SRatan Gupta OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX); 77282ab3e19SRatan Gupta 7738a2a675eSDeepak Kodihalli for (i = OPENBMC_VPD_KEY_PRODUCT_MFR; 774c9508db8SPatrick Venture i <= OPENBMC_VPD_KEY_PRODUCT_MAX; ++i) 77582ab3e19SRatan Gupta { 7768a2a675eSDeepak Kodihalli _append_to_dict(i, vpd_info[i].type_length_field, info); 77782ab3e19SRatan Gupta } 77882ab3e19SRatan Gupta break; 77982ab3e19SRatan Gupta default: 78082ab3e19SRatan Gupta /* TODO: Parse Multi Rec / Internal use area */ 78182ab3e19SRatan Gupta break; 78282ab3e19SRatan Gupta } 78382ab3e19SRatan Gupta 78482ab3e19SRatan Gupta #if IPMI_FRU_PARSER_DEBUG 78582ab3e19SRatan Gupta printf("parse_fru_area : Dictionary Packing Complete\n"); 78682ab3e19SRatan Gupta #endif 78782ab3e19SRatan Gupta rv = 0; 78882ab3e19SRatan Gupta return (rv); 78982ab3e19SRatan Gupta } 790