summaryrefslogtreecommitdiff
path: root/cmd/sbc_harness
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-03 16:29:59 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-05 21:34:27 -0600
commitbd50e8b0f423d50928c129bc884385b50fb1756f (patch)
tree71b835a2cf084d58994d0060e375ef634c000f32 /cmd/sbc_harness
parent45f90d1bf6a5f974ed8bc62b6838b5d2e906a3f8 (diff)
Add `uptime.txt`
Diffstat (limited to 'cmd/sbc_harness')
-rw-r--r--cmd/sbc_harness/CMakeLists.txt3
-rw-r--r--cmd/sbc_harness/fs_harness_uptime_txt.c156
-rw-r--r--cmd/sbc_harness/fs_harness_uptime_txt.h19
-rw-r--r--cmd/sbc_harness/main.c13
-rw-r--r--cmd/sbc_harness/static/Documentation/harness_uptime_txt.txt17
5 files changed, 208 insertions, 0 deletions
diff --git a/cmd/sbc_harness/CMakeLists.txt b/cmd/sbc_harness/CMakeLists.txt
index 64bf356..115361f 100644
--- a/cmd/sbc_harness/CMakeLists.txt
+++ b/cmd/sbc_harness/CMakeLists.txt
@@ -11,6 +11,8 @@ add_library(sbc_harness_objs OBJECT
main.c
usb_keyboard.c
tusb_log.c
+
+ fs_harness_uptime_txt.c
)
target_include_directories(sbc_harness_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/config)
target_include_directories(sbc_harness_objs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
@@ -74,6 +76,7 @@ target_embed_sources(sbc_harness_objs sbc_harness static.h
static/Documentation/YOUR_RIGHTS_AND_OBLIGATIONS/newlib.txt
static/Documentation/harness_rom_bin.txt
static/Documentation/harness_flash_bin.txt
+ static/Documentation/harness_uptime_txt.txt
)
endif()
diff --git a/cmd/sbc_harness/fs_harness_uptime_txt.c b/cmd/sbc_harness/fs_harness_uptime_txt.c
new file mode 100644
index 0000000..9216986
--- /dev/null
+++ b/cmd/sbc_harness/fs_harness_uptime_txt.c
@@ -0,0 +1,156 @@
+/* sbc_harness/fs_harness_uptime_txt.c - 9P access to harness uptime
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <stdio.h> /* for snprintf() */
+#include <stdlib.h> /* for malloc(), free() */
+
+#include <libhw/generic/alarmclock.h>
+#include <util9p/static.h>
+
+#include "fs_harness_uptime_txt.h"
+
+LO_IMPLEMENTATION_C(lib9p_srv_file, struct uptime_file, uptime_file, static);
+
+struct uptime_fio {
+ struct uptime_file *parent;
+ size_t buf_len;
+ char buf[24]; /* len(str(UINT64_MAX)+"ns\n\0") */
+};
+
+LO_IMPLEMENTATION_H(lib9p_srv_fio, struct uptime_fio, uptime_fio);
+LO_IMPLEMENTATION_C(lib9p_srv_fio, struct uptime_fio, uptime_fio, static);
+
+/* srv_file *******************************************************************/
+
+static void uptime_file_free(struct uptime_file *self) {
+ assert(self);
+}
+static struct lib9p_qid uptime_file_qid(struct uptime_file *self) {
+ assert(self);
+
+ return (struct lib9p_qid){
+ .type = LIB9P_QT_FILE,
+ .vers = 1,
+ .path = self->pathnum,
+ };
+}
+
+static struct lib9p_stat uptime_file_stat(struct uptime_file *self, struct lib9p_srv_ctx *ctx) {
+ assert(self);
+ assert(ctx);
+
+ uint64_t now = LO_CALL(bootclock, get_time_ns);
+ uint64_t size = 0;
+ while (now) {
+ size++;
+ now /= 10;
+ }
+ if (!size)
+ size++;
+ size += 3;
+
+ return (struct lib9p_stat){
+ .kern_type = 0,
+ .kern_dev = 0,
+ .file_qid = uptime_file_qid(self),
+ .file_mode = 0444,
+ .file_atime = UTIL9P_ATIME,
+ .file_mtime = UTIL9P_MTIME,
+ .file_size = size,
+ .file_name = lib9p_str(self->name),
+ .file_owner_uid = lib9p_str("root"),
+ .file_owner_gid = lib9p_str("root"),
+ .file_last_modified_uid = lib9p_str("root"),
+ .file_extension = lib9p_str(NULL),
+ .file_owner_n_uid = 0,
+ .file_owner_n_gid = 0,
+ .file_last_modified_n_uid = 0,
+ };
+}
+static void uptime_file_wstat(struct uptime_file *self, struct lib9p_srv_ctx *ctx,
+ struct lib9p_stat) {
+ assert(self);
+ assert(ctx);
+
+ lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem");
+}
+static void uptime_file_remove(struct uptime_file *self, struct lib9p_srv_ctx *ctx) {
+ assert(self);
+ assert(ctx);
+
+ lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem");
+}
+
+LIB9P_SRV_NOTDIR(struct uptime_file, uptime_file);
+
+static lo_interface lib9p_srv_fio uptime_file_fopen(struct uptime_file *self, struct lib9p_srv_ctx *ctx,
+ bool LM_UNUSED(rd), bool LM_UNUSED(wr), bool LM_UNUSED(trunc)) {
+ assert(self);
+ assert(ctx);
+
+ struct uptime_fio *ret = malloc(sizeof(struct uptime_fio));
+ ret->parent = self;
+ ret->buf_len = 0;
+
+ return lo_box_uptime_fio_as_lib9p_srv_fio(ret);
+}
+
+/* srv_fio ********************************************************************/
+
+static uint32_t uptime_fio_iounit(struct uptime_fio *self) {
+ assert(self);
+ return sizeof(self->buf)-1;
+}
+
+static void uptime_fio_iofree(struct uptime_fio *self) {
+ assert(self);
+ free(self);
+}
+
+static struct lib9p_qid uptime_fio_qid(struct uptime_fio *self) {
+ assert(self);
+ assert(self->parent);
+ return uptime_file_qid(self->parent);
+}
+
+static void uptime_fio_pread(struct uptime_fio *self, struct lib9p_srv_ctx *ctx,
+ uint32_t byte_count, uint64_t byte_offset,
+ struct iovec *ret) {
+ assert(self);
+ assert(ctx);
+ assert(ret);
+
+ if (byte_offset == 0 || self->buf_len == 0) {
+ uint64_t now = LO_CALL(bootclock, get_time_ns);
+ self->buf_len = snprintf(self->buf, sizeof(self->buf), "%"PRIu64"ns\n", now);
+ }
+
+ if (byte_offset > (uint64_t)self->buf_len) {
+ lib9p_error(&ctx->basectx,
+ LINUX_EINVAL, "offset is past end-of-file length");
+ return;
+ }
+
+ size_t beg_off = (size_t)byte_offset;
+ size_t end_off = beg_off + (size_t)byte_count;
+ if (end_off > self->buf_len)
+ end_off = self->buf_len;
+ *ret = (struct iovec){
+ .iov_base = &self->buf[beg_off],
+ .iov_len = end_off-beg_off,
+ };
+}
+
+static uint32_t uptime_fio_pwrite(struct uptime_fio *self, struct lib9p_srv_ctx *ctx,
+ void *LM_UNUSED(buf),
+ uint32_t LM_UNUSED(byte_count),
+ uint64_t LM_UNUSED(byte_offset)) {
+ assert(self);
+ assert(ctx);
+
+ lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem");
+ return 0;
+}
diff --git a/cmd/sbc_harness/fs_harness_uptime_txt.h b/cmd/sbc_harness/fs_harness_uptime_txt.h
new file mode 100644
index 0000000..7bf2945
--- /dev/null
+++ b/cmd/sbc_harness/fs_harness_uptime_txt.h
@@ -0,0 +1,19 @@
+/* sbc_harness/fs_harness_uptime_txt.h - 9P access to harness uptime
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _SBC_HARNESS_FS_HARNESS_UPTIME_TXT_H_
+#define _SBC_HARNESS_FS_HARNESS_UPTIME_TXT_H_
+
+#include <lib9p/srv.h>
+
+struct uptime_file {
+ char *name;
+ uint64_t pathnum;
+};
+LO_IMPLEMENTATION_H(lib9p_srv_file, struct uptime_file, uptime_file);
+#define lo_box_uptime_file_as_lib9p_srv_file(obj) util9p_box(uptime_file, obj)
+
+#endif /* _SBC_HARNESS_FS_HARNESS_UPTIME_TXT_H_ */
diff --git a/cmd/sbc_harness/main.c b/cmd/sbc_harness/main.c
index 2b2b3f8..3334bd8 100644
--- a/cmd/sbc_harness/main.c
+++ b/cmd/sbc_harness/main.c
@@ -32,6 +32,7 @@
/* local headers */
#include "usb_keyboard.h"
#include "static.h"
+#include "fs_harness_uptime_txt.h"
/* configuration **************************************************************/
@@ -45,6 +46,13 @@ enum { PATH_BASE = __COUNTER__ };
#define STATIC_FILE(STRNAME, ...) UTIL9P_STATIC_FILE(PATH_COUNTER, STRNAME, __VA_ARGS__)
#define STATIC_DIR(STRNAME, ...) UTIL9P_STATIC_DIR(PATH_COUNTER, STRNAME, __VA_ARGS__)
+#define API_FILE(STRNAME, SYMNAME, ...) \
+ lo_box_##SYMNAME##_file_as_lib9p_srv_file(&((struct SYMNAME##_file){ \
+ .name = STRNAME, \
+ .pathnum = PATH_COUNTER \
+ __VA_OPT__(,) __VA_ARGS__ \
+ }))
+
struct lib9p_srv_file root =
STATIC_DIR("",
STATIC_DIR("Documentation",
@@ -74,6 +82,9 @@ struct lib9p_srv_file root =
STATIC_FILE("harness_flash_bin.txt",
.data_start = _binary_static_Documentation_harness_flash_bin_txt_start,
.data_end = _binary_static_Documentation_harness_flash_bin_txt_end),
+ STATIC_FILE("harness_uptime_txt.txt",
+ .data_start = _binary_static_Documentation_harness_uptime_txt_txt_start,
+ .data_end = _binary_static_Documentation_harness_uptime_txt_txt_end),
),
STATIC_DIR("harness",
STATIC_FILE("rom.bin",
@@ -83,6 +94,8 @@ struct lib9p_srv_file root =
STATIC_FILE("flash.bin",
.data_start = (void*)0x10000000,
.data_size = PICO_FLASH_SIZE_BYTES),
+ API_FILE("uptime.txt",
+ uptime),
// TODO: system.log
// TODO: proc.txt
// TODO: cpuinfo.txt
diff --git a/cmd/sbc_harness/static/Documentation/harness_uptime_txt.txt b/cmd/sbc_harness/static/Documentation/harness_uptime_txt.txt
new file mode 100644
index 0000000..1ab86f7
--- /dev/null
+++ b/cmd/sbc_harness/static/Documentation/harness_uptime_txt.txt
@@ -0,0 +1,17 @@
+NAME
+ /harness/uptime.txt
+
+DESCRIPTION
+ Reading this file gives a text string of the format
+ `sprintf("%uns\n", uptime_ns)` indicating the harness's uptime
+ in an integer number of nanoseconds.
+
+BUGS
+ Using nanoseconds gives the illusion of more precision than
+ there actually is; the harness' clock only has microsecond
+ resolution; the last 3 digits of the returned nanosecond count
+ will always be 0.
+
+AUTHOR
+ Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ SPDX-License-Identifier: AGPL-3.0-or-later