From de0a88dad52762e7a085711c7a15ed5589c4ae79 Mon Sep 17 00:00:00 2001 From: Ellis Nguyen Date: Mon, 16 Mar 2026 21:51:36 +0000 Subject: [PATCH] [system] Add centralized status and POC for hello We want to centralize the error status by goign with a compacted 64 bit error reporting format. This can provide context, domain, and specific error code. The hello would is used to create an example of the error code foundation. This doesnt include the utlility to convert 64 error to human readable yet Signed-off-by: Ellis Nguyen --- BUILD | 8 ++++ examples/htool.c | 8 ++-- include/libhoth/status.h | 85 ++++++++++++++++++++++++++++++++++++++++ meson.build | 2 + protocol/BUILD | 3 ++ protocol/hello.c | 11 ++++-- protocol/hello.h | 4 +- protocol/hello_test.cc | 2 +- protocol/host_cmd.h | 4 ++ 9 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 include/libhoth/status.h diff --git a/BUILD b/BUILD index d0048cb..1ce7d8d 100644 --- a/BUILD +++ b/BUILD @@ -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"], diff --git a/examples/htool.c b/examples/htool.c index 59a9881..9c10e74 100644 --- a/examples/htool.c +++ b/examples/htool.c @@ -769,9 +769,11 @@ static int command_hello(const struct htool_invocation* inv) { } uint32_t output = 0; - const int rv = libhoth_hello(dev, input, &output); - if (rv) { - return rv; + const libhoth_error rv = libhoth_hello(dev, input, &output); + if (rv != HOTH_SUCCESS) { + fprintf(stderr, "libhoth_hello failed with error: 0x%016lx\n", + (unsigned long)rv); + return -1; } printf("output: 0x%08x\n", output); diff --git a/include/libhoth/status.h b/include/libhoth/status.h new file mode 100644 index 0000000..941e917 --- /dev/null +++ b/include/libhoth/status.h @@ -0,0 +1,85 @@ + +// Copyright 2022 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 + +// 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) << 32) | ((uint64_t)(space) << 16) | (uint64_t)(code)) + +// HothContextId: High 32 bits of the error code. +// Uniquely identifies the libhoth operation or subsystem. +enum HothContextId { + 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, +}; + +// HothHostSpace: Top 16 bits of the low 32-bit Base Error Code. +// Indicates the domain of host-side errors. +enum HothHostSpace { + 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_LIBHOTH = 0x0005, // libhoth internal errors +}; + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +// Firmware Error +enum hoth_fw_error_status { + HOTH_RES_SUCCESS = 0, + HOTH_RES_INVALID_COMMAND = 1, + HOTH_RES_ERROR = 2, + HOTH_RES_INVALID_PARAM = 3, + HOTH_RES_ACCESS_DENIED = 4, + HOTH_RES_INVALID_RESPONSE = 5, + HOTH_RES_INVALID_VERSION = 6, + HOTH_RES_INVALID_CHECKSUM = 7, + HOTH_RES_IN_PROGRESS = 8, + HOTH_RES_UNAVAILABLE = 9, + HOTH_RES_TIMEOUT = 10, + HOTH_RES_OVERFLOW = 11, + HOTH_RES_INVALID_HEADER = 12, + HOTH_RES_REQUEST_TRUNCATED = 13, + HOTH_RES_RESPONSE_TOO_BIG = 14, + HOTH_RES_BUS_ERROR = 15, + HOTH_RES_BUSY = 16, + HOTH_RES_INVALID_HEADER_VERSION = 17, + HOTH_RES_INVALID_HEADER_CRC = 18, + HOTH_RES_INVALID_DATA_CRC = 19, + HOTH_RES_DUP_UNAVAILABLE = 20, + HOTH_RES_MAX = UINT16_MAX +} __packed; + +#endif // LIBHOTH_INCLUDE_LIBHOTH_STATUS_H_ diff --git a/meson.build b/meson.build index 0cd1e43..c7cfc23 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,7 @@ project('libhoth', 'c', 'cpp', license: 'Apache-2.0', version: '0.0.0') +install_headers('include/libhoth/status.h', subdir: 'libhoth') + header_subdirs = ['libhoth'] libhoth_objs = [] libhoth_deps = [] diff --git a/protocol/BUILD b/protocol/BUILD index ee80cff..daeec98 100644 --- a/protocol/BUILD +++ b/protocol/BUILD @@ -8,6 +8,7 @@ cc_library( srcs = ["host_cmd.c"], hdrs = ["host_cmd.h"], deps = [ + "//:libhoth_status", "//transports:libhoth_device", ], ) @@ -390,6 +391,7 @@ cc_library( hdrs = ["hello.h"], deps = [ ":host_cmd", + "//:libhoth_status", "//transports:libhoth_device", ], ) @@ -399,6 +401,7 @@ cc_test( srcs = ["hello_test.cc"], deps = [ ":hello", + "//:libhoth_status", "//protocol/test:libhoth_device_mock", "//transports:libhoth_device", "@googletest//:gtest", diff --git a/protocol/hello.c b/protocol/hello.c index 9a05779..6784281 100644 --- a/protocol/hello.c +++ b/protocol/hello.c @@ -16,8 +16,8 @@ #include -int libhoth_hello(struct libhoth_device* const dev, const uint32_t input, - uint32_t* const output) { +libhoth_error libhoth_hello(struct libhoth_device* const dev, const uint32_t input, + uint32_t* const output) { const struct hoth_request_hello request = { .input = input, }; @@ -25,6 +25,11 @@ int libhoth_hello(struct libhoth_device* const dev, const uint32_t input, const int rv = libhoth_hostcmd_exec(dev, HOTH_CMD_HELLO, /*version=*/0, &request, sizeof(request), &response, sizeof(response), NULL); + + if (rv != LIBHOTH_OK) { + return LIBHOTH_ERR_CONSTRUCT(HOTH_CTX_CMD_EXEC, HOTH_HOST_SPACE_LIBHOTH, rv); + } + *output = response.output; - return rv; + return HOTH_SUCCESS; } diff --git a/protocol/hello.h b/protocol/hello.h index 88804d2..1a73c0c 100644 --- a/protocol/hello.h +++ b/protocol/hello.h @@ -17,6 +17,7 @@ #include +#include "libhoth/status.h" #include "protocol/host_cmd.h" #ifdef __cplusplus @@ -35,7 +36,8 @@ struct hoth_response_hello { uint32_t output; } __hoth_align4; -int libhoth_hello(struct libhoth_device* dev, uint32_t input, uint32_t* output); +libhoth_error libhoth_hello(struct libhoth_device* dev, uint32_t input, + uint32_t* output); #ifdef __cplusplus } diff --git a/protocol/hello_test.cc b/protocol/hello_test.cc index ea77bb6..232ae2d 100644 --- a/protocol/hello_test.cc +++ b/protocol/hello_test.cc @@ -39,6 +39,6 @@ TEST_F(LibHothTest, hello_test) { const uint32_t input = 0xa0b0c0d0; uint32_t output = 0; - EXPECT_EQ(libhoth_hello(&hoth_dev_, input, &output), LIBHOTH_OK); + EXPECT_EQ(libhoth_hello(&hoth_dev_, input, &output), HOTH_SUCCESS); EXPECT_EQ(output, response.output); } diff --git a/protocol/host_cmd.h b/protocol/host_cmd.h index 17e8100..eca28d7 100644 --- a/protocol/host_cmd.h +++ b/protocol/host_cmd.h @@ -18,6 +18,7 @@ #include #include +#include "libhoth/status.h" #include "transports/libhoth_device.h" #ifdef __cplusplus @@ -42,6 +43,7 @@ extern "C" { #define HOTH_CMD_BOARD_SPECIFIC_BASE 0x3E00 #define HOTH_CMD_BOARD_SPECIFIC_LAST 0x3FFF +/* enum hoth_status { HOTH_RES_SUCCESS = 0, HOTH_RES_INVALID_COMMAND = 1, @@ -66,6 +68,8 @@ enum hoth_status { HOTH_RES_DUP_UNAVAILABLE = 20, HOTH_RES_MAX = UINT16_MAX } __packed; +*/ +typedef enum hoth_fw_error_status hoth_status; #define HOTH_HOST_REQUEST_VERSION 3