Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ cc_library(
hdrs = [":gen_version_header"],
)

cc_library(
name = "libhoth_status",
hdrs = ["include/libhoth/status.h"],
strip_include_prefix = "include",
visibility = ["//visibility:public"],
)


genrule(
name = "gen_version_header",
outs = ["git_version.h"],
Expand Down
2 changes: 2 additions & 0 deletions examples/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ cc_test(
":htool_security_version",
"//examples/test:test_util",
"//protocol/test:libhoth_device_mock",
"//:libhoth_status",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
Expand Down Expand Up @@ -265,6 +266,7 @@ cc_binary(
"//transports:libhoth_spi",
"//transports:libhoth_usb",
"//transports:libhoth_usb_device",
"//:libhoth_status",
"@libusb",
] + select({
":dbus_backend": ["//transports:libhoth_dbus"],
Expand Down
4 changes: 3 additions & 1 deletion examples/htool.c
Original file line number Diff line number Diff line change
Expand Up @@ -769,11 +769,13 @@ static int command_hello(const struct htool_invocation* inv) {
}

uint32_t output = 0;
const int rv = libhoth_hello(dev, input, &output);
const libhoth_error rv = libhoth_hello(dev, input, &output);
if (rv) {
return rv;
}

printf("Rv: %ld\n", rv);

printf("output: 0x%08x\n", output);
return 0;
}
Expand Down
15 changes: 12 additions & 3 deletions examples/htool_provisioning_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,10 @@ TEST_F(HtoolProvisioningTest, GetProvisioningLogUnexpectedErrorFromDevice) {
.WillOnce(DoAll(CopyResp(&response, sizeof(header) + header.size),
Return(LIBHOTH_ERR_INTERFACE_NOT_FOUND)));

ASSERT_EQ(htool_get_provisioning_log(&inv), -1);
ASSERT_EQ(
htool_get_provisioning_log(&inv),
(int)LIBHOTH_ERR_CONSTRUCT(HOTH_CTX_CMD_EXEC, HOTH_HOST_SPACE_LIBHOTH,
HOTH_LIBHOTH_RECEIVE_ERROR));

// Verify output file is empty
FILE* fp = fopen(tmp_output_file.c_str(), "rb");
Expand Down Expand Up @@ -548,7 +551,10 @@ TEST_F(HtoolProvisioningTest, ValidateAndSignUnexpectedErrorFromDevice) {
.WillOnce(DoAll(CopyResp(signed_log_data.data(), signed_log_data.size()),
Return(LIBHOTH_ERR_INTERFACE_NOT_FOUND)));

ASSERT_EQ(htool_validate_and_sign(&inv), -1);
ASSERT_EQ(
htool_validate_and_sign(&inv),
(int)LIBHOTH_ERR_CONSTRUCT(HOTH_CTX_CMD_EXEC, HOTH_HOST_SPACE_LIBHOTH,
HOTH_LIBHOTH_RECEIVE_ERROR));

// Verify output file is empty
FILE* fp = fopen(tmp_output_file.c_str(), "rb");
Expand Down Expand Up @@ -712,7 +718,10 @@ TEST_F(HtoolProvisioningTest, ValidateAndSignTooLargeResponse) {
.WillOnce(DoAll(CopyResp(signed_log_data.data(), signed_log_data.size()),
Return(LIBHOTH_OK)));

ASSERT_EQ(htool_validate_and_sign(&inv), -1);
ASSERT_EQ(
htool_validate_and_sign(&inv),
(int)LIBHOTH_ERR_CONSTRUCT(HOTH_CTX_CMD_EXEC, HOTH_HOST_SPACE_LIBHOTH,
HOTH_LIBHOTH_RESPONSE_TOO_BIG));

// Verify output file size is 0
FILE* fp = fopen(tmp_output_file.c_str(), "rb");
Expand Down
24 changes: 17 additions & 7 deletions examples/htool_security_v2_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "examples/host_commands.h"
#include "examples/test/test_util.h"
#include "libhoth/status.h"
#include "protocol/test/libhoth_device_mock.h"

using ::testing::_;
Expand All @@ -21,10 +22,11 @@ using ::testing::SetArrayArgument;
struct libhoth_device* mock_dev = nullptr;
struct libhoth_device* htool_libhoth_device() { return mock_dev; }

int libhoth_hostcmd_exec(struct libhoth_device* dev, uint16_t command,
uint8_t version, const void* request,
size_t request_size, void* response,
size_t max_response_size, size_t* bytes_read) {
libhoth_error libhoth_hostcmd_exec(struct libhoth_device* dev, uint16_t command,
uint8_t version, const void* request,
size_t request_size, void* response,
size_t max_response_size,
size_t* bytes_read) {
LibHothDeviceMock* mock = (LibHothDeviceMock*)dev->user_ctx;
return mock->hostcmd_exec(dev, command, version, request, request_size,
response, max_response_size, bytes_read);
Expand Down Expand Up @@ -92,13 +94,18 @@ TEST_F(HtoolSecurityV2Test, ExecCmdHostCmdFailure) {
struct security_v2_buffer response_buffer = {
.data = response_storage, .size = sizeof(response_storage)};

EXPECT_CALL(mock_, hostcmd_exec(_, _, _, _, _, _, _, _)).WillOnce(Return(-1));
EXPECT_CALL(mock_, hostcmd_exec(_, _, _, _, _, _, _, _))
.WillOnce(Return(LIBHOTH_ERR_CONSTRUCT(HOTH_CTX_CMD_EXEC,
HOTH_HOST_SPACE_LIBHOTH,
HOTH_LIBHOTH_SEND_ERROR)));

int status =
htool_exec_security_v2_cmd(mock_dev, 1, 2, 3, &request_buffer, nullptr, 0,
&response_buffer, nullptr, 0);

ASSERT_EQ(status, -1);
ASSERT_EQ(status, (int)LIBHOTH_ERR_CONSTRUCT(HOTH_CTX_CMD_EXEC,
HOTH_HOST_SPACE_LIBHOTH,
HOTH_LIBHOTH_SEND_ERROR));
}

TEST_F(HtoolSecurityV2Test, SerializedCmdSuccess) {
Expand Down Expand Up @@ -167,7 +174,10 @@ TEST_F(HtoolSecurityV2Test, SerializedCmdExecFailure) {
struct security_v2_buffer response_buffer = {
.data = response_storage, .size = sizeof(response_storage)};

EXPECT_CALL(mock_, hostcmd_exec(_, _, _, _, _, _, _, _)).WillOnce(Return(-1));
EXPECT_CALL(mock_, hostcmd_exec(_, _, _, _, _, _, _, _))
.WillOnce(Return(LIBHOTH_ERR_CONSTRUCT(HOTH_CTX_CMD_EXEC,
HOTH_HOST_SPACE_LIBHOTH,
HOTH_LIBHOTH_SEND_ERROR)));

const struct security_v2_serialized_param* param_out1 = nullptr;
const struct security_v2_serialized_param** response_params[] = {&param_out1};
Expand Down
17 changes: 12 additions & 5 deletions examples/htool_target_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,32 +39,39 @@ int target_control_perform_action(
};

size_t response_length = 0;
int ret = libhoth_hostcmd_exec(
libhoth_error ret = libhoth_hostcmd_exec(
dev, HOTH_CMD_BOARD_SPECIFIC_BASE + HOTH_PRV_CMD_HOTH_TARGET_CONTROL,
/*version=*/0, &request, sizeof(request), response, sizeof(*response),
&response_length);

if (ret != 0) {
fprintf(stderr, "HOTH_TARGET_CONTROL error code: %d\n", ret);
fprintf(stderr, "HOTH_TARGET_CONTROL error code: %ld\n", ret);
switch (ret) {
case (HTOOL_ERROR_HOST_COMMAND_START + HOTH_RES_INVALID_COMMAND):
case (LIBHOTH_ERR_CONSTRUCT(HOTH_CTX_CMD_EXEC, HOTH_HOST_SPACE_FW,
HOTH_RES_FW_INVALID_COMMAND)):
fprintf(stderr,
"Command not supported, or requested action is forbidden on "
"function. Please confirm if the RoT FW version supports this "
"command, and requested action is allowed on the function\n");
break;
case (HTOOL_ERROR_HOST_COMMAND_START + HOTH_RES_INVALID_PARAM):
case (LIBHOTH_ERR_CONSTRUCT(HOTH_CTX_CMD_EXEC, HOTH_HOST_SPACE_FW,
HOTH_RES_FW_INVALID_PARAM)):
fprintf(stderr,
"Invalid function or action. Please confirm if the RoT "
"firmware version supports the given function, and action on "
"that function is correct\n");
break;
case (HTOOL_ERROR_HOST_COMMAND_START + HOTH_RES_ACCESS_DENIED):
case (LIBHOTH_ERR_CONSTRUCT(HOTH_CTX_CMD_EXEC, HOTH_HOST_SPACE_FW,
HOTH_RES_FW_ACCESS_DENIED)):
fprintf(stderr,
"Not authorized to perform requested action on function. "
"Please use `authz_host_command` commands to authorize RoT to "
"perform requested action on function\n");
break;
default:
fprintf(stderr,
"Unexpected error. Please check the transport layer and "
"RoT firmware are working correctly\n");
}
return -1;
}
Expand Down
2 changes: 2 additions & 0 deletions examples/htool_target_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#define LIBHOTH_EXAMPLES_HTOOL_TARGET_CONTROL_H_

#include "host_commands.h"
#include "libhoth/status.h"

#ifdef __cplusplus
extern "C" {
#endif
Expand Down
2 changes: 1 addition & 1 deletion examples/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ git_version_h = vcs_tag(
replace_string: '@GIT_COMMIT@',
)

incdir = include_directories('..')
incdir = libhoth_include_dirs
link_with = [libhoth.get_static_lib()]
c_args = []

Expand Down
102 changes: 102 additions & 0 deletions include/libhoth/status.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@

// Copyright 2026 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.

#ifndef LIBHOTH_INCLUDE_LIBHOTH_STATUS_H_
#define LIBHOTH_INCLUDE_LIBHOTH_STATUS_H_

#include <stdint.h>

// Represents success
#define HOTH_SUCCESS 0x0ULL

// Typedef for the error code
typedef uint64_t libhoth_error;

#define LIBHOTH_ERR_CONSTRUCT(ctx, space, code) \
((((uint64_t)(ctx) & 0xFFFFFFFFULL) << 32) | \
(((uint64_t)(space) & 0xFFFFULL) << 16) | ((uint64_t)(code) & 0xFFFFULL))

// hoth_context_id: High 32 bits of the error code.
// Uniquely identifies the libhoth operation or subsystem.
enum hoth_context_id {
HOTH_CTX_NONE = 0,

// Initialization / General
HOTH_CTX_INIT = 1,

// Transport layers
HOTH_CTX_USB = 10,
HOTH_CTX_SPI = 20,

// Command Execution
HOTH_CTX_CMD_EXEC = 30,
};

// hoth_host_space: Top 16 bits of the low 32-bit Base Error Code.
// Indicates the domain of host-side errors.
enum hoth_host_space {
HOTH_HOST_SPACE_FW = 0x0000, // Firmware errors directly
HOTH_HOST_SPACE_POSIX = 0x0001, // errno values
HOTH_HOST_SPACE_LIBUSB = 0x0002, // libusb_error values
HOTH_HOST_SPACE_HTOOL = 0x0003, // htool error codes
HOTH_HOST_SPACE_LIBHOTH = 0x0005, // libhoth internal errors
};

#ifndef __packed
#define __packed __attribute__((packed))
#endif

// Hoth error code: Low 16 bits of the 32-bit Base Error Code
// Firmware Error
enum hoth_fw_error_status {
HOTH_RES_FW_SUCCESS = 0,
HOTH_RES_FW_INVALID_COMMAND = 1,
HOTH_RES_FW_ERROR = 2,
HOTH_RES_FW_INVALID_PARAM = 3,
HOTH_RES_FW_ACCESS_DENIED = 4,
HOTH_RES_FW_INVALID_RESPONSE = 5,
HOTH_RES_FW_INVALID_VERSION = 6,
HOTH_RES_FW_INVALID_CHECKSUM = 7,
HOTH_RES_FW_IN_PROGRESS = 8,
HOTH_RES_FW_UNAVAILABLE = 9,
HOTH_RES_FW_TIMEOUT = 10,
HOTH_RES_FW_OVERFLOW = 11,
HOTH_RES_FW_INVALID_HEADER = 12,
HOTH_RES_FW_REQUEST_TRUNCATED = 13,
HOTH_RES_FW_RESPONSE_TOO_BIG = 14,
HOTH_RES_FW_BUS_ERROR = 15,
HOTH_RES_FW_BUSY = 16,
HOTH_RES_FW_INVALID_HEADER_VERSION = 17,
HOTH_RES_FW_INVALID_HEADER_CRC = 18,
HOTH_RES_FW_INVALID_DATA_CRC = 19,
HOTH_RES_FW_DUP_UNAVAILABLE = 20,
HOTH_RES_FW_MAX = UINT16_MAX
} __packed;

// Hoth error code: Low 16 bits of the 32-bit Base Error Code
// Libhoth Error
enum hoth_libhoth_error_status {
HOTH_LIBHOTH_SUCCESS = 0,
HOTH_LIBHOTH_ERROR = 1,
HOTH_LIBHOTH_REQUEST_TOO_BIG = 2,
HOTH_LIBHOTH_EC_ERROR = 3,
HOTH_LIBHOTH_SEND_ERROR = 4,
HOTH_LIBHOTH_RECEIVE_ERROR = 5,
HOTH_LIBHOTH_VALIDATE_ERROR = 6,
HOTH_LIBHOTH_RESPONSE_TOO_BIG = 7,
HOTH_LIBHOTH_MAX = UINT16_MAX
} __packed;

#endif // LIBHOTH_INCLUDE_LIBHOTH_STATUS_H_
4 changes: 4 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
project('libhoth', 'c', 'cpp', license: 'Apache-2.0', version: '0.0.0')

install_headers('include/libhoth/status.h', subdir: 'libhoth')

libhoth_include_dirs = include_directories('include', '.')

header_subdirs = ['libhoth']
libhoth_objs = []
libhoth_deps = []
Expand Down
3 changes: 3 additions & 0 deletions protocol/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ cc_library(
srcs = ["host_cmd.c"],
hdrs = ["host_cmd.h"],
deps = [
"//:libhoth_status",
"//transports:libhoth_device",
],
)
Expand All @@ -17,6 +18,7 @@ cc_test(
srcs = ["host_cmd_test.cc"],
deps = [
":host_cmd",
"//:libhoth_status",
"//protocol/test:libhoth_device_mock",
"//transports:libhoth_device",
"@googletest//:gtest",
Expand Down Expand Up @@ -390,6 +392,7 @@ cc_library(
hdrs = ["hello.h"],
deps = [
":host_cmd",
"//:libhoth_status",
"//transports:libhoth_device",
],
)
Expand Down
Loading
Loading