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 21*ce07ee0aSPatrick Venture #include <cstring> 224d49ae65SPatrick Venture #include <experimental/filesystem> 234d49ae65SPatrick Venture #include <fstream> 244d49ae65SPatrick Venture #include <sstream> 254d49ae65SPatrick Venture 264d49ae65SPatrick Venture namespace google 274d49ae65SPatrick Venture { 284d49ae65SPatrick Venture namespace ipmi 294d49ae65SPatrick Venture { 304d49ae65SPatrick Venture namespace fs = std::experimental::filesystem; 314d49ae65SPatrick Venture 324d49ae65SPatrick Venture struct CpldRequest 334d49ae65SPatrick Venture { 344d49ae65SPatrick Venture uint8_t subcommand; 354d49ae65SPatrick Venture uint8_t id; 364d49ae65SPatrick Venture } __attribute__((packed)); 374d49ae65SPatrick Venture 384d49ae65SPatrick Venture struct CpldReply 394d49ae65SPatrick Venture { 404d49ae65SPatrick Venture uint8_t subcommand; 414d49ae65SPatrick Venture uint8_t major; 424d49ae65SPatrick Venture uint8_t minor; 434d49ae65SPatrick Venture uint8_t point; 444d49ae65SPatrick Venture uint8_t subpoint; 454d49ae65SPatrick Venture } __attribute__((packed)); 464d49ae65SPatrick Venture 474d49ae65SPatrick Venture // 484d49ae65SPatrick Venture // Handle reading the cpld version from the tmpfs. 494d49ae65SPatrick Venture // 504d49ae65SPatrick Venture ipmi_ret_t CpldVersion(const uint8_t* reqBuf, uint8_t* replyBuf, 514d49ae65SPatrick Venture size_t* dataLen) 524d49ae65SPatrick Venture { 534d49ae65SPatrick Venture if ((*dataLen) < sizeof(struct CpldRequest)) 544d49ae65SPatrick Venture { 55*ce07ee0aSPatrick Venture std::fprintf(stderr, "Invalid command length: %u\n", 560dede335SPatrick Venture static_cast<uint32_t>(*dataLen)); 574d49ae65SPatrick Venture return IPMI_CC_INVALID; 584d49ae65SPatrick Venture } 594d49ae65SPatrick Venture 604d49ae65SPatrick Venture // reqBuf[0] is the subcommand. 614d49ae65SPatrick Venture // reqBuf[1] is the CPLD id. "/run/cpld{id}.version" is what we read. 624d49ae65SPatrick Venture // Verified that this cast actually returns the value 255 and not something 634d49ae65SPatrick Venture // negative in the case where reqBuf[1] is 0xff. However, it looks weird 644d49ae65SPatrick Venture // since I would expect int(uint8(0xff)) to be -1. So, just cast it 654d49ae65SPatrick Venture // unsigned. we're casting to an int width to avoid it thinking it's a 664d49ae65SPatrick Venture // letter, because it does that. 674d49ae65SPatrick Venture 684d49ae65SPatrick Venture const auto request = 694d49ae65SPatrick Venture reinterpret_cast<const struct CpldRequest*>(&reqBuf[0]); 704d49ae65SPatrick Venture 714d49ae65SPatrick Venture std::ostringstream opath; 724d49ae65SPatrick Venture opath << "/run/cpld" << static_cast<unsigned int>(request->id) 734d49ae65SPatrick Venture << ".version"; 744d49ae65SPatrick Venture // Check for file 754d49ae65SPatrick Venture 764d49ae65SPatrick Venture std::error_code ec; 774d49ae65SPatrick Venture if (!fs::exists(opath.str(), ec)) 784d49ae65SPatrick Venture { 79*ce07ee0aSPatrick Venture std::fprintf(stderr, "Path: '%s' doesn't exist.\n", 80*ce07ee0aSPatrick Venture opath.str().c_str()); 814d49ae65SPatrick Venture return IPMI_CC_INVALID; 824d49ae65SPatrick Venture } 834d49ae65SPatrick Venture // We're uninterested in the state of ec. 844d49ae65SPatrick Venture 854d49ae65SPatrick Venture // If file exists, read. 864d49ae65SPatrick Venture std::ifstream ifs; 874d49ae65SPatrick Venture ifs.exceptions(std::ifstream::failbit); 884d49ae65SPatrick Venture std::string value; 894d49ae65SPatrick Venture try 904d49ae65SPatrick Venture { 914d49ae65SPatrick Venture ifs.open(opath.str()); 924d49ae65SPatrick Venture ifs >> value; 934d49ae65SPatrick Venture } 944d49ae65SPatrick Venture catch (std::ios_base::failure& fail) 954d49ae65SPatrick Venture { 964d49ae65SPatrick Venture return IPMI_CC_INVALID; 974d49ae65SPatrick Venture } 984d49ae65SPatrick Venture 994d49ae65SPatrick Venture // If value parses as expected, return version. 1004d49ae65SPatrick Venture int major = 0; 1014d49ae65SPatrick Venture int minor = 0; 1024d49ae65SPatrick Venture int point = 0; 1034d49ae65SPatrick Venture int subpoint = 0; 1044d49ae65SPatrick Venture 1054d49ae65SPatrick Venture int num_fields = 1064d49ae65SPatrick Venture sscanf(value.c_str(), "%d.%d.%d.%d", &major, &minor, &point, &subpoint); 1074d49ae65SPatrick Venture if (num_fields == 0) 1084d49ae65SPatrick Venture { 109*ce07ee0aSPatrick Venture std::fprintf(stderr, "Invalid version.\n"); 1104d49ae65SPatrick Venture return IPMI_CC_INVALID; 1114d49ae65SPatrick Venture } 1124d49ae65SPatrick Venture 1134d49ae65SPatrick Venture // Truncate if the version is too high (documented). 1144d49ae65SPatrick Venture struct CpldReply reply; 1154d49ae65SPatrick Venture reply.subcommand = SysCpldVersion; 1164d49ae65SPatrick Venture reply.major = static_cast<uint8_t>(major); 1174d49ae65SPatrick Venture reply.minor = static_cast<uint8_t>(minor); 1184d49ae65SPatrick Venture reply.point = static_cast<uint8_t>(point); 1194d49ae65SPatrick Venture reply.subpoint = static_cast<uint8_t>(subpoint); 1204d49ae65SPatrick Venture 121*ce07ee0aSPatrick Venture std::memcpy(&replyBuf[0], &reply, sizeof(struct CpldReply)); 1224d49ae65SPatrick Venture (*dataLen) = sizeof(struct CpldReply); 1234d49ae65SPatrick Venture 1244d49ae65SPatrick Venture return IPMI_CC_OK; 1254d49ae65SPatrick Venture } 1264d49ae65SPatrick Venture 1274d49ae65SPatrick Venture } // namespace ipmi 1284d49ae65SPatrick Venture } // namespace google 129