* [PATCH ipmi-fru-parser 01/11] Checking in the basic IPMI FRU Parser Library. Parser has just enough intelligence to parse Chassis, Board & Product info areas. No support for multi-record in this version. This parser is a stripped down version of the parser in the FreeIPMI distribution.
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
@ 2015-11-08 3:58 ` OpenBMC Patches
2015-11-08 3:58 ` [PATCH ipmi-fru-parser 02/11] IPMI FRU Parser Interface OpenBMC Patches
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:58 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
Makefile | 19 ++
frup.c | 599 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 618 insertions(+)
create mode 100644 Makefile
create mode 100644 frup.c
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..cf75af3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,19 @@
+CXX ?= $(CROSS_COMPILE)g++
+
+IPMI_FRU_PARSER_LIB = libifp.so
+IPMI_FRU_PARSER_OBJS = frup.o
+
+INC_FLAGS += $(shell pkg-config --cflags --libs libsystemd) -I. -O2 --std=gnu++11
+LIB_FLAGS += $(shell pkg-config --libs libsystemd) -rdynamic
+#IPMID_PATH ?= -DHOST_IPMI_LIB_PATH=\"/usr/lib/host-ipmid/\"
+
+all: $(IPMI_FRU_PARSER_LIB)
+
+%.o: %.c
+ $(CXX) -fpic -c $< $(CXXFLAGS) $(INC_FLAG) $(IPMID_PATH) -o $@
+
+$(IPMI_FRU_PARSER_LIB): $(IPMI_FRU_PARSER_OBJS)
+ $(CXX) $^ -shared $(LDFLAGS) $(LIB_FLAGS) -o $@
+
+clean:
+ rm -f $(IPMI_FRU_PARSER_OBJS) $(IPMI_FRU_PARSER_LIB)
diff --git a/frup.c b/frup.c
new file mode 100644
index 0000000..d3471ff
--- /dev/null
+++ b/frup.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright (C) 2003-2014 FreeIPMI Core Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/*****************************************************************************\
+ * Copyright (C) 2007-2014 Lawrence Livermore National Security, LLC.
+ * Copyright (C) 2007 The Regents of the University of California.
+ * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ * Written by Albert Chu <chu11@llnl.gov>
+ * UCRL-CODE-232183
+ *
+ * This file is part of Ipmi-fru, a tool used for retrieving
+ * motherboard field replaceable unit (FRU) information. For details,
+ * see http://www.llnl.gov/linux/.
+ *
+ * Ipmi-fru is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * Ipmi-fru is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Ipmi-fru. If not, see <http://www.gnu.org/licenses/>.
+\*****************************************************************************/
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+
+#define uint8_t unsigned char
+#define uint32_t unsigned int
+
+#define ASSERT(x) if(!(x)) return -1;
+
+
+#define IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX 512
+#define IPMI_FRU_SENTINEL_VALUE 0xC1
+#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK 0xC0
+#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT 0x06
+#define IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK 0x3F
+#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE 0x03
+
+
+struct ipmi_fru_field
+{
+ uint8_t type_length_field[IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX];
+ /* store length of data stored in buffer */
+ unsigned int type_length_field_length;
+};
+
+typedef struct ipmi_fru_field ipmi_fru_field_t;
+
+static int
+_parse_type_length (const void *areabuf,
+ unsigned int areabuflen,
+ unsigned int current_area_offset,
+ uint8_t *number_of_data_bytes,
+ ipmi_fru_field_t *field)
+{
+ const uint8_t *areabufptr = (const uint8_t*) areabuf;
+ uint8_t type_length;
+ uint8_t type_code;
+
+ ASSERT (areabuf);
+ ASSERT (areabuflen);
+ ASSERT (number_of_data_bytes);
+
+ type_length = areabufptr[current_area_offset];
+
+ /* IPMI Workaround
+ *
+ * Dell P weredge R610
+ *
+ * My reading of the FRU Spec is that all non-custom fields are
+ * required to be listed by the vendor. However, on this
+ * motherboard, some areas list this, indicating that there is
+ * no more data to be parsed. So now, for "required" fields, I
+ * check to see if the type-length field is a sentinel before
+ * calling this function.
+ */
+
+ ASSERT (type_length != IPMI_FRU_SENTINEL_VALUE);
+
+ type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >> IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
+ (*number_of_data_bytes) = type_length & IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
+
+ /* Special Case: This shouldn't be a length of 0x01 (see type/length
+ * byte format in FRU Information Storage Definition).
+ */
+ if (type_code == IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE
+ && (*number_of_data_bytes) == 0x01)
+ {
+ return (-1);
+ }
+
+ if ((current_area_offset + 1 + (*number_of_data_bytes)) > areabuflen)
+ {
+ return (-1);
+ }
+
+ if (field)
+ {
+ memset (field->type_length_field,
+ '\0',
+ IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
+ memcpy (field->type_length_field,
+ &areabufptr[current_area_offset],
+ 1 + (*number_of_data_bytes));
+ field->type_length_field_length = 1 + (*number_of_data_bytes);
+ }
+
+ return (0);
+}
+
+int
+ipmi_fru_chassis_info_area (const void *areabuf,
+ unsigned int areabuflen,
+ uint8_t *chassis_type,
+ ipmi_fru_field_t *chassis_part_number,
+ ipmi_fru_field_t *chassis_serial_number,
+ ipmi_fru_field_t *chassis_custom_fields,
+ unsigned int chassis_custom_fields_len)
+{
+ const uint8_t *areabufptr = (const uint8_t*) areabuf;
+ unsigned int area_offset = 0;
+ unsigned int custom_fields_index = 0;
+ uint8_t number_of_data_bytes;
+ int rv = -1;
+
+ if (!areabuf || !areabuflen)
+ {
+ return (-1);
+ }
+
+ if (chassis_part_number)
+ memset (chassis_part_number,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (chassis_serial_number)
+ memset (chassis_serial_number,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (chassis_custom_fields && chassis_custom_fields_len)
+ memset (chassis_custom_fields,
+ '\0',
+ sizeof (ipmi_fru_field_t) * chassis_custom_fields_len);
+
+ if (chassis_type)
+ (*chassis_type) = areabufptr[area_offset];
+ area_offset++;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ chassis_part_number) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ chassis_serial_number) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ while (area_offset < areabuflen
+ && areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
+ {
+ ipmi_fru_field_t *field_ptr = NULL;
+
+ if (chassis_custom_fields && chassis_custom_fields_len)
+ {
+ if (custom_fields_index < chassis_custom_fields_len)
+ field_ptr = &chassis_custom_fields[custom_fields_index];
+ else
+ {
+ goto cleanup;
+ }
+ }
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ field_ptr) < 0)
+ goto cleanup;
+
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+ custom_fields_index++;
+ }
+
+
+ out:
+ rv = 0;
+ cleanup:
+ return (rv);
+}
+
+int
+ipmi_fru_board_info_area (const void *areabuf,
+ unsigned int areabuflen,
+ uint8_t *language_code,
+ uint32_t *mfg_date_time,
+ ipmi_fru_field_t *board_manufacturer,
+ ipmi_fru_field_t *board_product_name,
+ ipmi_fru_field_t *board_serial_number,
+ ipmi_fru_field_t *board_part_number,
+ ipmi_fru_field_t *board_fru_file_id,
+ ipmi_fru_field_t *board_custom_fields,
+ unsigned int board_custom_fields_len)
+{
+ const uint8_t *areabufptr = (const uint8_t*) areabuf;
+ uint32_t mfg_date_time_tmp = 0;
+ unsigned int area_offset = 0;
+ unsigned int custom_fields_index = 0;
+ uint8_t number_of_data_bytes;
+ int rv = -1;
+
+ if (!areabuf || !areabuflen)
+ {
+ return (-1);
+ }
+
+ if (board_manufacturer)
+ memset (board_manufacturer,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (board_product_name)
+ memset (board_product_name,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (board_serial_number)
+ memset (board_serial_number,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (board_part_number)
+ memset (board_part_number,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (board_fru_file_id)
+ memset (board_fru_file_id,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (board_custom_fields && board_custom_fields_len)
+ memset (board_custom_fields,
+ '\0',
+ sizeof (ipmi_fru_field_t) * board_custom_fields_len);
+
+ if (language_code)
+ (*language_code) = areabufptr[area_offset];
+ area_offset++;
+
+ if (mfg_date_time)
+ {
+ struct tm tm;
+ time_t t;
+
+ /* mfg_date_time is little endian - see spec */
+ mfg_date_time_tmp |= areabufptr[area_offset];
+ area_offset++;
+ mfg_date_time_tmp |= (areabufptr[area_offset] << 8);
+ area_offset++;
+ mfg_date_time_tmp |= (areabufptr[area_offset] << 16);
+ area_offset++;
+
+ /* mfg_date_time is in minutes, so multiple by 60 to get seconds */
+ mfg_date_time_tmp *= 60;
+
+ /* Posix says individual calls need not clear/set all portions of
+ * 'struct tm', thus passing 'struct tm' between functions could
+ * have issues. So we need to memset.
+ */
+ memset (&tm, '\0', sizeof(struct tm));
+
+ /* In FRU, epoch is 0:00 hrs 1/1/96
+ *
+ * So convert into ansi epoch
+ */
+
+ tm.tm_year = 96; /* years since 1900 */
+ tm.tm_mon = 0; /* months since January */
+ tm.tm_mday = 1; /* 1-31 */
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_isdst = -1;
+
+ if ((t = mktime (&tm)) == (time_t)-1)
+ {
+ goto cleanup;
+ }
+
+ mfg_date_time_tmp += (uint32_t)t;
+ (*mfg_date_time) = mfg_date_time_tmp;
+ }
+ else
+ area_offset += 3;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ board_manufacturer) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ board_product_name) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ board_serial_number) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (
+ areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ board_part_number) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ board_fru_file_id) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ while (area_offset < areabuflen
+ && areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
+ {
+ ipmi_fru_field_t *field_ptr = NULL;
+
+ if (board_custom_fields && board_custom_fields_len)
+ {
+ if (custom_fields_index < board_custom_fields_len)
+ field_ptr = &board_custom_fields[custom_fields_index];
+ else
+ {
+ goto cleanup;
+ }
+ }
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ field_ptr) < 0)
+ goto cleanup;
+
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+ custom_fields_index++;
+ }
+
+ out:
+ rv = 0;
+ cleanup:
+ return (rv);
+}
+
+int
+ipmi_fru_product_info_area (const void *areabuf,
+ unsigned int areabuflen,
+ uint8_t *language_code,
+ ipmi_fru_field_t *product_manufacturer_name,
+ ipmi_fru_field_t *product_name,
+ ipmi_fru_field_t *product_part_model_number,
+ ipmi_fru_field_t *product_version,
+ ipmi_fru_field_t *product_serial_number,
+ ipmi_fru_field_t *product_asset_tag,
+ ipmi_fru_field_t *product_fru_file_id,
+ ipmi_fru_field_t *product_custom_fields,
+ unsigned int product_custom_fields_len)
+{
+ const uint8_t *areabufptr = (const uint8_t*) areabuf;
+ unsigned int area_offset = 0;
+ unsigned int custom_fields_index = 0;
+ uint8_t number_of_data_bytes;
+ int rv = -1;
+
+ if (!areabuf || !areabuflen)
+ {
+ return (-1);
+ }
+
+ if (product_manufacturer_name)
+ memset (product_manufacturer_name,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (product_name)
+ memset (product_name,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (product_part_model_number)
+ memset (product_part_model_number,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (product_version)
+ memset (product_version,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (product_serial_number)
+ memset (product_serial_number,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (product_asset_tag)
+ memset (product_asset_tag,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (product_fru_file_id)
+ memset (product_fru_file_id,
+ '\0',
+ sizeof (ipmi_fru_field_t));
+ if (product_custom_fields && product_custom_fields_len)
+ memset (product_custom_fields,
+ '\0',
+ sizeof (ipmi_fru_field_t) * product_custom_fields_len);
+
+ if (language_code)
+ (*language_code) = areabufptr[area_offset];
+ area_offset++;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ product_manufacturer_name) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ product_name) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ product_part_model_number) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ product_version) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ product_serial_number) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ product_asset_tag) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
+ goto out;
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ product_fru_file_id) < 0)
+ goto cleanup;
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+
+ while (area_offset < areabuflen
+ && areabufptr[area_offset] != IPMI_FRU_SENTINEL_VALUE)
+ {
+ ipmi_fru_field_t *field_ptr = NULL;
+
+ if (product_custom_fields && product_custom_fields_len)
+ {
+ if (custom_fields_index < product_custom_fields_len)
+ field_ptr = &product_custom_fields[custom_fields_index];
+ else
+ {
+ goto cleanup;
+ }
+ }
+
+ if (_parse_type_length (areabufptr,
+ areabuflen,
+ area_offset,
+ &number_of_data_bytes,
+ field_ptr) < 0)
+ goto cleanup;
+
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+ custom_fields_index++;
+ }
+
+
+ out:
+ rv = 0;
+ cleanup:
+ return (rv);
+}
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ipmi-fru-parser 02/11] IPMI FRU Parser Interface.
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
2015-11-08 3:58 ` [PATCH ipmi-fru-parser 01/11] Checking in the basic IPMI FRU Parser Library. Parser has just enough intelligence to parse Chassis, Board & Product info areas. No support for multi-record in this version. This parser is a stripped down version of the parser in the FreeIPMI distribution OpenBMC Patches
@ 2015-11-08 3:58 ` OpenBMC Patches
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 03/11] Added interface function to parse wirte fru data message into a dictionary OpenBMC Patches
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:58 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
frup.h | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 frup.h
diff --git a/frup.h b/frup.h
new file mode 100644
index 0000000..2270470
--- /dev/null
+++ b/frup.h
@@ -0,0 +1,7 @@
+#ifndef OPENBMC_IPMI_FRU_PARSER_H
+#define OPENBMC_IPMI_FRU_PARSER_H
+
+/* Parse an IPMI write fru data message into a dictionary containing name value pair of VPD entries.*/
+int parse_fru (const void* msgbuf, sd_bus_message* vpdtbl);
+
+#endif
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ipmi-fru-parser 03/11] Added interface function to parse wirte fru data message into a dictionary.
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
2015-11-08 3:58 ` [PATCH ipmi-fru-parser 01/11] Checking in the basic IPMI FRU Parser Library. Parser has just enough intelligence to parse Chassis, Board & Product info areas. No support for multi-record in this version. This parser is a stripped down version of the parser in the FreeIPMI distribution OpenBMC Patches
2015-11-08 3:58 ` [PATCH ipmi-fru-parser 02/11] IPMI FRU Parser Interface OpenBMC Patches
@ 2015-11-08 3:59 ` OpenBMC Patches
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 04/11] Format string change in sd_bus_message_append OpenBMC Patches
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:59 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
frup.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 237 insertions(+), 13 deletions(-)
diff --git a/frup.c b/frup.c
index d3471ff..9711645 100644
--- a/frup.c
+++ b/frup.c
@@ -47,7 +47,19 @@
#define uint8_t unsigned char
#define uint32_t unsigned int
-#define ASSERT(x) if(!(x)) return -1;
+#define TEXTSTR(a) #a
+# define ASSERT(x) \
+do { \
+if (0 == (x)) { \
+fprintf(stderr, \
+"Assertion failed: %s, " \
+"%d at \'%s\'\n", \
+__FILE__, \
+__LINE__, \
+TEXTSTR(a)); \
+return -1; \
+} \
+} while (0)
#define IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX 512
@@ -57,6 +69,20 @@
#define IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK 0x3F
#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE 0x03
+/* OpenBMC defines for Parser */
+#define IPMI_FRU_AREA_TYPE_MAX 0x05
+#define IPMI_FRU_AREA_INTERNAL_USE 0x00
+#define IPMI_FRU_AREA_CHASSIS_INFO 0x01
+#define IPMI_FRU_AREA_BOARD_INFO 0x02
+#define IPMI_FRU_AREA_PRODUCT_INFO 0x03
+#define IPMI_FRU_AREA_MULTI_RECORD 0x04
+
+#define OPENBMC_VPD_KEY_LEN 64
+#define OPENBMC_VPD_VAL_LEN 512
+
+
+int sd_bus_message_append (void*, const char*, ...);
+typedef struct sd_bus_message sd_bus_message;
struct ipmi_fru_field
{
@@ -66,7 +92,91 @@ struct ipmi_fru_field
};
typedef struct ipmi_fru_field ipmi_fru_field_t;
+/*
+ * FRU Parser
+ */
+
+typedef struct ipmi_fru_area_info
+{
+ uint8_t off;
+ uint8_t len;
+} ipmi_fru_area_info_t;
+
+typedef struct ipmi_fru_common_hdr
+{
+ uint8_t fmtver;
+ uint8_t internal;
+ uint8_t chassis;
+ uint8_t board;
+ uint8_t product;
+ uint8_t multirec;
+} ipmi_fru_common_hdr_t;
+
+enum openbmc_vpd_key_id
+{
+ OPENBMC_VPD_KEY_CHASSIS_TYPE = 1, /* not a type/len */
+ OPENBMC_VPD_KEY_CHASSIS_PART_NUM,
+ OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,
+ /* TODO: chassis_custom_fields */
+
+ OPENBMC_VPD_KEY_BOARD_MFG_DATE, /* not a type/len */
+ OPENBMC_VPD_KEY_BOARD_MFR,
+ OPENBMC_VPD_KEY_BOARD_NAME,
+ OPENBMC_VPD_KEY_BOARD_SERIAL_NUM,
+ OPENBMC_VPD_KEY_BOARD_PART_NUM,
+ OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID,
+ /* TODO: board_custom_fields */
+
+ OPENBMC_VPD_KEY_PRODUCT_MFR,
+ OPENBMC_VPD_KEY_PRODUCT_NAME,
+ OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM,
+ OPENBMC_VPD_KEY_PRODUCT_VER,
+ OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM,
+ OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG,
+ OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID,
+ /* TODO: product_custom_fields */
+
+ OPENBMC_VPD_KEY_MAX,
+
+};
+
+const char* vpd_key_names [] =
+{
+ "Key Names Table Start",
+ "Chassis Type", /*OPENBMC_VPD_KEY_CHASSIS_TYPE*/
+ "Chassis Part Number", /*OPENBMC_VPD_KEY_CHASSIS_PART_NUM,*/
+ "Chassis Serial Number", /*OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,*/
+
+ /* TODO: chassis_custom_fields */
+
+ "Board Mfg Date", /* OPENBMC_VPD_KEY_BOARD_MFG_DATE, */ /* not a type/len */
+ "Board Manufacturer", /* OPENBMC_VPD_KEY_BOARD_MFR, */
+ "Board Name", /* OPENBMC_VPD_KEY_BOARD_NAME, */
+ "Board Serial Number", /* OPENBMC_VPD_KEY_BOARD_SERIAL_NUM, */
+ "Board Part Number", /* OPENBMC_VPD_KEY_BOARD_PART_NUM, */
+ "Board FRU File ID", /* OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID, */
+ /* TODO: board_custom_fields */
+
+ "Product Manufacturer", /* OPENBMC_VPD_KEY_PRODUCT_MFR, */
+ "Product Name", /* OPENBMC_VPD_KEY_PRODUCT_NAME, */
+ "Product Model Number", /* OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM, */
+ "Product Version", /* OPENBMC_VPD_KEY_PRODUCT_VER, */
+ "Product Serial Number", /* OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM, */
+ "Product Asset Tag", /* OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG, */
+ "Product FRU File ID", /* OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID, */
+ /* TODO: product_custom_fields */
+
+ "Key Names Table End" /*OPENBMC_VPD_KEY_MAX,*/
+};
+
+/*
+ * --------------------------------------------------------------------
+ *
+ * --------------------------------------------------------------------
+ */
+
+/* private method to parse type/length */
static int
_parse_type_length (const void *areabuf,
unsigned int areabuflen,
@@ -84,14 +194,14 @@ _parse_type_length (const void *areabuf,
type_length = areabufptr[current_area_offset];
- /* IPMI Workaround
+ /* ipmi workaround
*
- * Dell P weredge R610
+ * dell p weredge r610
*
- * My reading of the FRU Spec is that all non-custom fields are
- * required to be listed by the vendor. However, on this
+ * my reading of the fru spec is that all non-custom fields are
+ * required to be listed by the vendor. however, on this
* motherboard, some areas list this, indicating that there is
- * no more data to be parsed. So now, for "required" fields, I
+ * no more data to be parsed. so now, for "required" fields, i
* check to see if the type-length field is a sentinel before
* calling this function.
*/
@@ -101,8 +211,8 @@ _parse_type_length (const void *areabuf,
type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >> IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
(*number_of_data_bytes) = type_length & IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
- /* Special Case: This shouldn't be a length of 0x01 (see type/length
- * byte format in FRU Information Storage Definition).
+ /* special case: this shouldn't be a length of 0x01 (see type/length
+ * byte format in fru information storage definition).
*/
if (type_code == IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE
&& (*number_of_data_bytes) == 0x01)
@@ -294,19 +404,19 @@ ipmi_fru_board_info_area (const void *areabuf,
/* mfg_date_time is in minutes, so multiple by 60 to get seconds */
mfg_date_time_tmp *= 60;
- /* Posix says individual calls need not clear/set all portions of
+ /* posix says individual calls need not clear/set all portions of
* 'struct tm', thus passing 'struct tm' between functions could
- * have issues. So we need to memset.
+ * have issues. so we need to memset.
*/
memset (&tm, '\0', sizeof(struct tm));
- /* In FRU, epoch is 0:00 hrs 1/1/96
+ /* in fru, epoch is 0:00 hrs 1/1/96
*
- * So convert into ansi epoch
+ * so convert into ansi epoch
*/
tm.tm_year = 96; /* years since 1900 */
- tm.tm_mon = 0; /* months since January */
+ tm.tm_mon = 0; /* months since january */
tm.tm_mday = 1; /* 1-31 */
tm.tm_hour = 0;
tm.tm_min = 0;
@@ -597,3 +707,117 @@ ipmi_fru_product_info_area (const void *areabuf,
cleanup:
return (rv);
}
+
+
+int
+parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
+{
+ int ret = 0;
+ int rv = -1;
+ int i = 0;
+ ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
+ ipmi_fru_common_hdr_t* chdr = NULL;
+ uint8_t* hdr = NULL;
+
+
+ ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
+
+ /* Chassis */
+ uint8_t chassis_type;
+
+ /* Board */
+ uint32_t mfg_date_time;
+
+ /* Product */
+ unsigned int product_custom_fields_len;
+
+ ASSERT (msgbuf);
+ ASSERT (vpdtbl);
+
+ chdr = (ipmi_fru_common_hdr_t*) msgbuf;
+ hdr = (uint8_t*) msgbuf;
+
+ fru_area_info [ IPMI_FRU_AREA_INTERNAL_USE ].off = chdr->internal;
+ fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].off = chdr->chassis;
+ fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].off = chdr->board;
+ fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].off = chdr->product;
+ fru_area_info [ IPMI_FRU_AREA_MULTI_RECORD ].off = chdr->multirec;
+
+ if (chdr->internal)
+ {
+ fru_area_info [ IPMI_FRU_AREA_INTERNAL_USE ].len = 8*(*(hdr+chdr->internal+1));
+
+ /* TODO: Parse internal use area */
+ }
+
+ if (chdr->chassis)
+ {
+ fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].len = 8*(*(hdr+chdr->chassis+1));
+ ipmi_fru_chassis_info_area (hdr+chdr->chassis,
+ fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].len,
+ &chassis_type,
+ &vpd_info [OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
+ &vpd_info [OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
+ NULL, 0);
+ }
+
+ if (chdr->board)
+ {
+ fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].len = 8*(*(hdr+chdr->board+1));
+ ipmi_fru_board_info_area (hdr+chdr->board,
+ fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].len,
+ NULL,
+ &mfg_date_time,
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_MFR],
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_NAME],
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_PART_NUM],
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
+ NULL, 0);
+ }
+
+ if (chdr->product)
+ {
+ fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].len = 8*(*(hdr+chdr->product+1));
+ ipmi_fru_product_info_area (hdr+chdr->product,
+ fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].len,
+ NULL,
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_MFR],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_NAME],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_VER],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
+ NULL, 0);
+ }
+
+ if (chdr->multirec)
+ {
+ fru_area_info [ IPMI_FRU_AREA_MULTI_RECORD ].len = 8*(*(hdr+chdr->multirec+1));
+ /* TODO: Parse multi record area */
+ }
+
+ /* Populate VPD Table */
+ for (i=1; i<OPENBMC_VPD_KEY_MAX; i++)
+ {
+ if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
+ {
+ sd_bus_message_append (vpdtbl, "sd", vpd_key_names[i], chassis_type);
+ continue;
+ }
+
+ if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
+ {
+ sd_bus_message_append (vpdtbl, "sd", vpd_key_names[i], mfg_date_time);
+ continue;
+ }
+
+ sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], vpd_info [i].type_length_field);
+ }
+
+ out:
+ rv = 0;
+ cleanup:
+ return (rv);
+}
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ipmi-fru-parser 04/11] Format string change in sd_bus_message_append.
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
` (2 preceding siblings ...)
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 03/11] Added interface function to parse wirte fru data message into a dictionary OpenBMC Patches
@ 2015-11-08 3:59 ` OpenBMC Patches
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 05/11] Added interface parse_fru_area to parse a specific area and populate a name/value dictionary OpenBMC Patches
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:59 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
frup.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/frup.c b/frup.c
index 9711645..ab58426 100644
--- a/frup.c
+++ b/frup.c
@@ -803,13 +803,13 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
{
if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
{
- sd_bus_message_append (vpdtbl, "sd", vpd_key_names[i], chassis_type);
+ sd_bus_message_append (vpdtbl, "sy", vpd_key_names[i], chassis_type);
continue;
}
if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
{
- sd_bus_message_append (vpdtbl, "sd", vpd_key_names[i], mfg_date_time);
+ sd_bus_message_append (vpdtbl, "sa{y}", vpd_key_names[i], mfg_date_time);
continue;
}
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ipmi-fru-parser 05/11] Added interface parse_fru_area to parse a specific area and populate a name/value dictionary.
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
` (3 preceding siblings ...)
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 04/11] Format string change in sd_bus_message_append OpenBMC Patches
@ 2015-11-08 3:59 ` OpenBMC Patches
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 06/11] Removing depency in Makefile on the systemd library OpenBMC Patches
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:59 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
frup.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
frup.h | 11 +++++++
2 files changed, 119 insertions(+)
diff --git a/frup.c b/frup.c
index ab58426..d279666 100644
--- a/frup.c
+++ b/frup.c
@@ -117,6 +117,7 @@ enum openbmc_vpd_key_id
OPENBMC_VPD_KEY_CHASSIS_TYPE = 1, /* not a type/len */
OPENBMC_VPD_KEY_CHASSIS_PART_NUM,
OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,
+ OPENBMC_VPD_KEY_CHASSIS_MAX = OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,
/* TODO: chassis_custom_fields */
OPENBMC_VPD_KEY_BOARD_MFG_DATE, /* not a type/len */
@@ -125,6 +126,7 @@ enum openbmc_vpd_key_id
OPENBMC_VPD_KEY_BOARD_SERIAL_NUM,
OPENBMC_VPD_KEY_BOARD_PART_NUM,
OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID,
+ OPENBMC_VPD_KEY_BOARD_MAX = OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID,
/* TODO: board_custom_fields */
OPENBMC_VPD_KEY_PRODUCT_MFR,
@@ -134,6 +136,7 @@ enum openbmc_vpd_key_id
OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM,
OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG,
OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID,
+ OPENBMC_VPD_KEY_PRODUCT_MAX = OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID,
/* TODO: product_custom_fields */
OPENBMC_VPD_KEY_MAX,
@@ -821,3 +824,108 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
cleanup:
return (rv);
}
+
+int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, sd_bus_message* vpdtbl)
+{
+ int ret = 0;
+ int rv = -1;
+ int i = 0;
+ ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
+ ipmi_fru_common_hdr_t* chdr = NULL;
+ uint8_t* hdr = NULL;
+
+
+ ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
+
+ /* Chassis */
+ uint8_t chassis_type;
+
+ /* Board */
+ uint32_t mfg_date_time;
+
+ /* Product */
+ unsigned int product_custom_fields_len;
+
+ ASSERT (msgbuf);
+ ASSERT (vpdtbl);
+
+ chdr = (ipmi_fru_common_hdr_t*) msgbuf;
+ hdr = (uint8_t*) msgbuf;
+
+ fru_area_info [ IPMI_FRU_AREA_INTERNAL_USE ].off = chdr->internal;
+ fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].off = chdr->chassis;
+ fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].off = chdr->board;
+ fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].off = chdr->product;
+ fru_area_info [ IPMI_FRU_AREA_MULTI_RECORD ].off = chdr->multirec;
+
+ switch (area)
+ {
+ case IPMI_FRU_AREA_CHASSIS_INFO:
+ ipmi_fru_chassis_info_area (msgbuf,
+ len,
+ &chassis_type,
+ &vpd_info [OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
+ &vpd_info [OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
+ NULL, 0);
+
+ /* Populate VPD Table */
+ for (i=1; i<=OPENBMC_VPD_KEY_CHASSIS_MAX; i++)
+ {
+ if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
+ {
+ sd_bus_message_append (vpdtbl, "sy", vpd_key_names[i], chassis_type);
+ continue;
+ }
+ sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], vpd_info [i].type_length_field);
+ }
+ break;
+ case IPMI_FRU_AREA_BOARD_INFO:
+ ipmi_fru_board_info_area (msgbuf,
+ len,
+ NULL,
+ &mfg_date_time,
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_MFR],
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_NAME],
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_PART_NUM],
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
+ NULL, 0);
+
+ /* Populate VPD Table */
+ for (i=OPENBMC_VPD_KEY_BOARD_MFR; i<=OPENBMC_VPD_KEY_BOARD_MAX; i++)
+ {
+ if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
+ {
+ sd_bus_message_append (vpdtbl, "sa{y}", vpd_key_names[i], mfg_date_time);
+ continue;
+ }
+ sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], vpd_info [i].type_length_field);
+ }
+ break;
+ case IPMI_FRU_AREA_PRODUCT_INFO:
+ ipmi_fru_product_info_area (msgbuf,
+ len,
+ NULL,
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_MFR],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_NAME],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_VER],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
+ NULL, 0);
+ for (i=OPENBMC_VPD_KEY_PRODUCT_MFR; i<=OPENBMC_VPD_KEY_PRODUCT_MAX; i++)
+ {
+ sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], vpd_info [i].type_length_field);
+ }
+ break;
+ defualt:
+ /* TODO: Parse Multi Rec / Internal use area */
+ break;
+ }
+
+ out:
+ rv = 0;
+ cleanup:
+ return (rv);
+}
diff --git a/frup.h b/frup.h
index 2270470..b6b9476 100644
--- a/frup.h
+++ b/frup.h
@@ -3,5 +3,16 @@
/* Parse an IPMI write fru data message into a dictionary containing name value pair of VPD entries.*/
int parse_fru (const void* msgbuf, sd_bus_message* vpdtbl);
+int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, sd_bus_message* vpdtbl);
+
+enum openbmc_ipmi_fru_area_type
+{
+ IPMI_FRU_AREA_INTERNAL_USE = 0x00,
+ IPMI_FRU_AREA_CHASSIS_INFO,
+ IPMI_FRU_AREA_BOARD_INFO,
+ IPMI_FRU_AREA_PRODUCT_INFO,
+ IPMI_FRU_AREA_MULTI_RECORD,
+ IPMI_FRU_AREA_TYPE_MAX
+}
#endif
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ipmi-fru-parser 06/11] Removing depency in Makefile on the systemd library.
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
` (4 preceding siblings ...)
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 05/11] Added interface parse_fru_area to parse a specific area and populate a name/value dictionary OpenBMC Patches
@ 2015-11-08 3:59 ` OpenBMC Patches
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 07/11] Internal parser functions expect the area buffer to point to location where language code. Hence advance 2 bytes on the areabuf(to go past the fmt/version and len fields) and pass it to the area specific parser routines. Also fix bugs on offset/len calcuation OpenBMC Patches
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:59 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
Makefile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index cf75af3..bcb3648 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,8 @@ IPMI_FRU_PARSER_LIB = libifp.so
IPMI_FRU_PARSER_OBJS = frup.o
INC_FLAGS += $(shell pkg-config --cflags --libs libsystemd) -I. -O2 --std=gnu++11
-LIB_FLAGS += $(shell pkg-config --libs libsystemd) -rdynamic
+#LIB_FLAGS += $(shell pkg-config --libs libsystemd) -rdynamic
+LIB_FLAGS += -rdynamic
#IPMID_PATH ?= -DHOST_IPMI_LIB_PATH=\"/usr/lib/host-ipmid/\"
all: $(IPMI_FRU_PARSER_LIB)
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ipmi-fru-parser 07/11] Internal parser functions expect the area buffer to point to location where language code. Hence advance 2 bytes on the areabuf(to go past the fmt/version and len fields) and pass it to the area specific parser routines. Also fix bugs on offset/len calcuation.
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
` (5 preceding siblings ...)
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 06/11] Removing depency in Makefile on the systemd library OpenBMC Patches
@ 2015-11-08 3:59 ` OpenBMC Patches
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 08/11] Fix format string in sd_bus_message_append to add as dictionary. Store manufacturing time in ISO8601 format OpenBMC Patches
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:59 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
frup.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 94 insertions(+), 27 deletions(-)
diff --git a/frup.c b/frup.c
index d279666..87669f8 100644
--- a/frup.c
+++ b/frup.c
@@ -44,6 +44,7 @@
#include <string.h>
#include <time.h>
+#define IPMI_FRU_PARSER_DEBUG 1
#define uint8_t unsigned char
#define uint32_t unsigned int
@@ -61,7 +62,6 @@ return -1; \
} \
} while (0)
-
#define IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX 512
#define IPMI_FRU_SENTINEL_VALUE 0xC1
#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK 0xC0
@@ -70,12 +70,12 @@ return -1; \
#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE 0x03
/* OpenBMC defines for Parser */
-#define IPMI_FRU_AREA_TYPE_MAX 0x05
#define IPMI_FRU_AREA_INTERNAL_USE 0x00
#define IPMI_FRU_AREA_CHASSIS_INFO 0x01
#define IPMI_FRU_AREA_BOARD_INFO 0x02
#define IPMI_FRU_AREA_PRODUCT_INFO 0x03
#define IPMI_FRU_AREA_MULTI_RECORD 0x04
+#define IPMI_FRU_AREA_TYPE_MAX 0x05
#define OPENBMC_VPD_KEY_LEN 64
#define OPENBMC_VPD_VAL_LEN 512
@@ -110,7 +110,7 @@ typedef struct ipmi_fru_common_hdr
uint8_t board;
uint8_t product;
uint8_t multirec;
-} ipmi_fru_common_hdr_t;
+} __attribute__((packed)) ipmi_fru_common_hdr_t;
enum openbmc_vpd_key_id
{
@@ -178,7 +178,6 @@ const char* vpd_key_names [] =
*
* --------------------------------------------------------------------
*/
-
/* private method to parse type/length */
static int
_parse_type_length (const void *areabuf,
@@ -476,8 +475,7 @@ ipmi_fru_board_info_area (const void *areabuf,
if (areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE)
goto out;
- if (_parse_type_length (
- areabufptr,
+ if (_parse_type_length (areabufptr,
areabuflen,
area_offset,
&number_of_data_bytes,
@@ -724,6 +722,9 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
+ /*char ipmi_fru_field_str [ IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX ];
+ uint32_t len=0;*/
+ const uint8_t* ipmi_fru_field_str;
/* Chassis */
uint8_t chassis_type;
@@ -737,6 +738,18 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
ASSERT (msgbuf);
ASSERT (vpdtbl);
+ for (i=0; i<OPENBMC_VPD_KEY_MAX; i++)
+ {
+ memset (vpd_info[i].type_length_field, '\0', IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
+ vpd_info[i].type_length_field_length = 0;
+ }
+
+ for (i=0; i<IPMI_FRU_AREA_TYPE_MAX; i++)
+ {
+ fru_area_info [ i ].off = 0;
+ fru_area_info [ i ].len = 0;
+ }
+
chdr = (ipmi_fru_common_hdr_t*) msgbuf;
hdr = (uint8_t*) msgbuf;
@@ -748,15 +761,15 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
if (chdr->internal)
{
- fru_area_info [ IPMI_FRU_AREA_INTERNAL_USE ].len = 8*(*(hdr+chdr->internal+1));
+ fru_area_info [ IPMI_FRU_AREA_INTERNAL_USE ].len = 8*(*(hdr+8*chdr->internal+1));
/* TODO: Parse internal use area */
}
if (chdr->chassis)
{
- fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].len = 8*(*(hdr+chdr->chassis+1));
- ipmi_fru_chassis_info_area (hdr+chdr->chassis,
+ fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].len = 8*(*(hdr+8*chdr->chassis+1));
+ ipmi_fru_chassis_info_area (hdr+8*chdr->chassis+2,
fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].len,
&chassis_type,
&vpd_info [OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
@@ -766,8 +779,8 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
if (chdr->board)
{
- fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].len = 8*(*(hdr+chdr->board+1));
- ipmi_fru_board_info_area (hdr+chdr->board,
+ fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].len = 8*(*(hdr+8*chdr->board+1));
+ ipmi_fru_board_info_area (hdr+8*chdr->board+2,
fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].len,
NULL,
&mfg_date_time,
@@ -781,8 +794,8 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
if (chdr->product)
{
- fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].len = 8*(*(hdr+chdr->product+1));
- ipmi_fru_product_info_area (hdr+chdr->product,
+ fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].len = 8*(*(hdr+8*chdr->product+1));
+ ipmi_fru_product_info_area (hdr+8*chdr->product+2,
fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].len,
NULL,
&vpd_info [OPENBMC_VPD_KEY_PRODUCT_MFR],
@@ -797,26 +810,55 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
if (chdr->multirec)
{
- fru_area_info [ IPMI_FRU_AREA_MULTI_RECORD ].len = 8*(*(hdr+chdr->multirec+1));
+ fru_area_info [ IPMI_FRU_AREA_MULTI_RECORD ].len = 8*(*(hdr+8*chdr->multirec+1));
/* TODO: Parse multi record area */
}
+ for (i=0; i<IPMI_FRU_AREA_TYPE_MAX; i++)
+ {
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("IPMI_FRU_AREA_TYPE=[%d] : Offset=[%d] : Len=[%d]\n", i, fru_area_info [i].off, fru_area_info[i].len);
+#else
+;
+#endif
+ }
+
/* Populate VPD Table */
for (i=1; i<OPENBMC_VPD_KEY_MAX; i++)
{
if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
{
sd_bus_message_append (vpdtbl, "sy", vpd_key_names[i], chassis_type);
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("[%s] = [%d]\n", vpd_key_names[i], chassis_type);
+#else
+;
+#endif
continue;
}
if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
{
sd_bus_message_append (vpdtbl, "sa{y}", vpd_key_names[i], mfg_date_time);
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("[%s] = [%d]\n", vpd_key_names[i], mfg_date_time);
+#else
+;
+#endif
continue;
}
- sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], vpd_info [i].type_length_field);
+ /* FIXME: Field type encoding *ASSUMED* to be *BINARY* */
+ ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
+ sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], ipmi_fru_field_str);
+ if (vpd_info[i].type_length_field_length)
+ {
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("[%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
+#else
+;
+#endif
+ }
}
out:
@@ -833,9 +875,15 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
ipmi_fru_common_hdr_t* chdr = NULL;
uint8_t* hdr = NULL;
+ const uint8_t* ipmi_fru_field_str=NULL;
ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
+ for (i=0; i<OPENBMC_VPD_KEY_MAX; i++)
+ {
+ memset (vpd_info[i].type_length_field, '\0', IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
+ vpd_info[i].type_length_field_length = 0;
+ }
/* Chassis */
uint8_t chassis_type;
@@ -849,15 +897,6 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
ASSERT (msgbuf);
ASSERT (vpdtbl);
- chdr = (ipmi_fru_common_hdr_t*) msgbuf;
- hdr = (uint8_t*) msgbuf;
-
- fru_area_info [ IPMI_FRU_AREA_INTERNAL_USE ].off = chdr->internal;
- fru_area_info [ IPMI_FRU_AREA_CHASSIS_INFO ].off = chdr->chassis;
- fru_area_info [ IPMI_FRU_AREA_BOARD_INFO ].off = chdr->board;
- fru_area_info [ IPMI_FRU_AREA_PRODUCT_INFO ].off = chdr->product;
- fru_area_info [ IPMI_FRU_AREA_MULTI_RECORD ].off = chdr->multirec;
-
switch (area)
{
case IPMI_FRU_AREA_CHASSIS_INFO:
@@ -874,9 +913,20 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
{
sd_bus_message_append (vpdtbl, "sy", vpd_key_names[i], chassis_type);
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("Chassis : [%s] = [%d]\n", vpd_key_names[i], chassis_type);
+#else
+;
+#endif
continue;
}
- sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], vpd_info [i].type_length_field);
+ ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
+ sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], ipmi_fru_field_str);
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("Chassis : [%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
+#else
+;
+#endif
}
break;
case IPMI_FRU_AREA_BOARD_INFO:
@@ -897,9 +947,20 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
{
sd_bus_message_append (vpdtbl, "sa{y}", vpd_key_names[i], mfg_date_time);
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("Board : [%s] = [%d]\n", vpd_key_names[i], mfg_date_time);
+#else
+;
+#endif
continue;
}
- sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], vpd_info [i].type_length_field);
+ ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
+ sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], ipmi_fru_field_str);
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("Board : [%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
+#else
+;
+#endif
}
break;
case IPMI_FRU_AREA_PRODUCT_INFO:
@@ -916,7 +977,13 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
NULL, 0);
for (i=OPENBMC_VPD_KEY_PRODUCT_MFR; i<=OPENBMC_VPD_KEY_PRODUCT_MAX; i++)
{
- sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], vpd_info [i].type_length_field);
+ ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
+ sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], ipmi_fru_field_str);
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("Product : [%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
+#else
+;
+#endif
}
break;
defualt:
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ipmi-fru-parser 08/11] Fix format string in sd_bus_message_append to add as dictionary. Store manufacturing time in ISO8601 format.
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
` (6 preceding siblings ...)
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 07/11] Internal parser functions expect the area buffer to point to location where language code. Hence advance 2 bytes on the areabuf(to go past the fmt/version and len fields) and pass it to the area specific parser routines. Also fix bugs on offset/len calcuation OpenBMC Patches
@ 2015-11-08 3:59 ` OpenBMC Patches
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 09/11] Construct format string for sd_bus_message_append based on field type encoding OpenBMC Patches
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:59 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
frup.c | 39 +++++++++++++++++++++++++++++++--------
1 file changed, 31 insertions(+), 8 deletions(-)
diff --git a/frup.c b/frup.c
index 87669f8..7e39ad1 100644
--- a/frup.c
+++ b/frup.c
@@ -178,6 +178,25 @@ const char* vpd_key_names [] =
*
* --------------------------------------------------------------------
*/
+
+static size_t _to_time_str (uint32_t mfg_date_time, char* timestr, uint32_t len)
+{
+ struct tm tm;
+ time_t t;
+ size_t s;
+
+ ASSERT (timestr);
+ ASSERT (len);
+
+ memset (&tm, '\0', sizeof (struct tm));
+
+ t = mfg_date_time;
+ gmtime_r (&t, &tm);
+ s = strftime (timestr, len, "%F - %H:%M:%S", &tm);
+
+ return s;
+}
+
/* private method to parse type/length */
static int
_parse_type_length (const void *areabuf,
@@ -719,6 +738,7 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
ipmi_fru_common_hdr_t* chdr = NULL;
uint8_t* hdr = NULL;
+ char timestr [ OPENBMC_VPD_VAL_LEN ];
ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
@@ -828,7 +848,7 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
{
if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
{
- sd_bus_message_append (vpdtbl, "sy", vpd_key_names[i], chassis_type);
+ sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "y", chassis_type);
#if IPMI_FRU_PARSER_DEBUG
printf ("[%s] = [%d]\n", vpd_key_names[i], chassis_type);
#else
@@ -839,7 +859,8 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
{
- sd_bus_message_append (vpdtbl, "sa{y}", vpd_key_names[i], mfg_date_time);
+ _to_time_str (mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN);
+ sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", timestr);
#if IPMI_FRU_PARSER_DEBUG
printf ("[%s] = [%d]\n", vpd_key_names[i], mfg_date_time);
#else
@@ -850,7 +871,7 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
/* FIXME: Field type encoding *ASSUMED* to be *BINARY* */
ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
- sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], ipmi_fru_field_str);
+ sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
if (vpd_info[i].type_length_field_length)
{
#if IPMI_FRU_PARSER_DEBUG
@@ -876,6 +897,7 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
ipmi_fru_common_hdr_t* chdr = NULL;
uint8_t* hdr = NULL;
const uint8_t* ipmi_fru_field_str=NULL;
+ char timestr [ OPENBMC_VPD_VAL_LEN ];
ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
@@ -912,7 +934,7 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
{
if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
{
- sd_bus_message_append (vpdtbl, "sy", vpd_key_names[i], chassis_type);
+ sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "y", chassis_type);
#if IPMI_FRU_PARSER_DEBUG
printf ("Chassis : [%s] = [%d]\n", vpd_key_names[i], chassis_type);
#else
@@ -921,7 +943,7 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
continue;
}
ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
- sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], ipmi_fru_field_str);
+ sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
#if IPMI_FRU_PARSER_DEBUG
printf ("Chassis : [%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
#else
@@ -946,7 +968,8 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
{
if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
{
- sd_bus_message_append (vpdtbl, "sa{y}", vpd_key_names[i], mfg_date_time);
+ _to_time_str (mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN);
+ sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", timestr);
#if IPMI_FRU_PARSER_DEBUG
printf ("Board : [%s] = [%d]\n", vpd_key_names[i], mfg_date_time);
#else
@@ -955,7 +978,7 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
continue;
}
ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
- sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], ipmi_fru_field_str);
+ sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
#if IPMI_FRU_PARSER_DEBUG
printf ("Board : [%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
#else
@@ -978,7 +1001,7 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
for (i=OPENBMC_VPD_KEY_PRODUCT_MFR; i<=OPENBMC_VPD_KEY_PRODUCT_MAX; i++)
{
ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
- sd_bus_message_append (vpdtbl, "ss", vpd_key_names[i], ipmi_fru_field_str);
+ sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
#if IPMI_FRU_PARSER_DEBUG
printf ("Product : [%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
#else
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ipmi-fru-parser 09/11] Construct format string for sd_bus_message_append based on field type encoding.
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
` (7 preceding siblings ...)
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 08/11] Fix format string in sd_bus_message_append to add as dictionary. Store manufacturing time in ISO8601 format OpenBMC Patches
@ 2015-11-08 3:59 ` OpenBMC Patches
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 10/11] Merging IPMI FRU writer and parser OpenBMC Patches
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 11/11] Include sdbus header in frup.c OpenBMC Patches
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:59 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
Makefile | 10 +--
frup.c | 278 ++++++++++++++++++++++++++++++++++++++++-----------------------
frup.h | 4 +-
3 files changed, 185 insertions(+), 107 deletions(-)
diff --git a/Makefile b/Makefile
index bcb3648..8e74dd8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,17 +1,17 @@
-CXX ?= $(CROSS_COMPILE)g++
+CXX ?= $(CROSS_COMPILE)gcc
IPMI_FRU_PARSER_LIB = libifp.so
IPMI_FRU_PARSER_OBJS = frup.o
-INC_FLAGS += $(shell pkg-config --cflags --libs libsystemd) -I. -O2 --std=gnu++11
-#LIB_FLAGS += $(shell pkg-config --libs libsystemd) -rdynamic
+
+INC_FLAGS += -I. -O2 --std=gnu++11 -DIPMI_FRU_PARSER_DEBUG
+#INC_FLAGS += -I. -O2 --std=gnu++11
LIB_FLAGS += -rdynamic
-#IPMID_PATH ?= -DHOST_IPMI_LIB_PATH=\"/usr/lib/host-ipmid/\"
all: $(IPMI_FRU_PARSER_LIB)
%.o: %.c
- $(CXX) -fpic -c $< $(CXXFLAGS) $(INC_FLAG) $(IPMID_PATH) -o $@
+ $(CXX) -fpic -c $< $(CXXFLAGS) $(INC_FLAGS) $(IPMID_PATH) -o $@
$(IPMI_FRU_PARSER_LIB): $(IPMI_FRU_PARSER_OBJS)
$(CXX) $^ -shared $(LDFLAGS) $(LIB_FLAGS) -o $@
diff --git a/frup.c b/frup.c
index 7e39ad1..2d8cc3b 100644
--- a/frup.c
+++ b/frup.c
@@ -43,8 +43,8 @@
#include <unistd.h>
#include <string.h>
#include <time.h>
+#include <ctype.h>
-#define IPMI_FRU_PARSER_DEBUG 1
#define uint8_t unsigned char
#define uint32_t unsigned int
@@ -81,8 +81,11 @@ return -1; \
#define OPENBMC_VPD_VAL_LEN 512
+extern "C"
+{
int sd_bus_message_append (void*, const char*, ...);
typedef struct sd_bus_message sd_bus_message;
+};
struct ipmi_fru_field
{
@@ -117,7 +120,15 @@ enum openbmc_vpd_key_id
OPENBMC_VPD_KEY_CHASSIS_TYPE = 1, /* not a type/len */
OPENBMC_VPD_KEY_CHASSIS_PART_NUM,
OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,
- OPENBMC_VPD_KEY_CHASSIS_MAX = OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,
+ OPENBMC_VPD_KEY_CHASSIS_CUSTOM1,
+ OPENBMC_VPD_KEY_CHASSIS_CUSTOM2,
+ OPENBMC_VPD_KEY_CHASSIS_CUSTOM3,
+ OPENBMC_VPD_KEY_CHASSIS_CUSTOM4,
+ OPENBMC_VPD_KEY_CHASSIS_CUSTOM5,
+ OPENBMC_VPD_KEY_CHASSIS_CUSTOM6,
+ OPENBMC_VPD_KEY_CHASSIS_CUSTOM7,
+ OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,
+ OPENBMC_VPD_KEY_CHASSIS_MAX = OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,
/* TODO: chassis_custom_fields */
OPENBMC_VPD_KEY_BOARD_MFG_DATE, /* not a type/len */
@@ -126,7 +137,15 @@ enum openbmc_vpd_key_id
OPENBMC_VPD_KEY_BOARD_SERIAL_NUM,
OPENBMC_VPD_KEY_BOARD_PART_NUM,
OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID,
- OPENBMC_VPD_KEY_BOARD_MAX = OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID,
+ OPENBMC_VPD_KEY_BOARD_CUSTOM1,
+ OPENBMC_VPD_KEY_BOARD_CUSTOM2,
+ OPENBMC_VPD_KEY_BOARD_CUSTOM3,
+ OPENBMC_VPD_KEY_BOARD_CUSTOM4,
+ OPENBMC_VPD_KEY_BOARD_CUSTOM5,
+ OPENBMC_VPD_KEY_BOARD_CUSTOM6,
+ OPENBMC_VPD_KEY_BOARD_CUSTOM7,
+ OPENBMC_VPD_KEY_BOARD_CUSTOM8,
+ OPENBMC_VPD_KEY_BOARD_MAX = OPENBMC_VPD_KEY_BOARD_CUSTOM8,
/* TODO: board_custom_fields */
OPENBMC_VPD_KEY_PRODUCT_MFR,
@@ -136,38 +155,66 @@ enum openbmc_vpd_key_id
OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM,
OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG,
OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID,
- OPENBMC_VPD_KEY_PRODUCT_MAX = OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID,
- /* TODO: product_custom_fields */
+ OPENBMC_VPD_KEY_PRODUCT_CUSTOM1,
+ OPENBMC_VPD_KEY_PRODUCT_CUSTOM2,
+ OPENBMC_VPD_KEY_PRODUCT_CUSTOM3,
+ OPENBMC_VPD_KEY_PRODUCT_CUSTOM4,
+ OPENBMC_VPD_KEY_PRODUCT_CUSTOM5,
+ OPENBMC_VPD_KEY_PRODUCT_CUSTOM6,
+ OPENBMC_VPD_KEY_PRODUCT_CUSTOM7,
+ OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,
+ OPENBMC_VPD_KEY_PRODUCT_MAX = OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,
OPENBMC_VPD_KEY_MAX,
+ OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX=8,
};
const char* vpd_key_names [] =
{
"Key Names Table Start",
- "Chassis Type", /*OPENBMC_VPD_KEY_CHASSIS_TYPE*/
- "Chassis Part Number", /*OPENBMC_VPD_KEY_CHASSIS_PART_NUM,*/
- "Chassis Serial Number", /*OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,*/
-
- /* TODO: chassis_custom_fields */
-
- "Board Mfg Date", /* OPENBMC_VPD_KEY_BOARD_MFG_DATE, */ /* not a type/len */
- "Board Manufacturer", /* OPENBMC_VPD_KEY_BOARD_MFR, */
- "Board Name", /* OPENBMC_VPD_KEY_BOARD_NAME, */
- "Board Serial Number", /* OPENBMC_VPD_KEY_BOARD_SERIAL_NUM, */
- "Board Part Number", /* OPENBMC_VPD_KEY_BOARD_PART_NUM, */
- "Board FRU File ID", /* OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID, */
- /* TODO: board_custom_fields */
-
- "Product Manufacturer", /* OPENBMC_VPD_KEY_PRODUCT_MFR, */
- "Product Name", /* OPENBMC_VPD_KEY_PRODUCT_NAME, */
- "Product Model Number", /* OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM, */
- "Product Version", /* OPENBMC_VPD_KEY_PRODUCT_VER, */
- "Product Serial Number", /* OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM, */
- "Product Asset Tag", /* OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG, */
- "Product FRU File ID", /* OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID, */
- /* TODO: product_custom_fields */
+ "Type", /*OPENBMC_VPD_KEY_CHASSIS_TYPE*/
+ "Part Number", /*OPENBMC_VPD_KEY_CHASSIS_PART_NUM,*/
+ "Serial Number", /*OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM,*/
+ "Custom Field 1", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM1,*/
+ "Custom Field 2", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM2,*/
+ "Custom Field 3", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM3,*/
+ "Custom Field 4", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM4,*/
+ "Custom Field 5", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM5,*/
+ "Custom Field 6", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM6,*/
+ "Custom Field 7", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM7,*/
+ "Custom Field 8", /*OPENBMC_VPD_KEY_CHASSIS_CUSTOM8,*/
+
+ "Mfg Date", /* OPENBMC_VPD_KEY_BOARD_MFG_DATE, */ /* not a type/len */
+ "Manufacturer", /* OPENBMC_VPD_KEY_BOARD_MFR, */
+ "Name", /* OPENBMC_VPD_KEY_BOARD_NAME, */
+ "Serial Number", /* OPENBMC_VPD_KEY_BOARD_SERIAL_NUM, */
+ "Part Number", /* OPENBMC_VPD_KEY_BOARD_PART_NUM, */
+ "FRU File ID", /* OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID, */
+ "Custom Field 1", /*OPENBMC_VPD_KEY_BOARD_CUSTOM1,*/
+ "Custom Field 2", /*OPENBMC_VPD_KEY_BOARD_CUSTOM2,*/
+ "Custom Field 3", /*OPENBMC_VPD_KEY_BOARD_CUSTOM3,*/
+ "Custom Field 4", /*OPENBMC_VPD_KEY_BOARD_CUSTOM4,*/
+ "Custom Field 5", /*OPENBMC_VPD_KEY_BOARD_CUSTOM5,*/
+ "Custom Field 6", /*OPENBMC_VPD_KEY_BOARD_CUSTOM6,*/
+ "Custom Field 7", /*OPENBMC_VPD_KEY_BOARD_CUSTOM7,*/
+ "Custom Field 8", /*OPENBMC_VPD_KEY_BOARD_CUSTOM8,*/
+
+ "Manufacturer", /* OPENBMC_VPD_KEY_PRODUCT_MFR, */
+ "Name", /* OPENBMC_VPD_KEY_PRODUCT_NAME, */
+ "Model Number", /* OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM, */
+ "Version", /* OPENBMC_VPD_KEY_PRODUCT_VER, */
+ "Serial Number", /* OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM, */
+ "Asset Tag", /* OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG, */
+ "FRU File ID", /* OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID, */
+ "Custom Field 1", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM1,*/
+ "Custom Field 2", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM2,*/
+ "Custom Field 3", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM3,*/
+ "Custom Field 4", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM4,*/
+ "Custom Field 5", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM5,*/
+ "Custom Field 6", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM6,*/
+ "Custom Field 7", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM7,*/
+ "Custom Field 8", /*OPENBMC_VPD_KEY_PRODUCT_CUSTOM8,*/
"Key Names Table End" /*OPENBMC_VPD_KEY_MAX,*/
};
@@ -691,6 +738,7 @@ ipmi_fru_product_info_area (const void *areabuf,
&number_of_data_bytes,
product_fru_file_id) < 0)
goto cleanup;
+
area_offset += 1; /* type/length byte */
area_offset += number_of_data_bytes;
@@ -729,12 +777,42 @@ ipmi_fru_product_info_area (const void *areabuf,
}
+int _append_to_dict (uint8_t vpd_key_id, uint8_t* vpd_key_val, sd_bus_message* vpdtbl)
+{
+ int type_length = vpd_key_val[0];
+ int type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >> IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
+ int vpd_val_len = type_length & IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
+ int sdr=0;
+
+ switch (type_code)
+ {
+ case 0:
+ printf ("_append_to_dict: VPD Key = [%s] : Type Code = [BINARY] : Len = [%d] : Val = [%s]\n", vpd_key_names [vpd_key_id], vpd_val_len, &vpd_key_val[1]);
+ sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "ay", vpd_val_len, &vpd_key_val[1]);
+ /*sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "s", &vpd_key_val[1]);*/
+ break;
+ case 3:
+ printf ("_append_to_dict: VPD Key = [%s] : Type Code = [ASCII+Latin] : Len = [%d] : Val = [%s]\n", vpd_key_names [vpd_key_id], vpd_val_len, &vpd_key_val[1]);
+ sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[vpd_key_id], "s", &vpd_key_val[1]);
+ break;
+ }
+
+ if (sdr < 0)
+ {
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("_append_to_dict : sd_bus_message_append Failed [ %d ] for [%s]\n", sdr, vpd_key_names[vpd_key_id]);
+#endif
+ }
+}
+
int
parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
{
int ret = 0;
int rv = -1;
int i = 0;
+ int j = 0;
+ int isprintable = 0;
ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
ipmi_fru_common_hdr_t* chdr = NULL;
uint8_t* hdr = NULL;
@@ -742,9 +820,7 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
- /*char ipmi_fru_field_str [ IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX ];
- uint32_t len=0;*/
- const uint8_t* ipmi_fru_field_str;
+ uint8_t* ipmi_fru_field_str;
/* Chassis */
uint8_t chassis_type;
@@ -794,7 +870,8 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
&chassis_type,
&vpd_info [OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
&vpd_info [OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
- NULL, 0);
+ &vpd_info [OPENBMC_VPD_KEY_CHASSIS_CUSTOM1],
+ OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
}
if (chdr->board)
@@ -809,7 +886,8 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
&vpd_info [OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
&vpd_info [OPENBMC_VPD_KEY_BOARD_PART_NUM],
&vpd_info [OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
- NULL, 0);
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_CUSTOM1],
+ OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
}
if (chdr->product)
@@ -825,7 +903,8 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
&vpd_info [OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
&vpd_info [OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
&vpd_info [OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
- NULL, 0);
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_CUSTOM1],
+ OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
}
if (chdr->multirec)
@@ -838,8 +917,6 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
{
#if IPMI_FRU_PARSER_DEBUG
printf ("IPMI_FRU_AREA_TYPE=[%d] : Offset=[%d] : Len=[%d]\n", i, fru_area_info [i].off, fru_area_info[i].len);
-#else
-;
#endif
}
@@ -851,8 +928,6 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "y", chassis_type);
#if IPMI_FRU_PARSER_DEBUG
printf ("[%s] = [%d]\n", vpd_key_names[i], chassis_type);
-#else
-;
#endif
continue;
}
@@ -863,25 +938,16 @@ parse_fru (const void* msgbuf, sd_bus_message* vpdtbl)
sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", timestr);
#if IPMI_FRU_PARSER_DEBUG
printf ("[%s] = [%d]\n", vpd_key_names[i], mfg_date_time);
-#else
-;
#endif
continue;
}
-
- /* FIXME: Field type encoding *ASSUMED* to be *BINARY* */
- ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
- sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
- if (vpd_info[i].type_length_field_length)
- {
-#if IPMI_FRU_PARSER_DEBUG
- printf ("[%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
-#else
-;
-#endif
- }
- }
+ /* Append TypeLen Field to Dictionary */
+ _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
+
+ /*ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;*/
+ /*sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str); */
+ }
out:
rv = 0;
cleanup:
@@ -893,66 +959,72 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
int ret = 0;
int rv = -1;
int i = 0;
- ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
- ipmi_fru_common_hdr_t* chdr = NULL;
- uint8_t* hdr = NULL;
- const uint8_t* ipmi_fru_field_str=NULL;
- char timestr [ OPENBMC_VPD_VAL_LEN ];
-
-
- ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
- for (i=0; i<OPENBMC_VPD_KEY_MAX; i++)
- {
- memset (vpd_info[i].type_length_field, '\0', IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
- vpd_info[i].type_length_field_length = 0;
- }
+ int j = 0;
+ int sdr = 0;
+ int isprintable = 0;
/* Chassis */
uint8_t chassis_type;
-
/* Board */
uint32_t mfg_date_time;
-
/* Product */
unsigned int product_custom_fields_len;
+ ipmi_fru_area_info_t fru_area_info [ IPMI_FRU_AREA_TYPE_MAX ];
+ ipmi_fru_field_t vpd_info [ OPENBMC_VPD_KEY_MAX ];
+ char timestr [ OPENBMC_VPD_VAL_LEN ];
+
+ uint8_t* ipmi_fru_field_str=NULL;
+ ipmi_fru_common_hdr_t* chdr = NULL;
+ uint8_t* hdr = NULL;
+
ASSERT (msgbuf);
ASSERT (vpdtbl);
+ for (i=0; i<OPENBMC_VPD_KEY_MAX; i++)
+ {
+ memset (vpd_info[i].type_length_field, '\0', IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
+ vpd_info[i].type_length_field_length = 0;
+ }
+
switch (area)
{
case IPMI_FRU_AREA_CHASSIS_INFO:
- ipmi_fru_chassis_info_area (msgbuf,
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("Chassis : Buf len = [%d]\n", len);
+#endif
+ ipmi_fru_chassis_info_area ((uint8_t*)msgbuf+2,
len,
&chassis_type,
&vpd_info [OPENBMC_VPD_KEY_CHASSIS_PART_NUM],
&vpd_info [OPENBMC_VPD_KEY_CHASSIS_SERIAL_NUM],
- NULL, 0);
+ &vpd_info [OPENBMC_VPD_KEY_CHASSIS_CUSTOM1],
+ OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
/* Populate VPD Table */
for (i=1; i<=OPENBMC_VPD_KEY_CHASSIS_MAX; i++)
{
if (i==OPENBMC_VPD_KEY_CHASSIS_TYPE)
{
- sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "y", chassis_type);
#if IPMI_FRU_PARSER_DEBUG
- printf ("Chassis : [%s] = [%d]\n", vpd_key_names[i], chassis_type);
-#else
-;
+ printf ("Chassis : Appending [%s] = [%d]\n", vpd_key_names[i], chassis_type);
#endif
+ sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "y", chassis_type);
continue;
}
+
+ _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
+/*
ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
- sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
-#if IPMI_FRU_PARSER_DEBUG
- printf ("Chassis : [%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
-#else
-;
-#endif
+ sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
+*/
}
break;
case IPMI_FRU_AREA_BOARD_INFO:
- ipmi_fru_board_info_area (msgbuf,
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("Board : Buf len = [%d]\n", len);
+#endif
+ ipmi_fru_board_info_area ((uint8_t*)msgbuf+2,
len,
NULL,
&mfg_date_time,
@@ -961,7 +1033,8 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
&vpd_info [OPENBMC_VPD_KEY_BOARD_SERIAL_NUM],
&vpd_info [OPENBMC_VPD_KEY_BOARD_PART_NUM],
&vpd_info [OPENBMC_VPD_KEY_BOARD_FRU_FILE_ID],
- NULL, 0);
+ &vpd_info [OPENBMC_VPD_KEY_BOARD_CUSTOM1],
+ OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
/* Populate VPD Table */
for (i=OPENBMC_VPD_KEY_BOARD_MFR; i<=OPENBMC_VPD_KEY_BOARD_MAX; i++)
@@ -969,25 +1042,31 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
if (i==OPENBMC_VPD_KEY_BOARD_MFG_DATE)
{
_to_time_str (mfg_date_time, timestr, OPENBMC_VPD_VAL_LEN);
- sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", timestr);
#if IPMI_FRU_PARSER_DEBUG
- printf ("Board : [%s] = [%d]\n", vpd_key_names[i], mfg_date_time);
-#else
-;
+ printf ("Board : Appending [%s] = [%d]\n", vpd_key_names[i], timestr);
+#endif
+ sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", timestr);
+ if (sdr < 0)
+ {
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("ipmi_fru_board_info_area : sd_bus_message_append Failed [ %d ] for [%s]\n", sdr, vpd_key_names[i]);
#endif
+ }
continue;
}
+
+ _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
+/*
ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
- sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
-#if IPMI_FRU_PARSER_DEBUG
- printf ("Board : [%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
-#else
-;
-#endif
+ sdr = sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
+*/
}
break;
case IPMI_FRU_AREA_PRODUCT_INFO:
- ipmi_fru_product_info_area (msgbuf,
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("Product : Buf len = [%d]\n", len);
+#endif
+ ipmi_fru_product_info_area ((uint8_t*)msgbuf+2,
len,
NULL,
&vpd_info [OPENBMC_VPD_KEY_PRODUCT_MFR],
@@ -997,16 +1076,12 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
&vpd_info [OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM],
&vpd_info [OPENBMC_VPD_KEY_PRODUCT_ASSET_TAG],
&vpd_info [OPENBMC_VPD_KEY_PRODUCT_FRU_FILE_ID],
- NULL, 0);
+ &vpd_info [OPENBMC_VPD_KEY_PRODUCT_CUSTOM1],
+ OPENBMC_VPD_KEY_CUSTOM_FIELDS_MAX);
+
for (i=OPENBMC_VPD_KEY_PRODUCT_MFR; i<=OPENBMC_VPD_KEY_PRODUCT_MAX; i++)
{
- ipmi_fru_field_str = (unsigned char*) &(vpd_info[i].type_length_field) + 1;
- sd_bus_message_append (vpdtbl, "{sv}", vpd_key_names[i], "s", ipmi_fru_field_str);
-#if IPMI_FRU_PARSER_DEBUG
- printf ("Product : [%s] = [%s]\n", vpd_key_names[i], ipmi_fru_field_str);
-#else
-;
-#endif
+ _append_to_dict (i, vpd_info[i].type_length_field, vpdtbl);
}
break;
defualt:
@@ -1014,6 +1089,9 @@ int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, s
break;
}
+#if IPMI_FRU_PARSER_DEBUG
+ printf ("parse_fru_area : Dictionary Packing Complete\n");
+#endif
out:
rv = 0;
cleanup:
diff --git a/frup.h b/frup.h
index b6b9476..0269bf8 100644
--- a/frup.h
+++ b/frup.h
@@ -5,7 +5,7 @@
int parse_fru (const void* msgbuf, sd_bus_message* vpdtbl);
int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, sd_bus_message* vpdtbl);
-enum openbmc_ipmi_fru_area_type
+enum ipmi_fru_area_type
{
IPMI_FRU_AREA_INTERNAL_USE = 0x00,
IPMI_FRU_AREA_CHASSIS_INFO,
@@ -13,6 +13,6 @@ enum openbmc_ipmi_fru_area_type
IPMI_FRU_AREA_PRODUCT_INFO,
IPMI_FRU_AREA_MULTI_RECORD,
IPMI_FRU_AREA_TYPE_MAX
-}
+};
#endif
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ipmi-fru-parser 10/11] Merging IPMI FRU writer and parser.
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
` (8 preceding siblings ...)
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 09/11] Construct format string for sd_bus_message_append based on field type encoding OpenBMC Patches
@ 2015-11-08 3:59 ` OpenBMC Patches
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 11/11] Include sdbus header in frup.c OpenBMC Patches
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:59 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
Makefile | 26 ++-
frup.h | 2 +
writefrudata.C | 564 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
writefrudata.H | 53 ++++++
4 files changed, 637 insertions(+), 8 deletions(-)
create mode 100644 writefrudata.C
create mode 100644 writefrudata.H
diff --git a/Makefile b/Makefile
index 8e74dd8..076aa76 100644
--- a/Makefile
+++ b/Makefile
@@ -1,20 +1,30 @@
CXX ?= $(CROSS_COMPILE)gcc
-IPMI_FRU_PARSER_LIB = libifp.so
-IPMI_FRU_PARSER_OBJS = frup.o
+FRU_WRITE_AND_PARSER_LIB = libwritefrudata.so
+FRU_WRITE_AND_PARSER_OBJS = frup.o writefrudata.o
+INC_FLAGS += $(shell pkg-config --cflags --libs libsystemd) -I. -O2 --std=gnu++14
+LIB_FLAGS += $(shell pkg-config --libs libsystemd) -rdynamic
-INC_FLAGS += -I. -O2 --std=gnu++11 -DIPMI_FRU_PARSER_DEBUG
-#INC_FLAGS += -I. -O2 --std=gnu++11
-LIB_FLAGS += -rdynamic
+DESTDIR ?= /
+SBINDIR ?= /usr/sbin
+INCLUDEDIR ?= /usr/include
+LIBDIR ?= /usr/lib
-all: $(IPMI_FRU_PARSER_LIB)
+all: $(FRU_WRITE_AND_PARSER_LIB)
%.o: %.c
$(CXX) -fpic -c $< $(CXXFLAGS) $(INC_FLAGS) $(IPMID_PATH) -o $@
-$(IPMI_FRU_PARSER_LIB): $(IPMI_FRU_PARSER_OBJS)
+%.o: %.C
+ $(CXX) -fpic -c $< $(CXXFLAGS) $(INC_FLAGS) $(IPMID_PATH) -o $@
+
+$(FRU_WRITE_AND_PARSER_LIB): $(FRU_WRITE_AND_PARSER_OBJS)
$(CXX) $^ -shared $(LDFLAGS) $(LIB_FLAGS) -o $@
clean:
- rm -f $(IPMI_FRU_PARSER_OBJS) $(IPMI_FRU_PARSER_LIB)
+ rm -f $(FRU_WRITE_AND_PARSER_OBJS) $(FRU_WRITE_AND_PARSER_LIB)
+
+install:
+ install -m 0755 -d $(DESTDIR)$(LIBDIR)/host-ipmid
+ install -m 0755 $(FRU_WRITE_AND_PARSER_LIB) $(DESTDIR)$(LIBDIR)/host-ipmid
diff --git a/frup.h b/frup.h
index 0269bf8..3286260 100644
--- a/frup.h
+++ b/frup.h
@@ -1,6 +1,8 @@
#ifndef OPENBMC_IPMI_FRU_PARSER_H
#define OPENBMC_IPMI_FRU_PARSER_H
+#include <systemd/sd-bus.h>
+
/* Parse an IPMI write fru data message into a dictionary containing name value pair of VPD entries.*/
int parse_fru (const void* msgbuf, sd_bus_message* vpdtbl);
int parse_fru_area (const uint8_t area, const void* msgbuf, const uint8_t len, sd_bus_message* vpdtbl);
diff --git a/writefrudata.C b/writefrudata.C
new file mode 100644
index 0000000..30ba39a
--- /dev/null
+++ b/writefrudata.C
@@ -0,0 +1,564 @@
+#include <ipmid-api.h>
+#include <vector>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdio.h>
+#include "frup.h"
+#include "writefrudata.H"
+#include <systemd/sd-bus.h>
+
+void register_netfn_storage_write_fru() __attribute__((constructor));
+
+// Needed to be passed into fru parser alorithm
+typedef std::vector<fru_area_t> fru_area_vec_t;
+
+// OpenBMC System Manager dbus framework
+const char *bus_name = "org.openbmc.managers.System";
+const char *object_name = "/org/openbmc/managers/System";
+const char *intf_name = "org.openbmc.managers.System";
+
+//------------------------------------------------
+// Takes the pointer to stream of bytes and length
+// returns the 8 bit checksum per IPMI spec.
+//-------------------------------------------------
+unsigned char calculate_crc(unsigned char *data, int len)
+{
+ char crc = 0;
+ int byte = 0;
+
+ for(byte = 0; byte < len; byte++)
+ {
+ crc += *data++;
+ }
+
+ return(-crc);
+}
+
+//---------------------------------------------------------------------
+// Accepts a fru area offset in commom hdr and tells which area it is.
+//---------------------------------------------------------------------
+uint8_t get_fru_area_type(uint8_t area_offset)
+{
+ ipmi_fru_area_type type = IPMI_FRU_AREA_TYPE_MAX;
+
+ switch(area_offset)
+ {
+ case IPMI_FRU_INTERNAL_OFFSET:
+ type = IPMI_FRU_AREA_INTERNAL_USE;
+ break;
+
+ case IPMI_FRU_CHASSIS_OFFSET:
+ type = IPMI_FRU_AREA_CHASSIS_INFO;
+ break;
+
+ case IPMI_FRU_BOARD_OFFSET:
+ type = IPMI_FRU_AREA_BOARD_INFO;
+ break;
+
+ case IPMI_FRU_PRODUCT_OFFSET:
+ type = IPMI_FRU_AREA_PRODUCT_INFO;
+ break;
+
+ case IPMI_FRU_MULTI_OFFSET:
+ type = IPMI_FRU_AREA_MULTI_RECORD;
+ break;
+
+ default:
+ type = IPMI_FRU_AREA_TYPE_MAX;
+ }
+
+ return type;
+}
+
+//------------------------------------------------------------------------
+// Takes FRU data, invokes Parser for each fru record area and updates
+// Inventory
+//------------------------------------------------------------------------
+int ipmi_update_inventory(const uint8_t fruid, const uint8_t *fru_data,
+ fru_area_vec_t & area_vec)
+{
+ // Now, use this fru dictionary object and connect with FRU Inventory Dbus
+ // and update the data for this FRU ID.
+ int rc = 0;
+
+ // Dictionary object to hold Name:Value pair
+ sd_bus_message *fru_dict = NULL;
+
+ // SD Bus error report mechanism.
+ sd_bus_error bus_error = SD_BUS_ERROR_NULL;
+
+ // Gets a hook onto either a SYSTEM or SESSION bus
+ sd_bus *bus_type = NULL;
+
+ // Req message contains the specifics about which method etc that we want to
+ // access on which bus, object
+ sd_bus_message *response = NULL;
+
+ rc = sd_bus_open_system(&bus_type);
+ if(rc < 0)
+ {
+ fprintf(stderr,"ERROR: Getting a SYSTEM bus hook\n");
+ return -1;
+ }
+
+ // For each FRU area, extract the needed data , get it parsed and update
+ // the Inventory.
+ for(auto& iter : area_vec)
+ {
+ uint8_t area_type = (iter).type;
+
+ uint8_t area_data[(iter).len];
+ memset(area_data, 0x0, sizeof(area_data));
+
+ // Grab area specific data
+ memmove(area_data, (iter).offset, (iter).len);
+
+ // Need this to get respective DBUS objects
+ const char *area_name = NULL;
+
+ if(area_type == IPMI_FRU_AREA_CHASSIS_INFO)
+ {
+ area_name = "CHASSIS_";
+ }
+ else if(area_type == IPMI_FRU_AREA_BOARD_INFO)
+ {
+ area_name = "BOARD_";
+ }
+ else if(area_type == IPMI_FRU_AREA_PRODUCT_INFO)
+ {
+ area_name = "PRODUCT_";
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Invalid Area type :[%d]",area_type);
+ break;
+ }
+
+ // What we need is BOARD_1, PRODUCT_1, CHASSIS_1 etc..
+ char fru_area_name[16] = {0};
+ sprintf(fru_area_name,"%s%d",area_name, fruid);
+
+#ifdef __IPMI_DEBUG__
+ printf("Updating Inventory with :[%s]\n",fru_area_name);
+#endif
+ // Each area needs a clean set.
+ sd_bus_error_free(&bus_error);
+ sd_bus_message_unref(response);
+ sd_bus_message_unref(fru_dict);
+
+ // We want to call a method "getObjectFromId" on System Bus that is
+ // made available over OpenBmc system services.
+ rc = sd_bus_call_method(bus_type, // On the System Bus
+ bus_name, // Service to contact
+ object_name, // Object path
+ intf_name, // Interface name
+ "getObjectFromId", // Method to be called
+ &bus_error, // object to return error
+ &response, // Response message on success
+ "ss", // input message (string,byte)
+ "FRU_STR", // First argument to getObjectFromId
+ fru_area_name); // Second Argument
+
+ if(rc < 0)
+ {
+ fprintf(stderr, "Failed to issue method call: %s\n", bus_error.message);
+ break;
+ }
+
+ // Method getObjectFromId returns 3 parameters and all are strings, namely
+ // bus_name , object_path and interface name for accessing that particular
+ // FRU over Inventory SDBUS manager. 'sss' here mentions that format.
+ char *inv_bus_name, *inv_obj_path, *inv_intf_name;
+ rc = sd_bus_message_read(response, "(sss)", &inv_bus_name, &inv_obj_path, &inv_intf_name);
+ if(rc < 0)
+ {
+ fprintf(stderr, "Failed to parse response message:[%s]\n", strerror(-rc));
+ break;
+ }
+
+#ifdef __IPMI_DEBUG__
+ printf("fru_area=[%s], inv_bus_name=[%s], inv_obj_path=[%s],inv_intf_name=[%s]\n",
+ fru_area_name, inv_bus_name, inv_obj_path, inv_intf_name);
+#endif
+
+ // Constructor to allow further initializations and customization.
+ rc = sd_bus_message_new_method_call(bus_type,
+ &fru_dict,
+ inv_bus_name,
+ inv_obj_path,
+ inv_intf_name,
+ "update");
+ if(rc < 0)
+ {
+ fprintf(stderr,"ERROR: creating a update method call\n");
+ break;
+ }
+
+ // A Dictionary ({}) having (string, variant)
+ rc = sd_bus_message_open_container(fru_dict, 'a', "{sv}");
+ if(rc < 0)
+ {
+ fprintf(stderr,"ERROR:[%d] creating a dict container:\n",errno);
+ break;
+ }
+
+ // Fill the container with information
+ rc = parse_fru_area((iter).type, (void *)area_data, (iter).len, fru_dict);
+ if(rc < 0)
+ {
+ fprintf(stderr,"ERROR parsing FRU records\n");
+ break;
+ }
+
+ sd_bus_message_close_container(fru_dict);
+
+ // Now, Make the actual call to update the FRU inventory database with the
+ // dictionary given by FRU Parser. There is no response message expected for
+ // this.
+ rc = sd_bus_call(bus_type, // On the System Bus
+ fru_dict, // With the Name:value dictionary array
+ 0, //
+ &bus_error, // Object to return error.
+ &response); // Response message if any.
+
+ if(rc < 0)
+ {
+ fprintf(stderr, "ERROR:[%s] updating FRU inventory for ID:[0x%X]\n",
+ bus_error.message, fruid);
+ }
+ else
+ {
+ printf("SUCCESS: Updated:[%s] successfully\n",fru_area_name);
+ }
+ } // END walking the vector of areas and updating
+
+ sd_bus_error_free(&bus_error);
+ sd_bus_message_unref(response);
+ sd_bus_message_unref(fru_dict);
+ sd_bus_unref(bus_type);
+
+ return rc;
+}
+
+//-------------------------------------------------------------------------
+// Validates the CRC and if found good, calls fru areas parser and calls
+// Inventory Dbus with the dictionary of Name:Value for updating.
+//-------------------------------------------------------------------------
+int ipmi_validate_and_update_inventory(const uint8_t fruid, const uint8_t *fru_data)
+{
+ // Used for generic checksum calculation
+ uint8_t checksum = 0;
+
+ // This can point to any FRU entry.
+ uint8_t fru_entry;
+
+ // A generic offset locator for any FRU record.
+ uint8_t area_offset = 0;
+
+ // First 2 bytes in the record.
+ uint8_t fru_area_hdr[2] = {0};
+
+ // To hold info about individual FRU record areas.
+ fru_area_t fru_area;
+
+ // For parsing and updating Inventory.
+ fru_area_vec_t fru_area_vec;
+
+ int rc = 0;
+
+ uint8_t common_hdr[sizeof(struct common_header)] = {0};
+ memset(common_hdr, 0x0, sizeof(common_hdr));
+
+ // Copy first 8 bytes to verify common header
+ memcpy(common_hdr, fru_data, sizeof(common_hdr));
+
+ // Validate for first byte to always have a value of [1]
+ if(common_hdr[0] != IPMI_FRU_HDR_BYTE_ZERO)
+ {
+ fprintf(stderr, "ERROR: Common Header entry_1:[0x%X] Invalid.\n",common_hdr[0]);
+ return -1;
+ }
+ else
+ {
+ printf("SUCCESS: Validated [0x%X] in common header\n",common_hdr[0]);
+ }
+
+ // Validate the header checskum that is at last byte ( Offset: 7 )
+ checksum = calculate_crc(common_hdr, sizeof(common_hdr)-1);
+ if(checksum != common_hdr[IPMI_FRU_HDR_CRC_OFFSET])
+ {
+#ifdef __IPMI__DEBUG__
+ fprintf(stderr, "ERROR: Common Header checksum mismatch."
+ " Calculated:[0x%X], Embedded:[0x%X]\n",
+ checksum, common_hdr[IPMI_FRU_HDR_CRC_OFFSET]);
+#endif
+ return -1;
+ }
+ else
+ {
+ printf("SUCCESS: Common Header checksum MATCH:[0x%X]\n",checksum);
+ }
+
+ //-------------------------------------------
+ // TODO: Add support for Multi Record later
+ //-------------------------------------------
+
+ // Now start walking the common_hdr array that has offsets into other FRU
+ // record areas and validate those. Starting with second entry since the
+ // first one is always a [0x01]
+ for(fru_entry = IPMI_FRU_INTERNAL_OFFSET; fru_entry < (sizeof(struct common_header) -2); fru_entry++)
+ {
+ // Offset is 'value given in' internal_offset * 8 from the START of
+ // common header. So an an example, 01 00 00 00 01 00 00 fe has
+ // product area set at the offset 01 * 8 --> 8 bytes from the START of
+ // common header. That means, soon after the header checksum.
+ area_offset = common_hdr[fru_entry] * IPMI_EIGHT_BYTES;
+
+ if(area_offset)
+ {
+ memset((void *)&fru_area, 0x0, sizeof(fru_area_t));
+
+ // Enumerated FRU area.
+ fru_area.type = get_fru_area_type(fru_entry);
+
+ // From start of fru header + record offset, copy 2 bytes.
+ fru_area.offset = &((uint8_t *)fru_data)[area_offset];
+ memcpy(fru_area_hdr, fru_area.offset, sizeof(fru_area_hdr));
+
+ // A NON zero value means that the vpd packet has the data for that
+ // area. err if first element in the record header is _not_ a [0x01].
+ if(fru_area_hdr[0] != IPMI_FRU_HDR_BYTE_ZERO)
+ {
+ fprintf(stderr, "ERROR: Unexpected :[0x%X] found at Record header\n",
+ fru_area_hdr[0]);
+
+ // This vector by now may have had some entries. Since this is a
+ // failure now, clear the state data.
+ fru_area_vec.clear();
+ return -1;
+ }
+ else
+ {
+ printf("SUCCESS: Validated [0x%X] in fru record:[%d] header\n",
+ fru_area_hdr[0],fru_entry);
+ }
+
+ // Read Length bytes ( makes a complete record read now )
+ fru_area.len = fru_area_hdr[1] * IPMI_EIGHT_BYTES;
+#ifdef __IPMI_DEBUG__
+ printf("AREA NO[%d], SIZE = [%d]\n",fru_entry, fru_area.len);
+#endif
+ uint8_t fru_area_data[fru_area.len];
+ memset(fru_area_data, 0x0, sizeof(fru_area_data));
+
+ memmove(fru_area_data, fru_area.offset, sizeof(fru_area_data));
+
+ // Calculate checksum (from offset -> (Length-1)).
+ // All the bytes except the last byte( which is CRC :) ) will
+ // participate in calculating the checksum.
+ checksum = calculate_crc(fru_area_data, sizeof(fru_area_data)-1);
+
+ // Verify the embedded checksum in last byte with calculated checksum
+ // record_len -1 since length is some N but numbering is 0..N-1
+ if(checksum != fru_area_data[fru_area.len-1])
+ {
+#ifdef __IPMI_DEBUG__
+ fprintf(stderr, "ERROR: FRU Header checksum mismatch. "
+ " Calculated:[0x%X], Embedded:[0x%X]\n",
+ checksum, fru_area_data[fru_area.len - 1]);
+#endif
+ // This vector by now may have had some entries. Since this is a
+ // failure now, clear the state data.
+ fru_area_vec.clear();
+ return -1;
+ }
+ else
+ {
+ printf("SUCCESS: FRU Header checksum MATCH:[0x%X]\n",checksum);
+ }
+
+ // Everything is rihgt about this particular FRU record,
+ fru_area_vec.push_back(fru_area);
+
+ // Update the internal structure with info about this entry that is
+ // needed while handling each areas.
+ } // If the packet has data for a particular data record.
+ } // End walking all the fru records.
+
+ // If we reach here, then we have validated the crc for all the records and
+ // time to call FRU area parser to get a Name:Value pair dictionary.
+ // This will start iterating all over again on the buffer -BUT- now with the
+ // job of taking each areas, getting it parsed and then updating the
+ // DBUS.
+
+ if(!(fru_area_vec.empty()))
+ {
+ rc = ipmi_update_inventory(fruid, fru_data, fru_area_vec);
+ }
+
+ // We are done with this FRU write packet.
+ fru_area_vec.clear();
+
+ return rc;
+}
+
+///-----------------------------------------------------
+// Accepts the filename and validates per IPMI FRU spec
+//----------------------------------------------------
+int ipmi_validate_fru_area(const uint8_t fruid, const char *fru_file_name)
+{
+ int file_size = 0;
+ uint8_t *fru_data = NULL;
+ int bytes_read = 0;
+ int rc = 0;
+
+ FILE *fru_file = fopen(fru_file_name,"rb");
+ if(fru_file == NULL)
+ {
+ fprintf(stderr, "ERROR: opening:[%s]\n",fru_file_name);
+ perror("Error:");
+ return -1;
+ }
+
+ // Get the size of the file to allocate buffer to hold the entire contents.
+ if(fseek(fru_file, 0, SEEK_END))
+ {
+ perror("Error:");
+ fclose(fru_file);
+ return -1;
+ }
+
+ file_size = ftell(fru_file);
+ fru_data = (uint8_t *)malloc(file_size);
+
+ // Read entire file contents to the internal buffer
+ if(fseek(fru_file, 0, SEEK_SET))
+ {
+ perror("Error:");
+ fclose(fru_file);
+ return -1;
+ }
+
+ bytes_read = fread(fru_data, file_size, 1, fru_file);
+ if(bytes_read != 1)
+ {
+ fprintf(stderr, "ERROR reading common header. Bytes read=:[%d]\n",bytes_read);
+ perror("Error:");
+ fclose(fru_file);
+ return -1;
+ }
+ fclose(fru_file);
+
+ rc = ipmi_validate_and_update_inventory(fruid, fru_data);
+ if(rc == -1)
+ {
+ printf("ERROR: Validation failed for:[%d]\n",fruid);
+ }
+ else
+ {
+ printf("SUCCESS: Validated:[%s]\n",fru_file_name);
+ }
+
+ if(fru_data)
+ {
+ free(fru_data);
+ fru_data = NULL;
+ }
+
+ return rc;
+}
+
+///-------------------------------------------------------
+// Called by IPMI netfn router for write fru data command
+//--------------------------------------------------------
+ipmi_ret_t ipmi_storage_write_fru_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ FILE *fp = NULL;
+ char fru_file_name[16] = {0};
+ uint8_t offset = 0;
+ uint16_t len = 0;
+ ipmi_ret_t rc = IPMI_CC_INVALID;
+ int validate_rc = 0;
+ const char *mode = NULL;
+
+ // From the payload, extract the header that has fruid and the offsets
+ write_fru_data_t *reqptr = (write_fru_data_t*)request;
+
+ // There is no response data for this command.
+ *data_len = 0;
+
+ // Maintaining a temporary file to pump the data
+ sprintf(fru_file_name, "%s%02x", "/tmp/ipmifru", reqptr->frunum);
+
+ offset = ((uint16_t)reqptr->offsetms) << 8 | reqptr->offsetls;
+
+ // Length is the number of request bytes minus the header itself.
+ // The header contains an extra byte to indicate the start of
+ // the data (so didn't need to worry about word/byte boundaries)
+ // hence the -1...
+ len = ((uint16_t)*data_len) - (sizeof(write_fru_data_t)-1);
+
+#ifdef __IPMI__DEBUG__
+ printf("IPMI WRITE-FRU-DATA for [%s] Offset = [%d] Length = [%d]\n",
+ fru_file_name, offset, len);
+#endif
+
+ // offset would be zero if the cmd payload is targeting a new fru
+ if (offset == 0)
+ {
+ mode = "wb";
+ }
+ else
+ {
+ // offset would be non-zero if the cmd payload is continued for prev
+ // fru
+ mode = "rb+";
+ }
+
+ if ((fp = fopen(fru_file_name, mode)) != NULL)
+ {
+ if(fseek(fp, offset, SEEK_SET))
+ {
+ perror("Error:");
+ fclose(fp);
+ return rc;
+ }
+
+ if(fwrite(&reqptr->data, len, 1, fp) != 1)
+ {
+ perror("Error:");
+ fclose(fp);
+ return rc;
+ }
+
+ fclose(fp);
+ }
+ else
+ {
+ fprintf(stderr, "Error trying to write to fru file %s\n",fru_file_name);
+ return rc;
+ }
+
+ // We received some bytes. It may be full or partial. Run a validator.
+ validate_rc = ipmi_validate_fru_area(reqptr->frunum, fru_file_name);
+ if(validate_rc != -1)
+ {
+ // Success validating _and_ updating the Inventory. We no longer need
+ // this file.
+ remove(fru_file_name);
+ }
+
+ // convert the rc per ipmi spec
+ rc = (validate_rc != -1) ? IPMI_CC_OK : IPMI_CC_INVALID;
+
+ return rc;
+}
+
+void register_netfn_storage_write_fru()
+{
+ printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_WRITE_FRU_DATA);
+ ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_WRITE_FRU_DATA, NULL, ipmi_storage_write_fru_data);
+}
diff --git a/writefrudata.H b/writefrudata.H
new file mode 100644
index 0000000..42924a3
--- /dev/null
+++ b/writefrudata.H
@@ -0,0 +1,53 @@
+#ifndef __IPMI_WRITE_FRU_DATA_H__
+#define __IPMI_WRITE_FRU_DATA_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+// IPMI commands for Storage net functions.
+enum ipmi_netfn_storage_cmds
+{
+ IPMI_CMD_WRITE_FRU_DATA = 0x12
+};
+
+// Format of write fru data command
+struct write_fru_data_t
+{
+ uint8_t frunum;
+ uint8_t offsetls;
+ uint8_t offsetms;
+ uint8_t data;
+}__attribute__ ((packed));
+
+// Per IPMI v2.0 FRU specification
+struct common_header
+{
+ uint8_t fixed;
+ uint8_t internal_offset;
+ uint8_t chassis_offset;
+ uint8_t board_offset;
+ uint8_t product_offset;
+ uint8_t multi_offset;
+ uint8_t pad;
+ uint8_t crc;
+}__attribute__((packed));
+
+// Contains key info about a particular area.
+typedef struct
+{
+ uint8_t type;
+ uint8_t *offset;
+ size_t len;
+}__attribute__((packed)) fru_area_t;
+
+// first byte in header is 1h per IPMI V2 spec.
+#define IPMI_FRU_HDR_BYTE_ZERO 1
+#define IPMI_FRU_INTERNAL_OFFSET offsetof(struct common_header, internal_offset)
+#define IPMI_FRU_CHASSIS_OFFSET offsetof(struct common_header, chassis_offset)
+#define IPMI_FRU_BOARD_OFFSET offsetof(struct common_header, board_offset)
+#define IPMI_FRU_PRODUCT_OFFSET offsetof(struct common_header, product_offset)
+#define IPMI_FRU_MULTI_OFFSET offsetof(struct common_header, multi_offset)
+#define IPMI_FRU_HDR_CRC_OFFSET offsetof(struct common_header, crc)
+#define IPMI_EIGHT_BYTES 8
+
+#endif
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ipmi-fru-parser 11/11] Include sdbus header in frup.c
2015-11-08 3:58 [PATCH ipmi-fru-parser 00/11] Checking in the basic IPMI FRU Parser Library OpenBMC Patches
` (9 preceding siblings ...)
2015-11-08 3:59 ` [PATCH ipmi-fru-parser 10/11] Merging IPMI FRU writer and parser OpenBMC Patches
@ 2015-11-08 3:59 ` OpenBMC Patches
10 siblings, 0 replies; 12+ messages in thread
From: OpenBMC Patches @ 2015-11-08 3:59 UTC (permalink / raw)
To: openbmc
From: Hariharasubramanian R <hramasub@in.ibm.com>
---
frup.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/frup.c b/frup.c
index 2d8cc3b..96fd2ae 100644
--- a/frup.c
+++ b/frup.c
@@ -44,6 +44,7 @@
#include <string.h>
#include <time.h>
#include <ctype.h>
+#include <systemd/sd-bus.h>
#define uint8_t unsigned char
#define uint32_t unsigned int
@@ -80,13 +81,6 @@ return -1; \
#define OPENBMC_VPD_KEY_LEN 64
#define OPENBMC_VPD_VAL_LEN 512
-
-extern "C"
-{
-int sd_bus_message_append (void*, const char*, ...);
-typedef struct sd_bus_message sd_bus_message;
-};
-
struct ipmi_fru_field
{
uint8_t type_length_field[IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX];
--
2.6.3
^ permalink raw reply related [flat|nested] 12+ messages in thread