blob: 8f66a3b33b01e9c9756acfcddfd1deefa9a13e31 [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
Willy Tu9084f522022-11-03 08:17:54 +000084constexpr long fruEpochMinutes = 820454400;
85
Hariharasubramanian R44473092015-10-15 08:25:28 -050086struct ipmi_fru_field
87{
Patrick Venturec9508db2018-10-16 17:18:43 -070088 uint8_t type_length_field[IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX];
89 /* store length of data stored in buffer */
90 unsigned int type_length_field_length;
Hariharasubramanian R44473092015-10-15 08:25:28 -050091};
92
93typedef struct ipmi_fru_field ipmi_fru_field_t;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -050094/*
95 * FRU Parser
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050096 */
Hariharasubramanian R44473092015-10-15 08:25:28 -050097
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -050098typedef struct ipmi_fru_area_info
99{
100 uint8_t off;
101 uint8_t len;
102} ipmi_fru_area_info_t;
103
104typedef struct ipmi_fru_common_hdr
105{
106 uint8_t fmtver;
107 uint8_t internal;
108 uint8_t chassis;
109 uint8_t board;
110 uint8_t product;
111 uint8_t multirec;
112} __attribute__((packed)) ipmi_fru_common_hdr_t;
113
Patrick Venturec9508db2018-10-16 17:18:43 -0700114const char* vpd_key_names[] = {
115 "Key Names Table Start",
116 "Type", /*OPENBMC_VPD_KEY_CHASSIS_TYPE*/
117 "Part Number", /*OPENBMC_VPD_KEY_CHASSIS_PART_NUM,*/
118 "Serial Number", /*OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,*/
119 "Custom Field 1", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM1,*/
120 "Custom Field 2", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM2,*/
121 "Custom Field 3", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM3,*/
122 "Custom Field 4", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM4,*/
123 "Custom Field 5", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM5,*/
124 "Custom Field 6", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM6,*/
125 "Custom Field 7", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM7,*/
126 "Custom Field 8", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500127
Patrick Venturec9508db2018-10-16 17:18:43 -0700128 "Mfg Date",
129 /* OPENBMC_VPD_KEY_BOARD_MFG_DATE, */ /* not a type/len */
130 "Manufacturer", /* OPENBMC_VPD_KEY_BOARD_MFR, */
131 "Name", /* OPENBMC_VPD_KEY_BOARD_NAME, */
Patrick Williamscfa96af2023-05-10 07:50:26 -0500132 "Serial Number", /* OPENBMC_VPD_KEY_BOARD_SERIAL_NUM, */
133 "Part Number", /* OPENBMC_VPD_KEY_BOARD_PART_NUM, */
134 "FRU File ID", /* OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID, */
135 "Custom Field 1", /*OPENBMC_VPD_KEY_BOARD_CUSTOM1,*/
136 "Custom Field 2", /*OPENBMC_VPD_KEY_BOARD_CUSTOM2,*/
137 "Custom Field 3", /*OPENBMC_VPD_KEY_BOARD_CUSTOM3,*/
138 "Custom Field 4", /*OPENBMC_VPD_KEY_BOARD_CUSTOM4,*/
139 "Custom Field 5", /*OPENBMC_VPD_KEY_BOARD_CUSTOM5,*/
140 "Custom Field 6", /*OPENBMC_VPD_KEY_BOARD_CUSTOM6,*/
141 "Custom Field 7", /*OPENBMC_VPD_KEY_BOARD_CUSTOM7,*/
142 "Custom Field 8", /*OPENBMC_VPD_KEY_BOARD_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500143
Patrick Williamscfa96af2023-05-10 07:50:26 -0500144 "Manufacturer", /* OPENBMC_VPD_KEY_PRODUCT_MFR, */
145 "Name", /* OPENBMC_VPD_KEY_PRODUCT_NAME, */
146 "Model Number", /* OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM, */
147 "Version", /* OPENBMC_VPD_KEY_PRODUCT_VER, */
148 "Serial Number", /* OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM, */
149 "Asset Tag", /* OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG, */
150 "FRU File ID", /* OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID, */
151 "Custom Field 1", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM1,*/
152 "Custom Field 2", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM2,*/
153 "Custom Field 3", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM3,*/
154 "Custom Field 4", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM4,*/
155 "Custom Field 5", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM5,*/
156 "Custom Field 6", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM6,*/
157 "Custom Field 7", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM7,*/
158 "Custom Field 8", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500159
Patrick Venturec9508db2018-10-16 17:18:43 -0700160 "Key Names Table End" /*OPENBMC_VPD_KEY_MAX,*/
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500161};
162
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500163/*
164 * --------------------------------------------------------------------
165 *
166 * --------------------------------------------------------------------
167 */
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500168
Patrick Venturec9508db2018-10-16 17:18:43 -0700169static size_t _to_time_str(uint32_t mfg_date_time, char* timestr, uint32_t len)
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500170{
171 struct tm tm;
172 time_t t;
173 size_t s;
174
Patrick Venturec9508db2018-10-16 17:18:43 -0700175 ASSERT(timestr);
176 ASSERT(len);
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500177
Patrick Venturec9508db2018-10-16 17:18:43 -0700178 memset(&tm, '\0', sizeof(struct tm));
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500179
180 t = mfg_date_time;
Patrick Venturec9508db2018-10-16 17:18:43 -0700181 gmtime_r(&t, &tm);
Willy Tu9084f522022-11-03 08:17:54 +0000182 s = strftime(timestr, len, "%F - %H:%M:%S UTC", &tm);
Hariharasubramanian R4a0b6fb2015-10-31 22:45:48 -0500183
184 return s;
185}
186
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500187/* private method to parse type/length */
Patrick Venturec9508db2018-10-16 17:18:43 -0700188static int _parse_type_length(const void* areabuf, unsigned int areabuflen,
189 unsigned int current_area_offset,
190 uint8_t* number_of_data_bytes,
191 ipmi_fru_field_t* field)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500192{
Patrick Venturec9508db2018-10-16 17:18:43 -0700193 const uint8_t* areabufptr = (const uint8_t*)areabuf;
194 uint8_t type_length;
195 uint8_t type_code;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500196
Patrick Venturec9508db2018-10-16 17:18:43 -0700197 ASSERT(areabuf);
198 ASSERT(areabuflen);
199 ASSERT(number_of_data_bytes);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500200
Patrick Venturec9508db2018-10-16 17:18:43 -0700201 type_length = areabufptr[current_area_offset];
Hariharasubramanian R44473092015-10-15 08:25:28 -0500202
Patrick Venturec9508db2018-10-16 17:18:43 -0700203 /* ipmi workaround
204 *
205 * dell p weredge r610
206 *
207 * my reading of the fru spec is that all non-custom fields are
208 * required to be listed by the vendor. however, on this
209 * motherboard, some areas list this, indicating that there is
210 * no more data to be parsed. so now, for "required" fields, i
211 * check to see if the type-length field is a sentinel before
212 * calling this function.
213 */
Hariharasubramanian R44473092015-10-15 08:25:28 -0500214
Patrick Venturec9508db2018-10-16 17:18:43 -0700215 ASSERT(type_length != IPMI_FRU_SENTINEL_VALUE);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500216
Patrick Venturec9508db2018-10-16 17:18:43 -0700217 type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >>
218 IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
Patrick Williamscfa96af2023-05-10 07:50:26 -0500219 (*number_of_data_bytes) = type_length &
220 IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500221
Patrick Venturec9508db2018-10-16 17:18:43 -0700222 /* special case: this shouldn't be a length of 0x01 (see type/length
223 * byte format in fru information storage definition).
224 */
225 if (type_code == IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE &&
226 (*number_of_data_bytes) == 0x01)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500227 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700228 return (-1);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500229 }
230
Patrick Venturec9508db2018-10-16 17:18:43 -0700231 if ((current_area_offset + 1 + (*number_of_data_bytes)) > areabuflen)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500232 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700233 return (-1);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500234 }
235
Patrick Venturec9508db2018-10-16 17:18:43 -0700236 if (field)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500237 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700238 memset(field->type_length_field, '\0',
239 IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
240 memcpy(field->type_length_field, &areabufptr[current_area_offset],
241 1 + (*number_of_data_bytes));
242 field->type_length_field_length = 1 + (*number_of_data_bytes);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500243 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500244
Patrick Venturec9508db2018-10-16 17:18:43 -0700245 return (0);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500246}
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500247
Patrick Venturec9508db2018-10-16 17:18:43 -0700248int ipmi_fru_chassis_info_area(const void* areabuf, unsigned int areabuflen,
249 uint8_t* chassis_type,
250 ipmi_fru_field_t* chassis_part_number,
251 ipmi_fru_field_t* chassis_serial_number,
252 ipmi_fru_field_t* chassis_custom_fields,
253 unsigned int chassis_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500254{
Patrick Venturec9508db2018-10-16 17:18:43 -0700255 const uint8_t* areabufptr = (const uint8_t*)areabuf;
256 unsigned int area_offset = 0;
257 unsigned int custom_fields_index = 0;
258 uint8_t number_of_data_bytes;
259 int rv = -1;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500260
Patrick Venturec9508db2018-10-16 17:18:43 -0700261 if (!areabuf || !areabuflen)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500262 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700263 return (-1);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500264 }
265
Patrick Venturec9508db2018-10-16 17:18:43 -0700266 if (chassis_part_number)
267 memset(chassis_part_number, '\0', sizeof(ipmi_fru_field_t));
268 if (chassis_serial_number)
269 memset(chassis_serial_number, '\0', sizeof(ipmi_fru_field_t));
270 if (chassis_custom_fields && chassis_custom_fields_len)
271 memset(chassis_custom_fields, '\0',
272 sizeof(ipmi_fru_field_t) * chassis_custom_fields_len);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500273
Patrick Venturec9508db2018-10-16 17:18:43 -0700274 if (chassis_type)
275 (*chassis_type) = areabufptr[area_offset];
276 area_offset++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500277
Patrick Venturec9508db2018-10-16 17:18:43 -0700278 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
279 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500280
Patrick Venturec9508db2018-10-16 17:18:43 -0700281 if (_parse_type_length(areabufptr, areabuflen, area_offset,
282 &number_of_data_bytes, chassis_part_number) < 0)
283 goto cleanup;
284 area_offset += 1; /* type/length byte */
285 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500286
Patrick Venturec9508db2018-10-16 17:18:43 -0700287 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
288 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500289
Patrick Venturec9508db2018-10-16 17:18:43 -0700290 if (_parse_type_length(areabufptr, areabuflen, area_offset,
291 &number_of_data_bytes, chassis_serial_number) < 0)
292 goto cleanup;
293 area_offset += 1; /* type/length byte */
294 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500295
Patrick Venturec9508db2018-10-16 17:18:43 -0700296 while (area_offset < areabuflen &&
297 areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500298 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700299 ipmi_fru_field_t* field_ptr = NULL;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500300
Patrick Venturec9508db2018-10-16 17:18:43 -0700301 if (chassis_custom_fields && chassis_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500302 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700303 if (custom_fields_index < chassis_custom_fields_len)
304 field_ptr = &chassis_custom_fields[custom_fields_index];
305 else
Hariharasubramanian R44473092015-10-15 08:25:28 -0500306 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700307 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500308 }
309 }
310
Patrick Venturec9508db2018-10-16 17:18:43 -0700311 if (_parse_type_length(areabufptr, areabuflen, area_offset,
312 &number_of_data_bytes, field_ptr) < 0)
313 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500314
Patrick Venturec9508db2018-10-16 17:18:43 -0700315 area_offset += 1; /* type/length byte */
316 area_offset += number_of_data_bytes;
317 custom_fields_index++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500318 }
319
Patrick Venturec9508db2018-10-16 17:18:43 -0700320out:
321 rv = 0;
322cleanup:
323 return (rv);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500324}
325
Patrick Venturec9508db2018-10-16 17:18:43 -0700326int ipmi_fru_board_info_area(
327 const void* areabuf, unsigned int areabuflen, uint8_t* language_code,
328 uint32_t* mfg_date_time, ipmi_fru_field_t* board_manufacturer,
329 ipmi_fru_field_t* board_product_name, ipmi_fru_field_t* board_serial_number,
330 ipmi_fru_field_t* board_part_number, ipmi_fru_field_t* board_fru_file_id,
331 ipmi_fru_field_t* board_custom_fields, unsigned int board_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500332{
Patrick Venturec9508db2018-10-16 17:18:43 -0700333 const uint8_t* areabufptr = (const uint8_t*)areabuf;
Patrick Venturec9508db2018-10-16 17:18:43 -0700334 unsigned int area_offset = 0;
335 unsigned int custom_fields_index = 0;
336 uint8_t number_of_data_bytes;
337 int rv = -1;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500338
Patrick Venturec9508db2018-10-16 17:18:43 -0700339 if (!areabuf || !areabuflen)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500340 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700341 return (-1);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500342 }
343
Patrick Venturec9508db2018-10-16 17:18:43 -0700344 if (board_manufacturer)
345 memset(board_manufacturer, '\0', sizeof(ipmi_fru_field_t));
346 if (board_product_name)
347 memset(board_product_name, '\0', sizeof(ipmi_fru_field_t));
348 if (board_serial_number)
349 memset(board_serial_number, '\0', sizeof(ipmi_fru_field_t));
350 if (board_part_number)
351 memset(board_part_number, '\0', sizeof(ipmi_fru_field_t));
352 if (board_fru_file_id)
353 memset(board_fru_file_id, '\0', sizeof(ipmi_fru_field_t));
354 if (board_custom_fields && board_custom_fields_len)
355 memset(board_custom_fields, '\0',
356 sizeof(ipmi_fru_field_t) * board_custom_fields_len);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500357
Patrick Venturec9508db2018-10-16 17:18:43 -0700358 if (language_code)
359 (*language_code) = areabufptr[area_offset];
360 area_offset++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500361
Patrick Venturec9508db2018-10-16 17:18:43 -0700362 if (mfg_date_time)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500363 {
Willy Tu9084f522022-11-03 08:17:54 +0000364 unsigned int minutes = areabufptr[area_offset];
Patrick Venturec9508db2018-10-16 17:18:43 -0700365 area_offset++;
Willy Tu9084f522022-11-03 08:17:54 +0000366 minutes |= (areabufptr[area_offset] << 8);
Patrick Venturec9508db2018-10-16 17:18:43 -0700367 area_offset++;
Willy Tu9084f522022-11-03 08:17:54 +0000368 minutes |= (areabufptr[area_offset] << 16);
Patrick Venturec9508db2018-10-16 17:18:43 -0700369 area_offset++;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500370
Willy Tu9084f522022-11-03 08:17:54 +0000371 /* In fru, epoch is 0:00 hrs 1/1/96 == 820454400
372 * Remove it directly and remove the time conversion.
Patrick Venturec9508db2018-10-16 17:18:43 -0700373 */
Willy Tu9084f522022-11-03 08:17:54 +0000374 (*mfg_date_time) = fruEpochMinutes + static_cast<long>(minutes) * 60;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500375 }
Patrick Venturec9508db2018-10-16 17:18:43 -0700376 else
377 area_offset += 3;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500378
Patrick Venturec9508db2018-10-16 17:18:43 -0700379 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
380 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500381
Patrick Venturec9508db2018-10-16 17:18:43 -0700382 if (_parse_type_length(areabufptr, areabuflen, area_offset,
383 &number_of_data_bytes, board_manufacturer) < 0)
384 goto cleanup;
385 area_offset += 1; /* type/length byte */
386 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500387
Patrick Venturec9508db2018-10-16 17:18:43 -0700388 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
389 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500390
Patrick Venturec9508db2018-10-16 17:18:43 -0700391 if (_parse_type_length(areabufptr, areabuflen, area_offset,
392 &number_of_data_bytes, board_product_name) < 0)
393 goto cleanup;
394 area_offset += 1; /* type/length byte */
395 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500396
Patrick Venturec9508db2018-10-16 17:18:43 -0700397 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
398 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500399
Patrick Venturec9508db2018-10-16 17:18:43 -0700400 if (_parse_type_length(areabufptr, areabuflen, area_offset,
401 &number_of_data_bytes, board_serial_number) < 0)
402 goto cleanup;
403 area_offset += 1; /* type/length byte */
404 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500405
Patrick Venturec9508db2018-10-16 17:18:43 -0700406 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
407 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500408
Patrick Venturec9508db2018-10-16 17:18:43 -0700409 if (_parse_type_length(areabufptr, areabuflen, area_offset,
410 &number_of_data_bytes, board_part_number) < 0)
411 goto cleanup;
412 area_offset += 1; /* type/length byte */
413 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500414
Patrick Venturec9508db2018-10-16 17:18:43 -0700415 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
416 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500417
Patrick Venturec9508db2018-10-16 17:18:43 -0700418 if (_parse_type_length(areabufptr, areabuflen, area_offset,
419 &number_of_data_bytes, board_fru_file_id) < 0)
420 goto cleanup;
421 area_offset += 1; /* type/length byte */
422 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500423
Patrick Venturec9508db2018-10-16 17:18:43 -0700424 while (area_offset < areabuflen &&
425 areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500426 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700427 ipmi_fru_field_t* field_ptr = NULL;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500428
Patrick Venturec9508db2018-10-16 17:18:43 -0700429 if (board_custom_fields && board_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500430 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700431 if (custom_fields_index < board_custom_fields_len)
432 field_ptr = &board_custom_fields[custom_fields_index];
433 else
Hariharasubramanian R44473092015-10-15 08:25:28 -0500434 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700435 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500436 }
437 }
438
Patrick Venturec9508db2018-10-16 17:18:43 -0700439 if (_parse_type_length(areabufptr, areabuflen, area_offset,
440 &number_of_data_bytes, field_ptr) < 0)
441 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500442
Patrick Venturec9508db2018-10-16 17:18:43 -0700443 area_offset += 1; /* type/length byte */
444 area_offset += number_of_data_bytes;
445 custom_fields_index++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500446 }
447
Patrick Venturec9508db2018-10-16 17:18:43 -0700448out:
449 rv = 0;
450cleanup:
451 return (rv);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500452}
453
Patrick Venturec9508db2018-10-16 17:18:43 -0700454int ipmi_fru_product_info_area(
455 const void* areabuf, unsigned int areabuflen, uint8_t* language_code,
456 ipmi_fru_field_t* product_manufacturer_name, ipmi_fru_field_t* product_name,
457 ipmi_fru_field_t* product_part_model_number,
458 ipmi_fru_field_t* product_version, ipmi_fru_field_t* product_serial_number,
459 ipmi_fru_field_t* product_asset_tag, ipmi_fru_field_t* product_fru_file_id,
460 ipmi_fru_field_t* product_custom_fields,
461 unsigned int product_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500462{
Patrick Venturec9508db2018-10-16 17:18:43 -0700463 const uint8_t* areabufptr = (const uint8_t*)areabuf;
464 unsigned int area_offset = 0;
465 unsigned int custom_fields_index = 0;
466 uint8_t number_of_data_bytes;
467 int rv = -1;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500468
Patrick Venturec9508db2018-10-16 17:18:43 -0700469 if (!areabuf || !areabuflen)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500470 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700471 return (-1);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500472 }
473
Patrick Venturec9508db2018-10-16 17:18:43 -0700474 if (product_manufacturer_name)
475 memset(product_manufacturer_name, '\0', sizeof(ipmi_fru_field_t));
476 if (product_name)
477 memset(product_name, '\0', sizeof(ipmi_fru_field_t));
478 if (product_part_model_number)
479 memset(product_part_model_number, '\0', sizeof(ipmi_fru_field_t));
480 if (product_version)
481 memset(product_version, '\0', sizeof(ipmi_fru_field_t));
482 if (product_serial_number)
483 memset(product_serial_number, '\0', sizeof(ipmi_fru_field_t));
484 if (product_asset_tag)
485 memset(product_asset_tag, '\0', sizeof(ipmi_fru_field_t));
486 if (product_fru_file_id)
487 memset(product_fru_file_id, '\0', sizeof(ipmi_fru_field_t));
488 if (product_custom_fields && product_custom_fields_len)
489 memset(product_custom_fields, '\0',
490 sizeof(ipmi_fru_field_t) * product_custom_fields_len);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500491
Patrick Venturec9508db2018-10-16 17:18:43 -0700492 if (language_code)
493 (*language_code) = areabufptr[area_offset];
494 area_offset++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500495
Patrick Venturec9508db2018-10-16 17:18:43 -0700496 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
497 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500498
Patrick Venturec9508db2018-10-16 17:18:43 -0700499 if (_parse_type_length(areabufptr, areabuflen, area_offset,
500 &number_of_data_bytes,
501 product_manufacturer_name) < 0)
502 goto cleanup;
503 area_offset += 1; /* type/length byte */
504 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500505
Patrick Venturec9508db2018-10-16 17:18:43 -0700506 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
507 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500508
Patrick Venturec9508db2018-10-16 17:18:43 -0700509 if (_parse_type_length(areabufptr, areabuflen, area_offset,
510 &number_of_data_bytes, product_name) < 0)
511 goto cleanup;
512 area_offset += 1; /* type/length byte */
513 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500514
Patrick Venturec9508db2018-10-16 17:18:43 -0700515 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
516 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500517
Patrick Venturec9508db2018-10-16 17:18:43 -0700518 if (_parse_type_length(areabufptr, areabuflen, area_offset,
519 &number_of_data_bytes,
520 product_part_model_number) < 0)
521 goto cleanup;
522 area_offset += 1; /* type/length byte */
523 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500524
Patrick Venturec9508db2018-10-16 17:18:43 -0700525 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
526 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500527
Patrick Venturec9508db2018-10-16 17:18:43 -0700528 if (_parse_type_length(areabufptr, areabuflen, area_offset,
529 &number_of_data_bytes, product_version) < 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_serial_number) < 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, product_asset_tag) < 0)
548 goto cleanup;
549 area_offset += 1; /* type/length byte */
550 area_offset += number_of_data_bytes;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500551
Patrick Venturec9508db2018-10-16 17:18:43 -0700552 if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
553 goto out;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500554
Patrick Venturec9508db2018-10-16 17:18:43 -0700555 if (_parse_type_length(areabufptr, areabuflen, area_offset,
556 &number_of_data_bytes, product_fru_file_id) < 0)
557 goto cleanup;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500558
Patrick Venturec9508db2018-10-16 17:18:43 -0700559 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 while (area_offset < areabuflen &&
563 areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500564 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700565 ipmi_fru_field_t* field_ptr = NULL;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500566
Patrick Venturec9508db2018-10-16 17:18:43 -0700567 if (product_custom_fields && product_custom_fields_len)
Hariharasubramanian R44473092015-10-15 08:25:28 -0500568 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700569 if (custom_fields_index < product_custom_fields_len)
570 field_ptr = &product_custom_fields[custom_fields_index];
571 else
Hariharasubramanian R44473092015-10-15 08:25:28 -0500572 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700573 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500574 }
575 }
576
Patrick Venturec9508db2018-10-16 17:18:43 -0700577 if (_parse_type_length(areabufptr, areabuflen, area_offset,
578 &number_of_data_bytes, field_ptr) < 0)
579 goto cleanup;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500580
Patrick Venturec9508db2018-10-16 17:18:43 -0700581 area_offset += 1; /* type/length byte */
582 area_offset += number_of_data_bytes;
583 custom_fields_index++;
Hariharasubramanian R44473092015-10-15 08:25:28 -0500584 }
585
Patrick Venturec9508db2018-10-16 17:18:43 -0700586out:
587 rv = 0;
588cleanup:
589 return (rv);
Hariharasubramanian R44473092015-10-15 08:25:28 -0500590}
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500591
Patrick Venturec9508db2018-10-16 17:18:43 -0700592void _append_to_dict(uint8_t vpd_key_id, uint8_t* vpd_key_val,
593 IPMIFruInfo& info)
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500594{
595 int type_length = vpd_key_val[0];
Deepak Kodihalli8a2a6752017-02-11 03:04:38 -0600596 int type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >>
597 IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
Patrick Williamscfa96af2023-05-10 07:50:26 -0500598 int vpd_val_len = type_length &
599 IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500600
vishwa24afbb92016-06-10 06:08:56 -0500601 /* Needed to convert each uint8_t byte to a ascii */
602 char bin_byte[3] = {0};
603
604 /*
605 * Max number of characters needed to represent 1 unsigned byte in string
Gunnar Millsc19b8132018-06-14 08:56:17 -0500606 * is number of bytes multiplied by 2. Extra 3 for 0x and a ending '\0';
vishwa24afbb92016-06-10 06:08:56 -0500607 */
608 char bin_in_ascii_len = vpd_val_len * 2 + 3;
609
610 /* Binary converted to ascii in array */
Patrick Venturec9508db2018-10-16 17:18:43 -0700611 char* bin_in_ascii = (char*)malloc(bin_in_ascii_len);
vishwa24afbb92016-06-10 06:08:56 -0500612
613 /* For reading byte from the area */
Ratan Guptacb0d4e52016-12-22 19:05:57 +0530614 int val = 0;
vishwa24afbb92016-06-10 06:08:56 -0500615
Patrick Venturec9508db2018-10-16 17:18:43 -0700616 char* bin_copy = &((char*)bin_in_ascii)[2];
vishwa24afbb92016-06-10 06:08:56 -0500617
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500618 switch (type_code)
619 {
620 case 0:
vishwa24afbb92016-06-10 06:08:56 -0500621 memset(bin_in_ascii, 0x0, bin_in_ascii_len);
622
623 /* Offset 1 is where actual data starts */
Patrick Venturec9508db2018-10-16 17:18:43 -0700624 for (val = 1; val <= vpd_val_len; val++)
vishwa24afbb92016-06-10 06:08:56 -0500625 {
626 /* 2 bytes for data and 1 for terminating '\0' */
627 snprintf(bin_byte, 3, "%02x", vpd_key_val[val]);
628
Patrick Williams6f47bee2023-07-19 11:06:21 -0500629#pragma GCC diagnostic push
630#pragma GCC diagnostic ignored "-Wstringop-truncation"
vishwa24afbb92016-06-10 06:08:56 -0500631 /* Its a running string so strip off the '\0' */
632 strncat(bin_copy, bin_byte, 2);
Patrick Williams6f47bee2023-07-19 11:06:21 -0500633#pragma GCC diagnostic pop
vishwa24afbb92016-06-10 06:08:56 -0500634 }
635
636 /* We need the data represented as 0x...... */
Patrick Venturec9508db2018-10-16 17:18:43 -0700637 if (vpd_val_len > 0)
vishwa24afbb92016-06-10 06:08:56 -0500638 {
Brad Bishopec73c952018-11-21 16:04:13 -0500639 memcpy(bin_in_ascii, "0x", 2);
vishwa24afbb92016-06-10 06:08:56 -0500640 }
Andrew Geissler4e411662017-06-01 07:26:39 -0500641#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700642 printf("_append_to_dict: VPD Key = [%s] : Type Code = [BINARY] :"
643 " Len = [%d] : Val = [%s]\n",
644 vpd_key_names[vpd_key_id], vpd_val_len, bin_in_ascii);
Andrew Geissler4e411662017-06-01 07:26:39 -0500645#endif
Patrick Williamscfa96af2023-05-10 07:50:26 -0500646 info[vpd_key_id] = std::make_pair(vpd_key_names[vpd_key_id],
647 bin_in_ascii);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500648 break;
vishwa24afbb92016-06-10 06:08:56 -0500649
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500650 case 3:
Andrew Geissler4e411662017-06-01 07:26:39 -0500651#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700652 printf("_append_to_dict: VPD Key = [%s] : Type Code=[ASCII+Latin]"
653 " : Len = [%d] : Val = [%s]\n",
654 vpd_key_names[vpd_key_id], vpd_val_len, &vpd_key_val[1]);
Andrew Geissler4e411662017-06-01 07:26:39 -0500655#endif
Deepak Kodihalli8a2a6752017-02-11 03:04:38 -0600656 info[vpd_key_id] = std::make_pair(
Patrick Venturec9508db2018-10-16 17:18:43 -0700657 vpd_key_names[vpd_key_id],
658 std::string(vpd_key_val + 1, vpd_key_val + 1 + type_length));
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500659 break;
660 }
661
Patrick Venturec9508db2018-10-16 17:18:43 -0700662 if (bin_in_ascii)
vishwa24afbb92016-06-10 06:08:56 -0500663 {
664 free(bin_in_ascii);
665 bin_in_ascii = NULL;
666 }
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500667}
668
Patrick Venturec9508db2018-10-16 17:18:43 -0700669int parse_fru_area(const uint8_t area, const void* msgbuf, const size_t len,
670 IPMIFruInfo& info)
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500671{
Patrick Venturec9508db2018-10-16 17:18:43 -0700672 int rv = -1;
673 int i = 0;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500674
Patrick Venturec9508db2018-10-16 17:18:43 -0700675 /* Chassis */
676 uint8_t chassis_type;
677 /* Board */
678 uint32_t mfg_date_time;
679 /* Product */
680 // unsigned int product_custom_fields_len;
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500681
Patrick Venturec9508db2018-10-16 17:18:43 -0700682 // ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
683 ipmi_fru_field_t vpd_info[OPENBMC_VPD_KEY_MAX];
684 char timestr[OPENBMC_VPD_VAL_LEN];
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500685
Patrick Venturec9508db2018-10-16 17:18:43 -0700686 // uint8_t* ipmi_fru_field_str=NULL;
687 // ipmi_fru_common_hdr_t* chdr = NULL;
688 // uint8_t* hdr = NULL;
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500689
Patrick Venturec9508db2018-10-16 17:18:43 -0700690 ASSERT(msgbuf);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500691
Patrick Venturec9508db2018-10-16 17:18:43 -0700692 for (i = 0; i < OPENBMC_VPD_KEY_MAX; i++)
693 {
694 memset(vpd_info[i].type_length_field, '\0',
695 IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
696 vpd_info[i].type_length_field_length = 0;
697 }
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500698
Patrick Venturec9508db2018-10-16 17:18:43 -0700699 switch (area)
700 {
701 case IPMI_FRU_AREA_CHASSIS_INFO:
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500702#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700703 printf("Chassis : Buf len = [%d]\n", len);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500704#endif
Patrick Venturec9508db2018-10-16 17:18:43 -0700705 ipmi_fru_chassis_info_area(
706 (uint8_t*)msgbuf + 2, len, &chassis_type,
707 &vpd_info[OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
708 &vpd_info[OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
709 &vpd_info[OPENBMC_VPD_KEY_CHASSIS_CUSTOM1],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500710 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500711
Patrick Venturec9508db2018-10-16 17:18:43 -0700712 /* Populate VPD Table */
713 for (i = 1; i <= OPENBMC_VPD_KEY_CHASSIS_MAX; i++)
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500714 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700715 if (i == OPENBMC_VPD_KEY_CHASSIS_TYPE)
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500716 {
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500717#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700718 printf("Chassis : Appending [%s] = [%d]\n",
719 vpd_key_names[i], chassis_type);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500720#endif
Ratan Guptacb0d4e52016-12-22 19:05:57 +0530721 info[i] = std::make_pair(vpd_key_names[i],
Patrick Venturec9508db2018-10-16 17:18:43 -0700722 std::to_string(chassis_type));
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500723 continue;
724 }
Patrick Venturec9508db2018-10-16 17:18:43 -0700725 _append_to_dict(i, vpd_info[i].type_length_field, info);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500726 }
727 break;
Patrick Venturec9508db2018-10-16 17:18:43 -0700728 case IPMI_FRU_AREA_BOARD_INFO:
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500729#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700730 printf("Board : Buf len = [%d]\n", len);
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500731#endif
Patrick Venturec9508db2018-10-16 17:18:43 -0700732 ipmi_fru_board_info_area(
733 (uint8_t*)msgbuf + 2, len, NULL, &mfg_date_time,
734 &vpd_info[OPENBMC_VPD_KEY_BOARD_MFR],
735 &vpd_info[OPENBMC_VPD_KEY_BOARD_NAME],
736 &vpd_info[OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
737 &vpd_info[OPENBMC_VPD_KEY_BOARD_PART_NUM],
738 &vpd_info[OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
739 &vpd_info[OPENBMC_VPD_KEY_BOARD_CUSTOM1],
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500740 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
741
Patrick Venturec9508db2018-10-16 17:18:43 -0700742 /* Populate VPD Table */
743 for (i = OPENBMC_VPD_KEY_BOARD_MFG_DATE;
744 i <= OPENBMC_VPD_KEY_BOARD_MAX; i++)
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500745 {
Patrick Venturec9508db2018-10-16 17:18:43 -0700746 if (i == OPENBMC_VPD_KEY_BOARD_MFG_DATE)
747 {
748 _to_time_str(mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN);
749#if IPMI_FRU_PARSER_DEBUG
750 printf("Board : Appending [%s] = [%s]\n", vpd_key_names[i],
751 timestr);
752#endif
Patrick Williamscfa96af2023-05-10 07:50:26 -0500753 info[i] = std::make_pair(vpd_key_names[i],
754 std::string(timestr));
Patrick Venturec9508db2018-10-16 17:18:43 -0700755 continue;
756 }
757 _append_to_dict(i, vpd_info[i].type_length_field, info);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500758 }
759 break;
Patrick Venturec9508db2018-10-16 17:18:43 -0700760 case IPMI_FRU_AREA_PRODUCT_INFO:
761#if IPMI_FRU_PARSER_DEBUG
762 printf("Product : Buf len = [%d]\n", len);
763#endif
764 ipmi_fru_product_info_area(
765 (uint8_t*)msgbuf + 2, len, NULL,
766 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_MFR],
767 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_NAME],
768 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM],
769 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_VER],
770 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
771 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
772 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
773 &vpd_info[OPENBMC_VPD_KEY_PRODUCT_CUSTOM1],
774 OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
775
776 for (i = OPENBMC_VPD_KEY_PRODUCT_MFR;
777 i <= OPENBMC_VPD_KEY_PRODUCT_MAX; ++i)
778 {
779 _append_to_dict(i, vpd_info[i].type_length_field, info);
780 }
781 break;
782 default:
783 /* TODO: Parse Multi Rec / Internal use area */
784 break;
785 }
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500786
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500787#if IPMI_FRU_PARSER_DEBUG
Patrick Venturec9508db2018-10-16 17:18:43 -0700788 printf("parse_fru_area : Dictionary Packing Complete\n");
Hariharasubramanian Ra032c772015-10-20 07:28:19 -0500789#endif
Patrick Venturec9508db2018-10-16 17:18:43 -0700790 rv = 0;
791 return (rv);
Hariharasubramanian Rc2d79462015-10-16 06:47:56 -0500792}