xref: /openbmc/google-ipmi-sys/cpld.cpp (revision 0dede335)
14d49ae65SPatrick Venture /*
24d49ae65SPatrick Venture  * Copyright 2018 Google Inc.
34d49ae65SPatrick Venture  *
44d49ae65SPatrick Venture  * Licensed under the Apache License, Version 2.0 (the "License");
54d49ae65SPatrick Venture  * you may not use this file except in compliance with the License.
64d49ae65SPatrick Venture  * You may obtain a copy of the License at
74d49ae65SPatrick Venture  *
84d49ae65SPatrick Venture  *     http://www.apache.org/licenses/LICENSE-2.0
94d49ae65SPatrick Venture  *
104d49ae65SPatrick Venture  * Unless required by applicable law or agreed to in writing, software
114d49ae65SPatrick Venture  * distributed under the License is distributed on an "AS IS" BASIS,
124d49ae65SPatrick Venture  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134d49ae65SPatrick Venture  * See the License for the specific language governing permissions and
144d49ae65SPatrick Venture  * limitations under the License.
154d49ae65SPatrick Venture  */
164d49ae65SPatrick Venture 
174d49ae65SPatrick Venture #include "cpld.hpp"
184d49ae65SPatrick Venture 
194d49ae65SPatrick Venture #include "main.hpp"
204d49ae65SPatrick Venture 
214d49ae65SPatrick Venture #include <experimental/filesystem>
224d49ae65SPatrick Venture #include <fstream>
234d49ae65SPatrick Venture #include <sstream>
244d49ae65SPatrick Venture 
254d49ae65SPatrick Venture namespace google
264d49ae65SPatrick Venture {
274d49ae65SPatrick Venture namespace ipmi
284d49ae65SPatrick Venture {
294d49ae65SPatrick Venture namespace fs = std::experimental::filesystem;
304d49ae65SPatrick Venture 
314d49ae65SPatrick Venture struct CpldRequest
324d49ae65SPatrick Venture {
334d49ae65SPatrick Venture     uint8_t subcommand;
344d49ae65SPatrick Venture     uint8_t id;
354d49ae65SPatrick Venture } __attribute__((packed));
364d49ae65SPatrick Venture 
374d49ae65SPatrick Venture struct CpldReply
384d49ae65SPatrick Venture {
394d49ae65SPatrick Venture     uint8_t subcommand;
404d49ae65SPatrick Venture     uint8_t major;
414d49ae65SPatrick Venture     uint8_t minor;
424d49ae65SPatrick Venture     uint8_t point;
434d49ae65SPatrick Venture     uint8_t subpoint;
444d49ae65SPatrick Venture } __attribute__((packed));
454d49ae65SPatrick Venture 
464d49ae65SPatrick Venture //
474d49ae65SPatrick Venture // Handle reading the cpld version from the tmpfs.
484d49ae65SPatrick Venture //
494d49ae65SPatrick Venture ipmi_ret_t CpldVersion(const uint8_t* reqBuf, uint8_t* replyBuf,
504d49ae65SPatrick Venture                        size_t* dataLen)
514d49ae65SPatrick Venture {
524d49ae65SPatrick Venture     if ((*dataLen) < sizeof(struct CpldRequest))
534d49ae65SPatrick Venture     {
54*0dede335SPatrick Venture         fprintf(stderr, "Invalid command length: %u\n",
55*0dede335SPatrick Venture                 static_cast<uint32_t>(*dataLen));
564d49ae65SPatrick Venture         return IPMI_CC_INVALID;
574d49ae65SPatrick Venture     }
584d49ae65SPatrick Venture 
594d49ae65SPatrick Venture     // reqBuf[0] is the subcommand.
604d49ae65SPatrick Venture     // reqBuf[1] is the CPLD id. "/run/cpld{id}.version" is what we read.
614d49ae65SPatrick Venture     // Verified that this cast actually returns the value 255 and not something
624d49ae65SPatrick Venture     // negative in the case where reqBuf[1] is 0xff.  However, it looks weird
634d49ae65SPatrick Venture     // since I would expect int(uint8(0xff)) to be -1.  So, just cast it
644d49ae65SPatrick Venture     // unsigned. we're casting to an int width to avoid it thinking it's a
654d49ae65SPatrick Venture     // letter, because it does that.
664d49ae65SPatrick Venture 
674d49ae65SPatrick Venture     const auto request =
684d49ae65SPatrick Venture         reinterpret_cast<const struct CpldRequest*>(&reqBuf[0]);
694d49ae65SPatrick Venture 
704d49ae65SPatrick Venture     std::ostringstream opath;
714d49ae65SPatrick Venture     opath << "/run/cpld" << static_cast<unsigned int>(request->id)
724d49ae65SPatrick Venture           << ".version";
734d49ae65SPatrick Venture     // Check for file
744d49ae65SPatrick Venture 
754d49ae65SPatrick Venture     std::error_code ec;
764d49ae65SPatrick Venture     if (!fs::exists(opath.str(), ec))
774d49ae65SPatrick Venture     {
784d49ae65SPatrick Venture         fprintf(stderr, "Path: '%s' doesn't exist.\n", opath.str().c_str());
794d49ae65SPatrick Venture         return IPMI_CC_INVALID;
804d49ae65SPatrick Venture     }
814d49ae65SPatrick Venture     // We're uninterested in the state of ec.
824d49ae65SPatrick Venture 
834d49ae65SPatrick Venture     // If file exists, read.
844d49ae65SPatrick Venture     std::ifstream ifs;
854d49ae65SPatrick Venture     ifs.exceptions(std::ifstream::failbit);
864d49ae65SPatrick Venture     std::string value;
874d49ae65SPatrick Venture     try
884d49ae65SPatrick Venture     {
894d49ae65SPatrick Venture         ifs.open(opath.str());
904d49ae65SPatrick Venture         ifs >> value;
914d49ae65SPatrick Venture     }
924d49ae65SPatrick Venture     catch (std::ios_base::failure& fail)
934d49ae65SPatrick Venture     {
944d49ae65SPatrick Venture         return IPMI_CC_INVALID;
954d49ae65SPatrick Venture     }
964d49ae65SPatrick Venture 
974d49ae65SPatrick Venture     // If value parses as expected, return version.
984d49ae65SPatrick Venture     int major = 0;
994d49ae65SPatrick Venture     int minor = 0;
1004d49ae65SPatrick Venture     int point = 0;
1014d49ae65SPatrick Venture     int subpoint = 0;
1024d49ae65SPatrick Venture 
1034d49ae65SPatrick Venture     int num_fields =
1044d49ae65SPatrick Venture         sscanf(value.c_str(), "%d.%d.%d.%d", &major, &minor, &point, &subpoint);
1054d49ae65SPatrick Venture     if (num_fields == 0)
1064d49ae65SPatrick Venture     {
1074d49ae65SPatrick Venture         fprintf(stderr, "Invalid version.\n");
1084d49ae65SPatrick Venture         return IPMI_CC_INVALID;
1094d49ae65SPatrick Venture     }
1104d49ae65SPatrick Venture 
1114d49ae65SPatrick Venture     // Truncate if the version is too high (documented).
1124d49ae65SPatrick Venture     struct CpldReply reply;
1134d49ae65SPatrick Venture     reply.subcommand = SysCpldVersion;
1144d49ae65SPatrick Venture     reply.major = static_cast<uint8_t>(major);
1154d49ae65SPatrick Venture     reply.minor = static_cast<uint8_t>(minor);
1164d49ae65SPatrick Venture     reply.point = static_cast<uint8_t>(point);
1174d49ae65SPatrick Venture     reply.subpoint = static_cast<uint8_t>(subpoint);
1184d49ae65SPatrick Venture 
1194d49ae65SPatrick Venture     memcpy(&replyBuf[0], &reply, sizeof(struct CpldReply));
1204d49ae65SPatrick Venture     (*dataLen) = sizeof(struct CpldReply);
1214d49ae65SPatrick Venture 
1224d49ae65SPatrick Venture     return IPMI_CC_OK;
1234d49ae65SPatrick Venture }
1244d49ae65SPatrick Venture 
1254d49ae65SPatrick Venture } // namespace ipmi
1264d49ae65SPatrick Venture } // namespace google
127