This is an old revision of the document!


Firmware information

Testing on v1.08 on a C1 DNS-323

Note: I haven't tested writing to most of these devices, for fear of bricking my unit. Testers wanted!

Flash memory access

The 8MB flash chip is split into 8192 1K blocks, split into 5 sections and assigned to 21 devices.

There are 4 types of firmware devices:

  • /dev/mtdX: Raw access
  • /dev/mtdblockX: Block device, can be mounted (theoretically) and has random access
  • /dev/mtdcharX: Character device, serial access only, read/write from beginning to end
  • /dev/mtdrX: Presumed to be raw, read only access

The sections are as follows:

  • 0 - 64K - Configuration
  • 1 - 64K - Configuration
  • 2 - 1,536K - Kernel image
  • 3 - 6,336K - Compressed ramdisk image
  • 4 - 192K - uboot bootloader image

Every block is represented as one of each of the above device types, EXCEPT /dev/mtdcharX. Details below.

Configuration block

These contain the more volatile configuration files of the firmware. 0 is represented in mtdchar0 and mtdchar1, while 1 is represented in mtdchar1 and mtdchar2.

The behaviour of the block devices is rather odd. One can read and write to them with no problems initially, however, on reboot, problems start to occur. If both blocks are mounted and a file is written to both, the data is not saved. If only one block is mounted, and a file written to it, the data is saved to both blocks. You also need to manually unmount to save the data. I haven't tested for deleting data, or in the case of power loss.

The easiest thing to do is to only deal with 0 as the de-facto configuration block. Never mount or modify 1, and always ensure to unmount after your modifications.

If you want to flash this block with a default.tar.gz file, you could do something like this:

mkdir /sys/default
mount /dev/mtdblock0 /sys/default
cd /sys
tar xzf /mnt/HD_a2/default.tar.gz
umount /dev/mtdblock0
reboot

BRICK WARNING: Using a bad rc.init.sh can brick the device, as this is non-volatile memory you are writing to.

Kernel image

This contains the kernel image that is loaded by the bootloader. It is a standard Linux kernel binary, compiled for ARM. The easiest way to flash the kernel is to do a direct copy from a file:

dd if=/mnt/HD_a2/kernel.bin of=/dev/mtdblock2
reboot

This shouldn't affect running processes, as the kernel is copied into memory on boot. Oh, and BRICK WARNING. You probably won't ever need to do this unless you want to update the core kernel. Drivers etc. can be loaded through .ko files and insmod. The kernel image is also represented in mtdchar4 and mtdchar5.

Ramdisk image

This is essentially a compressed gzip file called ramdisk_el with a 64-byte header at the beginning. On boot, it is copied to a ramdisk, /dev/ram0, and mounted to the root. It contains all the necessary binaries and libraries to run the system. To work in the device, ramdisk images need to be 6MB or less when compressed, and 10MB exactly when expanded. Note that the compression is not limited to gzip, that is simply the default option specified for D-Link's mkimage program, found in the GPL files. Also specified in mkimage are the processor architecture and OS type, hinting at the possibility for further modification.

To flash the ramdisk, we first need to get our ramdisk image on a computer:

gunzip ramdisk_el.gz
mount ramdisk_el /mnt/ramdisk -o loop
#do modifications now
read x
umount /mnt/ramdisk
gzip ramdisk_el
mkimage -A arm -O linux -T ramdisk -C gzip -a 0x00800000 -n Ramdisk -d ramdisk_el.gz uRamdisk

Then we copy the image to the NAS, and:

dd if=/mnt/HD_a2/uRamdisk of=/dev/mtdblock3
reboot

This will permanently modify the firmware image, so BRICK WARNING. For a softer modification, you could try this for the second step:

dd if=/mnt/HD_a2/uRamdisk of=/mnt/HD_a2/ramdisk_el.gz skip=64 #This assumes gzip compression etc.
gunzip /mnt/HD_a2/ramdisk_el.gz
killall5
dd if=/mnt/HD_a2/ramdisk_el of=/dev/ram0
/bin/sh /etc/rc.sh

This will affect (i.e. kill) all running processes and effectively reset the system, and isn't a perfect solution, as the program memory is not reset, so environment variables will not be reset. However, if incorporated into a fun_plug, you can effectively run non-standard firmware while entirely removing the risk of bricking the device, as you can restore it by simply removing the drive.

Bootloader image

This is usually a binary of u-Boot 1.1.1 compiled for ARM. BRICK WARNING! This is the absolute first thing to be run on pressing the power button, and is completely out of the picture as soon as the kernel is loaded, so don't even think about flashing it unless you have a serial cable handy and are ready to use it.

The main purpose of flashing this section is to modify the kernel options passed. You would do the flashing, quite simply, like this:

dd if=/mnt/HD_a2/u-boot.bin of=/dev/mtdblock4
reboot

Other Devices

Storage

The kernel can cope with the standard 16 SCSI (read: high speed) devices, with 16 partitions each, named /dev/sd[a-p][0-15]. These will be used for USB storage devices and the two SATA drives. It can also theoretically handle one old IDE drive, /dev/hda[0-9].

RAID storage

When a RAID arrangement is set up between the SATA drives, they are mounted to /dev/md0 or both md0 and md1, depending on the RAID setting.

Loopback devices

There are a maximum of 5 loopback devices available, for mounting filsystem images: /dev/loop[0-5] They would be used like this:

mount /mnt/HD_a2/filesystem.img /mnt/img -o loop

Behind the scenes, a loop device would be used to interface between applications and the filesystem image.

Ramdisks

The kernel supports up to 3 ramdisks, each allocated 10MB exactly. Normally, only /dev/ram0 is in use, but after formatting, /dev/ram and /dev/ram1 can be used as well:

mke2fs -m 0 /dev/ram1
mount /dev/ram1 /mnt/ram1

Remember that, as with all ramdisks, the memory used is not recoverable until a reboot is performed, as the kernel flags it once it is touched. Also remember that the DNS-323 only has 64MB of ram, so use it wisely.

The size of the ramdisks is predetermined by the bootloader and kernel options.

Direct memory access

You can directly access the memory with the /dev/mem device. For some reason, copying the whole thing gives a “Bad address” error, and copying it back gives a segmentation fault, then locks up the device completely.

Kernel memory

This is located at /dev/kmem. Trying to read from this device gives a segmentation fault, as it is protected memory.

Flash devices

Presumably these are used to flash the firmware, however it can be written to directly as discussed above, and trying to read from these devices gives a “no such device” error. They are located at /dev/flasha[1-7] and /dev/flashb[1-7]. There are some symlinks that point to these blocks, namely:

  • flash_environment: flasha3
  • flash_kernel: flasha2
  • flash_monitor: flasha1
  • flash_reserved: flasha4

NAND Flash Transition Layer

Same story as the flash devices above. They are: /dev/nftla[1-7] and /dev/nftlb[1-4].

TTY

A number of TTY devices are theoretically available: /dev/tty, /dev/tty[0-3] and /dev/ttyS[0-1]. One of these should point to the serial connector on the mainboard, probably /dev/ttyS0. The virtual master/slave device, /dev/ptmx, is also supported.

Consoles

These are the IO ports for the various user sessions.

  • /dev/console: The system console
  • /dev/pts/X: Where X is the UID of the user

Pseudo-devices

These are not actual hardware ports, nor are they virtual devices or user sessions.

  • /dev/null: Accepts all input, outputs none, and destroys all
  • /dev/zero: Outputs a constant stream of nullbytes (0×00)
  • /dev/random: Generates random data. This one blocks.
  • /dev/uramdom: Generates random data. This one does not block.

Unused devices

A number of devices are present in /dev, and work on PC versions of Linux, but in this case do not:

  • /dev/mouse: Normally the mouse device, now just a symlink to /dev/null
  • /dev/fb: Framebuffer device. Symlink to /dev/fb0. As there is no graphics capability, this does not work.
  • /dev/rtc: Real time clock. Normally returns the current timestamp, but in this case is always busy, even when using hwclock.

Navigation

Personal Tools