blob: 2bf6792a98c273eb0551f57d2a3169967fa4745b [file] [edit]
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright OpenBMC Authors
#include "base.h"
#include "device-configuration.h"
#include "fpga/fpga-maps.h"
#include <cstring>
#include <gtest/gtest.h>
#include <vector>
// One negative test per libnsm function the FPGA discovery path adds: the
// inputs each one must refuse, and that a refusal leaves its outputs alone.
namespace
{
const std::vector<uint8_t> digest(32, 0x5a);
std::vector<uint8_t> readReply()
{
std::vector<uint8_t> msg(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_device_config_v2_resp) - 1 +
digest.size());
auto response = reinterpret_cast<nsm_msg *>(msg.data());
EXPECT_EQ(encode_get_device_config_v2_resp(
0, NSM_SUCCESS, ERR_NULL, digest.data(),
static_cast<uint16_t>(digest.size()), nullptr, 0,
response),
NSM_SW_SUCCESS);
return msg;
}
std::vector<uint8_t> configsReply(const std::vector<uint32_t> &types,
uint32_t total)
{
std::vector<uint8_t> msg(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_supported_device_configs_resp) -
sizeof(uint32_t) +
types.size() * sizeof(uint32_t));
auto response = reinterpret_cast<nsm_msg *>(msg.data());
EXPECT_EQ(encode_get_supported_device_configs_resp(
0, NSM_SUCCESS, ERR_NULL, 0, total, types.data(),
static_cast<uint16_t>(types.size()), response),
NSM_SW_SUCCESS);
return msg;
}
} // namespace
TEST(mmioNegative, encode_get_device_config_mmio_req)
{
std::vector<uint8_t> untouched(64, 0xaa);
std::vector<uint8_t> buffer = untouched;
auto msg = reinterpret_cast<nsm_msg *>(buffer.data());
EXPECT_EQ(
encode_get_device_config_mmio_req(
0, NSM_DEVICE_CONFIG_TYPE_MMIO_ACCESS, 0x1080, 8, nullptr),
NSM_SW_ERROR_NULL);
EXPECT_EQ(encode_get_device_config_mmio_req(
0, NSM_DEVICE_CONFIG_TYPE_MMIO_ACCESS, 0x1081, 8, msg),
NSM_SW_ERROR_DATA);
EXPECT_EQ(encode_get_device_config_mmio_req(
0, NSM_DEVICE_CONFIG_TYPE_MMIO_ACCESS, 0x1082, 8, msg),
NSM_SW_ERROR_DATA);
EXPECT_EQ(encode_get_device_config_mmio_req(
0, NSM_DEVICE_CONFIG_TYPE_MMIO_ACCESS, 0x1080, 0, msg),
NSM_SW_ERROR_DATA);
EXPECT_EQ(encode_get_device_config_mmio_req(
0, NSM_DEVICE_CONFIG_TYPE_MMIO_ACCESS, 0x1080,
NSM_MMIO_ACCESS_MAX_LENGTH_DWORDS + 1, msg),
NSM_SW_ERROR_DATA);
EXPECT_EQ(buffer, untouched);
}
TEST(mmioNegative, decode_get_device_config_mmio_resp)
{
std::vector<uint8_t> reply = readReply();
auto response = reinterpret_cast<nsm_msg *>(reply.data());
uint8_t cc = NSM_ERROR;
uint16_t reasonCode = ERR_NULL;
const std::vector<uint8_t> untouched(32, 0x55);
std::vector<uint8_t> data = untouched;
EXPECT_EQ(decode_get_device_config_mmio_resp(
nullptr, reply.size(), 8, &cc, &reasonCode, data.data()),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_device_config_mmio_resp(response, reply.size(), 8,
nullptr, &reasonCode,
data.data()),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_device_config_mmio_resp(response, reply.size(), 8,
&cc, nullptr, data.data()),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_device_config_mmio_resp(response, reply.size(), 8,
&cc, &reasonCode, nullptr),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_device_config_mmio_resp(
response, reply.size(), 0, &cc, &reasonCode, data.data()),
NSM_SW_ERROR_DATA);
EXPECT_EQ(decode_get_device_config_mmio_resp(
response, reply.size(),
NSM_MMIO_ACCESS_MAX_LENGTH_DWORDS + 1, &cc, &reasonCode,
data.data()),
NSM_SW_ERROR_DATA);
// a reply that carries fewer DWORDs than were asked for
EXPECT_EQ(decode_get_device_config_mmio_resp(
response, reply.size(), 9, &cc, &reasonCode, data.data()),
NSM_SW_ERROR_LENGTH);
for (size_t len = 0; len < reply.size(); ++len) {
EXPECT_NE(decode_get_device_config_mmio_resp(
response, len, 8, &cc, &reasonCode, data.data()),
NSM_SW_SUCCESS);
}
auto resp = reinterpret_cast<nsm_get_device_config_v2_resp *>(
response->payload);
resp->pending_config_length = htole16(4);
EXPECT_EQ(decode_get_device_config_mmio_resp(
response, reply.size(), 8, &cc, &reasonCode, data.data()),
NSM_SW_ERROR_LENGTH);
resp->pending_config_length = 0;
resp->hdr.data_size = htole16(8);
EXPECT_EQ(decode_get_device_config_mmio_resp(
response, reply.size(), 8, &cc, &reasonCode, data.data()),
NSM_SW_ERROR_LENGTH);
EXPECT_EQ(data, untouched);
}
TEST(mmioNegative, encode_set_device_config_mmio_req)
{
const std::vector<uint8_t> word(4, 0x11);
std::vector<uint8_t> untouched(64, 0xaa);
std::vector<uint8_t> buffer = untouched;
auto msg = reinterpret_cast<nsm_msg *>(buffer.data());
EXPECT_EQ(encode_set_device_config_mmio_req(
0, NSM_DEVICE_CONFIG_TYPE_MMIO_ACCESS, 0x1000, 1,
word.data(), nullptr),
NSM_SW_ERROR_NULL);
EXPECT_EQ(
encode_set_device_config_mmio_req(
0, NSM_DEVICE_CONFIG_TYPE_MMIO_ACCESS, 0x1000, 1, nullptr, msg),
NSM_SW_ERROR_NULL);
EXPECT_EQ(encode_set_device_config_mmio_req(
0, NSM_DEVICE_CONFIG_TYPE_MMIO_ACCESS, 0x1003, 1,
word.data(), msg),
NSM_SW_ERROR_DATA);
EXPECT_EQ(encode_set_device_config_mmio_req(
0, NSM_DEVICE_CONFIG_TYPE_MMIO_ACCESS, 0x1000, 0,
word.data(), msg),
NSM_SW_ERROR_DATA);
EXPECT_EQ(encode_set_device_config_mmio_req(
0, NSM_DEVICE_CONFIG_TYPE_MMIO_ACCESS, 0x1000,
NSM_MMIO_ACCESS_MAX_LENGTH_DWORDS + 1, word.data(), msg),
NSM_SW_ERROR_DATA);
EXPECT_EQ(buffer, untouched);
}
TEST(mmioNegative, encode_get_supported_device_configs_req)
{
EXPECT_EQ(encode_get_supported_device_configs_req(0, 0, nullptr),
NSM_SW_ERROR_NULL);
EXPECT_EQ(encode_get_supported_device_configs_req(0x1f, 7, nullptr),
NSM_SW_ERROR_NULL);
}
TEST(mmioNegative, decode_get_supported_device_configs_req)
{
std::vector<uint8_t> buffer(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_supported_device_configs_req));
auto msg = reinterpret_cast<nsm_msg *>(buffer.data());
ASSERT_EQ(encode_get_supported_device_configs_req(0, 5, msg),
NSM_SW_SUCCESS);
uint32_t handle = 0xee;
EXPECT_EQ(decode_get_supported_device_configs_req(
nullptr, buffer.size(), &handle),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_supported_device_configs_req(msg, buffer.size(),
nullptr),
NSM_SW_ERROR_NULL);
for (size_t len = 0; len < buffer.size(); ++len) {
EXPECT_EQ(
decode_get_supported_device_configs_req(msg, len, &handle),
NSM_SW_ERROR_LENGTH);
}
auto request = reinterpret_cast<nsm_get_supported_device_configs_req *>(
msg->payload);
request->hdr.data_size = htole16(8);
EXPECT_EQ(decode_get_supported_device_configs_req(msg, buffer.size(),
&handle),
NSM_SW_ERROR_LENGTH);
request->hdr.data_size = htole16(4);
request->hdr.command = NSM_GET_SUPPORTED_DEVICE_CONFIGS + 1;
EXPECT_EQ(decode_get_supported_device_configs_req(msg, buffer.size(),
&handle),
NSM_SW_ERROR_DATA);
EXPECT_EQ(handle, 0xeeu);
}
TEST(mmioNegative, encode_get_supported_device_configs_resp)
{
const std::vector<uint32_t> types = {1, 2};
std::vector<uint8_t> buffer(64);
auto msg = reinterpret_cast<nsm_msg *>(buffer.data());
EXPECT_EQ(encode_get_supported_device_configs_resp(
0, NSM_SUCCESS, ERR_NULL, 0, 2, types.data(), 2, nullptr),
NSM_SW_ERROR_NULL);
EXPECT_EQ(encode_get_supported_device_configs_resp(
0, NSM_SUCCESS, ERR_NULL, 0, 2, nullptr, 2, msg),
NSM_SW_ERROR_NULL);
EXPECT_EQ(encode_get_supported_device_configs_resp(
0, NSM_SUCCESS, ERR_NULL, 0, 1, types.data(), 2, msg),
NSM_SW_ERROR_DATA);
auto resp = reinterpret_cast<nsm_get_supported_device_configs_resp *>(
msg->payload);
EXPECT_EQ(le16toh(resp->hdr.data_size), 0u);
}
TEST(mmioNegative, decode_get_supported_device_configs_resp)
{
std::vector<uint8_t> reply = configsReply({1, 2, 3}, 3);
auto response = reinterpret_cast<nsm_msg *>(reply.data());
uint8_t cc = NSM_ERROR;
uint16_t reasonCode = ERR_NULL;
uint32_t nextHandle = 0;
uint32_t totalCount = 0;
const std::vector<uint32_t> untouched(4, 0x5555);
std::vector<uint32_t> out = untouched;
uint16_t count = 0;
EXPECT_EQ(decode_get_supported_device_configs_resp(
nullptr, reply.size(), &cc, &reasonCode, &nextHandle,
&totalCount, out.data(), 4, &count),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_supported_device_configs_resp(
response, reply.size(), nullptr, &reasonCode, &nextHandle,
&totalCount, out.data(), 4, &count),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_supported_device_configs_resp(
response, reply.size(), &cc, nullptr, &nextHandle,
&totalCount, out.data(), 4, &count),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_supported_device_configs_resp(
response, reply.size(), &cc, &reasonCode, nullptr,
&totalCount, out.data(), 4, &count),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_supported_device_configs_resp(
response, reply.size(), &cc, &reasonCode, &nextHandle,
nullptr, out.data(), 4, &count),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_supported_device_configs_resp(
response, reply.size(), &cc, &reasonCode, &nextHandle,
&totalCount, out.data(), 4, nullptr),
NSM_SW_ERROR_NULL);
EXPECT_EQ(decode_get_supported_device_configs_resp(
response, reply.size(), &cc, &reasonCode, &nextHandle,
&totalCount, nullptr, 4, &count),
NSM_SW_ERROR_NULL);
for (size_t len = 0; len < reply.size(); ++len) {
EXPECT_NE(decode_get_supported_device_configs_resp(
response, len, &cc, &reasonCode, &nextHandle,
&totalCount, out.data(), 4, &count),
NSM_SW_SUCCESS);
}
EXPECT_EQ(decode_get_supported_device_configs_resp(
response, reply.size(), &cc, &reasonCode, &nextHandle,
&totalCount, out.data(), 2, &count),
NSM_SW_ERROR_LENGTH);
EXPECT_EQ(count, 3u);
auto resp = reinterpret_cast<nsm_get_supported_device_configs_resp *>(
response->payload);
resp->hdr.data_size = htole16(2 * sizeof(uint32_t) + 5);
EXPECT_EQ(decode_get_supported_device_configs_resp(
response, reply.size(), &cc, &reasonCode, &nextHandle,
&totalCount, out.data(), 4, &count),
NSM_SW_ERROR_LENGTH);
resp->hdr.data_size = htole16(sizeof(uint32_t));
EXPECT_EQ(decode_get_supported_device_configs_resp(
response, reply.size(), &cc, &reasonCode, &nextHandle,
&totalCount, out.data(), 4, &count),
NSM_SW_ERROR_LENGTH);
resp->hdr.data_size =
htole16(2 * sizeof(uint32_t) + 3 * sizeof(uint32_t));
resp->total_count = htole32(1);
EXPECT_EQ(decode_get_supported_device_configs_resp(
response, reply.size(), &cc, &reasonCode, &nextHandle,
&totalCount, out.data(), 4, &count),
NSM_SW_ERROR_DATA);
EXPECT_EQ(out, untouched);
}
TEST(mmioNegative, nsm_fpga_map_identity_by_platform)
{
EXPECT_EQ(nsm_fpga_map_identity_by_platform(nullptr), nullptr);
EXPECT_EQ(nsm_fpga_map_identity_by_platform(""), nullptr);
EXPECT_EQ(nsm_fpga_map_identity_by_platform("lp30"), nullptr);
EXPECT_EQ(nsm_fpga_map_identity_by_platform("LP30 "), nullptr);
EXPECT_EQ(nsm_fpga_map_identity_by_platform("LP3"), nullptr);
EXPECT_EQ(nsm_fpga_map_identity_by_platform("GB300"), nullptr);
}