1*4d49ae65SPatrick Venture /* 2*4d49ae65SPatrick Venture * Copyright 2018 Google Inc. 3*4d49ae65SPatrick Venture * 4*4d49ae65SPatrick Venture * Licensed under the Apache License, Version 2.0 (the "License"); 5*4d49ae65SPatrick Venture * you may not use this file except in compliance with the License. 6*4d49ae65SPatrick Venture * You may obtain a copy of the License at 7*4d49ae65SPatrick Venture * 8*4d49ae65SPatrick Venture * http://www.apache.org/licenses/LICENSE-2.0 9*4d49ae65SPatrick Venture * 10*4d49ae65SPatrick Venture * Unless required by applicable law or agreed to in writing, software 11*4d49ae65SPatrick Venture * distributed under the License is distributed on an "AS IS" BASIS, 12*4d49ae65SPatrick Venture * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*4d49ae65SPatrick Venture * See the License for the specific language governing permissions and 14*4d49ae65SPatrick Venture * limitations under the License. 15*4d49ae65SPatrick Venture */ 16*4d49ae65SPatrick Venture 17*4d49ae65SPatrick Venture #include "cpld.hpp" 18*4d49ae65SPatrick Venture 19*4d49ae65SPatrick Venture #include "main.hpp" 20*4d49ae65SPatrick Venture 21*4d49ae65SPatrick Venture #include <experimental/filesystem> 22*4d49ae65SPatrick Venture #include <fstream> 23*4d49ae65SPatrick Venture #include <sstream> 24*4d49ae65SPatrick Venture 25*4d49ae65SPatrick Venture namespace google 26*4d49ae65SPatrick Venture { 27*4d49ae65SPatrick Venture namespace ipmi 28*4d49ae65SPatrick Venture { 29*4d49ae65SPatrick Venture namespace fs = std::experimental::filesystem; 30*4d49ae65SPatrick Venture 31*4d49ae65SPatrick Venture struct CpldRequest 32*4d49ae65SPatrick Venture { 33*4d49ae65SPatrick Venture uint8_t subcommand; 34*4d49ae65SPatrick Venture uint8_t id; 35*4d49ae65SPatrick Venture } __attribute__((packed)); 36*4d49ae65SPatrick Venture 37*4d49ae65SPatrick Venture struct CpldReply 38*4d49ae65SPatrick Venture { 39*4d49ae65SPatrick Venture uint8_t subcommand; 40*4d49ae65SPatrick Venture uint8_t major; 41*4d49ae65SPatrick Venture uint8_t minor; 42*4d49ae65SPatrick Venture uint8_t point; 43*4d49ae65SPatrick Venture uint8_t subpoint; 44*4d49ae65SPatrick Venture } __attribute__((packed)); 45*4d49ae65SPatrick Venture 46*4d49ae65SPatrick Venture // 47*4d49ae65SPatrick Venture // Handle reading the cpld version from the tmpfs. 48*4d49ae65SPatrick Venture // 49*4d49ae65SPatrick Venture ipmi_ret_t CpldVersion(const uint8_t* reqBuf, uint8_t* replyBuf, 50*4d49ae65SPatrick Venture size_t* dataLen) 51*4d49ae65SPatrick Venture { 52*4d49ae65SPatrick Venture if ((*dataLen) < sizeof(struct CpldRequest)) 53*4d49ae65SPatrick Venture { 54*4d49ae65SPatrick Venture fprintf(stderr, "Invalid command length: %lu\n", (*dataLen)); 55*4d49ae65SPatrick Venture return IPMI_CC_INVALID; 56*4d49ae65SPatrick Venture } 57*4d49ae65SPatrick Venture 58*4d49ae65SPatrick Venture // reqBuf[0] is the subcommand. 59*4d49ae65SPatrick Venture // reqBuf[1] is the CPLD id. "/run/cpld{id}.version" is what we read. 60*4d49ae65SPatrick Venture // Verified that this cast actually returns the value 255 and not something 61*4d49ae65SPatrick Venture // negative in the case where reqBuf[1] is 0xff. However, it looks weird 62*4d49ae65SPatrick Venture // since I would expect int(uint8(0xff)) to be -1. So, just cast it 63*4d49ae65SPatrick Venture // unsigned. we're casting to an int width to avoid it thinking it's a 64*4d49ae65SPatrick Venture // letter, because it does that. 65*4d49ae65SPatrick Venture 66*4d49ae65SPatrick Venture const auto request = 67*4d49ae65SPatrick Venture reinterpret_cast<const struct CpldRequest*>(&reqBuf[0]); 68*4d49ae65SPatrick Venture 69*4d49ae65SPatrick Venture std::ostringstream opath; 70*4d49ae65SPatrick Venture opath << "/run/cpld" << static_cast<unsigned int>(request->id) 71*4d49ae65SPatrick Venture << ".version"; 72*4d49ae65SPatrick Venture // Check for file 73*4d49ae65SPatrick Venture 74*4d49ae65SPatrick Venture std::error_code ec; 75*4d49ae65SPatrick Venture if (!fs::exists(opath.str(), ec)) 76*4d49ae65SPatrick Venture { 77*4d49ae65SPatrick Venture fprintf(stderr, "Path: '%s' doesn't exist.\n", opath.str().c_str()); 78*4d49ae65SPatrick Venture return IPMI_CC_INVALID; 79*4d49ae65SPatrick Venture } 80*4d49ae65SPatrick Venture // We're uninterested in the state of ec. 81*4d49ae65SPatrick Venture 82*4d49ae65SPatrick Venture // If file exists, read. 83*4d49ae65SPatrick Venture std::ifstream ifs; 84*4d49ae65SPatrick Venture ifs.exceptions(std::ifstream::failbit); 85*4d49ae65SPatrick Venture std::string value; 86*4d49ae65SPatrick Venture try 87*4d49ae65SPatrick Venture { 88*4d49ae65SPatrick Venture ifs.open(opath.str()); 89*4d49ae65SPatrick Venture ifs >> value; 90*4d49ae65SPatrick Venture } 91*4d49ae65SPatrick Venture catch (std::ios_base::failure& fail) 92*4d49ae65SPatrick Venture { 93*4d49ae65SPatrick Venture return IPMI_CC_INVALID; 94*4d49ae65SPatrick Venture } 95*4d49ae65SPatrick Venture 96*4d49ae65SPatrick Venture // If value parses as expected, return version. 97*4d49ae65SPatrick Venture int major = 0; 98*4d49ae65SPatrick Venture int minor = 0; 99*4d49ae65SPatrick Venture int point = 0; 100*4d49ae65SPatrick Venture int subpoint = 0; 101*4d49ae65SPatrick Venture 102*4d49ae65SPatrick Venture int num_fields = 103*4d49ae65SPatrick Venture sscanf(value.c_str(), "%d.%d.%d.%d", &major, &minor, &point, &subpoint); 104*4d49ae65SPatrick Venture if (num_fields == 0) 105*4d49ae65SPatrick Venture { 106*4d49ae65SPatrick Venture fprintf(stderr, "Invalid version.\n"); 107*4d49ae65SPatrick Venture return IPMI_CC_INVALID; 108*4d49ae65SPatrick Venture } 109*4d49ae65SPatrick Venture 110*4d49ae65SPatrick Venture // Truncate if the version is too high (documented). 111*4d49ae65SPatrick Venture struct CpldReply reply; 112*4d49ae65SPatrick Venture reply.subcommand = SysCpldVersion; 113*4d49ae65SPatrick Venture reply.major = static_cast<uint8_t>(major); 114*4d49ae65SPatrick Venture reply.minor = static_cast<uint8_t>(minor); 115*4d49ae65SPatrick Venture reply.point = static_cast<uint8_t>(point); 116*4d49ae65SPatrick Venture reply.subpoint = static_cast<uint8_t>(subpoint); 117*4d49ae65SPatrick Venture 118*4d49ae65SPatrick Venture memcpy(&replyBuf[0], &reply, sizeof(struct CpldReply)); 119*4d49ae65SPatrick Venture (*dataLen) = sizeof(struct CpldReply); 120*4d49ae65SPatrick Venture 121*4d49ae65SPatrick Venture return IPMI_CC_OK; 122*4d49ae65SPatrick Venture } 123*4d49ae65SPatrick Venture 124*4d49ae65SPatrick Venture } // namespace ipmi 125*4d49ae65SPatrick Venture } // namespace google 126