hiomap: Implement get_info
Change-Id: Ia1a536402cb08f869ea4321dd26683a72f95d05b
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/LICENSE b/LICENSE
index 261eeb9..463979c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright [yyyy] [name of copyright owner]
+ Copyright 2018 IBM Corp.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/MAINTAINERS b/MAINTAINERS
new file mode 100644
index 0000000..89a8fd8
--- /dev/null
+++ b/MAINTAINERS
@@ -0,0 +1,45 @@
+How to use this list:
+ Find the most specific section entry (described below) that matches where
+ your change lives and add the reviewers (R) and maintainers (M) as
+ reviewers. You can use the same method to track down who knows a particular
+ code base best.
+
+ Your change/query may span multiple entries; that is okay.
+
+ If you do not find an entry that describes your request at all, someone
+ forgot to update this list; please at least file an issue or send an email
+ to a maintainer, but preferably you should just update this document.
+
+Description of section entries:
+
+ Section entries are structured according to the following scheme:
+
+ X: NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>
+ X: ...
+ .
+ .
+ .
+
+ Where REPO_NAME is the name of the repository within the OpenBMC GitHub
+ organization; FILE_PATH is a file path within the repository, possibly with
+ wildcards; X is a tag of one of the following types:
+
+ M: Denotes maintainer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>;
+ if omitted from an entry, assume one of the maintainers from the
+ MAINTAINERS entry.
+ R: Denotes reviewer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>;
+ these people are to be added as reviewers for a change matching the repo
+ path.
+ F: Denotes forked from an external repository; has fields URL.
+
+ Line comments are to be denoted "# SOME COMMENT" (typical shell style
+ comment); it is important to follow the correct syntax and semantics as we
+ may want to use automated tools with this file in the future.
+
+ A change cannot be added to an OpenBMC repository without a MAINTAINER's
+ approval; thus, a MAINTAINER should always be listed as a reviewer.
+
+START OF MAINTAINERS LIST
+-------------------------
+
+M: Andrew Jeffery <andrew@aj.id.au> <!amboar>
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..7f6f9d8
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (C) 2018 IBM Corp.
+
+libhiomapdir = ${libdir}/ipmid-providers
+libhiomap_LTLIBRARIES = libhiomap.la
+
+libhiomap_la_SOURCES = hiomap.cpp
+
+libhiomap_la_LDFLAGS = $(SYSTEMD_LIBS)\
+ $(SDBUSPLUS_LIBS) \
+ $(PHOSPHOR_LOGGING_LIBS) \
+ -version-info 0:0:0 -shared
+
+libhiomap_la_CXXFLAGS = $(SYSTEMD_CFLAGS) \
+ $(SDBUSPLUS_CFLAGS) \
+ $(PHOSPHOR_LOGGING_CFLAGS) \
+ $(AM_CXXFLAGS)
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100755
index 0000000..ee24b53
--- /dev/null
+++ b/bootstrap.sh
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (C) 2018 IBM Corp.
+
+#!/bin/sh
+
+AUTOCONF_FILES="Makefile.in aclocal.m4 ar-lib autom4te.cache compile \
+ config.guess config.h.in config.sub configure depcomp install-sh \
+ ltmain.sh missing *libtool test-driver"
+
+case $1 in
+ clean)
+ test -f Makefile && make maintainer-clean
+ for file in ${AUTOCONF_FILES}; do
+ find -name "$file" | xargs -r rm -rf
+ done
+ exit 0
+ ;;
+esac
+
+autoreconf -i
+echo 'Run "./configure ${CONFIGURE_FLAGS} && make"'
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..5c033b0
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (C) 2018 IBM Corp.
+
+# Initialization
+AC_PREREQ([2.69])
+AC_INIT([openpower-host-ipmi-flash], [1.0], [])
+AC_CONFIG_HEADERS([config.h])
+AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign dist-xz])
+AM_SILENT_RULES([yes])
+
+# Checks for programs.
+AC_PROG_CXX
+AM_PROG_AR
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
+# Checks for libraries.
+PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 221])
+
+# Checks for header files.
+AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find systemd/sd-bus.h...systemd development package required])])
+AC_CHECK_HEADER(host-ipmid/ipmid-api.h, ,[AC_MSG_ERROR([Could not find host-ipmid/ipmid-api.h...host-ipmid package required])])
+PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],,\
+ AC_MSG_ERROR(["Requires sdbusplus package."]))
+PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],,\
+ AC_MSG_ERROR(["Requires phosphor-logging package."]))
+
+# Check for sdbus++ tool
+AC_PATH_PROG([SDBUSPLUSPLUS], [sdbus++])
+AS_IF([test "x$SDBUSPLUSPLUS" == "x"], AC_MSG_ERROR([Cannot find sdbus++]))
+
+# Checks for typedefs, structures, and compiler characteristics.
+AX_CXX_COMPILE_STDCXX(14, [noext])
+AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS])
+
+# Checks for library functions.
+LT_INIT([disable-static shared])
+
+# Check/set gtest specific functions.
+AX_PTHREAD([GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=1"],[GTEST_CPPFLAGS="-GTEST_HAS_PTHREAD=0"])
+AC_SUBST(GTEST_CPPFLAGS)
+
+AC_ARG_ENABLE([oe-sdk],
+ AS_HELP_STRING([--enable-oe-sdk], [Link testcases absolutely against OE SDK so they can be ran within it.])
+)
+AC_ARG_VAR(OECORE_TARGET_SYSROOT,
+ [Path to the OE SDK SYSROOT])
+AS_IF([test "x$enable_oe_sdk" == "xyes"],
+ AS_IF([test "x$OECORE_TARGET_SYSROOT" == "x"],
+ AC_MSG_ERROR([OECORE_TARGET_SYSROOT must be set with --enable-oe-sdk])
+ )
+ AC_MSG_NOTICE([Enabling OE-SDK at $OECORE_TARGET_SYSROOT])
+ [
+ testcase_flags="-Wl,-rpath,\${OECORE_TARGET_SYSROOT}/lib"
+ testcase_flags="${testcase_flags} -Wl,-rpath,\${OECORE_TARGET_SYSROOT}/usr/lib"
+ testcase_flags="${testcase_flags} -Wl,-dynamic-linker,`find \${OECORE_TARGET_SYSROOT}/lib/ld-*.so | sort -r -n | head -n1`"
+ ]
+ AC_SUBST([OESDK_TESTCASE_FLAGS], [$testcase_flags])
+)
+
+# Service dbus object manager
+AC_ARG_VAR(HIOMAPD_OBJ_PATH, [The Control Host D-Bus Object Manager])
+AS_IF([test "x$HIOMAPD_OBJ_PATH" == "x"],
+ [CONTROL_HOST_OBJ_MGR="/xyz/openbmc_project/hiomapd"])
+AC_DEFINE_UNQUOTED([HIOMAPD_OBJ_PATH], ["$HIOMAPD_OBJ_PATH"], [The Control Host D-Bus Object Manager])
+
+# Create configured output.
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/hiomap.cpp b/hiomap.cpp
new file mode 100644
index 0000000..f623e61
--- /dev/null
+++ b/hiomap.cpp
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (C) 2018 IBM Corp.
+
+#include "config.h"
+
+#include "hiomap.hpp"
+
+#include <endian.h>
+#include <host-ipmid/ipmid-api.h>
+#include <string.h>
+#include <systemd/sd-bus.h>
+
+#include <fstream>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/exception.hpp>
+
+using namespace sdbusplus;
+
+static void register_openpower_hiomap_commands() __attribute__((constructor));
+
+namespace openpower
+{
+namespace flash
+{
+
+/* TODO: Replace get/put with packed structs and direct assignment */
+template <typename T> static inline T get(void *buf)
+{
+ T t;
+ memcpy(&t, buf, sizeof(t));
+ return t;
+}
+
+template <typename T> static inline void put(void *buf, T &&t)
+{
+ memcpy(buf, &t, sizeof(t));
+}
+
+typedef ipmi_ret_t (*hiomap_command)(ipmi_request_t req, ipmi_response_t resp,
+ ipmi_data_len_t data_len,
+ ipmi_context_t context);
+
+struct errno_cc_entry
+{
+ int err;
+ int cc;
+};
+
+static const errno_cc_entry errno_cc_map[] = {
+ {0, IPMI_CC_OK},
+ {EBUSY, IPMI_CC_BUSY},
+ {ENOTSUP, IPMI_CC_INVALID},
+ {ETIMEDOUT, 0xc3}, /* FIXME: Replace when defined in ipmid-api.h */
+ {ENOSPC, 0xc4}, /* FIXME: Replace when defined in ipmid-api.h */
+ {EINVAL, IPMI_CC_PARM_OUT_OF_RANGE},
+ {ENODEV, IPMI_CC_SENSOR_INVALID},
+ {EPERM, IPMI_CC_INSUFFICIENT_PRIVILEGE},
+ {EACCES, IPMI_CC_INSUFFICIENT_PRIVILEGE},
+ {-1, IPMI_CC_UNSPECIFIED_ERROR},
+};
+
+static int hiomap_xlate_errno(int err)
+{
+ const errno_cc_entry *entry = &errno_cc_map[0];
+
+ while (!(entry->err == err || entry->err == -1))
+ {
+ entry++;
+ }
+
+ return entry->cc;
+}
+
+static ipmi_ret_t hiomap_get_info(ipmi_request_t request,
+ ipmi_response_t response,
+ ipmi_data_len_t data_len,
+ ipmi_context_t context)
+{
+ if (*data_len < 1)
+ {
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+
+ uint8_t *reqdata = (uint8_t *)request;
+ auto b = bus::new_system();
+ auto m = b.new_method_call(
+ "xyz.openbmc_project.Hiomapd", "/xyz/openbmc_project/Hiomapd",
+ "xyz.openbmc_project.Hiomapd.Protocol", "GetInfo");
+ m.append(reqdata[0]);
+
+ try
+ {
+ auto reply = b.call(m);
+
+ uint8_t version;
+ uint8_t blockSizeShift;
+ uint16_t timeout;
+ reply.read(version, blockSizeShift, timeout);
+
+ uint8_t *respdata = (uint8_t *)response;
+
+ /* FIXME: Assumes v2! */
+ put(&respdata[0], version);
+ put(&respdata[1], blockSizeShift);
+ put(&respdata[2], htole16(timeout));
+
+ *data_len = 4;
+ }
+ catch (const exception::SdBusError &e)
+ {
+ return hiomap_xlate_errno(e.get_errno());
+ }
+
+ return IPMI_CC_OK;
+}
+
+static const hiomap_command hiomap_commands[] = {
+ [0] = NULL, /* 0 is an invalid command ID */
+ [1] = NULL, /* RESET */
+ [2] = hiomap_get_info,
+};
+
+/* FIXME: Define this in the "right" place, wherever that is */
+/* FIXME: Double evaluation */
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static ipmi_ret_t hiomap_dispatch(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)
+{
+ if (*data_len < 2)
+ {
+ *data_len = 0;
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+
+ uint8_t *ipmi_req = (uint8_t *)request;
+ uint8_t *ipmi_resp = (uint8_t *)response;
+ uint8_t hiomap_cmd = ipmi_req[0];
+
+ if (hiomap_cmd == 0 || hiomap_cmd > ARRAY_SIZE(hiomap_commands) - 1)
+ {
+ *data_len = 0;
+ return IPMI_CC_PARM_OUT_OF_RANGE;
+ }
+ uint8_t *flash_req = ipmi_req + 2;
+ size_t flash_len = *data_len - 2;
+ uint8_t *flash_resp = ipmi_resp + 2;
+
+ ipmi_ret_t cc =
+ hiomap_commands[hiomap_cmd](flash_req, flash_resp, &flash_len, context);
+ if (cc != IPMI_CC_OK)
+ {
+ *data_len = 0;
+ return cc;
+ }
+
+ /* Populate the response command and sequence */
+ put(&ipmi_resp[0], ipmi_req[0]);
+ put(&ipmi_resp[1], ipmi_req[1]);
+
+ *data_len = flash_len + 2;
+
+ return cc;
+}
+} // namespace flash
+} // namespace openpower
+
+static void register_openpower_hiomap_commands()
+{
+ ipmi_register_callback(NETFUN_IBM_OEM, IPMI_CMD_HIOMAP, NULL,
+ openpower::flash::hiomap_dispatch, SYSTEM_INTERFACE);
+}
diff --git a/hiomap.hpp b/hiomap.hpp
new file mode 100644
index 0000000..6d91dd3
--- /dev/null
+++ b/hiomap.hpp
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/* Copyright (C) 2018 IBM Corp. */
+
+#ifndef HOSTFLASH_H
+#define HOSTFLASH_H
+
+#define IPMI_CMD_HIOMAP 0x5a
+
+#endif /* HOSTFLASH_H */