Refactor logic around unsupported command
Check if supported before querying for auth record and keyrotation
Do not log when unsupported
Tested: gpaste/4541942956032000
Google-Bug-Id: 435699868
Google-Bug-Id: 435214999
Change-Id: Iab5703ef4c8b1b9fb85aa8d7683411d14eecb75b
Signed-off-by: Christian Kungler <ckungler@google.com>
diff --git a/ec_util.cpp b/ec_util.cpp
index ccd9596..416dace 100644
--- a/ec_util.cpp
+++ b/ec_util.cpp
@@ -14,6 +14,7 @@
#include "ec_util.hpp"
+#include <cstdint>
#include <span>
#include <stdplus/print.hpp>
#include <stdplus/raw.hpp>
@@ -47,46 +48,43 @@
} // namespace
-class EcException {
- public:
- explicit EcException(uint16_t result) : result(result) {}
- uint16_t get_result() const { return result; }
-
- private:
- uint16_t result;
-};
-
-[[nodiscard]] std::span<const uint8_t> EcUtilImpl::getResponseBody(
- std::vector<uint8_t>& response) {
- std::span<const uint8_t> output = response;
- auto& rsp = stdplus::raw::extractRef<RspHeader>(output);
+[[nodiscard]] std::vector<uint8_t> EcUtilImpl::sendCommand(
+ uint16_t command, uint8_t* request_ptr, size_t request_size) const {
+ std::vector<uint8_t> response_bytes =
+ hostCmd->sendCommand(command, kVersionZero, request_ptr, request_size);
+ std::span<uint8_t> response = response_bytes;
+ auto& rsp = stdplus::raw::extractRef<RspHeader>(response);
if (rsp.result != EC_RES_SUCCESS) {
- throw EcException(rsp.result);
+ throw CommandRunException(command, rsp.result);
}
+ return {response.begin(), response.end()};
+}
- return output;
+bool EcUtilImpl::isHostCommandSupported(uint16_t cmd) const {
+ ec_request_is_host_command_supported req = {.command = cmd};
+
+ std::vector<uint8_t> response_body = sendCommand(
+ EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_IS_HOST_COMMAND_SUPPORTED,
+ reinterpret_cast<uint8_t*>(&req), sizeof(req));
+
+ ec_response_is_host_command_supported response_struct =
+ stdplus::raw::copyFrom<ec_response_is_host_command_supported>(
+ response_body);
+
+ return response_struct.is_allowed != 0;
}
ec_response_statistics EcUtilImpl::getHothStatistics() const {
- std::vector<uint8_t> response = hostCmd->sendCommand(
- EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_GET_STATISTICS, kVersionZero,
- /*request=*/nullptr, /*requestSize=*/0);
- std::span<const uint8_t> response_body;
- try {
- response_body = getResponseBody(response);
- } catch (const EcException& ec_exception) {
- stdplus::print(stderr, "{} received a bad response from Hoth {:#x}\n",
- __func__, static_cast<uint8_t>(ec_exception.get_result()));
- throw ResponseFailure();
- }
+ std::vector<uint8_t> response_body =
+ sendCommand(EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_GET_STATISTICS,
+ /*request_ptr=*/nullptr, /*request_size=*/0);
return stdplus::raw::copyFrom<ec_response_statistics>(response_body);
}
ec_response_chip_info EcUtilImpl::getHothChipInfo() const {
- std::vector<uint8_t> response = hostCmd->sendCommand(
- EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_CHIP_INFO, kVersionZero,
- /*request=*/nullptr, /*requestSize=*/0);
- std::span<const uint8_t> response_body = getResponseBody(response);
+ std::vector<uint8_t> response_body =
+ sendCommand(EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_CHIP_INFO,
+ /*request_ptr=*/nullptr, /*request_size=*/0);
return stdplus::raw::copyFrom<ec_response_chip_info>(response_body);
}
@@ -111,21 +109,11 @@
.index = i,
};
- std::vector<uint8_t> response = hostCmd->sendCommand(
+ std::vector<uint8_t> response_body = sendCommand(
EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
- kVersionZero, &req, sizeof(req));
- std::span<const uint8_t> response_body;
- try {
- response_body = getResponseBody(response);
- } catch (const EcException& ec_exception) {
- stdplus::print(stderr,
- "{} received a bad response "
- "from Hoth {:#x}\n",
- __func__, static_cast<uint8_t>(ec_exception.get_result()));
- throw ResponseFailure();
- }
+ reinterpret_cast<uint8_t*>(&req), sizeof(req));
if (response_body.size() != chunk_size) {
- stdplus::print(stderr, "Bad response length %d (expected %d)\n",
+ stdplus::print(stderr, "Bad response length {} (expected {})\n",
response_body.size(), chunk_size);
throw ResponseFailure();
}
@@ -150,22 +138,12 @@
.index = 0,
};
- std::vector<uint8_t> response = hostCmd->sendCommand(
+ std::vector<uint8_t> response_body = sendCommand(
EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
- kVersionZero, &req, sizeof(req));
- std::span<const uint8_t> response_body;
- try {
- response_body = getResponseBody(response);
- } catch (const EcException& ec_exception) {
- stdplus::print(stderr,
- "{} received a bad response "
- "from Hoth {:#x}\n",
- __func__, static_cast<uint8_t>(ec_exception.get_result()));
- throw ResponseFailure();
- }
+ reinterpret_cast<uint8_t*>(&req), sizeof(req));
const size_t chunk_size = HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE;
if (response_body.size() != chunk_size) {
- stdplus::print(stderr, "Bad response length %d (expected %d)\n",
+ stdplus::print(stderr, "Bad response length {} (expected {})\n",
response_body.size(), chunk_size);
throw ResponseFailure();
}
@@ -174,30 +152,30 @@
}
ec_authz_record_get_response EcUtilImpl::getHothAuthRecord() const {
+ const uint16_t kGetAuthRecordCmd =
+ EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_GET_AUTHZ_RECORD;
+
+ if (!isHostCommandSupported(kGetAuthRecordCmd)) {
+ throw CommandNotSupportedException(kGetAuthRecordCmd);
+ }
+
ec_authz_record_get_request request = {
.index = 0,
.reserved = {},
};
- std::vector<uint8_t> response = hostCmd->sendCommand(
- EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_GET_AUTHZ_RECORD,
- kVersionZero, &request, sizeof(request));
- std::span<const uint8_t> response_body;
- try {
- response_body = getResponseBody(response);
- } catch (const EcException& ec_exception) {
- if (ec_exception.get_result() == EC_RES_UNAVAILABLE) {
- // Unsupported, probably a Haven, do not log.
- } else {
- stdplus::print(stderr, "{} received a bad response from Hoth {:#x}\n",
- __func__, static_cast<uint8_t>(ec_exception.get_result()));
- }
- throw ResponseFailure();
- }
+ std::vector<uint8_t> response_body = sendCommand(
+ kGetAuthRecordCmd, reinterpret_cast<uint8_t*>(&request), sizeof(request));
return stdplus::raw::copyFrom<ec_authz_record_get_response>(response_body);
}
ec_response_key_rotation_status EcUtilImpl::getHothKeyRotationStatus() const {
+ const uint16_t keyRotationCommand =
+ EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_KEY_ROTATION_OP;
+ if (!isHostCommandSupported(keyRotationCommand)) {
+ throw CommandNotSupportedException(keyRotationCommand);
+ }
+
ec_request_key_rotation_record request = {
.operation = KEY_ROTATION_RECORD_GET_STATUS,
.packet_offset = 0,
@@ -205,25 +183,9 @@
.reserved = 0,
};
- std::vector<uint8_t> response = hostCmd->sendCommand(
- EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_KEY_ROTATION_OP,
- kVersionZero, &request, sizeof(request));
-
- std::span<const uint8_t> response_body;
- try {
- response_body = getResponseBody(response);
- } catch (const EcException& ec_exception) {
- if (ec_exception.get_result() == EC_RES_INVALID_COMMAND) {
- // TODO: b/434689086 - Do not log error to prevent spam whilst KeyRotation
- // support is being deployed.
- } else {
- stdplus::print(stderr,
- "{} received a bad response from "
- "Hoth {:#x}\n",
- __func__, static_cast<uint8_t>(ec_exception.get_result()));
- }
- throw ResponseFailure();
- }
+ std::vector<uint8_t> response_body =
+ sendCommand(keyRotationCommand, reinterpret_cast<uint8_t*>(&request),
+ sizeof(request));
return stdplus::raw::copyFrom<ec_response_key_rotation_status>(response_body);
}
diff --git a/ec_util.hpp b/ec_util.hpp
index 1a07fed..5b8f25d 100644
--- a/ec_util.hpp
+++ b/ec_util.hpp
@@ -14,6 +14,9 @@
#pragma once
+#include <cstddef>
+#include <cstdint>
+
#include "ec_util_interface.hpp"
#include "google3/host_commands.h"
#include "host_command.hpp"
@@ -22,10 +25,49 @@
namespace hoth {
namespace internal {
+class CommandNotSupportedException : public std::exception {
+ public:
+ explicit CommandNotSupportedException(uint16_t command) : command(command) {
+ std::stringstream ss;
+ ss << "EC Command 0x" << std::hex << command << " not supported";
+ this->message = ss.str();
+ }
+ const char* what() const noexcept override { return message.c_str(); }
+
+ uint16_t get_command() const { return command; }
+
+ private:
+ uint16_t command;
+ std::string message;
+};
+
+class CommandRunException : public std::exception {
+ public:
+ explicit CommandRunException(uint16_t command, uint16_t result)
+ : command(command), result(result) {
+ std::stringstream ss;
+ ss << "EC Command 0x" << std::hex << command << " returned error 0x"
+ << std::hex << result;
+ this->message = ss.str();
+ }
+ const char* what() const noexcept override { return message.c_str(); }
+
+ uint16_t get_command() const { return command; }
+ uint16_t get_result() const { return result; }
+
+ private:
+ uint16_t command;
+ uint16_t result;
+ std::string message;
+};
+
class EcUtilImpl : public EcUtil {
public:
explicit EcUtilImpl(HostCommand* hostCmd) : hostCmd(hostCmd) {}
+ // Check wether a command is supported and authorized.
+ bool isHostCommandSupported(uint16_t cmd) const override;
+
// Get the Hoth statistics by issuing an EC_PRV_CMD_HOTH_GET_STATISTICS
// Command.
ec_response_statistics getHothStatistics() const override;
@@ -50,8 +92,9 @@
ec_response_key_rotation_status getHothKeyRotationStatus() const override;
private:
- [[nodiscard]] static std::span<const uint8_t> getResponseBody(
- std::vector<uint8_t>& response);
+ [[nodiscard]] std::vector<uint8_t> sendCommand(uint16_t command,
+ uint8_t* request_ptr,
+ size_t request_size) const;
/** @brief Connection to Hoth for sending and receiving host commands */
HostCommand* hostCmd;
diff --git a/ec_util_interface.hpp b/ec_util_interface.hpp
index a26af17..cb12818 100644
--- a/ec_util_interface.hpp
+++ b/ec_util_interface.hpp
@@ -32,6 +32,9 @@
virtual ~EcUtil() = default;
+ // Check wether a command is supported (and authorized).
+ virtual bool isHostCommandSupported(uint16_t cmd) const = 0;
+
// Get the Hoth statistics by issuing an EC_PRV_CMD_HOTH_GET_STATISTICS
// Command.
virtual ec_response_statistics getHothStatistics() const = 0;
diff --git a/google3/host_commands.h b/google3/host_commands.h
index 5b5af87..4c0cbc2 100644
--- a/google3/host_commands.h
+++ b/google3/host_commands.h
@@ -506,6 +506,18 @@
little_uint32_t padding[3];
};
+/* Reports on whether a command is allowed to run given the current host command
+ * filtering that the firmware is using. In order for this command to return
+ * true, the command must exist and must have is_command_allowed() return true.
+ */
+#define EC_PRV_CMD_HOTH_IS_HOST_COMMAND_SUPPORTED 0x0011
+struct ec_request_is_host_command_supported {
+ little_uint16_t command;
+};
+struct ec_response_is_host_command_supported {
+ uint8_t is_allowed;
+};
+
/* Reset the target device. */
#define EC_PRV_CMD_HOTH_RESET_TARGET 0x0012
diff --git a/hoth_state.cpp b/hoth_state.cpp
index 2e81b4e..ff6b3ef 100644
--- a/hoth_state.cpp
+++ b/hoth_state.cpp
@@ -24,7 +24,7 @@
#include <stdplus/raw.hpp>
#include <xyz/openbmc_project/Control/Hoth/State/error.hpp>
-#include "ec_util_interface.hpp"
+#include "ec_util.hpp"
#include "google3/host_commands.h"
namespace google {
@@ -150,9 +150,13 @@
HothStateObject::authRecordCapabilities(
auth_record_resp.record.capabilities);
}
+ } catch (const internal::CommandNotSupportedException &e) {
+ // Do not log if unsupported
+ HothStateObject::hasValidAuthRecord(false);
} catch (const std::exception &e) {
stdplus::print(stderr, "Fetching Hoth auth record had an exception: {}\n",
e.what());
+ HothStateObject::hasValidAuthRecord(false);
}
try {
@@ -169,9 +173,15 @@
key_rotation_status.validation_key_data);
HothStateObject::keyRotationValidationHashData(
key_rotation_status.validation_hash_data);
+ } catch (const internal::CommandNotSupportedException &e) {
+ // Do not log if unsupported
+ HothStateObject::keyRotationValidationMethod(
+ KEY_ROTATION_VALIDATION_METHOD_GET_ERROR);
} catch (const std::exception &e) {
HothStateObject::keyRotationValidationMethod(
KEY_ROTATION_VALIDATION_METHOD_GET_ERROR);
+ stdplus::print(stderr, "Fetching Hoth key rotation had an exception: {}\n",
+ e.what());
}
}
diff --git a/test/ec_util_mock.hpp b/test/ec_util_mock.hpp
index 9b0daa6..a756057 100644
--- a/test/ec_util_mock.hpp
+++ b/test/ec_util_mock.hpp
@@ -14,31 +14,30 @@
#pragma once
-#include "google3/host_commands.h"
-
-#include "ec_util.hpp"
-
#include <gmock/gmock.h>
-namespace google
-{
-namespace hoth
-{
-namespace internal
-{
+#include <cstdint>
-class EcUtilMock : public EcUtil
-{
- public:
- MOCK_CONST_METHOD0(getHothStatistics, ec_response_statistics());
- MOCK_CONST_METHOD0(getHothChipInfo, ec_response_chip_info());
- MOCK_CONST_METHOD0(checkHothPersistentPanicInfo, bool());
- MOCK_CONST_METHOD0(getHothAuthRecord, ec_authz_record_get_response());
- MOCK_CONST_METHOD0(getHothKeyRotationStatus, ec_response_key_rotation_status());
+#include "ec_util.hpp"
+#include "google3/host_commands.h"
+
+namespace google {
+namespace hoth {
+namespace internal {
+
+class EcUtilMock : public EcUtil {
+ public:
+ MOCK_CONST_METHOD0(getHothStatistics, ec_response_statistics());
+ MOCK_CONST_METHOD0(getHothChipInfo, ec_response_chip_info());
+ MOCK_CONST_METHOD0(checkHothPersistentPanicInfo, bool());
+ MOCK_CONST_METHOD0(getHothAuthRecord, ec_authz_record_get_response());
+ MOCK_CONST_METHOD0(getHothKeyRotationStatus,
+ ec_response_key_rotation_status());
+ MOCK_CONST_METHOD1(isHostCommandSupported, bool(uint16_t));
};
-} // namespace internal
+} // namespace internal
-} // namespace hoth
+} // namespace hoth
-} // namespace google
+} // namespace google
diff --git a/test/ec_util_unittest.cpp b/test/ec_util_unittest.cpp
index d9ad71f..575b785 100644
--- a/test/ec_util_unittest.cpp
+++ b/test/ec_util_unittest.cpp
@@ -12,17 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "google3/host_commands.h"
-
#include "ec_util.hpp"
-#include "host_command_mock.hpp"
-#include "payload_update.hpp"
-
-#include <xyz/openbmc_project/Control/Hoth/error.hpp>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <xyz/openbmc_project/Control/Hoth/error.hpp>
+
+#include "google3/host_commands.h"
+#include "host_command_mock.hpp"
+#include "payload_update.hpp"
+
// NOLINTNEXTLINE(google-build-using-namespace)
using namespace std::literals;
using sdbusplus::error::xyz::openbmc_project::control::hoth::ResponseFailure;
@@ -30,76 +30,63 @@
using ::testing::_;
using ::testing::Return;
-namespace google
-{
-namespace hoth
-{
-namespace internal
-{
-namespace
-{
+namespace google {
+namespace hoth {
+namespace internal {
+namespace {
auto const goodResponseStr = "\x03\xfd\x00\x00\x00\x00\x00\x00"s;
-class EcUtilTest : public ::testing::Test
-{
- protected:
- EcUtilTest() : ecUtil(&hostCmd)
- {}
+class EcUtilTest : public ::testing::Test {
+ protected:
+ EcUtilTest() : ecUtil(&hostCmd) {}
- // Host Command interface handle
- internal::HostCommandMock hostCmd;
+ // Host Command interface handle
+ internal::HostCommandMock hostCmd;
- // EcUtil interface handle
- internal::EcUtilImpl ecUtil;
+ // EcUtil interface handle
+ internal::EcUtilImpl ecUtil;
};
-MATCHER_P(dummyMatches, req, "")
-{
- const auto *const arg_req = static_cast<const uint8_t *>(arg);
+MATCHER_P(dummyMatches, req, "") {
+ const auto* const arg_req = static_cast<const uint8_t*>(arg);
return *arg_req == req;
}
-class EcUtilStatisticTest : public EcUtilTest
-{};
+class EcUtilStatisticTest : public EcUtilTest {};
-TEST_F(EcUtilStatisticTest, sendCommandReturnsBadResultFails)
-{
- std::vector<uint8_t> rsp(goodResponseStr.begin(), goodResponseStr.end());
- // Change the RspHeader.result to something other than EC_RES_SUCCESS
- rsp[2] = internal::EC_RES_ERROR;
+TEST_F(EcUtilStatisticTest, sendCommandReturnsBadResultFails) {
+ std::vector<uint8_t> rsp(goodResponseStr.begin(), goodResponseStr.end());
+ // Change the RspHeader.result to something other than EC_RES_SUCCESS
+ rsp[2] = internal::EC_RES_ERROR;
- EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
- EC_PRV_CMD_HOTH_GET_STATISTICS,
- ecUtil.kVersionZero, nullptr, 0))
- .WillOnce(Return(rsp));
+ EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
+ EC_PRV_CMD_HOTH_GET_STATISTICS,
+ ecUtil.kVersionZero, nullptr, 0))
+ .WillOnce(Return(rsp));
- EXPECT_THROW(ecUtil.getHothStatistics(), ResponseFailure);
+ EXPECT_THROW(ecUtil.getHothStatistics(), CommandRunException);
}
-TEST_F(EcUtilStatisticTest, sendCommandReturnsGoodResponseSuccess)
-{
- std::vector<uint8_t> rsp(goodResponseStr.begin(), goodResponseStr.end());
- for (uint16_t i = 0; i < 256; i++)
- {
- rsp.push_back(0);
- }
+TEST_F(EcUtilStatisticTest, sendCommandReturnsGoodResponseSuccess) {
+ std::vector<uint8_t> rsp(goodResponseStr.begin(), goodResponseStr.end());
+ for (uint16_t i = 0; i < 256; i++) {
+ rsp.push_back(0);
+ }
- EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
- EC_PRV_CMD_HOTH_GET_STATISTICS,
- ecUtil.kVersionZero, nullptr, 0))
- .WillOnce(Return(rsp));
+ EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
+ EC_PRV_CMD_HOTH_GET_STATISTICS,
+ ecUtil.kVersionZero, nullptr, 0))
+ .WillOnce(Return(rsp));
- EXPECT_NO_THROW(ecUtil.getHothStatistics());
+ EXPECT_NO_THROW(ecUtil.getHothStatistics());
}
-class EcUtilPersistentPanicTest : public EcUtilTest
-{};
+class EcUtilPersistentPanicTest : public EcUtilTest {};
-struct panic_host_command_response
-{
- RspHeader hdr;
- uint8_t body[HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE];
+struct panic_host_command_response {
+ RspHeader hdr;
+ uint8_t body[HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE];
};
// Template of a persistent panic response, with the correct data_len, checksum
@@ -126,91 +113,112 @@
},
};
-TEST_F(EcUtilPersistentPanicTest, incorrectResponseSizeThrows)
-{
- std::vector<uint8_t> rsp_buf(sizeof(kPanicResponseTemplate), 0);
- auto* rsp = reinterpret_cast<panic_host_command_response*>(rsp_buf.data());
+TEST_F(EcUtilPersistentPanicTest, incorrectResponseSizeThrows) {
+ std::vector<uint8_t> rsp_buf(sizeof(kPanicResponseTemplate), 0);
+ auto* rsp = reinterpret_cast<panic_host_command_response*>(rsp_buf.data());
+ *rsp = kPanicResponseTemplate;
+ rsp->hdr.data_len -= 1;
+ rsp->hdr.checksum += 1;
+ rsp_buf.resize(sizeof(kPanicResponseTemplate) - 1);
+ EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
+ EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
+ ecUtil.kVersionZero, _,
+ sizeof(ec_request_persistent_panic_info)))
+ .Times(2)
+ .WillRepeatedly(Return(rsp_buf));
+ EXPECT_THROW(ecUtil.checkHothPersistentPanicInfo(), ResponseFailure);
+ EXPECT_THROW(ecUtil.getHothPersistentPanicInfo(), ResponseFailure);
+}
+
+TEST_F(EcUtilPersistentPanicTest, incorrectPanicMagicReturnsNullopt) {
+ std::vector<uint8_t> rsp_buf(sizeof(kPanicResponseTemplate), 0);
+ auto* rsp = reinterpret_cast<panic_host_command_response*>(rsp_buf.data());
+ *rsp = kPanicResponseTemplate;
+ rsp->body[143] -= 1;
+ rsp->hdr.checksum += 1;
+ EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
+ EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
+ ecUtil.kVersionZero, _,
+ sizeof(ec_request_persistent_panic_info)))
+ .Times(2)
+ .WillRepeatedly(Return(rsp_buf));
+ EXPECT_FALSE(ecUtil.checkHothPersistentPanicInfo());
+ EXPECT_FALSE(ecUtil.getHothPersistentPanicInfo());
+}
+
+TEST_F(EcUtilPersistentPanicTest, correctHostCommandReturnsFullPanicRecord) {
+ std::vector<uint8_t> rsp_bufs[12];
+ for (int i = 0; i < 12; ++i) {
+ rsp_bufs[i].resize(sizeof(panic_host_command_response));
+ auto* rsp =
+ reinterpret_cast<panic_host_command_response*>(rsp_bufs[i].data());
*rsp = kPanicResponseTemplate;
- rsp->hdr.data_len -= 1;
- rsp->hdr.checksum += 1;
- rsp_buf.resize(sizeof(kPanicResponseTemplate) - 1);
- EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
- EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
- ecUtil.kVersionZero, _,
- sizeof(ec_request_persistent_panic_info)))
- .Times(2)
- .WillRepeatedly(Return(rsp_buf));
- EXPECT_THROW(ecUtil.checkHothPersistentPanicInfo(), ResponseFailure);
- EXPECT_THROW(ecUtil.getHothPersistentPanicInfo(), ResponseFailure);
+ // Tweak the response a little bit to make each chunk slightly
+ // different.
+ rsp->body[0] += i;
+ rsp->body[HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE - 1] -= i;
+ }
+ EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
+ EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
+ ecUtil.kVersionZero, _,
+ sizeof(ec_request_persistent_panic_info)))
+ .Times(13)
+ .WillOnce(Return(rsp_bufs[0]))
+ .WillOnce(Return(rsp_bufs[0]))
+ .WillOnce(Return(rsp_bufs[1]))
+ .WillOnce(Return(rsp_bufs[2]))
+ .WillOnce(Return(rsp_bufs[3]))
+ .WillOnce(Return(rsp_bufs[4]))
+ .WillOnce(Return(rsp_bufs[5]))
+ .WillOnce(Return(rsp_bufs[6]))
+ .WillOnce(Return(rsp_bufs[7]))
+ .WillOnce(Return(rsp_bufs[8]))
+ .WillOnce(Return(rsp_bufs[9]))
+ .WillOnce(Return(rsp_bufs[10]))
+ .WillOnce(Return(rsp_bufs[11]));
+
+ EXPECT_TRUE(ecUtil.checkHothPersistentPanicInfo());
+
+ auto panic = ecUtil.getHothPersistentPanicInfo();
+ std::span<uint8_t> panic_buf(reinterpret_cast<uint8_t*>(&panic.value()),
+ sizeof(panic.value()));
+ for (uint8_t i = 0; i < 12; ++i) {
+ size_t chunk_start =
+ static_cast<uint32_t>(i) * HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE;
+ EXPECT_EQ(panic_buf[chunk_start], i);
+ EXPECT_EQ(
+ panic_buf[chunk_start + HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE - 1],
+ static_cast<uint8_t>(-i));
+ }
}
-TEST_F(EcUtilPersistentPanicTest, incorrectPanicMagicReturnsNullopt)
-{
- std::vector<uint8_t> rsp_buf(sizeof(kPanicResponseTemplate), 0);
- auto* rsp = reinterpret_cast<panic_host_command_response*>(rsp_buf.data());
- *rsp = kPanicResponseTemplate;
- rsp->body[143] -= 1;
- rsp->hdr.checksum += 1;
- EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
- EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
- ecUtil.kVersionZero, _,
- sizeof(ec_request_persistent_panic_info)))
- .Times(2)
- .WillRepeatedly(Return(rsp_buf));
- EXPECT_FALSE(ecUtil.checkHothPersistentPanicInfo());
- EXPECT_FALSE(ecUtil.getHothPersistentPanicInfo());
+class EcUtilAuthRecordTest : public EcUtilTest {};
+
+TEST_F(EcUtilAuthRecordTest, authRecordNotSupported) {
+ std::vector<uint8_t> rsp(goodResponseStr.begin(), goodResponseStr.end());
+ rsp.push_back(0);
+ EXPECT_CALL(hostCmd,
+ sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
+ EC_PRV_CMD_HOTH_IS_HOST_COMMAND_SUPPORTED,
+ _, _, _))
+ .WillOnce(Return(rsp));
+ EXPECT_THROW(ecUtil.getHothAuthRecord(), CommandNotSupportedException);
}
-TEST_F(EcUtilPersistentPanicTest, correctHostCommandReturnsFullPanicRecord)
-{
- std::vector<uint8_t> rsp_bufs[12];
- for (int i = 0; i < 12; ++i)
- {
- rsp_bufs[i].resize(sizeof(panic_host_command_response));
- auto* rsp =
- reinterpret_cast<panic_host_command_response*>(rsp_bufs[i].data());
- *rsp = kPanicResponseTemplate;
- // Tweak the response a little bit to make each chunk slightly
- // different.
- rsp->body[0] += i;
- rsp->body[HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE - 1] -= i;
- }
- EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
- EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
- ecUtil.kVersionZero, _,
- sizeof(ec_request_persistent_panic_info)))
- .Times(13)
- .WillOnce(Return(rsp_bufs[0]))
- .WillOnce(Return(rsp_bufs[0]))
- .WillOnce(Return(rsp_bufs[1]))
- .WillOnce(Return(rsp_bufs[2]))
- .WillOnce(Return(rsp_bufs[3]))
- .WillOnce(Return(rsp_bufs[4]))
- .WillOnce(Return(rsp_bufs[5]))
- .WillOnce(Return(rsp_bufs[6]))
- .WillOnce(Return(rsp_bufs[7]))
- .WillOnce(Return(rsp_bufs[8]))
- .WillOnce(Return(rsp_bufs[9]))
- .WillOnce(Return(rsp_bufs[10]))
- .WillOnce(Return(rsp_bufs[11]));
+class EcUtilKeyRotationTest : public EcUtilTest {};
- EXPECT_TRUE(ecUtil.checkHothPersistentPanicInfo());
-
- auto panic = ecUtil.getHothPersistentPanicInfo();
- std::span<uint8_t> panic_buf(reinterpret_cast<uint8_t*>(&panic.value()),
- sizeof(panic.value()));
- for (uint8_t i = 0; i < 12; ++i)
- {
- size_t chunk_start =
- static_cast<uint32_t>(i) * HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE;
- EXPECT_EQ(panic_buf[chunk_start], i);
- EXPECT_EQ(
- panic_buf[chunk_start + HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE - 1],
- static_cast<uint8_t>(-i));
- }
+TEST_F(EcUtilKeyRotationTest, authRecordNotSupported) {
+ std::vector<uint8_t> rsp(goodResponseStr.begin(), goodResponseStr.end());
+ rsp.push_back(0);
+ EXPECT_CALL(hostCmd,
+ sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
+ EC_PRV_CMD_HOTH_IS_HOST_COMMAND_SUPPORTED,
+ _, _, _))
+ .WillOnce(Return(rsp));
+ EXPECT_THROW(ecUtil.getHothKeyRotationStatus(), CommandNotSupportedException);
}
-} // namespace
-} // namespace internal
-} // namespace hoth
-} // namespace google
+} // namespace
+} // namespace internal
+} // namespace hoth
+} // namespace google