Skip to content

Helpdesk access from the U-Boot environment: fw_setenv vtesse <server> (#64) - #66

Merged
compot-dev merged 18 commits into
mainfrom
feat/uboot-env-64
Oct 18, 2026
Merged

compot-dev merged 18 commits into
mainfrom
feat/uboot-env-64

Conversation

@compot-dev

Copy link
Copy Markdown
Collaborator

Closes #64. Version 1.15.0.

Helpdesk access with one command, the way OpenIPC does it for VTun:

fw_setenv vtesse vtun.example.org   # on (at the next start of the service)
fw_setenv vtesse                    # off

What changes

  • cli/env.c: reads the variables with one fw_printenv; vtesse = host, optional vtesse_port, vtesse_session / vtesse_id_from, vtesse_password, vtesse_ip, vtesse_gw. Everything else stays in /etc/vtesse.conf.
  • Defaults with only the server, as OpenIPC's tunnel: port 5000, session = MAC of the default-route interface without colons, password = echo "$MAC" | sha1sum (SHA-1 of the upper-case MAC with colons and a newline; a small SHA-1 in env.c). The interface must have a MAC the client accepts.
  • Order per key: command line, U-Boot environment, /etc/vtesse.conf, defaults. A missing config file is fine when vtesse is set.
  • New options: --show-config (the settings in effect, then exit) and --no-env.
  • Service files: S99vtesse and vtesse.init start without /etc/vtesse.conf when vtesse is set.
  • --install: works without keys and without a config when vtesse is set; keys given are also stored with fw_setenv when available (never with --root). --uninstall leaves the variables and says so.
  • Docs: docs/usage.md (new section), docs/security.md (the derived password is not a secret), READMEs (one paragraph each), CHANGELOG.

Tests

  • tests/test_env.c: SHA-1 vectors (empty, abc, two-block, 1 M × a, padding at 55/56/64 bytes) and the VTun password; run natively and under qemu (arm32, big-endian mips).
  • tests/test_install.sh with a fake fw_printenv / fw_setenv: defaults with only the server (compared with sha1sum of the real interface MAC), env overriding the file key by key, --no-env, no file and no variable refused, --install without keys, no fw_setenv under --root, --uninstall leaving the variables.
  • Native, -D_FORTIFY_SOURCE=3, LWIP=0 and minimal builds without warnings; bench/bench.sh tap-test passes.
  • OpenIPC camera (from /tmp, the real environment only read): with only vtesse=<server>, --show-config gave session and password byte for byte equal to what the stock tunnel script computes on the same camera.

- vtesse (the server) and vtesse_port, vtesse_session / vtesse_id_from,
  vtesse_password, vtesse_ip, vtesse_gw are read with fw_printenv and
  override /etc/vtesse.conf key by key (command line first).
- With only vtesse set, the defaults of OpenIPC's VTun client: port 5000,
  session = MAC of the default-route interface, password = SHA-1 of
  "<MAC>\n" (echo "$MAC" | sha1sum), so the same server accepts it.
- --show-config prints the settings in effect, --no-env ignores the variables.
- S99vtesse and vtesse.init start without /etc/vtesse.conf when vtesse is
  set; --install needs no keys then and stores given keys with fw_setenv;
  --uninstall leaves the variables.
- The default interface for the device ID must have a MAC (shared in env.c).
- tests/test_env.c: SHA-1 vectors and the VTun password; test_install.sh:
  the environment with a fake fw_printenv / fw_setenv.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Enable helpdesk access through the U-Boot environment

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Allow fw_setenv vtesse  to start helpdesk access without a configuration file.
• Apply U-Boot settings per key, with OpenIPC-compatible session and password defaults.
• Update installation and service startup; add configuration inspection, tests, and security
 guidance.
Diagram

graph TD
  Boot["Service scripts"] --> CLI["vtesse CLI"] --> Merge["Merge settings"] --> Defaults["VTun defaults"] --> Tunnel["Tunnel client"]
  UBoot[("U-Boot vars")] --> Reader["Environment reader"] --> Merge
  Config[("Config file")] --> Merge
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Translate U-Boot variables in service scripts
  • ➕ Could leave the CLI configuration loader largely unchanged.
  • ➖ Would duplicate logic across init systems and exclude direct CLI use.
  • ➖ Would make credential derivation and precedence harder to keep consistent.

Recommendation: Keep environment loading in the CLI so direct runs and both service scripts share one configuration path. Review precedence and credential-derivation edge cases closely, particularly when file and environment values coexist.

Files changed (18) +632 / -52

Enhancement (6) +433 / -48
env.cRead U-Boot settings and derive VTun-compatible credentials +240/-0

Read U-Boot settings and derive VTun-compatible credentials

• Reads supported variables in one 'fw_printenv' call, provides 'fw_setenv' support, selects a MAC-bearing default interface, and computes the OpenIPC-compatible SHA-1 password.

cli/env.c

env.hDefine the U-Boot environment interface +56/-0

Define the U-Boot environment interface

• Declares the supported variable mapping, environment operations, interface helpers, and password-derivation functions.

cli/env.h

install.cSupport environment-backed installation +33/-41

Support environment-backed installation

• Allows installation without a config file or keys when 'vtesse' is set. Stores supplied supported keys with 'fw_setenv' outside '--root', reports retained variables on uninstall, and shares default-interface selection with the CLI.

cli/install.c

vtesse_cli.cMerge U-Boot settings into runtime configuration +97/-4

Merge U-Boot settings into runtime configuration

• Makes a missing config file acceptable when a U-Boot server exists, applies environment overrides per key, and fills missing VTun-compatible defaults. Adds '--no-env' and '--show-config'.

cli/vtesse_cli.c

S99vtessePermit BusyBox service startup from U-Boot settings +4/-2

Permit BusyBox service startup from U-Boot settings

• Allows startup without '/etc/vtesse.conf' when 'fw_printenv' reports a nonempty 'vtesse' server.

scripts/S99vtesse

vtesse.initPermit procd service startup from U-Boot settings +3/-1

Permit procd service startup from U-Boot settings

• Accepts a nonempty U-Boot 'vtesse' server as an alternative to the configuration file.

scripts/vtesse.init

Documentation (7) +89 / -0
CHANGELOG.mdRecord the 1.15.0 helpdesk-access release +18/-0

Record the 1.15.0 helpdesk-access release

• Documents U-Boot variables, VTun-compatible defaults, service and installer behavior, and the new CLI options.

CHANGELOG.md

README.mdIntroduce one-command helpdesk access +2/-0

Introduce one-command helpdesk access

• Explains how to enable or disable access through 'fw_setenv' and links to the detailed guide.

README.md

README.ru.mdDocument helpdesk access in Russian +2/-0

Document helpdesk access in Russian

• Adds the U-Boot setup and default-credentials overview to the Russian README.

README.ru.md

README.zh-CN.mdDocument helpdesk access in Simplified Chinese +2/-0

Document helpdesk access in Simplified Chinese

• Adds the U-Boot setup and default-credentials overview to the Chinese README.

README.zh-CN.md

security.mdExplain U-Boot credential exposure +11/-0

Explain U-Boot credential exposure

• Warns that environment values persist and are readable with sufficient access, and that the MAC-derived default password is not secret.

docs/security.md

testing.mdRecord camera validation of VTun defaults +6/-0

Record camera validation of VTun defaults

• Documents an OpenIPC camera check comparing the generated session and password against its stock tunnel script.

docs/testing.md

usage.mdDocument U-Boot helpdesk configuration +48/-0

Document U-Boot helpdesk configuration

• Adds setup commands, variable mappings, precedence, defaults, installer behavior, CLI options, and security caveats.

docs/usage.md

Other (5) +110 / -4
MakefileBuild the environment module and its unit test +5/-2

Build the environment module and its unit test

• Links 'cli/env.o' into the CLI and adds 'test_env' to the test targets.

Makefile

build-musl.shRun environment tests under QEMU +1/-1

Run environment tests under QEMU

• Includes 'test_env' in the cross-architecture QEMU test loop.

ci/build-musl.sh

version.hBump the version to 1.15.0 +1/-1

Bump the version to 1.15.0

• Updates the version reported by the CLI for this release.

include/vtesse/version.h

test_env.cVerify SHA-1 and OpenIPC password derivation +57/-0

Verify SHA-1 and OpenIPC password derivation

• Adds standard SHA-1 vectors, padding-boundary cases, a million-byte input, and a MAC-derived VTun password check.

tests/test_env.c

test_install.shExercise U-Boot configuration and installation +46/-0

Exercise U-Boot configuration and installation

• Uses fake 'fw_printenv' and 'fw_setenv' commands to test server-only defaults, per-key overrides, '--no-env', missing settings, environment-backed installation, '--root' write protection, and uninstall retention.

tests/test_install.sh

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (8) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Installer drops keys without U-Boot tools ✓ Resolved
Description
do_install() passes the existing configuration and environment-backed mode to build_config(),
which returns before merging command-line keys when fw_setenv is unavailable. With an existing
config, --install --port, --session, or another supported key is therefore neither written to
U-Boot nor preserved in /etc/vtesse.conf, so the installed service continues using the old
settings.
Code

cli/install.c[R929-930]

+    } else if ((n && !root[0] && !ve_can_write() && env_conflict(&env, set, n) < 0) ||
+               build_config(old, set, n, conf, env_host[0] ? &env : NULL) < 0) {
Evidence
The installer enters the environment-aware build_config() path when fw_setenv is unavailable,
but build_config() returns immediately for any non-null environment instead of building the
configuration. Consequently, an existing config file is left unchanged and supplied keys are lost.

Graceful operation without U-Boot environment utilities
cli/install.c[516-520]
cli/install.c[929-930]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
When `vtesse` is supplied by the U-Boot environment but `fw_setenv` is unavailable, `build_config()` exits early and discards command-line settings if an existing configuration file is present.
## Fix Focus Areas
- cli/install.c[516-520]
- cli/install.c[929-930]
## Recommended Fix
When U-Boot writes are unavailable, merge supported command-line settings into `/etc/vtesse.conf` while retaining the environment-provided server and other overrides. Keep the existing conflict checks for keys already set in U-Boot, and ensure the resulting file is written before installation continues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unavailable tools block helpdesk installs ✓ Resolved
Description
do_install() falls back to full file configuration whenever command-line settings are present but
fw_setenv is unavailable, even when vtesse already supplies the server. On a device with no
config file, that path rejects the install for missing host or password instead of skipping the
unavailable environment write and installing successfully.
Code

cli/install.c[R871-884]

+    /* the server is in the U-Boot environment and there is no file: given keys go
+     * there too (below), so no file is needed */
+    if (!old && env_host[0] && (n == 0 || ve_can_write())) {
+        const kv_t *gw = find(set, n, "gw"), *ip = find(set, n, "ip");
+
+        /* the same rule as for a file: a gateway needs an address */
+        if (gw && !ip && !env.ip[0]) {
+            fprintf(stderr, "vtesse: --gw needs --ip (or vtesse_ip)\n");
+            free(old);
+            return 1;
+        }
+        /* helpdesk set-up (#64): the settings come from the U-Boot environment */
+        conf[0] = '\0';
+    } else if (build_config(old, set, n, conf) < 0) {
Evidence
The checklist requires install behavior not to fail solely because fw_setenv is unavailable. The
changed branch only skips build_config() when there are no command-line settings or
ve_can_write() succeeds; otherwise it invokes full configuration validation, which cannot succeed
without a host and password in the missing file.

Install, uninstall, and unavailable-tool behavior
cli/install.c[871-884]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An environment-backed install with command-line settings fails when `fw_setenv` is unavailable because the code requires a complete configuration file instead of treating the environment write as optional.
## Fix Focus Areas
- cli/install.c[871-884]
## Recommended Fix
When `vtesse` is present and the config file is missing, allow the install to proceed even if `fw_setenv` is unavailable. Skip persistence of command-line settings when the tool is absent, or write a valid fallback configuration, while retaining failure handling when an available `fw_setenv` command actually returns an error.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Configured tunnels ignore boot overrides ✓ Resolved
Description
main() enables environment processing only when ve_load() reports a nonempty vtesse host, so
vtesse_port, vtesse_session, vtesse_password, vtesse_ip, or vtesse_gw are ignored when the
host remains in the configuration file. A device with a configured host and an optional U-Boot
override therefore keeps the file value instead of applying the environment value for that key,
breaking the required per-key precedence.
Code

cli/vtesse_cli.c[R866-872]

+    if (!no_env)
+        env_mode = ve_load(&env);
+    rc = load_config(config, &c, !env_mode);
+    if (rc < 0)
return 2;
+    if (env_mode) {
+        apply_env(&c, &env);
Evidence
The checklist requires each supported U-Boot key to take precedence over the configuration file
independently. ve_load() reports success only when e->host is nonempty, and main() calls
apply_env() only when that result is true, so optional environment keys are skipped when the host
is supplied by the file.

Apply supported environment overrides and precedence
cli/env.c[48-84]
cli/vtesse_cli.c[866-872]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Environment processing is gated on `vtesse` being present, so optional U-Boot variables cannot override matching keys in an existing configuration file unless the host is also moved into U-Boot.
## Fix Focus Areas
- cli/vtesse_cli.c[866-872]
- cli/env.c[48-84]
## Recommended Fix
Separate environment loading from helpdesk-mode activation: retain the nonempty `vtesse` host as the condition for allowing a missing configuration file and applying VTun defaults, but apply every nonempty supported environment key to an existing configuration file regardless of whether `vtesse` is set. Preserve command-line overrides after environment application and keep config-only keys excluded from the environment mapping.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View action required (2)
4. README hides helpdesk password exposure ✓ Resolved
Description
The new README.md paragraph describes how the default password is derived but does not say that
vtesse_password is readable by root or from a flash dump, nor that this mode is no stronger than
OpenIPC VTun. Readers using the README therefore miss the credential exposure and security limit
documented elsewhere in the PR.
Code

README.md[85]

+**Helpdesk access** on an OpenIPC camera with vtesse installed: `fw_setenv vtesse vtun.example.org` and a reboot are enough, as with `fw_setenv vtun` for VTun. With only the server set, the port is 5000, the session is the MAC of the default interface and the password is derived from it the way OpenIPC's VTun client does; `vtesse_port`, `vtesse_password` and other variables override that ([U-Boot environment](docs/usage.md#u-boot-environment-helpdesk-access)). `fw_setenv vtesse` turns it off.
Evidence
The checklist requires the README to document root/flash-dump exposure, the non-secret MAC-derived
password, and the security limit of helpdesk mode. The changed README paragraph mentions derivation
and helpdesk access but omits those warnings, while the PR's security documentation contains the
missing statements.

Helpdesk security documentation
README.md[85-85]
docs/security.md[45-51]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The README helpdesk section explains the MAC-derived password but omits that `vtesse_password` can be read by root or from a flash dump and that this mode is no stronger than VTun on OpenIPC.
## Fix Focus Areas
- README.md[85-85]
## Recommended Fix
Expand the helpdesk access paragraph to state that U-Boot variables, including `vtesse_password`, are readable by root and from flash dumps, that the MAC-derived password is not secret, and that this mode is intended only for helpdesk access with no stronger security than OpenIPC VTun.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Failed environment writes leave stale settings ✓ Resolved
Description
do_install() logs a failed ve_set() call but continues to service startup and can return
success. If an old vtesse value survives a failed write of a new --host, runtime environment
precedence makes the service use the old server despite the newly written config.
Code

cli/install.c[R917-920]

+                    if (ve_set(ve_vars[v].name, set[k].val) == 0)
+                        printf("U-Boot environment: %s set\n", ve_vars[v].name);
+                    else
+                        fprintf(stderr, "vtesse: fw_setenv %s failed\n", ve_vars[v].name);
Evidence
Failed writes only emit a diagnostic; startup proceeds, while the runtime applies surviving
environment keys over the file.

cli/install.c[909-922]
cli/install.c[963-973]
cli/env.c[101-115]
cli/vtesse_cli.c[247-279]
cli/vtesse_cli.c[854-860]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A failed U-Boot update allows installation to succeed while the service may use stale environment settings instead of the supplied keys.
## Fix Focus Areas
- cli/install.c[909-922]
- cli/install.c[963-973]
## Recommended Fix
Treat attempted `fw_setenv` failures as installation failures before starting or restarting the service. Report which key failed, and test a nonzero `fw_setenv` exit with a pre-existing conflicting environment value.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

6. Install succeeds with conflicting identities 🐞 Bug ≡ Correctness
Description
do_install() accepts an environment-backed setup without checking whether both vtesse_session
and vtesse_id_from are set. With both variables present and no config file, it can install and
attempt to start the service, but main() rejects the same environment before connecting.
Code

cli/install.c[934]

+    if (!old && env_host[0] && (n == 0 || env_write)) {
Evidence
The no-file environment path skips build_config(), and the later service path proceeds. Runtime
has an unconditional rejection for the two environment identity variables.

cli/install.c[919-946]
cli/install.c[1058-1069]
cli/vtesse_cli.c[883-887]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An environment-only install succeeds when both identity variables are set, although the runtime client refuses to start.
## Fix Focus Areas
- cli/install.c[919-946]
- cli/vtesse_cli.c[883-887]
## Recommended Fix
Before accepting an environment-backed install, reject the same conflicting identity-variable combination that runtime rejects.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Install accepts an unusable boot interface 🐞 Bug ≡ Correctness
Description
do_install() does not resolve an existing vtesse_id_from before accepting an environment-backed
installation. If that variable names a missing interface or one without a usable MAC, installation
can proceed while the client exits during identity resolution.
Code

cli/install.c[934]

+    if (!old && env_host[0] && (n == 0 || env_write)) {
Evidence
The environment-only path accepts the settings without resolving the interface. The runtime path
calls id_from_interface() and returns an error when it cannot obtain a usable identity.

cli/install.c[919-946]
cli/vtesse_cli.c[923-932]
cli/vtesse_cli.c[333-353]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An environment-backed install can accept an interface identity that the client cannot resolve.
## Fix Focus Areas
- cli/install.c[919-946]
- cli/vtesse_cli.c[923-932]
## Recommended Fix
Validate an effective environment-provided id_from against the runtime interface and MAC requirements before completing a live installation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Config preview can show the wrong identity 🐞 Bug ≡ Correctness
Description
main() skips the default-route wait for --show-config but still immediately derives the session
and password from the currently selected interface. If an uplink route appears during the wait that
normal startup performs, the preview can show eth0-derived settings while the service uses the
uplink’s MAC.
Code

cli/vtesse_cli.c[897]

+        if (!show_config && (!c.password[0] || (!c.session[0] && !c.id_from[0] && !id_from))) {
Evidence
Only normal startup waits for a route; both paths subsequently select an interface and derive
settings from it. The selector falls back to eth0 when it finds no suitable default route.

cli/vtesse_cli.c[895-913]
cli/vtesse_cli.c[937-949]
cli/env.c[197-215]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The preview and normal startup can derive different credentials while the boot uplink is coming up.
## Fix Focus Areas
- cli/vtesse_cli.c[895-913]
- cli/vtesse_cli.c[937-949]
## Recommended Fix
Use the same route-selection timing for the preview, or explicitly defer reporting derived values when the route needed by normal startup is not yet available.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View review recommended (11)
9. Install skips an available U-Boot writer 🐞 Bug ≡ Correctness
Description
ve_can_write() skips empty components of PATH, although ve_set_script() launches fw_setenv
through execlp(), which searches the current directory for those components. When fw_setenv is
available only through an empty component, --install treats it as unavailable and does not store
the supplied keys in U-Boot.
Code

cli/env.c[111]

+        if (n && n < 512) {
Evidence
The availability check excludes zero-length components, while the actual writer uses PATH-based
executable lookup; the installer gates its U-Boot write on that check.

cli/env.c[103-118]
cli/env.c[140-146]
cli/install.c[989-1015]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`ve_can_write()` overlooks `fw_setenv` when an empty PATH component makes it available from the current directory, so installation skips an available U-Boot writer.
## Fix Focus Areas
- cli/env.c[103-118]
- cli/env.c[140-146]
## Recommended Fix
Make the availability check handle empty PATH components the same way the subsequent executable lookup does, including leading and trailing empty components.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. Config preview hides command-line listeners 🐞 Bug ≡ Correctness
Description
--show-config prints file UDP relays but omits command-line --udp-relay, --socks, --forward,
and --listen settings before returning. When any of those options is supplied, the preview leaves
out listeners or relays that a normal run would activate.
Code

cli/vtesse_cli.c[R981-987]

+        for (i = 0; i < c.route_count; i++)
+            printf("route %s\n", c.route[i]);
+        for (i = 0; i < c.udp_relay_count; i++)
+            printf("udp_relay %s\n", c.udp_relay[i]);
+        if (c.socks_user[0])
+            printf("socks_user %s\nsocks_password (set)\n", c.socks_user);
+        return 0;
Evidence
The CLI parses these options into relay and proxy state, but the new preview prints only file relays
and returns before the normal path creates and reports the listeners.

cli/vtesse_cli.c[816-844]
cli/vtesse_cli.c[976-987]
cli/vtesse_cli.c[1053-1090]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`--show-config` omits command-line relays and proxy listeners from its preview of effective settings.
## Fix Focus Areas
- cli/vtesse_cli.c[976-987]
- cli/vtesse_cli.c[816-844]
## Recommended Fix
Include the parsed command-line UDP relays, SOCKS listener, forwards, and listener address in the preview alongside the file settings, without starting those services.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Install accepts a gateway the service then rejects 🐞 Bug ≡ Correctness
Description
do_install() skips build_config() and effective-configuration validation when /etc/vtesse.conf
is absent and vtesse is set in the environment, allowing fw_setenv to store a gateway without an
IP or a malformed vtesse_port. An environment-only install, including --install --no-start, can
therefore report success even though main() later rejects the gateway/IP combination or the CLI
rejects the port, preventing the installed service from starting until the invalid setting is
corrected.
Code

cli/install.c[R872-875]

+    if (!old && env_host[0] && (n == 0 || ve_can_write())) {
+        /* helpdesk set-up (#64): the settings come from the U-Boot environment */
+        conf[0] = '\0';
+    } else if (build_config(old, set, n, conf) < 0) {
Evidence
build_config() contains the check that a gateway needs an IP, but the environment-only install
branch bypasses it; the per-argument check_value check does not validate the relationship between
settings. That branch also leaves the configuration empty without validating effective environment
values, while runtime rejects both a gateway without an IP and a malformed environment port.

cli/install.c[607-610]
cli/install.c[1213-1233]
cli/vtesse_cli.c[922-925]
cli/install.c[860-875]
cli/env.c[48-80]
cli/vtesse_cli.c[270-277]
cli/vtesse_cli.c[228-238]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An environment-only install can accept and store settings that the installed service later rejects, including a gateway without an IP and a malformed port.
## Fix Focus Areas
- cli/install.c[860-878]
- cli/vtesse_cli.c[861-916]
## Recommended Fix
Before taking the empty-configuration branch or copying and installing service artifacts, validate the effective environment-only configuration, including overrides and defaults, using the same checks applied at runtime. In particular, reject a `gw` setting when neither `ip` nor an existing `vtesse_ip` (`env.ip`) is present; print the existing "gw and route need ip" message and return 1. Reject malformed effective port values as well.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. Failed boot reads can start a doomed service ✓ Resolved
Description
S99vtesse and vtesse.init accept nonempty output from fw_printenv -n vtesse without checking
its exit status. If that command prints a server but fails, the scripts allow a no-config start
while the client discards failed environment reads and exits for lack of a config file.
Code

scripts/S99vtesse[R25-27]

+        *) server=$(fw_printenv -n vtesse 2>/dev/null) ;;
+    esac
+    if [ ! -f "$CONFIG" ] && [ -z "$server" ]; then
Evidence
Both boot gates inspect command output alone, whereas ve_load() clears values after an
unsuccessful fw_printenv exit; the client then requires the missing config file.

scripts/S99vtesse[23-28]
scripts/vtesse.init[14-16]
cli/env.c[85-101]
cli/vtesse_cli.c[876-880]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The boot scripts can start a no-config service using output from an unsuccessful environment read.
## Fix Focus Areas
- scripts/S99vtesse[23-28]
- scripts/vtesse.init[14-16]
- cli/env.c[85-101]
## Recommended Fix
In both service scripts, require a successful fw_printenv exit status as well as a nonempty server before allowing startup without the config file.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


13. Helpdesk tunnels use the wrong device ID ✓ Resolved
Description
ve_route_iface() accepts the first route with a zero destination without checking its mask, so it
can mistake a 0.0.0.0/1 route for the default route. If that route appears before the actual
default route on another MAC-capable interface, environment-mode startup derives the session and
password from the wrong interface.
Code

cli/vtesse_cli.c[899]

+            for (waited = 0; waited < ENV_ROUTE_WAIT && ve_route_iface(ifname, sizeof(ifname)) < 0; waited++) {
Evidence
The newly added runtime wait uses ve_route_iface(). That function tests dst == 0 but never
checks the route mask; the selected interface feeds both the session default and password
derivation.

cli/env.c[174-187]
cli/vtesse_cli.c[895-907]
cli/vtesse_cli.c[934-946]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Environment-mode startup can select a non-default route's interface when a zero-destination route has a nonzero mask.
## Fix Focus Areas
- cli/env.c[174-189]
- cli/vtesse_cli.c[899-907]
## Recommended Fix
Parse the route mask alongside the destination and accept only an actual default route before deriving the interface-dependent credentials.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. Malformed boot IP widens the tunnel subnet ✓ Resolved
Description
apply_env() copies vtesse_ip into the runtime configuration, where parse_prefix() uses
atoi() without validating the prefix text. A value such as 1.2.3.4/garbage consequently passes
validation with a /0 mask, which the userspace stack receives as its static network setting.
Code

cli/vtesse_cli.c[R275-276]

+        else if (!strcmp(key, "ip"))
+            v = e->ip, dst = c->ip, size = sizeof(c->ip);
Evidence
The new environment override reaches parse_prefix(), whose atoi() call converts a nonnumeric
suffix to zero. The resulting mask is then assigned to the static stack configuration.

cli/vtesse_cli.c[275-276]
cli/vtesse_cli.c[314-329]
cli/vtesse_cli.c[956-964]
cli/vtesse_cli.c[1070-1080]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A malformed `vtesse_ip` prefix can be interpreted as `/0` instead of rejected.
## Fix Focus Areas
- cli/vtesse_cli.c[275-276]
- cli/vtesse_cli.c[314-329]
## Recommended Fix
Parse the prefix with full-string numeric validation and reject empty, nonnumeric, or out-of-range suffixes before applying the static network setting.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


15. A stale interface overrides a new session ✓ Resolved
Description
apply_env() processes vtesse_id_from after vtesse_session and clears the session, even when
the session variable was just set to a valid value. If support changes the session with `fw_setenv
vtesse_session ... while an older vtesse_id_from` remains, the client uses the old interface
instead and fails to start if that interface no longer has a usable MAC.
Code

cli/vtesse_cli.c[R294-295]

+        else if (!strcmp(key, "id_from"))
+            c->session[0] = '\0';
Evidence
The variable table lists session before id_from, and apply_env() iterates in that order while
clearing the opposite field for each value. Runtime then resolves the surviving id_from through
id_from_interface(), whose failure prevents startup.

cli/env.c[17-24]
cli/vtesse_cli.c[259-295]
cli/vtesse_cli.c[900-909]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
When both U-Boot identity variables are set, `apply_env()` silently discards `vtesse_session` in favor of `vtesse_id_from`. A stale interface variable can therefore override a newly supplied session and prevent startup.
## Fix Focus Areas
- cli/vtesse_cli.c[253-299]
- cli/env.c[17-24]
## Recommended Fix
Detect when both identity variables are nonempty and fail with an explicit message telling the user to clear one, rather than silently choosing by iteration order. Add a test covering a valid session alongside a stale interface variable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


16. Helpdesk tunnel may not come up when booted before the network ✓ Resolved
Description
In environment mode, main() picks the device-ID interface and the derived password exactly once at
startup, using ve_default_iface(). If no default route exists yet, that function falls back to
eth0, and if eth0 has no MAC it fails with exit code 2. On a camera whose uplink (for example
wlan0 with background udhcpc) gets its default route only after S99vtesse runs, the client
either exits for good, because S99vtesse uses start-stop-daemon -b with no respawn, or keeps
reconnecting with an eth0-derived session and password that the VTun server rejects.
Code

cli/vtesse_cli.c[R886-890]

+        if (!c.session[0] && !c.id_from[0] && !id_from &&
+            ve_default_iface(c.id_from, sizeof(c.id_from)) < 0) {
+            fprintf(stderr, "no interface with a MAC for the device ID: set vtesse_session or vtesse_id_from\n");
+            return 2;
+        }
Evidence
ve_default_iface reads /proc/net/route once and falls back to eth0 (env.c 174-191). main() calls
it for the session (vtesse_cli.c 886-890) and again for the password (918-923), and returns 2 on
failure. S99vtesse starts the daemon once in the background with no respawn, and its start check
only looks at the variable, not at the network, so a start before the route exists is either fatal
or uses the wrong MAC until someone restarts the service by hand.

cli/env.c[174-191]
cli/vtesse_cli.c[882-927]
scripts/S99vtesse[20-35]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
In U-Boot environment mode the session/password interface is resolved once at startup. If the default route is not there yet, the client either exits (S99vtesse has no respawn) or uses eth0's MAC instead of the real uplink's.
## Fix Focus Areas
- cli/vtesse_cli.c[882-927]
- cli/env.c[174-191]
- scripts/S99vtesse[20-35]
## Recommended Fix
When only `vtesse` is set and no session/password override is present, wait (with a bounded retry, e.g. up to 60 s) until /proc/net/route has a default route through an interface with a MAC, before deriving the session and password. Only fall back to eth0 once that wait times out. Or let S99vtesse retry: run the client in a loop, or wait for the default route before starting it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


17. Install fails on hosts with unconfigured U-Boot tools ✓ Resolved
Description
do_install() decides whether to write U-Boot variables from ve_can_write() alone, and that only
checks that a fw_setenv binary is on PATH; it never checks that the device actually has a working
U-Boot environment. On a PC or router that has fw_setenv installed but no usable
/etc/fw_env.config, vtesse --install --host X --password P writes the binary, config and init
script, then ve_set_script() fails and the install returns 1 with "the service is not started".
Before this PR the same install worked, and the ticket says this step should be skipped silently on
such systems.
Code

cli/install.c[R987-988]

+    /* the given keys also go to the U-Boot environment, when the device has one (#64) */
+    if (n && !root[0] && ve_can_write()) {
Evidence
ve_can_write() (env.c 103-119) only calls access("/fw_setenv", X_OK) on each PATH directory.
ve_load() already treats a failing fw_printenv (no fw_env.config) as "no environment" and stays
silent, but the write path in do_install() (install.c 988-1014) runs whenever `n && !root[0] &&
ve_can_write(), and turns any non-zero fw_setenv exit into a fatal return 1. The -s -` call is
reached even when ve_load() could not read any environment at all.

cli/env.c[103-119]
cli/env.c[85-100]
cli/install.c[987-1020]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`--install` with keys aborts on systems where `fw_setenv` is installed but there is no working U-Boot environment, for example a PC with u-boot-tools and no fw_env.config. The reason is that `ve_can_write()` only checks PATH.
## Fix Focus Areas
- cli/env.c[85-119]
- cli/install.c[918-921]
- cli/install.c[987-1020]
## Recommended Fix
Have `ve_load()` report whether `fw_printenv` succeeded, for example through an `ok` field in `ve_t` or a separate return flag. In `do_install()`, require both that `fw_printenv` succeeded and that `ve_can_write()` is true before building and running the `fw_setenv -s -` script. Use the same condition everywhere `ve_can_write()` is used to pick the env path (the env-only path and `env_conflict`). When the environment is not readable, treat it as "no fw_setenv" and skip the step silently, as the ticket requires.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


18. Reinstall rejects a working tunnel ✓ Resolved
Description
build_config() rejects a file containing both session and id_from before its new
environment-backed return, even when vtesse_session or vtesse_id_from makes those file values
mutually exclusive at runtime. With a U-Boot identity override, the client can use that file
successfully, but a later --install fails without changing the installation.
Code

cli/install.c[R620-621]

+    if (env)
+        return 0;
Evidence
The installer passes the loaded environment to build_config(), where the existing two-key
rejection runs before the new environment-backed return. The runtime merge instead clears the
opposite identity field when applying an environment identity variable.

cli/install.c[919-944]
cli/install.c[609-621]
cli/vtesse_cli.c[291-295]
cli/vtesse_cli.c[873-881]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An environment identity override makes a file containing both identity keys usable at runtime, but `build_config()` rejects the file during reinstall.
## Fix Focus Areas
- cli/install.c[609-621]
- cli/vtesse_cli.c[291-295]
## Recommended Fix
When validating identity keys in environment-backed mode, account for the environment value that replaces the file's identity setting. Preserve rejection when the effective settings still conflict.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


19. A boot override starts an unusable service ✓ Resolved
Description
S99vtesse accepts a U-Boot server as sufficient to start without a config file even when its
configured ARGS includes --no-env. With that override in /etc/default/vtesse, the launched
client ignores the server and exits because the file is missing.
Code

scripts/S99vtesse[R22-23]

+    if [ ! -f "$CONFIG" ] && [ -z "$(fw_printenv -n vtesse 2>/dev/null)" ]; then
+        echo "vtesse: neither $CONFIG nor vtesse in the U-Boot environment, not starting"
Evidence
The script sources ARGS before checking only file existence and fw_printenv, then passes ARGS to the
client. The client skips ve_load under --no-env and requires the absent file.

scripts/S99vtesse[14-28]
cli/vtesse_cli.c[782-785]
cli/vtesse_cli.c[873-877]
cli/vtesse_cli.c[174-180]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The boot script starts an environment-only installation even when its arguments tell the client to ignore that environment.
## Fix Focus Areas
- scripts/S99vtesse[14-28]
## Recommended Fix
Make the missing-file guard account for `--no-env` in the configured arguments, so it does not launch a client with neither an effective file nor an effective U-Boot server.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

20. A mistyped config path is silently ignored 🐞 Bug ◔ Observability
Description
When vtesse is set in the U-Boot environment, main() calls load_config(config, &c, !env_mode),
and on ENOENT that function returns 1 without printing anything, whatever --config path was
given. A run such as vtesse --config /etc/vtese.conf --tap on a camera with vtesse set quietly
drops the routes, relays, SOCKS users and keys the operator meant to load and connects with the VTun
defaults, and nothing tells them the file was never read.
Code

cli/vtesse_cli.c[R178-179]

+        if (errno == ENOENT && !must_exist)
+            return 1;
Evidence
load_config returns 1 with no message when the file is missing and must_exist is 0. main
passes !env_mode for every path, including one given explicitly with --config. The only check
after that is rc < 0, so the missing file is never reported.

cli/vtesse_cli.c[168-182]
cli/vtesse_cli.c[876-880]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
In environment mode a missing config file is skipped without any message, so a mistyped `--config` path is silently ignored.
## Fix Focus Areas
- cli/vtesse_cli.c[176-180]
- cli/vtesse_cli.c[876-880]
## Recommended Fix
When `load_config` returns 1, print a one-line note such as `<path> not found: settings from the U-Boot environment`. Also consider requiring the file to exist when `--config` was given explicitly, which means it differs from the default `/etc/vtesse.conf` that the service uses.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


21. Each new boot variable needs five matching edits 🐞 Bug ⚙ Maintainability
Description
The mapping from a variable to its config key to its field is written out separately in ve_vars
and field() (env.c), in env_value() (install.c), and in apply_env() and env_any()
(vtesse_cli.c). Adding a variable such as vtesse_route to ve_vars without updating every copy
compiles cleanly, but the new variable is then dropped without notice at load time (field()
returns NULL), ignored at runtime, or never treated as a conflict at install.
Code

cli/install.c[R641-647]

+static const char *env_value(const ve_t *e, const char *key)
+{
+    return !strcmp(key, "host") ? e->host : !strcmp(key, "port") ? e->port :
+           !strcmp(key, "session") ? e->session : !strcmp(key, "id_from") ? e->id_from :
+           !strcmp(key, "password") ? e->password : !strcmp(key, "ip") ? e->ip :
+           !strcmp(key, "gw") ? e->gw : "";
+}
Evidence
Each of these functions repeats the same key-to-field chain of strcmp comparisons. ve_load uses
field() and skips a variable when dst is NULL. apply_env leaves v NULL for a key it does not
know and skips it. env_value returns an empty string for an unknown key, so env_conflict never
flags it.

cli/env.c[17-47]
cli/install.c[640-676]
cli/vtesse_cli.c[248-300]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The variable/key/field mapping is copied in four functions plus the `ve_vars` table, so adding a variable needs several edits that must stay in sync.
## Fix Focus Areas
- cli/env.c[17-47]
- cli/env.h[25-31]
- cli/install.c[640-647]
- cli/vtesse_cli.c[248-300]
## Recommended Fix
Add `offset` and `size` fields to `ve_var_t` (using `offsetof(ve_t, ...)`), or export a `ve_field(const ve_t *, size_t index)` accessor. Then have `field()`, `env_value()`, `env_any()` and `apply_env()` loop over `ve_vars` instead of repeating the `strcmp` chains. Keep the special port and session/id_from handling as explicit cases.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can move or hide resolved findings to focus on what still needs action

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread README.md Resolved
Comment thread cli/install.c Resolved
Comment thread cli/install.c Resolved
Comment thread cli/install.c Resolved
Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/install.c Resolved
Comment thread cli/vtesse_cli.c Resolved
- A failed fw_setenv stops --install before the service starts; storing
  vtesse_session clears vtesse_id_from and the reverse.
- --root does not use this machine's U-Boot environment.
- With the server in the environment and no config file, --install with
  some keys stores them there instead of demanding a full config.
- The MAC-derived password also applies with an explicit vtesse_session
  (default-route interface).
- vtesse_port must be 1..65535: a typo is refused, not turned into 5000.
- READMEs: the variables are readable with root or a flash dump, and the
  derived password is no secret.
@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment thread docs/testing.md Resolved
Comment thread cli/install.c Resolved
Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/install.c Resolved
Comment thread cli/install.c Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 16a18e9

- A failed fw_setenv restores the variables already written in that run.
- An environment-only --install refuses --gw without --ip / vtesse_ip.
- --show-config also lists routes, UDP relays and the SOCKS5 user.
- --uninstall --root does not report this machine's variables.
@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/env.c Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit d2aad04

- The derived password uses the default-route interface, as OpenIPC's
  tunnel does, whatever vtesse_id_from names for the session.
- An invalid port= in the file is refused instead of becoming 5000.
- A U-Boot value too long for its field is reported, not silently dropped.
@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/install.c Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit b85f3e8

- Every vtesse_* variable overrides its key also without vtesse; only the
  server variable allows a missing file and brings the VTun defaults.
- --install writes the variables in one fw_setenv -s - batch on stdin: the
  password never shows in the process list, and nothing is half written
  (replaces the rollback).
- --show-config refuses a session name the client would refuse.
@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment thread cli/install.c Resolved
Comment thread cli/env.c Resolved
Comment thread cli/install.c Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 5be36d4

@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment thread cli/install.c Resolved
Comment thread cli/install.c Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit fe6ddad

Comment thread cli/env.c Resolved
Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/install.c Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 25d2365

@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment thread cli/install.c Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 62894b6

@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/vtesse_cli.c Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 4bc239a

@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/vtesse_cli.c Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit d079193

@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment thread cli/install.c Resolved
Comment thread cli/install.c Resolved
Comment thread cli/vtesse_cli.c Resolved
Comment thread scripts/S99vtesse Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 890a797

- --install with the server in the U-Boot environment, no config file and
  no fw_setenv keeps the given keys in /etc/vtesse.conf instead of refusing
  for a missing server and password; a key whose variable is already set is
  refused, as the variable would override the file.
- ve_set_script() restores the previous SIGPIPE disposition after the write,
  so the commands started later do not inherit SIG_IGN.
- With no config file, --install --host NEW names the new server.
- While vtesse (the server) is set, build_config() takes the server, the
  defaults and the derived password as coming from the environment: a
  keys-only /etc/vtesse.conf no longer breaks a later --install, and gets
  no port or id_from defaults.
- Without fw_setenv, a given key whose vtesse_* variable is set is refused
  also when the config file exists (env_conflict replaces build_env_file).
- --show-config checks the file's udp_relay entries as a start does.
- ve_load() uses nothing from a fw_printenv that failed, and says so when
  it printed vtesse variables (no fw_env.config stays silent).
- ve_set() is gone: --install writes only through the fw_setenv -s batch.
- The fw_setenv script is built with a bounds check (script_add); too long
  settings stop --install instead of overrunning the buffer.
- --install refuses control characters in any value.
- While vtesse is set, a valid vtesse_port lets a reinstall keep a file
  whose port is invalid (the variable wins at runtime).
- S99vtesse: with --no-env in ARGS the environment does not stand in for
  a missing config file.
- While vtesse is set, vtesse_session or vtesse_id_from lets a reinstall
  keep a file with both session and id_from (the variable replaces both).
- --install writes the U-Boot environment only when fw_printenv read it
  (ve_t.ok) and fw_setenv is in PATH: u-boot-tools without fw_env.config
  (a PC, a router) no longer make an install with keys fail; the step is
  skipped as without fw_setenv.
- vtesse_session and vtesse_id_from both set: the client refuses to start
  instead of picking one by the order of the variables.
- With only the server in the environment, a start (not --show-config)
  waits up to 60 s for a default route through an interface with a MAC
  before the VTun defaults fall back to eth0: Wi-Fi uplinks get their
  route after S99vtesse.
- A default route is destination and mask 0 (a VPN's 0.0.0.0/1 is not).
- The boot wait ends at any default route; through PPPoE or tun (no MAC)
  eth0 is taken at once instead of after 60 s.
- ip prefixes are parsed digits only: "/garbage" is refused, not /0.
@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

Comment thread cli/vtesse_cli.c Resolved
Comment thread cli/install.c Resolved
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 76df998

@compot-dev
compot-dev merged commit 7ed8b22 into main Oct 18, 2026
10 checks passed
@compot-dev
compot-dev deleted the feat/uboot-env-64 branch October 18, 2026 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Helpdesk access from the U-Boot environment: fw_setenv vtesse <server>, as with vtun

1 participant