blob: 8b67f3e3854fcaeec1e969f2e26c35a23c8cf586 [file] [log] [blame]
Brad Bishop613a5b32017-01-05 20:58:13 -05001/**
2 * Copyright © 2016 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <cstdlib>
Brad Bishop08379a32017-03-06 21:28:46 -050017#include <experimental/filesystem>
Brad Bishop613a5b32017-01-05 20:58:13 -050018#include <memory>
Matthew Barth048ac872017-03-09 14:36:08 -060019#include <phosphor-logging/elog.hpp>
20#include <phosphor-logging/elog-errors.hpp>
21#include <xyz/openbmc_project/Control/Device/error.hpp>
Brad Bishop613a5b32017-01-05 20:58:13 -050022#include "sysfs.hpp"
23#include "util.hpp"
Brad Bishop613a5b32017-01-05 20:58:13 -050024
Matthew Barth048ac872017-03-09 14:36:08 -060025using namespace phosphor::logging;
26
Brad Bishop613a5b32017-01-05 20:58:13 -050027std::string findHwmon(const std::string& ofNode)
28{
Brad Bishop08379a32017-03-06 21:28:46 -050029 namespace fs = std::experimental::filesystem;
Brad Bishop613a5b32017-01-05 20:58:13 -050030 static constexpr auto hwmonRoot = "/sys/class/hwmon";
Brad Bishop08379a32017-03-06 21:28:46 -050031 static constexpr auto ofRoot = "/sys/firmware/devicetree/base";
Brad Bishop613a5b32017-01-05 20:58:13 -050032
Brad Bishop08379a32017-03-06 21:28:46 -050033 fs::path fullOfPath{ofRoot};
34 fullOfPath /= ofNode;
Brad Bishop613a5b32017-01-05 20:58:13 -050035
Brad Bishop08379a32017-03-06 21:28:46 -050036 for (const auto& hwmonInst : fs::directory_iterator(hwmonRoot))
Brad Bishop613a5b32017-01-05 20:58:13 -050037 {
Brad Bishop08379a32017-03-06 21:28:46 -050038 auto path = hwmonInst.path();
39 path /= "of_node";
Brad Bishop613a5b32017-01-05 20:58:13 -050040
Brad Bishop08379a32017-03-06 21:28:46 -050041 if (fs::canonical(path) != fullOfPath)
Brad Bishop613a5b32017-01-05 20:58:13 -050042 {
43 continue;
44 }
45
Brad Bishop08379a32017-03-06 21:28:46 -050046 return hwmonInst.path();
Brad Bishop613a5b32017-01-05 20:58:13 -050047 }
48
49 return std::string();
50}
51
Brad Bishop4db64422017-02-16 11:33:32 -050052int readSysfsWithCallout(const std::string& root,
53 const std::string& instance,
54 const std::string& type,
55 const std::string& id,
56 const std::string& sensor)
57{
Brad Bishop5ec68ab2017-03-27 13:41:02 -040058 namespace fs = std::experimental::filesystem;
59
Brad Bishop4db64422017-02-16 11:33:32 -050060 int value = 0;
Brad Bishop5ec68ab2017-03-27 13:41:02 -040061 std::ifstream ifs;
62 fs::path instancePath{root};
63 instancePath /= instance;
Brad Bishop4db64422017-02-16 11:33:32 -050064 std::string fullPath = make_sysfs_path(instancePath,
65 type, id, sensor);
Brad Bishop4db64422017-02-16 11:33:32 -050066
67 ifs.exceptions(std::ifstream::failbit
68 | std::ifstream::badbit
69 | std::ifstream::eofbit);
70 try
71 {
72 ifs.open(fullPath);
73 ifs >> value;
74 }
75 catch (const std::exception& e)
76 {
77 // Too many GCC bugs (53984, 66145) to do
78 // this the right way...
Brad Bishop4db64422017-02-16 11:33:32 -050079
80 // errno should still reflect the error from the failing open
81 // or read system calls that got us here.
82 auto rc = errno;
Brad Bishop5ec68ab2017-03-27 13:41:02 -040083 instancePath /= "device";
Brad Bishop4db64422017-02-16 11:33:32 -050084 phosphor::logging::log<phosphor::logging::level::ERR>(
85 strerror(rc),
Brad Bishop5ec68ab2017-03-27 13:41:02 -040086 phosphor::logging::entry(
87 "CALLOUT_DEVICE_PATH=%s",
88 fs::canonical(instancePath).c_str()),
Brad Bishop4db64422017-02-16 11:33:32 -050089 phosphor::logging::entry("CALLOUT_ERRNO=%d", rc));
90 exit(EXIT_FAILURE);
91 }
92
93 return value;
94}
95
Matthew Barth048ac872017-03-09 14:36:08 -060096uint64_t writeSysfsWithCallout(const uint64_t& value,
97 const std::string& root,
98 const std::string& instance,
99 const std::string& type,
100 const std::string& id,
101 const std::string& sensor)
102{
103 namespace fs = std::experimental::filesystem;
104
105 std::string valueStr = std::to_string(value);
106 std::ofstream ofs;
107 fs::path instancePath{root};
108 instancePath /= instance;
109 std::string fullPath = make_sysfs_path(instancePath,
110 type, id, sensor);
111
112 ofs.exceptions(std::ofstream::failbit
113 | std::ofstream::badbit
114 | std::ofstream::eofbit);
115 try
116 {
117 ofs.open(fullPath);
118 ofs << valueStr;
119 }
120 catch (const std::exception& e)
121 {
122 // errno should still reflect the error from the failing open
123 // or write system calls that got us here.
124 auto rc = errno;
125 instancePath /= "device";
126 using namespace sdbusplus::xyz::openbmc_project::Control::Device::Error;
127 try
128 {
129 elog<WriteFailure>(
130 xyz::openbmc_project::Control::Device::
131 WriteFailure::CALLOUT_ERRNO(rc),
132 xyz::openbmc_project::Control::Device::
133 WriteFailure::CALLOUT_DEVICE_PATH(
134 fs::canonical(instancePath).c_str()));
135 }
136 catch (WriteFailure& elog)
137 {
138 commit(elog.name());
139 }
140 exit(EXIT_FAILURE);
141 }
142
143 return value;
144}
145
Brad Bishop613a5b32017-01-05 20:58:13 -0500146// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4