Recent Linux on the D-Link DNS-313
(Last boot 2018-02-24 on v4.16-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.

Quick Install of Hard Disk Boot with Busybox or 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.

Kernel TODO