diff options
author | Patrick Venture <venture@google.com> | 2018-09-12 08:53:29 -0700 |
---|---|---|
committer | Patrick Venture <venture@google.com> | 2018-09-15 13:11:30 -0700 |
commit | ef3aeadc9be37c47d0627e576e81a74a5bb9e94f (patch) | |
tree | 95c183977468b107bdd3faaaa988b5d853be2f00 /process.cpp | |
parent | baa73da1abaaf05ea1133319405fb2b891825618 (diff) | |
download | phosphor-ipmi-blobs-ef3aeadc9be37c47d0627e576e81a74a5bb9e94f.tar.gz phosphor-ipmi-blobs-ef3aeadc9be37c47d0627e576e81a74a5bb9e94f.zip |
initial drop of phosphor-ipmi-blobs
This implements a majority of the OEM IPMI BLOBS protocol. The only
piece missing from this is the timed expiration of sessions.
Change-Id: I82c9d17b625c94fc3340edcfabbbf1ffeb5ad7ac
Signed-off-by: Patrick Venture <venture@google.com>
Diffstat (limited to 'process.cpp')
-rw-r--r-- | process.cpp | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/process.cpp b/process.cpp new file mode 100644 index 0000000..595b5c2 --- /dev/null +++ b/process.cpp @@ -0,0 +1,162 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "process.hpp" + +#include "ipmi.hpp" + +#include <cstring> +#include <vector> + +namespace blobs +{ + +/* Used by all commands with data. */ +struct BmcRx +{ + uint8_t cmd; + uint16_t crc; + uint8_t data; /* one byte minimum of data. */ +} __attribute__((packed)); + +IpmiBlobHandler validateBlobCommand(CrcInterface* crc, const uint8_t* reqBuf, + uint8_t* replyCmdBuf, size_t* dataLen) +{ + IpmiBlobHandler cmd; + size_t requestLength = (*dataLen); + /* We know dataLen is at least 1 already */ + auto command = static_cast<BlobOEMCommands>(reqBuf[0]); + + /* Validate it's at least well-formed. */ + if (!validateRequestLength(command, requestLength)) + { + return nullptr; + } + + /* If there is a payload. */ + if (requestLength > sizeof(uint8_t)) + { + /* Verify the request includes: command, crc16, data */ + if (requestLength < sizeof(struct BmcRx)) + { + return nullptr; + } + + /* We don't include the command byte at offset 0 as part of the crc + * payload area or the crc bytes at the beginning. + */ + size_t requestBodyLen = requestLength - 3; + + /* We start after the command byte. */ + std::vector<uint8_t> bytes(requestBodyLen); + + /* It likely has a well-formed payload. */ + struct BmcRx request; + std::memcpy(&request, reqBuf, sizeof(request)); + uint16_t crcValue = request.crc; + + /* Set the in-place CRC to zero. */ + std::memcpy(bytes.data(), &reqBuf[3], requestBodyLen); + + crc->clear(); + crc->compute(bytes.data(), bytes.size()); + + /* Crc expected but didn't match. */ + if (crcValue != crc->get()) + { + return nullptr; + } + } + + /* Grab the corresponding handler for the command (could do map or array + * of function pointer lookup). + */ + switch (command) + { + case BlobOEMCommands::bmcBlobGetCount: + cmd = getBlobCount; + break; + case BlobOEMCommands::bmcBlobEnumerate: + cmd = enumerateBlob; + break; + case BlobOEMCommands::bmcBlobOpen: + cmd = openBlob; + break; + case BlobOEMCommands::bmcBlobRead: + cmd = readBlob; + break; + case BlobOEMCommands::bmcBlobWrite: + cmd = writeBlob; + break; + case BlobOEMCommands::bmcBlobCommit: + cmd = commitBlob; + break; + case BlobOEMCommands::bmcBlobClose: + cmd = closeBlob; + break; + case BlobOEMCommands::bmcBlobDelete: + cmd = deleteBlob; + break; + case BlobOEMCommands::bmcBlobStat: + cmd = statBlob; + break; + case BlobOEMCommands::bmcBlobSessionStat: + cmd = sessionStatBlob; + break; + default: + return nullptr; + } + + return cmd; +} + +ipmi_ret_t processBlobCommand(IpmiBlobHandler cmd, ManagerInterface* mgr, + CrcInterface* crc, const uint8_t* reqBuf, + uint8_t* replyCmdBuf, size_t* dataLen) +{ + ipmi_ret_t result = cmd(mgr, reqBuf, replyCmdBuf, dataLen); + if (result != IPMI_CC_OK) + { + return result; + } + + size_t replyLength = (*dataLen); + + /* The command, whatever it was, returned success. */ + if (replyLength == 0) + { + return result; + } + + /* The response, if it has one byte, has three, to include the crc16. */ + if (replyLength < (sizeof(uint16_t) + 1)) + { + return IPMI_CC_INVALID; + } + + /* The command, whatever it was, replied, so let's set the CRC. */ + crc->clear(); + replyCmdBuf[0] = 0x00; + replyCmdBuf[1] = 0x00; + crc->compute(replyCmdBuf, replyLength); + + /* Copy the CRC into place. */ + uint16_t crcValue = crc->get(); + std::memcpy(replyCmdBuf, &crcValue, sizeof(crcValue)); + + return result; +} +} // namespace blobs |