Recent Linux on the D-Link DNS-313
(Last boot 2018-05-16 on v4.17-rc1 with OpenWRT as rootfs)

D-Link DNS-313

D-Link DNS-313

The D-Link DNS-313 is a very vanilla NAS released by D-Link in October 2007 with TV adverts and everything, using the Gemini platform, and ARMv4 Faraday silicon design. Firmware was still being released in 2010. The source files are dated october 2013. It has the following features (see the datasheet for details):

This NAS only has a mere 512KB of Flash memory, just enough to hold the boot loader. It will install the Linux kernel and the initrd and root filesystem on the harddrive, which makes it a very rewarding hacking target: it is possible to avoid any of the brutal hardware hacking below, just take out the drive, mount partition 3 in another cradle and replace these:

And the NAS will come up with your custom kernel, initrd/initramfs and rootfs. These images uses a custom header for the bootloader to recognize them, you can add it simply by using my dns313-header.c program. The idea is to integrate this special header tagger into OpenWRT/LEDE.

You might wonder how those files end up on the harddrive in the first place. I think this is done using the supplied driver CDs for Windows and Mac. I think those drivers talk to the boot loader on the board over USB and downloads these images for initial boot after initializing the hard drive. I haven't even tested this and I have never bootstrapped the NAS this way because I have no Windows nor Mac installation to use the CDs with.

As of may 2018 OpenWRT already supports the DNS-313 pretty well and most changes to it are upstream in the OpenWRT tree or in the Linux upstream kernel.

Quick Install of Hard Disk Boot with Busybox or OpenWRT

It is possible to prepare a SATA hard disk and use that to boot OpenWRT and set the device up as a NAS without any soldering or other trickery. All you need to know is how to use OpenWRT.

My first bootlog of OpenWRT booting on the DNS-313.

Pre-cooked harddisk images

These contain the three harddisk images (rd.gz, rootfs.tgz and zImage) with the special D-Link headers and work with the Busybox or OpenWRT rootfs:es, they are development snapshots that I tested myself. Ethernet works but not USB.

Set Up as NAS

Essentially a basic configuration as OpenWRT NAS is very simple and straight forward.

  cd /
  mkdir samba
  chown nobody samba
  chgrp nogroup samba

Edit /etc/config/samba to contain something like this:

config samba
    option 'name'                   'DNS-313'
    option 'workgroup'              'WORKGROUP'
    option 'description'            'DNS-313'
    option 'homes'                  '0'
    option 'interface'              'lan'

config sambashare
    option 'name'                   'files'
    option 'path'                   '/samba'
    option 'guest_ok'               'yes'
    option 'create_mask'            '0700'
    option 'dir_mask'               '0700'
    option 'read_only'              'no'

Reboot and you can browse to the IP number (etc) of your NAS and upload and download files to /samba, of course you can set up whatever partition etc you like.

Getting into it

The case is a very easily dismantled standard aluminium profile with the PCB slotted in.

Circuit board photos

Identified electronics:

Connecting a UART

For deep core hacking like kicking kernels directly from the network over TFTP and interactive initramfs console it is necessary to mount a UART. I guess this is not necessary if you just want to kick a fresh kernel from the harddrive and use/develop the DNS-313 from there. But this page is for hardware-savvy people like myself.

The UART is located above the SoC right of the G751-2f temperature sensor:

D-Link DNS-313 UART

You need to solder three leads for GND, RX and TX. I don't know if the fourth lead supplies UART power, maybe it does? I just used these three anyways (OK do not complain about my bad soldering, I'm 45 years old and my eyesight and precision is degrading. Or I was just sloppy, only one cup of coffee so far this morning):

D-Link DNS-313 UART soldered

Once you verified that the UART is working (see below, both RX and TX must work so you get an interactive console) then do not leave it like this! The soldered wires are usually not super-stable there. Instead do what I always do: cover the soldered leads in a blob of epoxy glue! Else they will inevitably come off. Then connect the things to a UART-to-serial adapter/converter such as this SparkFun FTDI adapter like this:

D-Link DNS-313 FTDI

Then open (in this case) /dev/ttyUSB0 in minicom set it to 19200 baud, no hardware flow control (obviously, do you see any CTS or DTS leads) 8 bits, 1 stop bit. In minicom you may need to hit B to move to the 19200 baud setting. Then power on the device.

Once the UART is properly connected then connect the DC connector and power on the device using the pushbutton on the front. The blue (power) LED should blink and then come on permanently and the following should appear in the console if no harddrive is connected:

found magic num
found magic num
found magic num
bootLoader made time: 1238800322
bootLoader version: 2.00b08
bootloader model name : dns-313v3
Waiting for disk ready & detect ...
Failed to init IDE disks!
Failed to init IDE disks!

As you see it fails to find an IDE disk. It's because I haven't connected one. At this point, the console is interactive, so just hit CTRL+C twice and then the green (hard disk) LED comes on, and this happens:

Aborted by user!
Not found /.boot/zImage
can not boot from ide

Processor: SL3512c3
CPU Rate: 300000000
AHB Bus Clock:150MHz    Ratio:2/1
MAC 1 Address: 14:D6:4D:A8:3C:4F
MAC 2 Address: 00:50:C2:22:22:22
inet addr:
Kernel RAM Location: 0x00600000  Filename: /.boot/zImage
Initrd RAM Location: 0x00800000  Filename: /.boot/ramdisk.bin.gz

Andge Test Code 0.03 (DAS Mode LED) ...
PHY 0 Addr 1 Vendor ID: 0x001cc912
==> enter ^C to abort booting within 2 seconds ......

Boot Menu
0: Reboot
1: Start the Kernel Code
5: Enter Command Line Interface
6: Set IP Address
8: Show Configuration
I: Initialize IDE
X: Upgrade Boot

=> Select:

So now you have a ROM/Flash root prompt. This is all the software that the DNS-313 stores in its flash: the rest is loaded from the IDE drive or from the network.

Booting a kernel

This procedure requires a UART and will boot a kernel over the network using TFTP.

Compiling the kernel

To compile the kernel you first need a ARMv4 toolchain to build it with, then you need to configure and compile the kernel, and possibly also attach an initramfs.

I use a special gemini.mak makefile that I put in the root of the kernel directory, edit the makefile to select the right DTB then I type:

  make -f gemini.mak config && make -f gemini.mak build
And this will build the whole kernel, attaching an initramfs and a DTB file, and put the resulting zImage in $HOME as well as in /var/lib/tftpboot if it is writeable. You will need the rootfs-gemini.cpio rootfs for this to succeed.

Pre-built kernel images with rootfs

Analyzing the vendor code

Some information could be obtained by plowing through the (messy) vendor code. In drivers/char/g751.c we find:

#define GPIO_SET             2
#define SMBCLK_PIN           16
#define SMBDATA_PIN          15

So it is clear that the G751 temperature sensor is sitting on an emulated SMB (I2C) bus on GPIO lines 15 and 16. But this mocky chardev is actually used for all LED and fan control as well:

#define FAN_SPEED_LOW_PIN    11
#define FAN_SPEED_HIGH_PIN   12

So GPIO lines 11, 12, 13 are used for controlling the fan.

The boot loader code gives other hints. This can be found at dns-313_gpl_v2.01/source/Image/src/sl-boot-64M/src/sys/sys_main.c in the source release:

  #ifdef USB_DEV_MO
  vbus = REG32(SL2312_GPIO_BASE + 0x04)&BIT(17)  ; //read GPIO0[17]->data in 0x04
  vbus = REG32(SL2312_GPIO_BASE + 0x04)&BIT(18)  ; //read GPIO0[17]->data in 0x04
  }       //printf("vbus : %x\n",vbus);
  vbus = 1;

This is a hint that GPIO 17 and 18 is used for VBUS detection.

Further digging in the emac driver gives that GPIO lines 22 and 21 are used for MDIO to the PHY, and the PHY is on address 1 on the MDIO bus. This seems to be the case with almost all SL3512-based NAS things so no big surprise there.

In the initrd.tgz provided with the sources I found a file named /sbin/fan.script which provides the info that the fan should turn on at low speed at 43 degrees celsius and high speed at 47 degrees celsius.

Analyzing the flash contents

This device does not use the flash for the operating system or the root filesystem: it is just 512KiB and way too small to even fit a Linux kernel. Instead, there is a partition with a RedBoot-derived boot loader, and two partitions just named "MTD1" and "MTD2", each containing a (very small) file system.

The RedBoot image contains the MAC address used, at offset 0x1D2F4 thru 0x1D2F9. To be sure we found the right thing, we can check for the string "dns-313" at offset 0x1D204. I came up with this little script for setting the ethernet MAC from the ROM:


if [ -b /dev/mtdblock0 ] ; then
    DEVID=`dd if=/dev/mtdblock0 bs=1 skip=119508 count=7 2>/dev/null`
    MACADDR=`dd if=/dev/mtdblock0 bs=1 skip=119540 count=6 2>/dev/null | hexdump -n6 -e '/1 ":%02X"' | sed s/^://g`
    if [ "x$DEVID" = "xdns-313" ] ; then
         echo "$DEVID ethernet address: $MACADDR"
         ifconfig eth0 hw ether $MACADDR 2>/dev/null
         echo "Unknown firmware revision - can't extract MAC address"
    echo "No MTD device"

The MTD1 and MTD2 partitions turn out to be two copies of the same file system of minix type with the following content:

  # ls -al
  totalt 44
  drwxr-xr-x. 2 root root 1184  2 jan  2000 .
  drwxr-xr-x. 1 root root   28 16 jan 14.16 ..
  -rwxr--r--. 1 root root 1525  4 dec  2008 cacert.pem
  -rwxr--r--. 1 root root 1751  4 dec  2008 cakey.pem
  -rwxr-xr-x. 1 root root   36  4 dec  2008
  -rwxr-xr-x. 1 root root  126  1 jan  1970 ddns.conf
  -rwxr-xr-x. 1 root root  136  1 jan  1970 email.conf
  -rwxr-xr-x. 1 root root   47  1 jan  1970 group
  -rwxr-xr-x. 1 root root   72  3 sep  2007 hosts
  -rwxr-xr-x. 1 root root   15  1 jan  1970 language.conf
  -rwxr-xr-x. 1 root root   25  1 jan  1970 log.conf
  -rwxr-xr-x. 1 root root  242 20 mar  2009 mt-daapd.conf
  -rwxr-xr-x. 1 root root  249  1 jan  1970 mt-daapd.playlist
  -rwxr-xr-x. 1 root root   15  1 jan  1970 mtdversion
  -rw-r--r--. 1 root root    0  1 jan  1970 newftp
  -rwxr-xr-x. 1 root root  146  1 jan  1970 passwd
  -rwxr-xr-x. 1 root root  172  3 sep  2007 pf_param.conf
  -rwxr-xr-x. 1 root root  185 30 sep  2007 pure-ftpd.conf
  -rwxr-xr-x. 1 root root   26  1 jan  1970 quota
  -rwxr-xr-x. 1 root root  302  9 aug  2007
  -rwxr-xr-x. 1 root root   12  1 jan  1970 resolv.conf
  -rwxr-xr-x. 1 root root    2  1 jan  1970 rtc.conf
  -rwxr--r--. 1 root root 3204  4 dec  2008 server.pem
  -rwxrwxrwx. 1 root root  109 26 jul  2007 shadow
  -rwxr-xr-x. 1 root root 1148  6 jul  2008 sib2.conf
  -rwxr-xr-x. 1 root root  760  1 jan  1970 sib_ap.conf
  -rwxr-xr-x. 1 root root 1148 12 jan  2009 sib.conf
  -rw-------. 1 root root  464 27 maj  2009 smb.default
  -rwxr-xr-x. 1 root root    1  1 jan  1970 smbpasswd
  -rwxr-xr-x. 1 root root   89  1 jan  1970 tr069.conf
  -rwxr-xr-x. 1 root root 1320  1 jan  1970 udhcpd.conf
  -rwxr-xr-x. 1 root root 1296  1 jan  1970 udhcpd.conf.def
  -rwxrwxrwx. 1 root root   23 10 feb  2009 upnpav.conf
  -rwxr-xr-x. 1 root root  143 11 mar  2009 upnpscript
  -rwxr-xr-x. 1 root root    0  1 jan  1970 v2.8
  -rw-r--r--. 1 root root    8 30 jul  2009 version2.txt
  -rw-r--r--. 1 root root   37 30 jul  2009 version.txt

Apparently there are just copies of random configuration files in the flash. Other D-Link NAS products seem to have more or less identical configuration files. None of them have very much relevance for running your own OpenWRT instance on the system, it might be that the OpenWRT /etc/config directory should simply be mounted here, so the configuration persists over a reinstall.

As sideband information we see that the product was configured 2007-2008 and someone made the last changes to the configuration in may 2009, which fits nicely with the device being released in 2010.

Kernel TODO