mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-06 15:43:02 +02:00
Merge pull request #1356 from kernelkit/nanopi
Misc. fixes for NanoPi R2S
This commit is contained in:
@@ -4,6 +4,7 @@ config BR2_PACKAGE_FRIENDLYARM_NANOPI_R2S
|
||||
select SDCARD_AUX
|
||||
select BR2_PACKAGE_INPUT_EVENT_DAEMON
|
||||
select BR2_PACKAGE_LINUX_FIRMWARE_RTL_815X
|
||||
select BR2_PACKAGE_INPUT_EVENT_DAEMON
|
||||
help
|
||||
FriendlyElec NanoPi R2S is a compact router board based on
|
||||
the Rockchip RK3328 SoC with dual Gigabit Ethernet ports.
|
||||
|
||||
@@ -4,6 +4,9 @@ define FRIENDLYARM_NANOPI_R2S_LINUX_CONFIG_FIXUPS
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_ROCKCHIP_IOMMU)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_ROCKCHIP_PM_DOMAINS)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_ROCKCHIP_IODOMAIN)
|
||||
# TODO: for some reason this just locks up the device
|
||||
# so we'll have to rely on the softdog :-(
|
||||
# $(call KCONFIG_ENABLE_OPT,CONFIG_DW_WATCHDOG)
|
||||
|
||||
# PHY drivers
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_PHY_ROCKCHIP_EMMC)
|
||||
@@ -51,6 +54,10 @@ define FRIENDLYARM_NANOPI_R2S_LINUX_CONFIG_FIXUPS
|
||||
$(call KCONFIG_SET_OPT,CONFIG_NVMEM_ROCKCHIP_EFUSE,m)
|
||||
$(call KCONFIG_SET_OPT,CONFIG_NVMEM_ROCKCHIP_OTP,m)
|
||||
|
||||
# Input layer
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_INPUT_MISC)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_INPUT_RK805_PWRKEY)
|
||||
|
||||
# Network: STMMAC Ethernet (WAN port - RK3328 GMAC with RTL8211E PHY)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_VENDOR_STMICRO)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_STMMAC_ETH)
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
From c4463ec64f9732bd67b8cfd2b73adc10e50d1178 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Sun, 18 Jan 2026 23:26:37 +0100
|
||||
Subject: [PATCH] initctl: escape special characters in JSON output
|
||||
Organization: Wires
|
||||
|
||||
Strings like command, description, and environment may contain characters
|
||||
that need escaping for valid JSON, e.g., embedded quotes in command line
|
||||
arguments like -V "NanoPi R2S".
|
||||
|
||||
Add json_escape() helper to handle quotes, backslashes, and control chars.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/initctl.c | 78 +++++++++++++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 69 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/initctl.c b/src/initctl.c
|
||||
index 25c52cf..435e2da 100644
|
||||
--- a/src/initctl.c
|
||||
+++ b/src/initctl.c
|
||||
@@ -1036,6 +1036,62 @@ static int svc_compare(svc_t *svc, char *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Escape a string for safe JSON output. Handles quotes, backslashes,
|
||||
+ * and control characters. Returns pointer to static buffer.
|
||||
+ */
|
||||
+static char *json_escape(const char *str)
|
||||
+{
|
||||
+ static char buf[1024];
|
||||
+ char *ptr = buf;
|
||||
+ size_t left = sizeof(buf) - 1;
|
||||
+
|
||||
+ if (!str)
|
||||
+ return "";
|
||||
+
|
||||
+ while (*str && left > 1) {
|
||||
+ char c = *str++;
|
||||
+
|
||||
+ switch (c) {
|
||||
+ case '"':
|
||||
+ case '\\':
|
||||
+ *ptr++ = '\\';
|
||||
+ *ptr++ = c;
|
||||
+ left -= 2;
|
||||
+ break;
|
||||
+ case '\n':
|
||||
+ *ptr++ = '\\';
|
||||
+ *ptr++ = 'n';
|
||||
+ left -= 2;
|
||||
+ break;
|
||||
+ case '\r':
|
||||
+ *ptr++ = '\\';
|
||||
+ *ptr++ = 'r';
|
||||
+ left -= 2;
|
||||
+ break;
|
||||
+ case '\t':
|
||||
+ *ptr++ = '\\';
|
||||
+ *ptr++ = 't';
|
||||
+ left -= 2;
|
||||
+ break;
|
||||
+ default:
|
||||
+ if ((unsigned char)c < 0x20) {
|
||||
+ /* Other control chars: use \uXXXX */
|
||||
+ int n = snprintf(ptr, left, "\\u%04x", (unsigned char)c);
|
||||
+ ptr += n;
|
||||
+ left -= n;
|
||||
+ } else {
|
||||
+ *ptr++ = c;
|
||||
+ left--;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ *ptr = '\0';
|
||||
+
|
||||
+ return buf;
|
||||
+}
|
||||
+
|
||||
static int json_status_one(FILE *fp, svc_t *svc, char *indent, int prev)
|
||||
{
|
||||
long now = jiffies();
|
||||
@@ -1051,14 +1107,16 @@ static int json_status_one(FILE *fp, svc_t *svc, char *indent, int prev)
|
||||
fprintf(fp,
|
||||
"%s"
|
||||
"%s{\n"
|
||||
- "%s \"identity\": \"%s\",\n"
|
||||
- "%s \"description\": \"%s\",\n"
|
||||
+ "%s \"identity\": \"%s\",\n",
|
||||
+ prev ? ",\n" : indent, prev ? indent : "",
|
||||
+ indent, svc_ident(svc, NULL, 0));
|
||||
+ fprintf(fp,
|
||||
+ "%s \"description\": \"%s\",\n",
|
||||
+ indent, json_escape(svc->desc));
|
||||
+ fprintf(fp,
|
||||
"%s \"type\": \"%s\",\n"
|
||||
"%s \"forking\": %s,\n"
|
||||
"%s \"status\": \"%s\",\n",
|
||||
- prev ? ",\n" : indent, prev ? indent : "",
|
||||
- indent, svc_ident(svc, NULL, 0),
|
||||
- indent, svc->desc,
|
||||
indent, svc_typestr(svc),
|
||||
indent, svc->forking ? "true" : "false",
|
||||
indent, svc_status(svc));
|
||||
@@ -1080,15 +1138,17 @@ static int json_status_one(FILE *fp, svc_t *svc, char *indent, int prev)
|
||||
}
|
||||
|
||||
fprintf(fp,
|
||||
- "%s \"origin\": \"%s\",\n"
|
||||
+ "%s \"origin\": \"%s\",\n",
|
||||
+ indent, svc->file[0] ? svc->file : "built-in");
|
||||
+ svc_command(svc, buf, sizeof(buf), 0);
|
||||
+ fprintf(fp,
|
||||
"%s \"command\": \"%s\",\n",
|
||||
- indent, svc->file[0] ? svc->file : "built-in",
|
||||
- indent, svc_command(svc, buf, sizeof(buf), 0));
|
||||
+ indent, json_escape(buf));
|
||||
|
||||
svc_environ(svc, buf, sizeof(buf), 0);
|
||||
if (buf[0])
|
||||
fprintf(fp,
|
||||
- "%s \"environment\": \"%s\",\n", indent, buf);
|
||||
+ "%s \"environment\": \"%s\",\n", indent, json_escape(buf));
|
||||
|
||||
svc_cond(svc, buf, sizeof(buf), 0);
|
||||
if (buf[0])
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -161,7 +161,7 @@ class PadDhcpServer:
|
||||
|
||||
class PadSensor:
|
||||
name = 30
|
||||
value = 20
|
||||
value = 22
|
||||
status = 10
|
||||
|
||||
@classmethod
|
||||
@@ -186,14 +186,6 @@ class PadLldp:
|
||||
port_id = 20
|
||||
|
||||
|
||||
class PadDiskUsage:
|
||||
mount = 18
|
||||
size = 12
|
||||
used = 12
|
||||
avail = 12
|
||||
percent = 6
|
||||
|
||||
|
||||
def format_memory_bytes(bytes_val):
|
||||
"""Convert bytes to human-readable format"""
|
||||
if bytes_val == 0:
|
||||
@@ -221,11 +213,6 @@ def format_uptime_seconds(seconds):
|
||||
else:
|
||||
return f"{seconds // 86400}d"
|
||||
|
||||
@classmethod
|
||||
def table_width(cls):
|
||||
"""Total width of disk usage table"""
|
||||
return cls.mount + cls.size + cls.used + cls.avail + cls.percent
|
||||
|
||||
|
||||
class Column:
|
||||
"""Column definition for SimpleTable"""
|
||||
@@ -2134,7 +2121,7 @@ def show_hardware(json):
|
||||
sensors = [c for c in components if c.get("class") == "iana-hardware:sensor"]
|
||||
wifi_radios = [c for c in components if c.get("class") == "infix-hardware:wifi"]
|
||||
|
||||
width = max(PadSensor.table_width(), 100)
|
||||
width = max(PadSensor.table_width(), 62)
|
||||
|
||||
# Display full-width inverted heading
|
||||
print(Decore.invert(f"{'HARDWARE COMPONENTS':<{width}}"))
|
||||
@@ -2158,12 +2145,12 @@ def show_hardware(json):
|
||||
Decore.title("WiFi radios", width)
|
||||
|
||||
radios_table = SimpleTable([
|
||||
Column('NAME'),
|
||||
Column('MANUFACTURER'),
|
||||
Column('NAME', flexible=True),
|
||||
Column('MANUFACTURER', flexible=True),
|
||||
Column('BANDS', 'right'),
|
||||
Column('STANDARDS', 'right'),
|
||||
Column('MAX AP', 'right')
|
||||
])
|
||||
], min_width=width)
|
||||
|
||||
for component in wifi_radios:
|
||||
phy = component.get("name", "")
|
||||
@@ -2208,10 +2195,10 @@ def show_hardware(json):
|
||||
Decore.title("USB Ports", width)
|
||||
|
||||
usb_table = SimpleTable([
|
||||
Column('NAME'),
|
||||
Column('NAME', flexible=True),
|
||||
Column('STATE'),
|
||||
Column('OPER')
|
||||
])
|
||||
], min_width=width)
|
||||
|
||||
for component in usb_ports:
|
||||
port = USBport(component)
|
||||
@@ -2939,7 +2926,7 @@ def show_system(json):
|
||||
except (ValueError, KeyError):
|
||||
pass
|
||||
|
||||
width = PadDiskUsage.table_width()
|
||||
width = 62
|
||||
print(Decore.invert(f"{'SYSTEM INFORMATION':<{width}}"))
|
||||
print(f"{'OS Name':<20}: {platform.get('os-name', 'Unknown')}")
|
||||
print(f"{'OS Version':<20}: {platform.get('os-version', 'Unknown')}")
|
||||
@@ -3022,23 +3009,23 @@ def show_system(json):
|
||||
disk_filtered = [d for d in disk if d.get("mount") != "/"]
|
||||
if disk_filtered:
|
||||
Decore.title("Disk Usage", width)
|
||||
hdr = (f"{'MOUNTPOINT':<{PadDiskUsage.mount}}"
|
||||
f"{'SIZE':>{PadDiskUsage.size}}"
|
||||
f"{'USED':>{PadDiskUsage.used}}"
|
||||
f"{'AVAIL':>{PadDiskUsage.avail}}"
|
||||
f"{'USE%':>{PadDiskUsage.percent}}")
|
||||
print(Decore.invert(hdr))
|
||||
disk_table = SimpleTable([
|
||||
Column('MOUNTPOINT', flexible=True),
|
||||
Column('SIZE', 'right'),
|
||||
Column('USED', 'right'),
|
||||
Column('AVAIL', 'right'),
|
||||
Column('USE%', 'right')
|
||||
], min_width=width)
|
||||
|
||||
for d in disk_filtered:
|
||||
mount = d.get("mount", "?")
|
||||
size = d.get("size", "?")
|
||||
used = d.get("used", "?")
|
||||
avail = d.get("available", "?")
|
||||
percent = d.get("percent", "?")
|
||||
print(f"{mount:<{PadDiskUsage.mount}}"
|
||||
f"{size:>{PadDiskUsage.size}}"
|
||||
f"{used:>{PadDiskUsage.used}}"
|
||||
f"{avail:>{PadDiskUsage.avail}}"
|
||||
f"{percent:>{PadDiskUsage.percent}}")
|
||||
disk_table.row(
|
||||
d.get("mount", "?"),
|
||||
d.get("size", "?"),
|
||||
d.get("used", "?"),
|
||||
d.get("available", "?"),
|
||||
d.get("percent", "?")
|
||||
)
|
||||
disk_table.print()
|
||||
|
||||
|
||||
def show_dhcp_server(json, stats):
|
||||
|
||||
@@ -183,22 +183,21 @@ def add_services(out):
|
||||
services = []
|
||||
|
||||
for d in data:
|
||||
if "pid" not in d or "status" not in d or "identity" not in d or "description" not in d:
|
||||
try:
|
||||
services.append({
|
||||
"pid": d["pid"],
|
||||
"name": d["identity"],
|
||||
"status": d["status"],
|
||||
"description": d["description"],
|
||||
"statistics": {
|
||||
"memory-usage": str(d.get("memory", 0)),
|
||||
"uptime": str(d.get("uptime", 0)),
|
||||
"restart-count": int(d.get("restarts", 0))
|
||||
}
|
||||
})
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
entry = {
|
||||
"pid": d["pid"],
|
||||
"name": d["identity"],
|
||||
"status": d["status"],
|
||||
"description": d["description"],
|
||||
"statistics": {
|
||||
"memory-usage": str(d.get("memory", 0)),
|
||||
"uptime": str(d.get("uptime", 0)),
|
||||
"restart-count": int(d.get("restarts", 0))
|
||||
}
|
||||
}
|
||||
services.append(entry)
|
||||
|
||||
insert(out, "infix-system:services", "service", services)
|
||||
|
||||
def add_software(out):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[7mHARDWARE COMPONENTS [0m
|
||||
────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
[7mHARDWARE COMPONENTS [0m
|
||||
──────────────────────────────────────────────────────────────
|
||||
[1mBoard Information[0m
|
||||
Model : Standard PC (i440FX + PIIX, 1996)
|
||||
Manufacturer : QEMU
|
||||
Base MAC Address : 00:a0:85:00:03:00
|
||||
────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
──────────────────────────────────────────────────────────────
|
||||
[1mUSB Ports[0m
|
||||
[7mNAME STATE OPER [0m
|
||||
USB1 locked enabled
|
||||
USB2 locked enabled
|
||||
[7mNAME STATE OPER [0m
|
||||
USB1 locked enabled
|
||||
USB2 locked enabled
|
||||
|
||||
Reference in New Issue
Block a user