Skip to content

Commit 9d37427

Browse files
committed
fix: don't expose eMMC as USB mass storage when no image is mounted
When /boot/usb.disk0 exists but is empty (the default state), the USB gadget init script (S03usbdev) sets /dev/mmcblk0p3 as the mass storage backing file. This exposes the NanoKVM's raw eMMC partition (~162MB, ext4/exfat) as a USB disk to the host computer. On Legacy BIOS systems, the BIOS attempts to boot from this device, reads invalid data (no MBR), and enters a HLT loop — completely hanging the system with no keyboard input accepted. The only recovery is a physical power cycle. Similarly, the Go server (image.go) re-mounts /dev/mmcblk0p3 whenever an ISO image is unmounted, re-exposing the eMMC partition. Changes: S03usbdev: Flip the empty-file check so that when usb.disk0 is empty, no backing file is set. The mass_storage device (with removable=1) reports "no media inserted" — which BIOS handles safely by skipping to the next boot device. When usb.disk0 contains a path, that path is used as before. image.go: Remove the imageNone constant (/dev/mmcblk0p3). When unmounting an image (empty request), the device stays unmounted instead of falling back to the eMMC partition. GetMountedImage retains backward compatibility by treating mmcblk0p3 as "no image" for devices that haven't rebooted yet. No changes needed to virtual-device.go — with this fix, toggling "Virtual Disk" ON creates the mass_storage gadget with no media (correct behavior), and users mount ISOs through the existing UI. Refs: #633, #385, #438, #187
1 parent 4af32fc commit 9d37427

2 files changed

Lines changed: 19 additions & 20 deletions

File tree

kvmapp/system/init.d/S03usbdev

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,15 @@ start_usb_dev(){
106106
fi
107107
echo "NanoKVM USB Mass Storage0520" > functions/mass_storage.disk0/lun.0/inquiry_string
108108
disk=$(cat /boot/usb.disk0)
109-
if [ -z "${disk}" ]
109+
if [ -n "${disk}" ]
110110
then
111-
# if [ ! -e /mnt/usbdisk.img ]
112-
# then
113-
# fallocate -l 8G /mnt/usbdisk.img
114-
# mkfs.vfat /mnt/usbdisk.img
115-
# fi
116-
echo /dev/mmcblk0p3 > functions/mass_storage.disk0/lun.0/file
117-
else
118111
cat /boot/usb.disk0 > functions/mass_storage.disk0/lun.0/file
119112
fi
113+
# When usb.disk0 is empty, no backing file is set. The device
114+
# reports "no media" (removable=1). Previously this defaulted to
115+
# /dev/mmcblk0p3, exposing the NanoKVM's raw eMMC partition as a
116+
# USB disk — causing Legacy BIOS systems to hang during boot.
117+
# See: https://github.com/sipeed/NanoKVM/issues/633
120118
fi
121119

122120
ls /sys/class/udc/ | cat > UDC

server/service/storage/image.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818

1919
const (
2020
imageDirectory = "/data"
21-
imageNone = "/dev/mmcblk0p3"
2221
cdromFlag = "/sys/kernel/config/usb_gadget/g0/functions/mass_storage.disk0/lun.0/cdrom"
2322
mountDevice = "/sys/kernel/config/usb_gadget/g0/functions/mass_storage.disk0/lun.0/file"
2423
inquiryString = "/sys/kernel/config/usb_gadget/g0/functions/mass_storage.disk0/lun.0/inquiry_string"
@@ -109,16 +108,17 @@ func (s *Service) MountImage(c *gin.Context) {
109108
}
110109

111110
// mount
112-
image := req.File
113-
if image == "" {
114-
image = imageNone
115-
}
116-
117-
if err := os.WriteFile(mountDevice, []byte(image), 0o666); err != nil {
118-
log.Errorf("mount file %s failed: %s", image, err)
119-
rsp.ErrRsp(c, -2, "mount image failed")
120-
return
111+
if req.File != "" {
112+
if err := os.WriteFile(mountDevice, []byte(req.File), 0o666); err != nil {
113+
log.Errorf("mount file %s failed: %s", req.File, err)
114+
rsp.ErrRsp(c, -2, "mount image failed")
115+
return
116+
}
121117
}
118+
// When req.File is empty the device stays unmounted (no media).
119+
// Previously this wrote /dev/mmcblk0p3, exposing the NanoKVM's raw
120+
// eMMC partition as a USB disk — causing Legacy BIOS boot hangs.
121+
// See: https://github.com/sipeed/NanoKVM/issues/633
122122

123123
h := hid.GetHid()
124124
h.Lock()
@@ -156,8 +156,9 @@ func (s *Service) GetMountedImage(c *gin.Context) {
156156
return
157157
}
158158

159-
image := strings.ReplaceAll(string(content), "\n", "")
160-
if image == imageNone {
159+
image := strings.TrimSpace(string(content))
160+
if image == "/dev/mmcblk0p3" {
161+
// Backward compat: treat eMMC partition as "no image mounted"
161162
image = ""
162163
}
163164

0 commit comments

Comments
 (0)