blob: 454c6714acf4cb58aba1c7b1628ec6abec944a11 [file] [log] [blame]
// Copyright 2024 Google LLC
//
// 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 "message_util.hpp"
#include <stdplus/print.hpp>
#include <stdplus/raw.hpp>
#include <xyz/openbmc_project/Control/Hoth/error.hpp>
#include <cstring>
#include <span>
namespace google
{
namespace hoth
{
namespace internal
{
using sdbusplus::error::xyz::openbmc_project::control::hoth::CommandFailure;
using sdbusplus::error::xyz::openbmc_project::control::hoth::ResponseFailure;
void populateReqHeader(uint16_t command, uint8_t command_version,
const void* request, size_t request_size,
ReqHeader* request_header)
{
if (!request_header)
{
stdplus::print(stderr, "Request header argument cannot be NULL\n");
throw CommandFailure();
}
if (request_size > 0 && !request)
{
stdplus::print(stderr,
"Request data argument cannot be NULL with size > 0\n");
throw CommandFailure();
}
if (request_size > UINT16_MAX)
{
stdplus::print(stderr,
"Error, request_size({}) bigger than UINT16_MAX\n",
request_size);
throw CommandFailure();
}
request_header->struct_version = SUPPORTED_STRUCT_VERSION;
request_header->checksum = 0;
request_header->command = command;
request_header->command_version = command_version;
request_header->reserved = 0;
request_header->data_len = static_cast<uint16_t>(request_size);
// Note that we've set |checksum| to zero earlier, so this is deterministic.
request_header->checksum -= calculateChecksum(
stdplus::raw::asSpan<uint8_t>(*request_header),
std::span<const uint8_t>(reinterpret_cast<const uint8_t*>(request),
request_size));
}
size_t reqLen(const std::vector<uint8_t>& req)
{
struct ReqHeader header;
if (req.size() < sizeof(header))
{
stdplus::print(stderr, "Command is too short: `{} < {}`\n", req.size(),
sizeof(header));
throw CommandFailure();
}
std::memcpy(&header, req.data(), sizeof(header));
if (header.struct_version != SUPPORTED_STRUCT_VERSION)
{
stdplus::print(stderr, "Unsupported struct_version in command {}\n",
static_cast<uint16_t>(header.struct_version));
throw CommandFailure();
}
return sizeof(header) + header.data_len;
}
size_t rspLen(const std::vector<uint8_t>& rsp)
{
struct RspHeader header;
if (rsp.size() < sizeof(header))
{
stdplus::print(stderr, "Response is too short `{} < {}`\n", rsp.size(),
sizeof(header));
throw ResponseFailure();
}
std::memcpy(&header, rsp.data(), sizeof(header));
if (header.struct_version != SUPPORTED_STRUCT_VERSION)
{
stdplus::print(stderr, "Unsupported struct_version in response {}\n",
static_cast<uint16_t>(header.struct_version));
throw ResponseFailure();
}
return sizeof(header) + header.data_len;
}
std::vector<uint8_t> generateErrorResponse(uint8_t error)
{
RspHeader rsp = {};
rsp.struct_version = SUPPORTED_STRUCT_VERSION;
rsp.result = error;
rsp.checksum -= calculateChecksum(stdplus::raw::asSpan<uint8_t>(rsp));
std::vector<uint8_t> ret;
ret.resize(sizeof(rsp));
std::memcpy(ret.data(), &rsp, sizeof(rsp));
return ret;
}
} // namespace internal
} // namespace hoth
} // namespace google