blob: 5388926811be5e6c94e08331be9fe6eaf2bf5c79 [file] [log] [blame]
Marri Devender Rao0acf0572017-07-03 12:25:47 -05001#include <map>
2#include <phosphor-logging/elog-errors.hpp>
3#include "xyz/openbmc_project/Common/error.hpp"
4#include "read_fru_data.hpp"
5#include "fruread.hpp"
6#include "host-ipmid/ipmid-api.h"
7#include "utils.hpp"
8
9extern const FruMap frus;
10
11namespace ipmi
12{
13namespace fru
14{
15using namespace phosphor::logging;
16using InternalFailure =
17 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
18
19static constexpr auto INV_INTF = "xyz.openbmc_project.Inventory.Manager";
20static constexpr auto OBJ_PATH = "/xyz/openbmc_project/inventory";
21static constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";
22
23namespace cache
24{
25 //User initiate read FRU info area command followed by
26 //FRU read command. Also data is read in small chunks of
27 //the specified offset and count.
28 //Caching the data which will be invalidated when ever there
29 //is a change in FRU properties.
30 FRUAreaMap fruMap;
31}
32/**
33 * @brief Read the property value from Inventory
34 *
35 * @param[in] bus dbus
36 * @param[in] intf Interface
37 * @param[in] propertyName Name of the property
38 * @param[in] path Object path
39 * @return property value
40 */
41std::string readProperty(const std::string& intf,
42 const std::string& propertyName,
43 const std::string& path)
44{
45 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
46 auto service = ipmi::getService(bus, INV_INTF, OBJ_PATH);
47 std::string objPath = OBJ_PATH + path;
48 auto method = bus.new_method_call(service.c_str(),
49 objPath.c_str(),
50 PROP_INTF,
51 "Get");
52 method.append(intf, propertyName);
53 auto reply = bus.call(method);
54 if (reply.is_method_error())
55 {
56 //If property is not found simply return empty value
57 log<level::INFO>("Property value not set",
58 entry("Property=%s", propertyName),
59 entry("Path=%s", objPath));
60 return {};
61 }
62 sdbusplus::message::variant<std::string> property;
63 reply.read(property);
64 std::string value =
65 sdbusplus::message::variant_ns::get<std::string>(property);
66 return value;
67}
68
69/**
70 * @brief Read FRU property values from Inventory
71 *
72 * @param[in] fruNum FRU id
73 * @return populate FRU Inventory data
74 */
75FruInventoryData readDataFromInventory(const FRUId& fruNum)
76{
77 auto iter = frus.find(fruNum);
78 if (iter == frus.end())
79 {
80 log<level::ERR>("Unsupported FRU ID ",entry("FRUID=%d", fruNum));
81 elog<InternalFailure>();
82 }
83
84 FruInventoryData data;
85 auto& instanceList = iter->second;
86 for (auto& instance : instanceList)
87 {
88 for (auto& interfaceList : instance.second)
89 {
90 for (auto& properties : interfaceList.second)
91 {
92 decltype(auto) pdata = properties.second;
93 auto value = readProperty(
94 interfaceList.first, properties.first,
95 instance.first);
96 data[pdata.section].emplace(properties.first, value);
97 }
98 }
99 }
100 return data;
101}
102
103const FruAreaData& getFruAreaData(const FRUId& fruNum)
104{
105 auto iter = cache::fruMap.find(fruNum);
106 if (iter != cache::fruMap.end())
107 {
108 return iter->second;
109 }
110 auto invData = readDataFromInventory(fruNum);
111
112 //Build area info based on inventory data
113 FruAreaData newdata = buildFruAreaData(std::move(invData));
114 cache::fruMap.emplace(fruNum, std::move(newdata));
115 return cache::fruMap.at(fruNum);
116}
117} //fru
118} //ipmi