1 /* 2 * Copyright 2018 Google Inc. 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 17 #include "cpld.hpp" 18 19 #include "errors.hpp" 20 #include "handler.hpp" 21 #include "ipmi.hpp" 22 23 #include <cstring> 24 25 namespace google 26 { 27 namespace ipmi 28 { 29 30 struct CpldRequest 31 { 32 uint8_t subcommand; 33 uint8_t id; 34 } __attribute__((packed)); 35 36 struct CpldReply 37 { 38 uint8_t subcommand; 39 uint8_t major; 40 uint8_t minor; 41 uint8_t point; 42 uint8_t subpoint; 43 } __attribute__((packed)); 44 45 // 46 // Handle reading the cpld version from the tmpfs. 47 // 48 ipmi_ret_t cpldVersion(const uint8_t* reqBuf, uint8_t* replyBuf, 49 size_t* dataLen, const HandlerInterface* handler) 50 { 51 struct CpldRequest request; 52 53 if ((*dataLen) < sizeof(request)) 54 { 55 std::fprintf(stderr, "Invalid command length: %u\n", 56 static_cast<uint32_t>(*dataLen)); 57 return IPMI_CC_REQ_DATA_LEN_INVALID; 58 } 59 60 // reqBuf[0] is the subcommand. 61 // reqBuf[1] is the CPLD id. "/run/cpld{id}.version" is what we read. 62 // Verified that this cast actually returns the value 255 and not something 63 // negative in the case where reqBuf[1] is 0xff. However, it looks weird 64 // since I would expect int(uint8(0xff)) to be -1. So, just cast it 65 // unsigned. we're casting to an int width to avoid it thinking it's a 66 // letter, because it does that. 67 std::memcpy(&request, &reqBuf[0], sizeof(request)); 68 69 try 70 { 71 auto values = 72 handler->getCpldVersion(static_cast<unsigned int>(request.id)); 73 74 // Truncate if the version is too high (documented). 75 struct CpldReply reply; 76 reply.subcommand = SysCpldVersion; 77 reply.major = std::get<0>(values); 78 reply.minor = std::get<1>(values); 79 reply.point = std::get<2>(values); 80 reply.subpoint = std::get<3>(values); 81 82 std::memcpy(&replyBuf[0], &reply, sizeof(reply)); 83 (*dataLen) = sizeof(reply); 84 return IPMI_CC_OK; 85 } 86 catch (const IpmiException& e) 87 { 88 return e.getIpmiError(); 89 } 90 } 91 92 } // namespace ipmi 93 } // namespace google 94