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 "process.hpp" 18 19 #include "ipmi.hpp" 20 21 #include <cstring> 22 #include <unordered_map> 23 #include <vector> 24 25 namespace blobs 26 { 27 28 /* Used by all commands with data. */ 29 struct BmcRx 30 { 31 uint8_t cmd; 32 uint16_t crc; 33 uint8_t data; /* one byte minimum of data. */ 34 } __attribute__((packed)); 35 36 static const std::unordered_map<BlobOEMCommands, IpmiBlobHandler> handlers = { 37 {BlobOEMCommands::bmcBlobGetCount, getBlobCount}, 38 {BlobOEMCommands::bmcBlobEnumerate, enumerateBlob}, 39 {BlobOEMCommands::bmcBlobOpen, openBlob}, 40 {BlobOEMCommands::bmcBlobRead, readBlob}, 41 {BlobOEMCommands::bmcBlobWrite, writeBlob}, 42 {BlobOEMCommands::bmcBlobCommit, commitBlob}, 43 {BlobOEMCommands::bmcBlobClose, closeBlob}, 44 {BlobOEMCommands::bmcBlobDelete, deleteBlob}, 45 {BlobOEMCommands::bmcBlobStat, statBlob}, 46 {BlobOEMCommands::bmcBlobSessionStat, sessionStatBlob}, 47 {BlobOEMCommands::bmcBlobWriteMeta, writeMeta}, 48 }; 49 50 IpmiBlobHandler validateBlobCommand(CrcInterface* crc, const uint8_t* reqBuf, 51 uint8_t* replyCmdBuf, size_t* dataLen) 52 { 53 size_t requestLength = (*dataLen); 54 /* We know dataLen is at least 1 already */ 55 auto command = static_cast<BlobOEMCommands>(reqBuf[0]); 56 57 /* Validate it's at least well-formed. */ 58 if (!validateRequestLength(command, requestLength)) 59 { 60 return nullptr; 61 } 62 63 /* If there is a payload. */ 64 if (requestLength > sizeof(uint8_t)) 65 { 66 /* Verify the request includes: command, crc16, data */ 67 if (requestLength < sizeof(struct BmcRx)) 68 { 69 return nullptr; 70 } 71 72 /* We don't include the command byte at offset 0 as part of the crc 73 * payload area or the crc bytes at the beginning. 74 */ 75 size_t requestBodyLen = requestLength - 3; 76 77 /* We start after the command byte. */ 78 std::vector<uint8_t> bytes(requestBodyLen); 79 80 /* It likely has a well-formed payload. */ 81 struct BmcRx request; 82 std::memcpy(&request, reqBuf, sizeof(request)); 83 uint16_t crcValue = request.crc; 84 85 /* Set the in-place CRC to zero. */ 86 std::memcpy(bytes.data(), &reqBuf[3], requestBodyLen); 87 88 crc->clear(); 89 crc->compute(bytes.data(), bytes.size()); 90 91 /* Crc expected but didn't match. */ 92 if (crcValue != crc->get()) 93 { 94 return nullptr; 95 } 96 } 97 98 /* Grab the corresponding handler for the command. */ 99 auto found = handlers.find(command); 100 if (found == handlers.end()) 101 { 102 return nullptr; 103 } 104 105 return found->second; 106 } 107 108 ipmi_ret_t processBlobCommand(IpmiBlobHandler cmd, ManagerInterface* mgr, 109 CrcInterface* crc, const uint8_t* reqBuf, 110 uint8_t* replyCmdBuf, size_t* dataLen) 111 { 112 ipmi_ret_t result = cmd(mgr, reqBuf, replyCmdBuf, dataLen); 113 if (result != IPMI_CC_OK) 114 { 115 return result; 116 } 117 118 size_t replyLength = (*dataLen); 119 120 /* The command, whatever it was, returned success. */ 121 if (replyLength == 0) 122 { 123 return result; 124 } 125 126 /* The response, if it has one byte, has three, to include the crc16. */ 127 if (replyLength < (sizeof(uint16_t) + 1)) 128 { 129 return IPMI_CC_INVALID; 130 } 131 132 /* The command, whatever it was, replied, so let's set the CRC. */ 133 crc->clear(); 134 replyCmdBuf[0] = 0x00; 135 replyCmdBuf[1] = 0x00; 136 crc->compute(replyCmdBuf, replyLength); 137 138 /* Copy the CRC into place. */ 139 uint16_t crcValue = crc->get(); 140 std::memcpy(replyCmdBuf, &crcValue, sizeof(crcValue)); 141 142 return result; 143 } 144 } // namespace blobs 145