Skip to content

S03usbdev: derive USB serial number from SoC hardware UID - #746

Open
JakeHillion wants to merge 1 commit into
sipeed:mainfrom
JakeHillion:jj/wlpzynswntvx
Open

JakeHillion wants to merge 1 commit into
sipeed:mainfrom
JakeHillion:jj/wlpzynswntvx

Conversation

@JakeHillion

Copy link
Copy Markdown

The USB gadget serial number was hardcoded to '0123456789ABCDEF', meaning every NanoKVM device presented the same serial to the host.

Read the SoC unique identifier from /sys/class/cvi-base/base_uid on each boot and concatenate its two halves into a single hex string for use as the USB serial number. Falls back to the old hardcoded value if the UID file is not present.

This gives each device a stable, hardware-derived serial number without requiring any persistent state, and satisfies the USB Mass Storage requirement of at least 12 characters. This means you can query the USB interface on the machine the KVM is plugged into to find out which NanoKVM is plugged in, instead of that there is a NanoKVM plugged in.

Test plan:

Installed script on two NanoKVMs with:
scp kvmapp/system/init.d/S03usbdev root@kvm04:/etc/init.d/S03usbdev

Plugged into a Linux machine, before I got:

[jake@li-bl-eq14-1:~]$ nix shell nixpkgs#usbutils --command lsusb -v | grep NanoKVM -A 50
Bus 003 Device 006: ID 3346:1009 sipeed NanoKVM
Negotiated speed: High Speed (480Mbps)
Device Descriptor:
...
  idVendor           0x3346 sipeed
  idProduct          0x1009 NanoKVM
  bcdDevice            5.10
  iManufacturer           1 sipeed
  iProduct                2 NanoKVM
  iSerial                 3 0123456789ABCDEF

After the update, I get the same, but the serial number is now unique per device. I unplugged the devices and plugged them back in, this is now a consistent and unique identifier between my NanoKVMs from the host device.

The USB gadget serial number was hardcoded to '0123456789ABCDEF',
meaning every NanoKVM device presented the same serial to the host.

Read the SoC unique identifier from /sys/class/cvi-base/base_uid on
each boot and concatenate its two halves into a single hex string for
use as the USB serial number. Falls back to the old hardcoded value if
the UID file is not present.

This gives each device a stable, hardware-derived serial number
without requiring any persistent state, and satisfies the USB Mass
Storage requirement of at least 12 characters. This means you can query
the USB interface on the machine the KVM is plugged into to find out
_which_ NanoKVM is plugged in, instead of that there is a NanoKVM
plugged in.

Test plan:

Installed script on two NanoKVMs with:
    scp kvmapp/system/init.d/S03usbdev root@kvm04:/etc/init.d/S03usbdev

Plugged into a Linux machine, before I got:

```
[jake@li-bl-eq14-1:~]$ nix shell nixpkgs#usbutils --command lsusb -v | grep NanoKVM -A 50
Bus 003 Device 006: ID 3346:1009 sipeed NanoKVM
Negotiated speed: High Speed (480Mbps)
Device Descriptor:
...
  idVendor           0x3346 sipeed
  idProduct          0x1009 NanoKVM
  bcdDevice            5.10
  iManufacturer           1 sipeed
  iProduct                2 NanoKVM
  iSerial                 3 0123456789ABCDEF
```

After the update, I get the same, but the serial number is now unique
per device. I unplugged the devices and plugged them back in, this is
now a consistent and unique identifier between my NanoKVMs from the host
device.
winstar0070 added a commit to Stella-IT/NanoKVM that referenced this pull request Feb 12, 2026
Use the unique hardware UID from /sys/class/cvi-base/base_uid as the
USB serial number instead of a hardcoded value. Falls back to the
default if the UID file is not available.

Cherry-picked from: sipeed#746
Original author: JakeHillion
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Jul 28, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 2, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 3, 2026
Every NanoKVM reports the same USB serial, 0123456789ABCDEF, so a host
that sees two of them cannot tell them apart. Udev rules, drive letters
and per-device settings all key off that string, so the second device
inherits whatever the first one was given. This is upstream sipeed#746.

The SG2002 exposes a per-chip UID at /sys/class/cvi-base/base_uid, which
the same script already reads to derive the gadget MACs. Use it here too.

The constant stays as a fallback, and a length guard decides when. Mass
storage requires a serial of at least 12 characters, so a short or
unexpected UID keeps the old value rather than handing the gadget a
serial the host rejects and failing to enumerate at all.
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 3, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.
@yuzi-co

yuzi-co commented Aug 3, 2026

Copy link
Copy Markdown

I had written the same change independently before finding this PR, so I have dropped mine. One difference is worth folding in here.

The -f test confirms the file exists, but it does not confirm that awk '{print $2}' returns anything. If the field is missing or the format differs on a variant, _serial ends up empty or short, and the empty string is then written as the serial number.

That matters more than it looks. As you note, mass storage requires a serial of at least 12 characters. A serial that fails that requirement does not degrade to the old behaviour — the gadget fails to enumerate, so the operator loses keyboard, mouse and disk rather than just losing the ability to tell two devices apart. The fallback would be the safer outcome in that case, but the current shape cannot reach it once the file exists.

A length check picks the fallback instead:

serial='0123456789ABCDEF'
if [ -f /sys/class/cvi-base/base_uid ]
then
    uid_serial=$(awk '{print $2}' /sys/class/cvi-base/base_uid | tr -d '_')
    if [ ${#uid_serial} -ge 12 ]
    then
        serial="$uid_serial"
    fi
fi
echo "$serial" > strings/0x409/serialnumber

${#var} is POSIX and busybox ash supports it, so it needs nothing extra on the device.

I have not seen a board where base_uid is malformed — this is defensive rather than a reported failure. But the cost of being wrong is asymmetric enough that I think it earns the four lines.

Otherwise this reads correctly to me, and the per-device serial is genuinely useful once you have more than one on a bench.

yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 4, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.

(cherry picked from commit f6cceba)
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 4, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.

(cherry picked from commit f6cceba)
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 4, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.

(cherry picked from commit f6cceba)
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 7, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 10, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 16, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 16, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.

(cherry picked from commit f6cceba)
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 16, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.

(cherry picked from commit f6cceba)
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 16, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 18, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.
yuzi-co added a commit to yuzi-co/IronKVM that referenced this pull request Aug 24, 2026
Four upstream fixes to the same gadget setup, none of them merged.

Do not expose the eMMC as a USB disk (upstream sipeed#741). With /boot/usb.disk0
empty - the out-of-box state - the gadget's backing file pointed at
/dev/mmcblk0p3. That partition has no MBR, so a Legacy BIOS reads sector 0,
finds no 0x55AA signature and hangs in a HLT loop with no keyboard; the only
way out is a physical power cycle. Leaving the backing file unset makes the
device report "no media" and the BIOS moves on. MountImage wrote the same
device when unmounting, so the raw partition came back on every eject.
GetMountedImage still reads it as "nothing mounted" for devices that have
not rebooted yet.

Default wakeup_on_write to off (upstream sipeed#754). Every HID write attempted a
USB remote wakeup. Hosts that refuse it - common in BIOS, during restart,
and on several chipsets - leave the DWC2 endpoint wedged, so keyboard and
mouse die until the gadget is rebuilt. The opt-out flag /boot/usb.notwakeup
becomes the opt-in flag /boot/usb.wakeup.

Derive both gadget MACs from the chip UID (upstream sipeed#828). dev_addr and
host_addr were left unset, so the kernel picked random MACs on every bind
and the attached PC registered a new network adapter each reboot.

Derive the USB serial from the chip UID (upstream sipeed#746). Every NanoKVM
reported 0123456789ABCDEF, so a host could not tell two of them apart. Added
a length guard the original lacks: mass storage requires at least 12
characters, so a short UID keeps the old constant rather than handing the
gadget a serial the host rejects.
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.

2 participants