Disclaimer: the information provided on this page is given as is, i.e. without warranty that you will not break your system following it. Additionally, do not expect to get support and warranty from NETGEAR if this happens.

Debian and grsec kernel on NETGEAR ReadyNAS 102

This page documents some efforts to get a recent grsec-enabled kernel and latest Debian system running on NETGEAR ReadyNAS 102, instead of the original (Marvell/NETGEAR-patched) kernel and custom system. At the time of writing (June 2015), everything needed to support the device is now available in upstream kernel (v4.0). Check Changelog and Todo list below to see current status and progresses. This is the same kind of work I previously performed for Netgear ReadyNAS Duo v2.

As the platform are very similar and I already spent quite some time documenting Duo v2 hardware, only the main differences are given here:

Here is the main table of contents for the page, with links to the various sections of the page.


Changelog i.e. work done

Todo list i.e. work in progress

Hardware Specs

This section is dedicated to the hardware specs of the NETGEAR ReadyNAS 102. It is based on visual inspection of RN102 main board and two daughter boards, completed with reading of NETGEAR 3.0.57 kernel sources and publicly available (read Google-gathered) information. This is the same method I previously used for its older brother, the ReadyNAS Duo v2.

When available, additional information and software handling details are given for each hardware part. For instance, if you are looking for informations related to the fan controller, simply click the link above to get the details of what is used and how support is provided.

Each picture available on this page is a thumbnail of a larger picture. The larger one can be accessed by clicking the thumbnail.

If you are in a hurry looking for a specific info, you can use this table of contents to directly access information on a specific hardware part of the system or get an overview of what a NETGEAR ReadyNAS 102 is made of.

Marvell Armada 370

The ReadyNAS 102 is powered by an (ARMv7-based) Marvell ARMADA 370 SoC. The CPU comes with a FPU and NX bit support. The SoC includes a 16-bit DDR3 memory interface, two ethernet MAC controllers (one routed on the 102), two DMA/XOR engines, a network security engine, two UART interfaces, thermal support, etc. The following Armada 370 SoC block diagrams (extracted from the product brief) provides an overview of supported functionalities:

The following excerpt (also fro the product brief) provides an expected typical use of the SoC in 2 bay NAS implementations:

The ReadyNAS 102 uses this architecture with some additional hardware parts to support more functionalities (specific RTC with alarm support, USB 3.0, eSATA controller, etc)

Here is what /proc/cpuinfo reports for the CPU:

# cat /proc/cpuinfo
Processor	: Marvell PJ4Bv7 Processor rev 1 (v7l)
BogoMIPS	: 1196.85
Features	: swp half thumb fastmult vfp edsp vfpv3 vfpv3d16 
CPU implementer	: 0x56
CPU architecture: 7
CPU variant	: 0x1
CPU part	: 0x581
CPU revision	: 1

Hardware	: Marvell Armada-370
Revision	: 0000
Serial		: 0000000000000000

Hynix H27U1G8F2BTR

The ReadyNAS 102 comes with 128MB of NAND flash. This is provided by a single Hynix H27U1G8F2BTR chip, as depicted below. The same chip was used on the ReadyNAS Duo v2.

Here is what NETGEAR default kernel reports about the NAND of the 102 and its layout:

armada-nand armada-nand.0: Init. HAL based NFC in 8bit mode with DMA Disabled using BCH 4bit ECC
NAND device: Manufacturer ID: 0xad, Chip ID: 0xf1 (Hynix NAND 128MiB 3,3V 8-bit)
Bad block table found at page 65472, version 0x01
Bad block table found at page 65408, version 0x01
mtd: no mtd-id
5 cmdlinepart partitions found on MTD device armada-nand
Creating 5 MTD partitions on "armada-nand":
0x000000000000-0x000000180000 : "u-boot"
0x000000180000-0x0000001a0000 : "u-boot-env"
0x000000200000-0x000000800000 : "uImage"
0x000000800000-0x000000c00000 : "minirootfs"
0x000000c00000-0x000008000000 : "ubi"

Hynix H5TQ2G83DFRH9C

The ReadyNAS 102 comes with 512MB of RAM connected to the SoC. This is provided by two soldered Hynix H5TQ2G83DFRH9C chips.

Intersil ISL12057 I2C bus RTC

The RaedyNAS 102 comes with an Intersil ISL12057 I2C bus RTC chip, as depicted below.

The Intersil ISL 12057 is a low power RTC and Alarm chip. A short patch (596 LoC) has been written by NETGEAR for the ReadyNAS 102 kernel (based on 3.0.56) but has never been pushed upstream. I decided to implement a driver for the chip based solely on existing ISL 12008 kernel driver and ISL12057 datasheet and push it upstream.

Fresco Logic FL1009 USB3.0/xHCI host controller

The USB3.0/xHCI controller used by the device is a Fresco Logic FL1009, as depicted below. A product brief is locally cached here. The FL1009 is a 2-port PCIe, which was the first one to gain USB-IF certification. It has also being demoed by Fresco Logic to hit speeds in excess of 400MB/s.

GMT G762 PWM Fan controller

The rotation speed of the fan is controlled by a GMT G762 PWM fan controller chip. Both of those (fan and controller) are the same as the one used on RN102 old brother (i.e. ReadyNAS Duo v2)

After some work, I managed to get G762 driver accepted upstream in 3.11 kernel. That been done, it can now easily be referenced in Duo v2 (done) and RN102 .dts file.

Take a look at the fancontrol section to see how the fan controller can be coupled with the temperature sensor.

Main daughter board (USB 3.0 eSata, serial, ethernet and fan connector)

The ReadyNAS 102 mainboard has two connected daughter boards:

The main daughter board is depicted below.

Mainboard front buttons and LED

The following picture provides an overview of the five leds, two buttons (Power and USB copy) and the USB port available on the front of the device, under the enclosure.

The four power (#1 from left to right on the picture), SATA1 (#3), SATA2 (#4) and backup (#5) LEDs are all connected to specific MPP of the SoC configured as GPIO (respectively MPP 57, 15, 14 and 56) and can be controlled easily from userland. The activity LED (#2) is on the contrary connected directly to the SATA controller and will flash upon activity.

In the .dts I pushed upstream to support the NAS (available in 3.12), the default initial behavior of those LEDs is the following:

The initial behaviour (state, trigger) provided in the .dts file can be modified very easily via /sys entries. This is described in more details in a specific section (Configuring custom LED behaviour) below.

Regarding the Power and Backup buttons, they are also connected to specific MPP of the SoC configured as GPIO. When pressed, they generate a signal on the referenced pin of the SoC which is converted as an input event by the kernel. In the .dts,

Those can easily be catched from userspace in order to act upon their reception and perform specific actions. This is described in more details in a specific section (Configuring custom actions for buttons) below.

Marvell 88E1318 Gigabit Ethernet PHY

The Marvell ARMADA 370 SoC comes with two integrated Ethernet MAC but does not include the required PHY. The ReadyNAS 102 has a Marvell 88E1318 Gigabit Ethernet PHY connected to the SoC via a RGMII interface.

Marvell 88SE9170-NNX2 Sata Controller

The ReadyNAS 102 includes a specific Marvell 88SE9170 2 ports PCIe 2.0 1X SATA storage controller

Marvell G47B

Protechnic Electric Co MG9212YB-25 Fan

The fan on the 102 is the same as the one found on its old brother, the Duo v2, i.e. a 92mmx92mmx25mm Protechnic Electric CO MG9212YB-25 Fan a Protechnic Electric Co MG9212YB-25 Fan.

Richtek RT8105

I kept a local copy of the datasheet.

Serial interface / Console

Marvell SoC directly embbeds two UARTs. In the NAS, one is rooted up to the main daughter board and associated pins are directly available under a simple sticker at the rear of the device, on the left side above the kensington port, as depicted above.

Once the sticker removed, the four pins of the serial console on the main daughter board can be used to get access to the device. Note that the serial port is a 3.3V one, i.e. you need a specific adapter like the one depicted below and cannot use a usual 12V serial or USB serial dongle for that purpose..

The specific purpose of each pin is depicted below

Below is what default NETGEAR kernel reports about the serial console.

Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0xd0012000 (irq = 41) is a 16550A
console [ttyS0] enabled

and what 3.11 reports about it:

Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
d0012000.serial: ttyS0 at MMIO 0xd0012000 (irq = 17) is a 16550A
console [ttyS0] enabled, bootconsole disabled

Texas Instruments - TPS65251

This is the same chip as on Netgear ReadyNAS Duo v2.

I kept a local copy of the datasheet just in case you have

CR2032 Battery

The CR2032 battery is used to provide power to the ISL 12057 RTC chip when the NAS is not powered.

Step by step kernel build

This section documents in details a step by step build and install of a 3.11.1 kernel on the ReadyNAS Duo v2. The steps should be similar for a more recent kernel version. The procedure described in this section is very similar to the one given for ReadyNAS Duo v2. Although this creates duplication, this makes the page self-sufficient.

Cross-compilation toolchain

The first thing needed to compile the kernel is a cross-compilation toolchain. Assuming you are on Debian, you could previously just use emdebian.org repositories to get the required packages:

root@small# cat > /etc/apt/sources.list.d/emdebian.sources.list
deb http://www.emdebian.org/debian unstable main
^D
root@small# apt-get update
root@small# apt-get install binutils-arm-linux-gnueabi \
                            gcc-4.7-arm-linux-gnueabi \
                            libgcc1-armel-cross \
                            linux-libc-dev-armel-cross

Now (2014), the best way to get a proper cross-compilation toolchain is to build one using crosstool-ng. It is straigthforward to get an arm-unknown-linux-gnueabi one.

Here, we could also use an arm-[unknown-]linux-gnueabihf- toolchain (Armada 370 has a FPU) instead of the arm-[unknown-]linux-gnueabi- one. Even though I did not performed specific tests, this should have no performance impact for kernel whereas it may have on userland for specific applications.

Kernel Build

Now that we have a compiler to create arm binaries, let's first grab our kernel.

arno@small$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.11.1.tar.xz
arno@small$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.11.1.tar.sign
arno@small$ gpg --verify linux-3.11.1.tar.sign
gpg: Signature made Sat 14 Sep 2013 04:07:21 PM CEST using RSA key ID 6092693E
gpg: Good sig. from "Greg KH (Linux kernel stable release signing key) <greg@kroah.com>"
arno@small$ tar xf linux-3.11.1.tar

As 3.11 kernel is still missing RN102 .dts file (which will be available in 3.12) and ISL 12057 RTC chip support, we need to patch the kernel to complete the support:

arno@small$ wget http://natisbad.org/NAS2/linux-3.11.1-rn102-support.patch
arno@small$ wget http://natisbad.org/NAS2/linux-3.11.1-rn102-support.patch.sign
arno@small$ gpg --verify linux-3.11.1-rn102-support.patch.sign
gpg: Signature made Sun 29 Sep 2013 07:27:05 PM CEST using RSA key ID A7AE341B
gpg: Good signature from "Arnaud Ebalard <arno@natisbad.org>"
arno@small$ cd linux-3.11.1 
arno@small$ patch -p1 -i ../linux-3.11.1-rn102-support.patch
patching file arch/arm/boot/dts/armada-370-netgear-rn102.dts
patching file arch/arm/boot/dts/Makefile
patching file drivers/rtc/Kconfig
patching file drivers/rtc/Makefile
patching file drivers/rtc/rtc-isl12057.c

Let's now configure the kernel. In order to bootstrap with a working config and then make it fit your needs feature-wise, the best way is to use the one I provide below:

arno@small$ wget -O .config http://natisbad.org/NAS2/config-rn102-3.11.1 
arno@small$ export ARCH=arm
arno@small$ export CROSS_COMPILE=arm-linux-gnueabi-
arno@small$ make oldconfig
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/zconf.lex.c
  SHIPPED scripts/kconfig/zconf.hash.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf --oldconfig Kconfig
#
# configuration written to .config
#
arno@small$ make menuconfig

The last make menuconfig allow you to change the kernel configuration to fit your needs.

Let's now build the kernel zImage, append to it our Netgear ReadyNAS 102 .dtb (Device Tree Blob) generated from our .dts (Device Tree Source) file and then make a uImage out of it. The resulting uImage is then copied to our tftp folder to be served to the NAS to be loaded by u-boot. So, in the same shell (where ARCH and CROSS_COMPILE where previously defined):

arno@small$ LOADADDR=0x00008000 make -j 16
arno@small$ cat arch/arm/boot/dts/armada-370-netgear-rn102.dtb >> arch/arm/boot/zImage 
arno@small$ LOADADDR=0x00008000 make uImage 
arno@small$ sudo cp arch/arm/boot/uImage /srv/tftp/

tftp setup to serve kernel image (and later Debian installer).

The best way to push required binaries (kernel images, debian installer) to the NAS is probably via tftp. This is done quite simply from your Debian host by installing openbsd-inetd and atftpd packages (I got issues with tftpd packages so I would suggest not to use it). If you have a firewall running on your host, you need to temporarily allow incoming connection on 69/udp.

arno@small$ sudo apt-get install openbsd-inetd atftpd
arno@small$ sudo /etc/init.d/openbsd-inetd restart
arno@small$ sudo iptables -A INPUT -i eth0 -p udp --dport 69 -j ACCEPT

From now on, everything we put in /srv/tftp will be accessible from u-boot, which will allow us to boot the kernel image we built and put there for example. But to interact with u-boot, we need to access to the serial console.

Serial access to u-boot and system console

Details of serial console access is described in hardware section.

Then, once our 3.3V USB/serial dongle is connected on one side to the serial console of the RN102 and on the other to an USB port of our host, we can simply plug the power cord without powering the device. The following appears:

arno@small$ screen /dev/ttyUSB0 115200

BootROM 1.08
Booting from NAND flash
DDR3 Training Sequence - Ver 2.1.7 
DDR3 Training Sequence - Ended Successfully 
BootROM: Image checksum verification PASSED

 __   __                      _ _
|  \/  | __ _ _ ____   _____| | |
| |\/| |/ _` | '__\ \ / / _ \ | |
| |  | | (_| | |   \ V /  __/ | |
|_|  |_|\__,_|_|    \_/ \___|_|_|
         _   _     ____              _
        | | | |   | __ )  ___   ___ | |_ 
        | | | |___|  _ \ / _ \ / _ \| __| 
        | |_| |___| |_) | (_) | (_) | |_ 
         \___/    |____/ \___/ \___/ \__| 
 ** LOADER **


U-Boot 2009.08 (Feb 07 2013 - 11:13:03)Marvell version: 1.1.2 NQ
02/07/2013 ReadyNAS-102N104 V1.9
U-Boot Addressing:
       Code:            00600000:006AFFF0
       BSS:             006F9240
       Stack:           0x5fff70
       PageTable:       0x8e0000
       Heap address:    0x900000:0xe00000
Board: DB-88F6710-BP
SoC:   MV6710 A1
CPU:   Marvell PJ4B v7 UP (Rev 1) LE
       CPU @ 1200Mhz, L2 @ 600Mhz
       DDR @ 600Mhz, TClock @ 200Mhz
       DDR 16Bit Width, FastPath Memory Access
PEX 0: Root Complex Interface, Detected Link X1
PEX 1: Root Complex Interface, Detected Link X1
DRAM:  512 MB
       CS 0: base 0x00000000 size 512 MB
       Addresses 14M - 0M are saved for the U-Boot usage.
NAND:  (ID 0xf1ad)      128 MiB
Bad block table found at page 65472, version 0x01
Bad block table found at page 65408, version 0x01
FPU not initialized
USB 0: Host Mode
USB 1: Host Mode
Shutting down unused interfaces:
       GBE0
       SDIO
       AUDIO
       TDM
Modules/Interfaces Detected:
       RGMII1 Phy
       PEX0 (Lane 0)
       PEX1 (Lane 1)
       SATA0 (Lane 2)
       SATA1 (Lane 3)
Power supply plug on, please press power button!

We can then power on the device (push the power button on the front of the device). This will present a 3 seconds countdown which allow us to interrupt the boot process and access u-boot, simply by hitting a key. Let's do just that.

Power On!

MMC:   MRVL_MMC: 0
Net:   egiga1 [PRIME]
Hit any key to stop autoboot:  0 
Marvell>>

For the record, let's just print current u-boot environment

Marvell>> printenv
ethaddr=00:50:43:00:02:02
eth1addr=2C:B0:5D:BF:2E:ED
SerialNum=3ER133ET00672
Product=ReadyNAS 102
SKUNum=RN102
UUID=824db5e4-9648-11e2-a6b3-2cb05dbf2eed
Manufacturer=NETGEAR
Version=V1.0
AC_Power_fail_detect=open
console=console=ttyS0,115200
mtdids=nand0=armada-nand
mtdparts=mtdparts=armada-nand:4m(boot),-(rootfs)
sata_delay_reset=0
enaExtDisk=no
MALLOC_len=5
ethprime=egiga1
bootargs_root=root=/dev/nfs rw
bootargs_end=:10.4.50.254:255.255.255.0:KW40:eth0:none
image_name=uImage
load_addr=0x02000000
bootcmd=nand read 0x2000000 0x200000 0x400000;nand read 0x30000000x800000 0x400000;bootm      \
        0x2000000 0x3000000 standalone=fsload $load_addr $image_name;setenv bootargs $console \
        $mtdparts root=/dev/mtdblock0 rw ip=$ipaddr:$serverip$bootargs_end; bootm $load_addr;
bootdelay=3
ethmtu=1500
eth1mtu=1500
mvNetConfig=mv_net_config=1,(00:50:43:11:11:11,0:1:2:3:4),mtu=1500
usb0Mode=host
usb1Mode=host
usbActive=0
yuk_ethaddr=00:00:00:EE:51:81
nandEcc=1bit
netretry=no
rcvrip=169.254.100.100
loadaddr=0x02000000
autoload=no
eeeEnable=no
HW_version=MVT
Startup=Normal
ethact=egiga1
ipaddr=192.168.58.21
serverip=192.168.58.135
mainlineLinux=yes
stdin=serial
stdout=serial
stderr=serial
enaMonExt=no
pexMode=RC
setL2CacheWT=no
sata_dma_mode=yes
netbsd_en=no
vxworks_en=no
disaMvPnp=no
enaAutoRecovery=yes
pcieTune=no
bootargs=console=ttyS0,115200 mtdparts=armada-nand:0x180000@0(u-boot),                        \
         0x20000@0x180000(u-boot-env),0x600000@0x200000(uImage),                              \
         0x400000@0x800000(minirootfs),-(ubi); reason=normal bdtype=rn102

Environment size: 1500/131068 bytes

As you can see, the environment contains the expected address of the tftp server (serverip parameter) and the NAS IP address (ipaddr):

...

Net:   egiga0 [PRIME]
Hit any key to stop autoboot:  0 
Marvell>> printenv
...
ipaddr=192.168.58.21
serverip=192.168.58.135
...

As you can see above, u-boot environment expects the tftp server to be available at IP address 192.168.58.135. Let's just configure that adress on our host:

arno@small# sudo ip addr add 192.168.58.135/24 dev eth0

Booting your first kernel

Let's now load kernel image we built (uImage) in memory at address 0x1200000

Marvell>> tftpboot 1200000 uImage
Using egiga1 device
TFTP from server 192.168.58.135; our IP address is 192.168.58.21
Filename 'uImage'.
Load address: 0x1200000
Loading: #################################################################
         #################################################################
         #################################################################
         #######################################################
done
Bytes transferred = 3667163 (37f4db hex)

Now that we have our kernel uImage loaded in RAM at address 0x1200000, we can try and check if the kernel boots by issuing the following command:

Marvell>> set serverip 192.168.58.135
Marvell>> set ipaddr 192.168.58.21
Marvell>> set bootargs console=ttyS0,115200 earlyprintk
Marvell>> bootm 0x1200000

This should fail at some point (e.g. no root device) but this is a good test before proceding to the next section.

Step by step Debian install

Now that we have a working kernel, the next step is boot it and use an initrd version of a debian installer to install the system. So the first step is to get a Debian installer. As the Armada 370 SoC has an FPU, we can either use an armel or armhf one, depending on the kind of Debian package architecture we want. In practice, there is no specific reason not go for an armhf installer. For that purpose, you can use current Efikamx mx5 one (or a local working copy (Sep 24 2013)).

Now, considering you choosed the current uInitrd Debian installer and both the kernel and the installer are in your tftp server folder:

Marvell>> set bootargs console=ttyS0,115200 earlyprintk
Marvell>> tftpboot 1200000 uImage
Using egiga1 device
TFTP from server 192.168.58.135; our IP address is 192.168.58.21
Filename 'uImage'.
Load address: 0x1200000
Loading: #################################################################
         #################################################################
         #################################################################
         #######################################################
done
Bytes transferred = 3667163 (37f4db hex)
Marvell>> tftpboot 2000000 uInitrd
Using egiga1 device
TFTP from server 192.168.58.135; our IP address is 192.168.58.21
Filename 'uInitrd'.
Load address: 0x2000000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #######################################################
done
Bytes transferred = 5485034 (53b1ea hex)
Marvell>> bootm 0x1200000 0x2000000

At that point, you should be at home and be able to complete the install of the system as usual. Based on the number of disks, their size and your RAID/lvm setup, you should either be able to boot directly the main partition of your disk (say /dev/sda1) or you may need an uInitramfs.

Building an uInitramfs (required for large disk w/ GPT partitions and/or LVM/RAID installs)

Once Debian install is over, you can reboot the NAS and use the process above to boot again the kernel and the Debian installer. This time, the idea is to get up to the partition manager so that all your partitions (raid, lvm, ext4) are set up and mounted. By executing a shell, we will create an initramfs and then install the kernel and this initramfs (as a replacement of NETGEAR ones on the NAND flash). So, from the Debian installer shell you can remount your disk. Below the root system is on a lvm volume - /dev/mapper/vgr-lvr - but yours could be on something like /dev/sda1 if you did something simple:

root@humble# cd /
root@humble# mkdir tgt
root@humble# mount /dev/mapper/vgr-lvr /tgt
root@humble# cd tgt
root@humble# mount -o bind /proc proc/
root@humble# mount -o bind /dev dev/
root@humble# mount -o bind /dev/pts dev/pts
root@humble# mount -o bind /sys sys 
root@humble# chroot . /bin/bash

Let's install initramfs tools, build one ...

root@humble# apt-get install initramfs-tools
root@humble# mkinitramfs -o /tmp/initramfs-3.11.1 -r /dev/mapper/vgr-lvr -v 

... , and make it understandable by u-boot:

root@humble# apt-get install uboot-mkimage
root@humble# mkimage -A arm -O linux -T ramdisk -C none -a 0x00000000 -e 0x00000000 \
                  -n initramfs -d /tmp/initramfs-3.11.1  /tmp/uInitramfs

Once this is done, you can save the generated uInitramfs; for instance to a USB key. The idea is to be able to make it available in next section via tftp, USB or disk.

Also note that based on your root device (/dev/mapper/vgr-lvr here), you will also have to change the bootargs command in order to provide that information to the kernel (possibly with an additional rootdelay option). In our case:

Marvell>> set bootargs console=ttyS0,115200 earlyprintk root=/dev/mapper/vgr-lvr
Marvell>> saveenv

Boot strategies

Upon boot, the NAS will load u-boot, which will then - based on the content of its environment - load at least an uImage (and possibly an uInitramfs) from some given location and start your favourite distribution, most probably available on SATA disks.

In practice, the main factor impacting the boot strategies available to you is the size of the disks put in the NAS. If you put large disks (say more than 2TB), then those will be partitioned with a GPT which will prevent installing and load the kernel from a partition (say /boot) available on the disk. In that case, the only available methods are to load the kernel from NAND, a USB key or tftp.

Additionally, if you intend to install the system on a RAID/lvm (say ext4 on LVM on a two disks software RAID1 array), even if you are able to load the kernel, you will not be able to go any further without using an uinitramfs because Linux kernel can not automount RAID array.

In the end, the best method is probably to have u-boot load both an uImage and an uInitramfs from NAND (or USB).

Anyway, the three methods are all described below.

Booting from NAND

IMHO, the most simple way to store and boot an uImage (and possibly an uInitramfs) is to put those in NAND and get them loaded via u-boot at startup. This is basically the purpose of the NAND and how NETGEAR uses it. From the bootloader, you can see how the NAND is partitioned:

Marvell>> nand info
Device 0: nand0, sector size 128 KiB

Marvell>> printenv
...
mtdparts=nand_mtd:
0x180000@0(u-boot)
0x20000@0x180000(u-boot-env)
0x600000@0x200000(uImage)
0x1000000@0x800000(minirootfs)
0x6800000@0x1800000(jffs2)
...

It contains (in that order) some space for u-boot itself (1536 KB), u-boot environment (128 KB), kernel uImage (6 MB) and a rootfs/initrd (16 MB) and a jffs2 partition (104 MB).

As discussed earlier, the funny part is that NAND controller support is not available in mainline kernel (3.11 at the time of writing). For that reason, the only way to install uImage and uInitramfs in NAND is from u-boot.

So let's first load our kernel in RAM at address 0x1200000 via tftp, erase kernel partition and then write the kernel to it from RAM:

Marvell>> tftpboot 0x1200000 uImage
Using egiga1 device
TFTP from server 192.168.58.135; our IP address is 192.168.58.21
Filename 'uImage370'.
Load address: 0x1200000
Loading: #################################################################
         #################################################################
         #################################################################
         ######################################
done
Bytes transferred = 3411987 (341013 hex)

Marvell>> nand erase 0x200000 0x600000
NAND erase: device 0 offset 0x200000, size 0x600000
Erasing at 0x7e0000 -- 100% complete.
OK

Marvell>> nand write 0x1200000 0x200000 0x600000

NAND write: device 0 offset 0x200000, size 0x600000
 6291456 bytes written: OK

Then, we can do the same for our uinitramfs by loading it in RAM at address 0x2000000:

Marvell>> tftpboot 0x2000000 uinitramfs-3.11.1
Using egiga1 device
TFTP from server 192.168.58.135; our IP address is 192.168.58.21
Filename 'uinitramfs-3.11.1'.
Load address: 0x2000000
Loading: #################################################################
         #################################################################
         #################################################################
         ##########################
done
Bytes transferred = 3238266 (31697a hex)

Marvell>> nand erase 0x800000 0x400000
NAND erase: device 0 offset 0x800000, size 0x400000
Erasing at 0xbe0000 -- 100% complete.
OK

Marvell>> nand write 0x2000000 0x800000 0x400000

NAND write: device 0 offset 0x800000, size 0x400000
 4194304 bytes written: OK

Then, in order to actually have u-boot automatically load those elements from NAND at startup and boot them, we need to update bootcmd to the following and then save the environment:

Marvell>> set bootcmd "nand read 0x1200000 0x200000 0x600000; \
                       nand read 0x2000000 0x800000 0x400000; \
                       ping 192.168.58.135; \
                       bootm 0x1200000 0x2000000"

Marvell>> saveenv
Saving Environment to NAND...
Erasing 0x180000 - 0x1a0000:    [Done]
Writing to Nand:                [Done]

You might wonder why the ping call in previous command. This is to temporarily workaround what seems to be an ethernet PHY initialization issue. If you do not force u-boot to init the PHY, then the ethernet interface will not work properly when the system has booted. Well, the issue was fixed in 3.12 and backported in stable kernels. So, if your kernel is recent enough, everything should work as expected.

Booting from USB

WORK IN PROGRESS

Booting from SATA disk

WORK IN PROGRESS

Notes on PaX/grsec support

Working PaX/grsec configurations for recent kernels are available from that page.

Making MAC address stable

This is not per se a real issue but the MAC address of the RN102 available from the u-boot environment is not automatically set during the boot process. At the time of writing no good solution has been found by the kernel maintainers. In the future, the idea is for Marvell to release updated bootloader version which will modify the DTB before handling it out to the kernel and will thus be able to set expected MAC addresses.

Anyway, until this happens, the only proper^W way to get a stable MAC address is to have a userspace script set it during boot before having the interface configured. On Debian, this easily done using the following snippet in /etc/network/interfaces:

root@humble:~# cat /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
        pre-up ip link set dev eth0 address 00:50:44:00:02:02

Automatic fan control based on NAS temperature

After having installed fancontrol package ...

root@humble:/sys/bus/i2c# apt-get install fancontrol

... , you first need to run pwmconfig to create an initial configuration referencing the temperature sensor and the fan controller, and the various temperature and fan rotation limits. You will end up with a configuration file (/etc/fancontrol)like the following (stock 3.11 kernel):

root@humble:/sys/bus/i2c# cat /etc/fancontrol 
# Configuration file generated by pwmconfig, changes will be lost
INTERVAL=5
DEVPATH=hwmon0=devices/soc.0/internal-regs.1/d0011000.i2c/i2c-0/0-003e hwmon1=
DEVNAME=hwmon0=g762 hwmon1=armada_thermal
FCTEMPS=hwmon0/device/pwm1=hwmon1/temp1_input
FCFANS= hwmon0/device/pwm1=hwmon0/device/fan1_input
MINTEMP=hwmon0/device/pwm1=40
MAXTEMP=hwmon0/device/pwm1=60
MINSTART=hwmon0/device/pwm1=40
MINSTOP=hwmon0/device/pwm1=40
MINPWM=40
MAWPWM=175

Obviously, you may change the configuration (e.g. modify MAXTEMP and/or MAXPWM values) based on your needs (noise vs SoC temperature).

As a side note, I do not go here into the details of the fan driving mode (PWM vs DC) and the fan speed control modes (manual i.e. open-loop and automatic i.e. closed-loop) the g762 fan controller supports. By default, Netgear's u-boot puts g762 driver in manual fan speed control (/sys/bus/i2c/drivers/g762/0-003e/pwm1_enable is set to 1) and DC mode (/sys/bus/i2c/drivers/g762/0-003e/pwm1_mode set to 0). Addditional information is available in kernel g762 documentation (Documentation/hwmon/g762).

Configuring custom LED behaviour

WORK IN PROGRESS

Configuring custom actions for buttons

As discussed earlier, the 3 buttons available on the board (Power and Backup at the front, Reset at the rear) are all defined (in .dts file) to report a specific input type when pressed. By increasing kernel log level (man 5 proc), you can observe that behaviour on the console (on a kernel configured with CONFIG_INPUT_EVBUG). This will also appear in your syslog file:

root@humble# echo 8 > /proc/sys/kernel/printk
evbug: Event. Dev: input0, Type: 1, Code: 116, Value: 1             <- pressing Power button
evbug: Event. Dev: input0, Type: 0, Code: 0, Value: 0
evbug: Event. Dev: input0, Type: 1, Code: 116, Value: 0             <- releasing Power button
evbug: Event. Dev: input0, Type: 0, Code: 0, Value: 0
evbug: Event. Dev: input0, Type: 1, Code: 133, Value: 1             <- pressing Backup button
evbug: Event. Dev: input0, Type: 0, Code: 0, Value: 0
evbug: Event. Dev: input0, Type: 1, Code: 133, Value: 0             <- releasing Backup button
evbug: Event. Dev: input0, Type: 0, Code: 0, Value: 0
evbug: Event. Dev: input0, Type: 1, Code: 408, Value: 1             <- pressing Reset button
evbug: Event. Dev: input0, Type: 0, Code: 0, Value: 0
evbug: Event. Dev: input0, Type: 1, Code: 408, Value: 0             <- releasing Reset button
evbug: Event. Dev: input0, Type: 0, Code: 0, Value: 0
root@humble# echo 1 > /proc/sys/kernel/printk

A possible way to configure custom actions when the button is pressed would be to continuously monitor /dev/input/event0 output (see Documentation/input/input.txt). But that would require parsing binary data in the following format:

struct input_event {
	struct timeval time;
	unsigned short type;
	unsigned short code;
	unsigned int value;
};

We could develop something in C to monitor the flow of events and perform dedicated actions upon occurrence of a given event but that would be overkill considering this can more easily be done in Python with something like the following. You can use this script as a basis.

Configuring alarm for poweroff and automatic reboot

Alarm IRQ pin (IRQ#2) of ISL12057 RTC chip is not directly connected to the SoC on RN102, RN104 and RN2120, but to a PMIC (TPS65251), handling powering of the device. The PMIC does not provide a way to report the status of the IRQ#2 pin. This is not a common design pattern on Linux and requires some specific kernel adaptation. This is the reason why alarm support (1a67e256dbd8, 298ff0122ab1, fd71493d6797) for those NAS took a bit longer than expected. If you are interested by the details, the commit messages and the code provides more information.

As also documented in alarm support commits, using the alarm feature now available on the device is very simple. Here is a straightforward example of how this can be done:

# echo `date '+%s' -d '+ 1 minutes'` > /sys/class/rtc/rtc0/wakealarm
# shutdown -h now

After having configured the alarm one minute in the future, and then having powered off the system, you should see it come back to life after a minute. Now, if you want to poweroff the device each night and have it come back say in the morning or in the afternoon, you simply need to create a crontab. This is left as an exercise for the reader.