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