blob: dddeee4d7ac2bfa4eb04ea8a8585d853a5702184 [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\*****************************************************************************/
Ratan Gupta19c617b2017-02-10 15:39:40 +053042#include "frup.hpp"
Hariharasubramanian R44473092015-10-15 08:25:28 -050043
Patrick Venturec9508db2018-10-16 17:18:43 -070044#include <ctype.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <systemd/sd-bus.h>
49#include <time.h>
50#include <unistd.h>
Hariharasubramanian R44473092015-10-15 08:25:28 -050051
Patrick Venturec9508db2018-10-16 17:18:43 -070052#define TEXTSTR(a) #a
53#define ASSERT(x) \
54 do \
55 { \
56 if (0 == (x)) \
57 { \
58 fprintf(stderr, \
59 "Assertion failed: %s, " \
60 "%d at \'%s\'\n", \
61 __FILE__, __LINE__, TEXTSTR(a)); \
62 return -1; \
63 } \
64 } while (0)
65
66#define IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX 512
67#define IPMI_FRU_SENTINEL_VALUE 0xC1
68#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK 0xC0
69#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT 0x06
Hariharasubramanian R44473092015-10-15 08:25:28 -050070#define IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK 0x3F
Patrick Venturec9508db2018-10-16 17:18:43 -070071#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE 0x03
Hariharasubramanian R44473092015-10-15 08:25:28 -050072
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050073/* OpenBMC defines for Parser */
Patrick Venturec9508db2018-10-16 17:18:43 -070074#define IPMI_FRU_AREA_INTERNAL_USE 0x00
75#define IPMI_FRU_AREA_CHASSIS_INFO 0x01
76#define IPMI_FRU_AREA_BOARD_INFO 0x02
77#define IPMI_FRU_AREA_PRODUCT_INFO 0x03
78#define IPMI_FRU_AREA_MULTI_RECORD 0x04
79#define IPMI_FRU_AREA_TYPE_MAX 0x05
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050080
Patrick Venturec9508db2018-10-16 17:18:43 -070081#define OPENBMC_VPD_KEY_LEN 64
82#define OPENBMC_VPD_VAL_LEN 512
Hariharasubramanian R44473092015-10-15 08:25:28 -050083
84struct ipmi_fru_field
85{
Patrick Venturec9508db2018-10-16 17:18:43 -070086 uint8_t type_length_field[IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX];
87 /* store length of data stored in buffer */
88 unsigned int type_length_field_length;
Hariharasubramanian R44473092015-10-15 08:25:28 -050089};
90
91typedef struct ipmi_fru_field ipmi_fru_field_t;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -050092/*
93 * FRU Parser
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050094 */
Hariharasubramanian R44473092015-10-15 08:25:28 -050095
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050096typedef struct ipmi_fru_area_info
97{
98 uint8_t off;
99 uint8_t len;
100} ipmi_fru_area_info_t;
101
102typedef struct ipmi_fru_common_hdr
103{
104 uint8_t fmtver;
105 uint8_t internal;
106 uint8_t chassis;
107 uint8_t board;
108 uint8_t product;
109 uint8_t multirec;
110} __attribute__((packed)) ipmi_fru_common_hdr_t;
111
Patrick Venturec9508db2018-10-16 17:18:43 -0700112const char* vpd_key_names[] = {
113 "Key Names Table Start",
114 "Type", /*OPENBMC_VPD_KEY_CHASSIS_TYPE*/
115 "Part Number", /*OPENBMC_VPD_KEY_CHASSIS_PART_NUM,*/
116 "Serial Number", /*OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,*/
117 "Custom Field 1", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM1,*/
118 "Custom Field 2", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM2,*/
119 "Custom Field 3", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM3,*/
120 "Custom Field 4", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM4,*/
121 "Custom Field 5", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM5,*/
122 "Custom Field 6", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM6,*/
123 "Custom Field 7", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM7,*/
124 "Custom Field 8", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500125
Patrick Venturec9508db2018-10-16 17:18:43 -0700126 "Mfg Date",
127 /* OPENBMC_VPD_KEY_BOARD_MFG_DATE, */ /* not a type/len */
128 "Manufacturer", /* OPENBMC_VPD_KEY_BOARD_MFR, */
129 "Name", /* OPENBMC_VPD_KEY_BOARD_NAME, */
Patrick Williamscfa96af2023-05-10 07:50:26 -0500130 "Serial Number", /* OPENBMC_VPD_KEY_BOARD_SERIAL_NUM, */
131 "Part Number", /* OPENBMC_VPD_KEY_BOARD_PART_NUM, */
132 "FRU File ID", /* OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID, */
133 "Custom Field 1", /*OPENBMC_VPD_KEY_BOARD_CUSTOM1,*/
134 "Custom Field 2", /*OPENBMC_VPD_KEY_BOARD_CUSTOM2,*/
135 "Custom Field 3", /*OPENBMC_VPD_KEY_BOARD_CUSTOM3,*/
136 "Custom Field 4", /*OPENBMC_VPD_KEY_BOARD_CUSTOM4,*/
137 "Custom Field 5", /*OPENBMC_VPD_KEY_BOARD_CUSTOM5,*/
138 "Custom Field 6", /*OPENBMC_VPD_KEY_BOARD_CUSTOM6,*/
139 "Custom Field 7", /*OPENBMC_VPD_KEY_BOARD_CUSTOM7,*/
140 "Custom Field 8", /*OPENBMC_VPD_KEY_BOARD_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500141
Patrick Williamscfa96af2023-05-10 07:50:26 -0500142 "Manufacturer", /* OPENBMC_VPD_KEY_PRODUCT_MFR, */
143 "Name", /* OPENBMC_VPD_KEY_PRODUCT_NAME, */
144 "Model Number", /* OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM, */
145 "Version", /* OPENBMC_VPD_KEY_PRODUCT_VER, */
146 "Serial Number", /* OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM, */
147 "Asset Tag", /* OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG, */
148 "FRU File ID", /* OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID, */
149 "Custom Field 1", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM1,*/
150 "Custom Field 2", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM2,*/
151 "Custom Field 3", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM3,*/
152 "Custom Field 4", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM4,*/
153 "Custom Field 5", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM5,*/
154 "Custom Field 6", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM6,*/
155 "Custom Field 7", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM7,*/
156 "Custom Field 8", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500157
Patrick Venturec9508db2018-10-16 17:18:43 -0700158 "Key Names Table End" /*OPENBMC_VPD_KEY_MAX,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500159};
160
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500161/*
162 * --------------------------------------------------------------------
163 *
164 * --------------------------------------------------------------------
165 */
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500166
Patrick Venturec9508db2018-10-16 17:18:43 -0700167static size_t _to_time_str(uint32_t mfg_date_time, char* timestr, uint32_t len)
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500168{
169 struct tm tm;
170 time_t t;
171 size_t s;
172
Patrick Venturec9508db2018-10-16 17:18:43 -0700173 ASSERT(timestr);
174 ASSERT(len);
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500175
Patrick Venturec9508db2018-10-16 17:18:43 -0700176 memset(&tm, '\0', sizeof(struct tm));
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500177
178 t = mfg_date_time;
Patrick Venturec9508db2018-10-16 17:18:43 -0700179 gmtime_r(&t, &tm);
180 s = strftime(timestr, len, "%F - %H:%M:%S", &tm);
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500181
182 return s;
183}
184
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500185/* private method to parse type/length */
Patrick Venturec9508db2018-10-16 17:18:43 -0700186static int _parse_type_length(const void* areabuf, unsigned int areabuflen,
187 unsigned int current_area_offset,
188 uint8_t* number_of_data_bytes,
189 ipmi_fru_field_t* field)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500190{
Patrick Venturec9508db2018-10-16 17:18:43 -0700191 const uint8_t* areabufptr = (const uint8_t*)areabuf;
192 uint8_t type_length;
193 uint8_t type_code;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500194
Patrick Venturec9508db2018-10-16 17:18:43 -0700195 ASSERT(areabuf);
196 ASSERT(areabuflen);
197 ASSERT(number_of_data_bytes);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500198
Patrick Venturec9508db2018-10-16 17:18:43 -0700199 type_length = areabufptr[current_area_offset];
Hariharasubramanian R44473092015-10-15 08:25:28 -0500200
Patrick Venturec9508db2018-10-16 17:18:43 -0700201 /* ipmi workaround
202 *
203 * dell p weredge r610
204 *
205 * my reading of the fru spec is that all non-custom fields are
206 * required to be listed by the vendor. however, on this
207 * motherboard, some areas list this, indicating that there is
208 * no more data to be parsed. so now, for "required" fields, i
209 * check to see if the type-length field is a sentinel before
210 * calling this function.
211 */
Hariharasubramanian R44473092015-10-15 08:25:28 -0500212
Patrick Venturec9508db2018-10-16 17:18:43 -0700213 ASSERT(type_length != IPMI_FRU_SENTINEL_VALUE);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500214
Patrick Venturec9508db2018-10-16 17:18:43 -0700215 type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >>
216 IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
Patrick Williamscfa96af2023-05-10 07:50:26 -0500217 (*number_of_data_bytes) = type_length &
218 IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500219
Patrick Venturec9508db2018-10-16 17:18:43 -0700220 /* special case: this shouldn't be a length of 0x01 (see type/length
221 * byte format in fru information storage definition).
222 */
223 if (type_code == IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE &&
224 (*number_of_data_bytes) == 0x01)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500225 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700226 return (-1);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500227 }
228
Patrick Venturec9508db2018-10-16 17:18:43 -0700229 if ((current_area_offset + 1 + (*number_of_data_bytes)) > areabuflen)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500230 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700231 return (-1);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500232 }
233
Patrick Venturec9508db2018-10-16 17:18:43 -0700234 if (field)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500235 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700236 memset(field->type_length_field, '\0',
237 IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
238 memcpy(field->type_length_field, &areabufptr[current_area_offset],
239 1 + (*number_of_data_bytes));
240 field->type_length_field_length = 1 + (*number_of_data_bytes);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500241 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500242
Patrick Venturec9508db2018-10-16 17:18:43 -0700243 return (0);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500244}
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500245
Patrick Venturec9508db2018-10-16 17:18:43 -0700246int ipmi_fru_chassis_info_area(const void* areabuf, unsigned int areabuflen,
247 uint8_t* chassis_type,
248 ipmi_fru_field_t* chassis_part_number,
249 ipmi_fru_field_t* chassis_serial_number,
250 ipmi_fru_field_t* chassis_custom_fields,
251 unsigned int chassis_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500252{
Patrick Venturec9508db2018-10-16 17:18:43 -0700253 const uint8_t* areabufptr = (const uint8_t*)areabuf;
254 unsigned int area_offset = 0;
255 unsigned int custom_fields_index = 0;
256 uint8_t number_of_data_bytes;
257 int rv = -1;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500258
Patrick Venturec9508db2018-10-16 17:18:43 -0700259 if (!areabuf || !areabuflen)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500260 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700261 return (-1);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500262 }
263
Patrick Venturec9508db2018-10-16 17:18:43 -0700264 if (chassis_part_number)
265 memset(chassis_part_number, '\0', sizeof(ipmi_fru_field_t));
266 if (chassis_serial_number)
267 memset(chassis_serial_number, '\0', sizeof(ipmi_fru_field_t));
268 if (chassis_custom_fields && chassis_custom_fields_len)
269 memset(chassis_custom_fields, '\0',
270 sizeof(ipmi_fru_field_t) * chassis_custom_fields_len);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500271
Patrick Venturec9508db2018-10-16 17:18:43 -0700272 if (chassis_type)
273 (*chassis_type) = areabufptr[area_offset];
274 area_offset++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500275
Patrick Venturec9508db2018-10-16 17:18:43 -0700276 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
277 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500278
Patrick Venturec9508db2018-10-16 17:18:43 -0700279 if (_parse_type_length(areabufptr, areabuflen, area_offset,
280 &number_of_data_bytes, chassis_part_number) < 0)
281 goto cleanup;
282 area_offset += 1; /* type/length byte */
283 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500284
Patrick Venturec9508db2018-10-16 17:18:43 -0700285 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
286 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500287
Patrick Venturec9508db2018-10-16 17:18:43 -0700288 if (_parse_type_length(areabufptr, areabuflen, area_offset,
289 &number_of_data_bytes, chassis_serial_number) < 0)
290 goto cleanup;
291 area_offset += 1; /* type/length byte */
292 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500293
Patrick Venturec9508db2018-10-16 17:18:43 -0700294 while (area_offset < areabuflen &&
295 areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500296 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700297 ipmi_fru_field_t* field_ptr = NULL;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500298
Patrick Venturec9508db2018-10-16 17:18:43 -0700299 if (chassis_custom_fields && chassis_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500300 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700301 if (custom_fields_index < chassis_custom_fields_len)
302 field_ptr = &chassis_custom_fields[custom_fields_index];
303 else
Hariharasubramanian R44473092015-10-15 08:25:28 -0500304 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700305 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500306 }
307 }
308
Patrick Venturec9508db2018-10-16 17:18:43 -0700309 if (_parse_type_length(areabufptr, areabuflen, area_offset,
310 &number_of_data_bytes, field_ptr) < 0)
311 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500312
Patrick Venturec9508db2018-10-16 17:18:43 -0700313 area_offset += 1; /* type/length byte */
314 area_offset += number_of_data_bytes;
315 custom_fields_index++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500316 }
317
Patrick Venturec9508db2018-10-16 17:18:43 -0700318out:
319 rv = 0;
320cleanup:
321 return (rv);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500322}
323
Patrick Venturec9508db2018-10-16 17:18:43 -0700324int ipmi_fru_board_info_area(
325 const void* areabuf, unsigned int areabuflen, uint8_t* language_code,
326 uint32_t* mfg_date_time, ipmi_fru_field_t* board_manufacturer,
327 ipmi_fru_field_t* board_product_name, ipmi_fru_field_t* board_serial_number,
328 ipmi_fru_field_t* board_part_number, ipmi_fru_field_t* board_fru_file_id,
329 ipmi_fru_field_t* board_custom_fields, unsigned int board_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500330{
Patrick Venturec9508db2018-10-16 17:18:43 -0700331 const uint8_t* areabufptr = (const uint8_t*)areabuf;
332 uint32_t mfg_date_time_tmp = 0;
333 unsigned int area_offset = 0;
334 unsigned int custom_fields_index = 0;
335 uint8_t number_of_data_bytes;
336 int rv = -1;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500337
Patrick Venturec9508db2018-10-16 17:18:43 -0700338 if (!areabuf || !areabuflen)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500339 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700340 return (-1);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500341 }
342
Patrick Venturec9508db2018-10-16 17:18:43 -0700343 if (board_manufacturer)
344 memset(board_manufacturer, '\0', sizeof(ipmi_fru_field_t));
345 if (board_product_name)
346 memset(board_product_name, '\0', sizeof(ipmi_fru_field_t));
347 if (board_serial_number)
348 memset(board_serial_number, '\0', sizeof(ipmi_fru_field_t));
349 if (board_part_number)
350 memset(board_part_number, '\0', sizeof(ipmi_fru_field_t));
351 if (board_fru_file_id)
352 memset(board_fru_file_id, '\0', sizeof(ipmi_fru_field_t));
353 if (board_custom_fields && board_custom_fields_len)
354 memset(board_custom_fields, '\0',
355 sizeof(ipmi_fru_field_t) * board_custom_fields_len);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500356
Patrick Venturec9508db2018-10-16 17:18:43 -0700357 if (language_code)
358 (*language_code) = areabufptr[area_offset];
359 area_offset++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500360
Patrick Venturec9508db2018-10-16 17:18:43 -0700361 if (mfg_date_time)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500362 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700363 struct tm tm;
364 time_t t;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500365
Patrick Venturec9508db2018-10-16 17:18:43 -0700366 /* mfg_date_time is little endian - see spec */
367 mfg_date_time_tmp |= areabufptr[area_offset];
368 area_offset++;
369 mfg_date_time_tmp |= (areabufptr[area_offset] << 8);
370 area_offset++;
371 mfg_date_time_tmp |= (areabufptr[area_offset] << 16);
372 area_offset++;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500373
Patrick Venturec9508db2018-10-16 17:18:43 -0700374 /* mfg_date_time is in minutes, so multiple by 60 to get seconds */
375 mfg_date_time_tmp *= 60;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500376
Patrick Venturec9508db2018-10-16 17:18:43 -0700377 /* posix says individual calls need not clear/set all portions of
378 * 'struct tm', thus passing 'struct tm' between functions could
379 * have issues. so we need to memset.
380 */
381 memset(&tm, '\0', sizeof(struct tm));
Hariharasubramanian R44473092015-10-15 08:25:28 -0500382
Patrick Venturec9508db2018-10-16 17:18:43 -0700383 /* in fru, epoch is 0:00 hrs 1/1/96
384 *
385 * so convert into ansi epoch
386 */
Hariharasubramanian R44473092015-10-15 08:25:28 -0500387
Patrick Venturec9508db2018-10-16 17:18:43 -0700388 tm.tm_year = 96; /* years since 1900 */
389 tm.tm_mon = 0; /* months since january */
390 tm.tm_mday = 1; /* 1-31 */
391 tm.tm_hour = 0;
392 tm.tm_min = 0;
393 tm.tm_sec = 0;
394 tm.tm_isdst = -1;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500395
Patrick Venturec9508db2018-10-16 17:18:43 -0700396 if ((t = mktime(&tm)) == (time_t)-1)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500397 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700398 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500399 }
400
Patrick Venturec9508db2018-10-16 17:18:43 -0700401 mfg_date_time_tmp += (uint32_t)t;
402 (*mfg_date_time) = mfg_date_time_tmp;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500403 }
Patrick Venturec9508db2018-10-16 17:18:43 -0700404 else
405 area_offset += 3;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500406
Patrick Venturec9508db2018-10-16 17:18:43 -0700407 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
408 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500409
Patrick Venturec9508db2018-10-16 17:18:43 -0700410 if (_parse_type_length(areabufptr, areabuflen, area_offset,
411 &number_of_data_bytes, board_manufacturer) < 0)
412 goto cleanup;
413 area_offset += 1; /* type/length byte */
414 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500415
Patrick Venturec9508db2018-10-16 17:18:43 -0700416 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
417 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500418
Patrick Venturec9508db2018-10-16 17:18:43 -0700419 if (_parse_type_length(areabufptr, areabuflen, area_offset,
420 &number_of_data_bytes, board_product_name) < 0)
421 goto cleanup;
422 area_offset += 1; /* type/length byte */
423 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500424
Patrick Venturec9508db2018-10-16 17:18:43 -0700425 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
426 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500427
Patrick Venturec9508db2018-10-16 17:18:43 -0700428 if (_parse_type_length(areabufptr, areabuflen, area_offset,
429 &number_of_data_bytes, board_serial_number) < 0)
430 goto cleanup;
431 area_offset += 1; /* type/length byte */
432 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500433
Patrick Venturec9508db2018-10-16 17:18:43 -0700434 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
435 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500436
Patrick Venturec9508db2018-10-16 17:18:43 -0700437 if (_parse_type_length(areabufptr, areabuflen, area_offset,
438 &number_of_data_bytes, board_part_number) < 0)
439 goto cleanup;
440 area_offset += 1; /* type/length byte */
441 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500442
Patrick Venturec9508db2018-10-16 17:18:43 -0700443 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
444 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500445
Patrick Venturec9508db2018-10-16 17:18:43 -0700446 if (_parse_type_length(areabufptr, areabuflen, area_offset,
447 &number_of_data_bytes, board_fru_file_id) < 0)
448 goto cleanup;
449 area_offset += 1; /* type/length byte */
450 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500451
Patrick Venturec9508db2018-10-16 17:18:43 -0700452 while (area_offset < areabuflen &&
453 areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500454 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700455 ipmi_fru_field_t* field_ptr = NULL;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500456
Patrick Venturec9508db2018-10-16 17:18:43 -0700457 if (board_custom_fields && board_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500458 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700459 if (custom_fields_index < board_custom_fields_len)
460 field_ptr = &board_custom_fields[custom_fields_index];
461 else
Hariharasubramanian R44473092015-10-15 08:25:28 -0500462 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700463 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500464 }
465 }
466
Patrick Venturec9508db2018-10-16 17:18:43 -0700467 if (_parse_type_length(areabufptr, areabuflen, area_offset,
468 &number_of_data_bytes, field_ptr) < 0)
469 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500470
Patrick Venturec9508db2018-10-16 17:18:43 -0700471 area_offset += 1; /* type/length byte */
472 area_offset += number_of_data_bytes;
473 custom_fields_index++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500474 }
475
Patrick Venturec9508db2018-10-16 17:18:43 -0700476out:
477 rv = 0;
478cleanup:
479 return (rv);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500480}
481
Patrick Venturec9508db2018-10-16 17:18:43 -0700482int ipmi_fru_product_info_area(
483 const void* areabuf, unsigned int areabuflen, uint8_t* language_code,
484 ipmi_fru_field_t* product_manufacturer_name, ipmi_fru_field_t* product_name,
485 ipmi_fru_field_t* product_part_model_number,
486 ipmi_fru_field_t* product_version, ipmi_fru_field_t* product_serial_number,
487 ipmi_fru_field_t* product_asset_tag, ipmi_fru_field_t* product_fru_file_id,
488 ipmi_fru_field_t* product_custom_fields,
489 unsigned int product_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500490{
Patrick Venturec9508db2018-10-16 17:18:43 -0700491 const uint8_t* areabufptr = (const uint8_t*)areabuf;
492 unsigned int area_offset = 0;
493 unsigned int custom_fields_index = 0;
494 uint8_t number_of_data_bytes;
495 int rv = -1;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500496
Patrick Venturec9508db2018-10-16 17:18:43 -0700497 if (!areabuf || !areabuflen)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500498 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700499 return (-1);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500500 }
501
Patrick Venturec9508db2018-10-16 17:18:43 -0700502 if (product_manufacturer_name)
503 memset(product_manufacturer_name, '\0', sizeof(ipmi_fru_field_t));
504 if (product_name)
505 memset(product_name, '\0', sizeof(ipmi_fru_field_t));
506 if (product_part_model_number)
507 memset(product_part_model_number, '\0', sizeof(ipmi_fru_field_t));
508 if (product_version)
509 memset(product_version, '\0', sizeof(ipmi_fru_field_t));
510 if (product_serial_number)
511 memset(product_serial_number, '\0', sizeof(ipmi_fru_field_t));
512 if (product_asset_tag)
513 memset(product_asset_tag, '\0', sizeof(ipmi_fru_field_t));
514 if (product_fru_file_id)
515 memset(product_fru_file_id, '\0', sizeof(ipmi_fru_field_t));
516 if (product_custom_fields && product_custom_fields_len)
517 memset(product_custom_fields, '\0',
518 sizeof(ipmi_fru_field_t) * product_custom_fields_len);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500519
Patrick Venturec9508db2018-10-16 17:18:43 -0700520 if (language_code)
521 (*language_code) = areabufptr[area_offset];
522 area_offset++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500523
Patrick Venturec9508db2018-10-16 17:18:43 -0700524 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
525 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500526
Patrick Venturec9508db2018-10-16 17:18:43 -0700527 if (_parse_type_length(areabufptr, areabuflen, area_offset,
528 &number_of_data_bytes,
529 product_manufacturer_name) < 0)
530 goto cleanup;
531 area_offset += 1; /* type/length byte */
532 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500533
Patrick Venturec9508db2018-10-16 17:18:43 -0700534 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
535 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500536
Patrick Venturec9508db2018-10-16 17:18:43 -0700537 if (_parse_type_length(areabufptr, areabuflen, area_offset,
538 &number_of_data_bytes, product_name) < 0)
539 goto cleanup;
540 area_offset += 1; /* type/length byte */
541 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500542
Patrick Venturec9508db2018-10-16 17:18:43 -0700543 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
544 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500545
Patrick Venturec9508db2018-10-16 17:18:43 -0700546 if (_parse_type_length(areabufptr, areabuflen, area_offset,
547 &number_of_data_bytes,
548 product_part_model_number) < 0)
549 goto cleanup;
550 area_offset += 1; /* type/length byte */
551 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500552
Patrick Venturec9508db2018-10-16 17:18:43 -0700553 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
554 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500555
Patrick Venturec9508db2018-10-16 17:18:43 -0700556 if (_parse_type_length(areabufptr, areabuflen, area_offset,
557 &number_of_data_bytes, product_version) < 0)
558 goto cleanup;
559 area_offset += 1; /* type/length byte */
560 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500561
Patrick Venturec9508db2018-10-16 17:18:43 -0700562 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
563 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500564
Patrick Venturec9508db2018-10-16 17:18:43 -0700565 if (_parse_type_length(areabufptr, areabuflen, area_offset,
566 &number_of_data_bytes, product_serial_number) < 0)
567 goto cleanup;
568 area_offset += 1; /* type/length byte */
569 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500570
Patrick Venturec9508db2018-10-16 17:18:43 -0700571 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
572 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500573
Patrick Venturec9508db2018-10-16 17:18:43 -0700574 if (_parse_type_length(areabufptr, areabuflen, area_offset,
575 &number_of_data_bytes, product_asset_tag) < 0)
576 goto cleanup;
577 area_offset += 1; /* type/length byte */
578 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500579
Patrick Venturec9508db2018-10-16 17:18:43 -0700580 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
581 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500582
Patrick Venturec9508db2018-10-16 17:18:43 -0700583 if (_parse_type_length(areabufptr, areabuflen, area_offset,
584 &number_of_data_bytes, product_fru_file_id) < 0)
585 goto cleanup;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500586
Patrick Venturec9508db2018-10-16 17:18:43 -0700587 area_offset += 1; /* type/length byte */
588 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500589
Patrick Venturec9508db2018-10-16 17:18:43 -0700590 while (area_offset < areabuflen &&
591 areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500592 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700593 ipmi_fru_field_t* field_ptr = NULL;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500594
Patrick Venturec9508db2018-10-16 17:18:43 -0700595 if (product_custom_fields && product_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500596 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700597 if (custom_fields_index < product_custom_fields_len)
598 field_ptr = &product_custom_fields[custom_fields_index];
599 else
Hariharasubramanian R44473092015-10-15 08:25:28 -0500600 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700601 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500602 }
603 }
604
Patrick Venturec9508db2018-10-16 17:18:43 -0700605 if (_parse_type_length(areabufptr, areabuflen, area_offset,
606 &number_of_data_bytes, field_ptr) < 0)
607 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500608
Patrick Venturec9508db2018-10-16 17:18:43 -0700609 area_offset += 1; /* type/length byte */
610 area_offset += number_of_data_bytes;
611 custom_fields_index++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500612 }
613
Patrick Venturec9508db2018-10-16 17:18:43 -0700614out:
615 rv = 0;
616cleanup:
617 return (rv);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500618}
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500619
Patrick Venturec9508db2018-10-16 17:18:43 -0700620void _append_to_dict(uint8_t vpd_key_id, uint8_t* vpd_key_val,
621 IPMIFruInfo& info)
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500622{
623 int type_length = vpd_key_val[0];
Deepak Kodihalli8a2a6752017-02-11 03:04:38 -0600624 int type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >>
625 IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
Patrick Williamscfa96af2023-05-10 07:50:26 -0500626 int vpd_val_len = type_length &
627 IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500628
vishwa24afbb92016-06-10 06:08:56 -0500629 /* Needed to convert each uint8_t byte to a ascii */
630 char bin_byte[3] = {0};
631
632 /*
633 * Max number of characters needed to represent 1 unsigned byte in string
Gunnar Millsc19b8132018-06-14 08:56:17 -0500634 * is number of bytes multiplied by 2. Extra 3 for 0x and a ending '\0';
vishwa24afbb92016-06-10 06:08:56 -0500635 */
636 char bin_in_ascii_len = vpd_val_len * 2 + 3;
637
638 /* Binary converted to ascii in array */
Patrick Venturec9508db2018-10-16 17:18:43 -0700639 char* bin_in_ascii = (char*)malloc(bin_in_ascii_len);
vishwa24afbb92016-06-10 06:08:56 -0500640
641 /* For reading byte from the area */
Ratan Guptacb0d4e52016-12-22 19:05:57 +0530642 int val = 0;
vishwa24afbb92016-06-10 06:08:56 -0500643
Patrick Venturec9508db2018-10-16 17:18:43 -0700644 char* bin_copy = &((char*)bin_in_ascii)[2];
vishwa24afbb92016-06-10 06:08:56 -0500645
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500646 switch (type_code)
647 {
648 case 0:
vishwa24afbb92016-06-10 06:08:56 -0500649 memset(bin_in_ascii, 0x0, bin_in_ascii_len);
650
651 /* Offset 1 is where actual data starts */
Patrick Venturec9508db2018-10-16 17:18:43 -0700652 for (val = 1; val <= vpd_val_len; val++)
vishwa24afbb92016-06-10 06:08:56 -0500653 {
654 /* 2 bytes for data and 1 for terminating '\0' */
655 snprintf(bin_byte, 3, "%02x", vpd_key_val[val]);
656
657 /* Its a running string so strip off the '\0' */
658 strncat(bin_copy, bin_byte, 2);
659 }
660
661 /* We need the data represented as 0x...... */
Patrick Venturec9508db2018-10-16 17:18:43 -0700662 if (vpd_val_len > 0)
vishwa24afbb92016-06-10 06:08:56 -0500663 {
Brad Bishopec73c952018-11-21 16:04:13 -0500664 memcpy(bin_in_ascii, "0x", 2);
vishwa24afbb92016-06-10 06:08:56 -0500665 }
Andrew Geissler4e411662017-06-01 07:26:39 -0500666#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700667 printf("_append_to_dict: VPD Key = [%s] : Type Code = [BINARY] :"
668 " Len = [%d] : Val = [%s]\n",
669 vpd_key_names[vpd_key_id], vpd_val_len, bin_in_ascii);
Andrew Geissler4e411662017-06-01 07:26:39 -0500670#endif
Patrick Williamscfa96af2023-05-10 07:50:26 -0500671 info[vpd_key_id] = std::make_pair(vpd_key_names[vpd_key_id],
672 bin_in_ascii);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500673 break;
vishwa24afbb92016-06-10 06:08:56 -0500674
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500675 case 3:
Andrew Geissler4e411662017-06-01 07:26:39 -0500676#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700677 printf("_append_to_dict: VPD Key = [%s] : Type Code=[ASCII+Latin]"
678 " : Len = [%d] : Val = [%s]\n",
679 vpd_key_names[vpd_key_id], vpd_val_len, &vpd_key_val[1]);
Andrew Geissler4e411662017-06-01 07:26:39 -0500680#endif
Deepak Kodihalli8a2a6752017-02-11 03:04:38 -0600681 info[vpd_key_id] = std::make_pair(
Patrick Venturec9508db2018-10-16 17:18:43 -0700682 vpd_key_names[vpd_key_id],
683 std::string(vpd_key_val + 1, vpd_key_val + 1 + type_length));
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500684 break;
685 }
686
Patrick Venturec9508db2018-10-16 17:18:43 -0700687 if (bin_in_ascii)
vishwa24afbb92016-06-10 06:08:56 -0500688 {
689 free(bin_in_ascii);
690 bin_in_ascii = NULL;
691 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500692}
693
Patrick Venturec9508db2018-10-16 17:18:43 -0700694int parse_fru_area(const uint8_t area, const void* msgbuf, const size_t len,
695 IPMIFruInfo& info)
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500696{
Patrick Venturec9508db2018-10-16 17:18:43 -0700697 int rv = -1;
698 int i = 0;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500699
Patrick Venturec9508db2018-10-16 17:18:43 -0700700 /* Chassis */
701 uint8_t chassis_type;
702 /* Board */
703 uint32_t mfg_date_time;
704 /* Product */
705 // unsigned int product_custom_fields_len;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500706
Patrick Venturec9508db2018-10-16 17:18:43 -0700707 // ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
708 ipmi_fru_field_t vpd_info[OPENBMC_VPD_KEY_MAX];
709 char timestr[OPENBMC_VPD_VAL_LEN];
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500710
Patrick Venturec9508db2018-10-16 17:18:43 -0700711 // uint8_t* ipmi_fru_field_str=NULL;
712 // ipmi_fru_common_hdr_t* chdr = NULL;
713 // uint8_t* hdr = NULL;
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500714
Patrick Venturec9508db2018-10-16 17:18:43 -0700715 ASSERT(msgbuf);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500716
Patrick Venturec9508db2018-10-16 17:18:43 -0700717 for (i = 0; i < OPENBMC_VPD_KEY_MAX; i++)
718 {
719 memset(vpd_info[i].type_length_field, '\0',
720 IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
721 vpd_info[i].type_length_field_length = 0;
722 }
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500723
Patrick Venturec9508db2018-10-16 17:18:43 -0700724 switch (area)
725 {
726 case IPMI_FRU_AREA_CHASSIS_INFO:
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500727#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700728 printf("Chassis : Buf len = [%d]\n", len);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500729#endif
Patrick Venturec9508db2018-10-16 17:18:43 -0700730 ipmi_fru_chassis_info_area(
731 (uint8_t*)msgbuf + 2, len, &chassis_type,
732 &vpd_info[OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
733 &vpd_info[OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
734 &vpd_info[OPENBMC_VPD_KEY_CHASSIS_CUSTOM1],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500735 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500736
Patrick Venturec9508db2018-10-16 17:18:43 -0700737 /* Populate VPD Table */
738 for (i = 1; i <= OPENBMC_VPD_KEY_CHASSIS_MAX; i++)
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500739 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700740 if (i == OPENBMC_VPD_KEY_CHASSIS_TYPE)
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500741 {
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500742#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700743 printf("Chassis : Appending [%s] = [%d]\n",
744 vpd_key_names[i], chassis_type);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500745#endif
Ratan Guptacb0d4e52016-12-22 19:05:57 +0530746 info[i] = std::make_pair(vpd_key_names[i],
Patrick Venturec9508db2018-10-16 17:18:43 -0700747 std::to_string(chassis_type));
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500748 continue;
749 }
Patrick Venturec9508db2018-10-16 17:18:43 -0700750 _append_to_dict(i, vpd_info[i].type_length_field, info);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500751 }
752 break;
Patrick Venturec9508db2018-10-16 17:18:43 -0700753 case IPMI_FRU_AREA_BOARD_INFO:
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500754#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700755 printf("Board : Buf len = [%d]\n", len);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500756#endif
Patrick Venturec9508db2018-10-16 17:18:43 -0700757 ipmi_fru_board_info_area(
758 (uint8_t*)msgbuf + 2, len, NULL, &mfg_date_time,
759 &vpd_info[OPENBMC_VPD_KEY_BOARD_MFR],
760 &vpd_info[OPENBMC_VPD_KEY_BOARD_NAME],
761 &vpd_info[OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
762 &vpd_info[OPENBMC_VPD_KEY_BOARD_PART_NUM],
763 &vpd_info[OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
764 &vpd_info[OPENBMC_VPD_KEY_BOARD_CUSTOM1],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500765 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
766
Patrick Venturec9508db2018-10-16 17:18:43 -0700767 /* Populate VPD Table */
768 for (i = OPENBMC_VPD_KEY_BOARD_MFG_DATE;
769 i <= OPENBMC_VPD_KEY_BOARD_MAX; i++)
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500770 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700771 if (i == OPENBMC_VPD_KEY_BOARD_MFG_DATE)
772 {
773 _to_time_str(mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN);
774#if IPMI_FRU_PARSER_DEBUG
775 printf("Board : Appending [%s] = [%s]\n", vpd_key_names[i],
776 timestr);
777#endif
Patrick Williamscfa96af2023-05-10 07:50:26 -0500778 info[i] = std::make_pair(vpd_key_names[i],
779 std::string(timestr));
Patrick Venturec9508db2018-10-16 17:18:43 -0700780 continue;
781 }
782 _append_to_dict(i, vpd_info[i].type_length_field, info);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500783 }
784 break;
Patrick Venturec9508db2018-10-16 17:18:43 -0700785 case IPMI_FRU_AREA_PRODUCT_INFO:
786#if IPMI_FRU_PARSER_DEBUG
787 printf("Product : Buf len = [%d]\n", len);
788#endif
789 ipmi_fru_product_info_area(
790 (uint8_t*)msgbuf + 2, len, NULL,
791 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_MFR],
792 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_NAME],
793 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM],
794 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_VER],
795 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
796 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
797 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
798 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_CUSTOM1],
799 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
800
801 for (i = OPENBMC_VPD_KEY_PRODUCT_MFR;
802 i <= OPENBMC_VPD_KEY_PRODUCT_MAX; ++i)
803 {
804 _append_to_dict(i, vpd_info[i].type_length_field, info);
805 }
806 break;
807 default:
808 /* TODO: Parse Multi Rec / Internal use area */
809 break;
810 }
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500811
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500812#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700813 printf("parse_fru_area : Dictionary Packing Complete\n");
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500814#endif
Patrick Venturec9508db2018-10-16 17:18:43 -0700815 rv = 0;
816 return (rv);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500817}