summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-05-13 15:48:00 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-05-13 15:48:00 +0800
commitb5faa01c335354f6b4090757603343ad26071591 (patch)
tree6497889fd4181955e82a15b87f3a245808418c96
parent1274be88b61b685a7792e77fc38b90b8a30fcab7 (diff)
downloadlume-b5faa01c335354f6b4090757603343ad26071591.tar.gz
lume-b5faa01c335354f6b4090757603343ad26071591.tar.xz
feat: add printk and vprintk functions with Linux-style log level parsing
-rw-r--r--na/include/lume/klog.h20
-rw-r--r--na/lib/klog.cc50
2 files changed, 70 insertions, 0 deletions
diff --git a/na/include/lume/klog.h b/na/include/lume/klog.h
index 457dcfe..b63810f 100644
--- a/na/include/lume/klog.h
+++ b/na/include/lume/klog.h
@@ -108,6 +108,11 @@ void klog(KlogLevel level, const char* fmt, ...);
__attribute__((format(printf, 3, 4)))
void klog_ex(KlogLevel level, KlogSubsys subsys, const char* fmt, ...);
+/* Linux-style printk interface */
+__attribute__((format(printf, 1, 2)))
+int printk(const char* fmt, ...);
+int vprintk(const char* fmt, __builtin_va_list va);
+
/* Set runtime log level filter. Messages above this level are
* still stored in the ring buffer but not printed to console. */
void klog_set_level(KlogLevel level);
@@ -160,6 +165,21 @@ void klog_stats(KlogStats* out);
#define pr_debug(fmt, ...) do {} while (0)
#endif
+/* Linux kernel loglevel prefixes */
+#define KERN_SOH "\001"
+#define KERN_EMERG KERN_SOH "0"
+#define KERN_ALERT KERN_SOH "1"
+#define KERN_CRIT KERN_SOH "2"
+#define KERN_ERR KERN_SOH "3"
+#define KERN_WARNING KERN_SOH "4"
+#define KERN_NOTICE KERN_SOH "5"
+#define KERN_INFO KERN_SOH "6"
+#define KERN_DEBUG KERN_SOH "7"
+
+/* Boot stage log (thin wrapper over printk) */
+#define BOOT_STAGE(n, desc) \
+ printk(KERN_INFO "STAGE%u %s\n", (unsigned)(n), (desc))
+
extern "C" [[noreturn]] void kernel_panic(const char* msg, const char* detail = nullptr);
#ifdef __cplusplus
diff --git a/na/lib/klog.cc b/na/lib/klog.cc
index c67971b..bf081de 100644
--- a/na/lib/klog.cc
+++ b/na/lib/klog.cc
@@ -86,6 +86,27 @@ static const char* klog_subsys_name(KlogSubsys subsys)
return "?";
}
+static const char* parse_kern_level(const char* fmt, KlogLevel* level)
+{
+ if (!fmt || !level) {
+ return fmt;
+ }
+
+ /* Linux-style "\001n" prefix (KERN_SOH) */
+ if (fmt[0] == '\001' && fmt[1] >= '0' && fmt[1] <= '7') {
+ *level = static_cast<KlogLevel>(fmt[1] - '0');
+ return fmt + 2;
+ }
+
+ /* Alternate "<n>" prefix */
+ if (fmt[0] == '<' && fmt[1] >= '0' && fmt[1] <= '7' && fmt[2] == '>') {
+ *level = static_cast<KlogLevel>(fmt[1] - '0');
+ return fmt + 3;
+ }
+
+ return fmt;
+}
+
/* ========================================================================
* Ring Buffer Operations
* ======================================================================== */
@@ -320,6 +341,35 @@ static void klog_vex(KlogLevel level, KlogSubsys subsys,
}
}
+int vprintk(const char* fmt, __builtin_va_list va)
+{
+ KlogLevel level = KLOG_INFO;
+ const char* real_fmt = parse_kern_level(fmt, &level);
+
+ __builtin_va_list va_copy;
+ __builtin_va_copy(va_copy, va);
+
+ char tmp[KLOG_LINE_MAX + 1];
+ int len = vsnprintf_(tmp, KLOG_LINE_MAX, real_fmt, va_copy);
+ __builtin_va_end(va_copy);
+
+ klog_vex(level, KLOG_SUBSYS_GENERIC, real_fmt, va);
+
+ if (len < 0) {
+ return 0;
+ }
+ return len;
+}
+
+int printk(const char* fmt, ...)
+{
+ __builtin_va_list va;
+ __builtin_va_start(va, fmt);
+ int ret = vprintk(fmt, va);
+ __builtin_va_end(va);
+ return ret;
+}
+
void klog_set_level(KlogLevel level)
{
g_klog.console_level = level;