Post

How To: Hotfixing the NanoKVM Pro to get WiFi working

How to fix the NanoKVM Pro WiFi

How To: Hotfixing the NanoKVM Pro to get WiFi working

Introduction

The NanoKVM Pro Desk is a cheap Ubuntu based KVM over IP by Sipeed. As of the current firmware v1.0.7 WiFi does not appear to be working. I have tried enabling WiFi both via the WebGUI (whilst connected to Ethernet) and in Access Point mode (with Ethernet disconnected) and it fails to connect. The reason for this appears to be a result of some faulty scripts, so I have made workaround below.

Enabling SSH

  • Login to the NanoKVM,
  • Then go to Settings
  • Then Device
  • You can now enable SSH

Enable SSH Toggle

  • You can now login to SSH using the username root and your webgui password.

Do not expose SSH to the public Internet.

Hotfixing WiFi

This hotfix may break in future firmware updates.

The NanoKVM Pro does not use Ubuntu NetworkManager instead it appears to use wpa_supplicant & dhclient with a combination of custom scripts.

First we confirm the state of WiFi connection:

1
2
3
4
5
6
7
8
9
root@kvm-g33k:~# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether ab:12:cd:34:ef:56 brd ff:ff:ff:ff:ff:ff
3: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
4: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000
    link/ether 12:ab:34:cd:56:ef brd ff:ff:ff:ff:ff:ff

As mentioned, NanoKVM uses some a custom Ubuntu Service and Script, which in the current firmware version (v1.0.7 at time of writing) appears to be faulty.

First we backup the original wifi.service in case we need to restore it in the future.

1
mv /etc/systemd/system/wifi.service /etc/systemd/system/wifi.service.old

Now we create a new wifi.service:

1
vi /etc/systemd/system/wifi.service

Paste the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=Custom WiFi bring-up
After=boot.mount network-pre.target
Wants=network-pre.target
Requires=boot.mount

[Service]
Type=oneshot
ExecStart=/opt/scripts/wifi.sh start
# ExecStop is optional now; leave it if you want a manual stop to cleanly disconnect
ExecStop=/opt/scripts/wifi.sh stop
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Now backup the WiFi script:

1
mv /opt/scripts/wifi.sh /opt/scripts/wifi.sh.old

Now create the new wifi.sh script:

1
vi /opt/scripts/wifi.sh

Paste the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/bin/sh

gen_hostapd_conf() {
  ssid="$1"; pass="$2"
  cat <<EOF
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=$ssid
hw_mode=g
channel=1
beacon_int=100
dtim_period=2
max_num_sta=255
rts_threshold=-1
fragm_threshold=-1
macaddr_acl=0
auth_algs=3
wpa=2
wpa_passphrase=$pass
ieee80211n=1
EOF
}

dhcp_client_run() {
  dhclient -v wlan0 || true
}

wpa_supplicant_run() {
  wpa_supplicant -B -i wlan0 -Dnl80211 -c /etc/wpa_supplicant.conf
}

wpa_supplicant_stop() {
  pkill -x wpa_supplicant 2>/dev/null || true
  ifconfig wlan0 down 2>/dev/null || true
}

wpa_supplicant_start() {
  if [ -e /boot/wifi.sta ]; then
    echo "wifi mode: sta"
    if [ -e /boot/wpa_supplicant.conf ]; then
      cp /boot/wpa_supplicant.conf /etc/wpa_supplicant.conf
    else
      ssid=""; pass=""
      [ -e /boot/wifi.ssid ] && ssid="$(cat /boot/wifi.ssid)"
      [ -e /boot/wifi.pass ] && pass="$(cat /boot/wifi.pass)"
      if [ -n "$ssid$pass" ]; then
        {
          echo "ctrl_interface=/run/wpa_supplicant"
          wpa_passphrase "$ssid" "$pass"
        } > /etc/wpa_supplicant.conf
      else
        echo "No SSID/PASS in /boot; skipping STA." >&2
        return 1
      fi
    fi
    ifconfig wlan0 up
    wpa_supplicant_run
    sleep 2
    dhcp_client_run
    return 0
  elif [ -e /boot/wifi.ap ]; then
    echo "wifi mode: ap"
    # (AP bits left as-is; fix typo)
    ifconfig wlan0 up
    ip addr flush dev wlan0
    # hostapd/udhcpd start would go here
    return 0
  elif [ -e /boot/wifi.mon ]; then
    echo "wifi mode: mon"
    airmon-ng start wlan0
    return 0
  else
    # default: try a fallback network if desired
    return 0
  fi
}

wifi_stop() {
  pkill -x wpa_supplicant 2>/dev/null || true
  dhclient -r wlan0 2>/dev/null || true
  ifconfig wlan0 down 2>/dev/null || true
}

wifi_start() {
  # device-specific pinmux
  devmem 0x104F200C 32 0x00000008
  devmem 0x104F2018 32 0x00000008
  devmem 0x104F2024 32 0x00000008
  devmem 0x104F2030 32 0x00000008
  devmem 0x104F203C 32 0x00000008
  devmem 0x104F2048 32 0x00000008

  lsmod | grep -q aic8800_bsp || insmod /soc/ko/aic8800_bsp.ko
  if lsmod | grep -q aic8800_fdrv; then
    echo "aic8800_fdrv already loaded"
  else
    insmod /soc/ko/aic8800_fdrv.ko
  fi

  # actually start Wi-Fi in STA/AP/mon per /boot flags
  wpa_supplicant_start
}

case "$1" in
  start)   echo "wifi start";   wifi_start ;;
  stop)    echo "wifi stop";    wifi_stop  ;;
  restart) echo "wifi restart"; wifi_stop; wifi_start ;;
  *) echo "usage: $0 {start|stop|restart}"; exit 1 ;;
esac

Now make the script executable:

1
chmod +x /opt/scripts/wifi.sh

Enable WiFi Client mode:

1
touch /boot/wifi.sta

Now we need to configure our WiFi SSID and Password. I use the read command to handle special characters:

1
2
3
4
root@kvm-g33k:~# read -r -p "SSID: " ssid; echo
SSID: GeekHome
root@kvm-g33k:~# read -rs -p "Password: " pass; echo
Password:

(Your password will be hidden).

Next we write the WiFi SSID and Password to the configuration files:

1
2
printf '%s' "$ssid" > /boot/wifi.ssid
printf '%s' "$pass" > /boot/wifi.pass

Reload and restart the Wifi service:

1
2
systemctl daemon-reload
systemctl restart wifi.service

You should now find WiFi is connected and if you reboot the NanoKVM it connects automatically on startup. Don’t forget to disable SSH!

This post is licensed under CC BY 4.0 by the author.