Debian on Sheeva Plug internal NAND flash


After a bit of work, I got the sheeva plug working the way I wanted it to. First of all, I grabbed a spare 1G USB flash disk I had laying around and installed Debian squeeze to it by following tbm’s instructions here:

http://www.cyrius.com/debian/kirkwood/sheevaplug/install.html

After debian was installed to the USB disk, I removed it from the plug and used dd on my laptop to create an image of the filesystem. I mounted the filesystem as a loopback device and created a jffs2 partition image from it after doing a bit of minor tweaking. I placed the USB disk back in the plug and booted to it. Using this intermediate filesystem and the mtd-tools package, I wrote the new jffs2 image to the NAND mtd device. I then modified the uboot environment to suit, saved, and now have a working setup.

Detailed instructions are below.

pre-requisites

Connect the plug to your network with the rj-45/cat5 cable.

Connect a USB flash drive to the plug. I used a 1G drive, but 512M should be sufficient.

Install the ‘tftpd’ package on a machine on your network. You’ll also need screen on the machine that you use to connect to the plug’s serial terminal. I’ll assume these are the same host. You need the IP address of the tftp server. In this example, we will assume that the IP is 192.168.1.2 and that you will assign 192.168.1.200 to the plug.

$ sudo apt-get install tftpd screen

Place uImage, uInitrd, and uBoot in the /srv/tftp directory:

$ sudo wget -O /srv/tftp/uImage http://www.cyrius.com/tmp/beta1/marvell/sheevaplug/uImage
$ sudo wget -O /srv/tftp/uInitrd http://www.cyrius.com/tmp/beta1/marvell/sheevaplug/uInitrd
$ sudo wget -O /srv/tftp/uBoot http://wp.colliertech.org/cj/wp-content/uploads/2010/09/07/uboot.bin

Connecting to the serial console

We are now ready to boot the plug. Note that you have to be quick with the screen command. I recommend you type it out and get ready to press the enter key. You have to interrupt the bootloader in order to enter the u-boot console. Attach the power and immediately enter the following command:

$ screen -S sheeva /dev/ttyUSB0 cs8,ixoff,115200

If you did this right, you should see a prompt like this:

Marvell>>

update uboot

As per tbm’s instructions, you can now update the uboot if needed. Instructions for that are here:

http://www.cyrius.com/debian/kirkwood/sheevaplug/uboot-upgrade.html

I’ll put them inline here for completeness.

Marvell>> setenv serverip 192.168.1.2 # IP of your TFTP server
Marvell>> setenv ipaddr 192.168.1.200 # IP of the plug
Marvell>> bubt uboot.bin

be sure to answer ‘n’ to the question about env parameters.

Now reset the device. Don’t forget to interrupt the bootloader so we can get back to the prompt:

Marvell>> reset

Let the device know that you will be running a mainline kernel and set the arcNumber:

Marvell>> setenv mainlineLinux yes
Marvell>> setenv arcNumber 2097
Marvell>> saveenv
Marvell>> reset

Install Debian to the USB disk

Interrupt the boot process once more. We are now ready to run the debian installer. I’ll leave the details as an exercise for the reader. The following should put you into the installer, which you are probably quite familiar with by now.

NB: I will assume that you will use a single ext3 partition for the entire system. This will make it easier to build a jffs2 image out of the resultant partition on the USB disk.

Marvell>> setenv serverip 192.168.1.2
Marvell>> setenv ipaddr 192.168.1.147
Marvell>> tftpboot 0x01100000 uInitrd
Marvell>> tftpboot 0x00800000 uImage
Marvell>> setenv bootargs console=ttyS0,115200n8 base-installer/initramfs-tools/driver-policy=most
Marvell>> bootm 0x00800000 0x01100000

build a jffs2 image

Once the installation has completed, power down the plug and remove the USB disk. Put the USB disk in the machine you used to get the console on the plug and note what device the kernel assigns to it. In my case, it was given sdc, so debian is installed to /dev/sdc1. I will use these values for this example.

If the filesystem was automatically mounted, unmount it. Create a disk image of the partition and mount it as a loopback device.

$ sudo umount /dev/sdc1
$ dd if=/dev/sdc1 of=/tmp/debian.img
$ mkdir /tmp/mnt
$ sudo mount -o loop /tmp/debian.img /tmp/mnt

You can now remove the USB disk and return it to the plug.

Modify the /etc/fstab file. The root filesystem will be /dev/mtdblock2 and of fs type jffs2. My fstab file looks like the following:

proc            /proc           proc    defaults        0       0
/dev/mtdblock2 /               jffs2    errors=remount-ro 0       1

We can now create a jffs2 image from the mounted and altered fresh install:

$ sudo mkfs.jffs2 -l \
  -e 0x20000 \
  -X zlib \
  --eraseblock=128KiB \
  --pad \
  --output=/tmp/rootfs.jffs2 \
  --compression-mode=priority \
  -n \
  --squash \
  -r /tmp/mnt

write jffs2 to nand

Now that we have an image to flash to the NAND, let’s boot off of the USB disk. It should now be attached to the plug. Power on the plug and use screen to get a console. Interrupt the bootloader and enter the following commands:

Marvell>> setenv bootargs_console console=ttyS0,115200
Marvell>> setenv bootcmd_usb 'usb start; ext2load usb 0:1 0x01100000 /boot/uInitrd; ext2load usb 0:1 0x00800000 /boot/uImage'
Marvell>> setenv bootcmd 'setenv bootargs $(bootargs_console); run bootcmd_usb; bootm 0x00800000 0x01100000'
Marvell>> run bootcmd

Log in as root with the credentials you configured during the install. You will need to install a few packages in order to complete the nand flash. You can then ssh to the host on which you created the jffs2 image and cat it to stdout, piping this to nandwrite:

$ sudo apt-get install mtd-utils
$ ssh user@192.168.1.2 cat /tmp/rootfs.jffs2 | sudo nandwrite /dev/mtd2 -p -

You now have a jffs2 image on the nand.

Configure u-boot

One more reboot to set u-boot’s environment, and you will be done. Power down and remove the USB disk. Power on and get the serial console using screen. Break into the bootloader and enter the following commands:

Marvell>> setenv bootargs_console console=ttyS0,115200
Marvell>> setenv mtdpartitions mtdparts=orion_mtd:0x400000@0x100000(uImage),0x1fb00000@0x500000(rootfs)
Marvell>> setenv bootargs_root root=/dev/mtdblock2 rw rootfstype=jffs2
Marvell>> setenv bootcmd 'setenv bootargs $(bootargs_console) $(mtdpartitions) $(bootargs_root); nand read.e 0x00800000 0x00100000 0x00400000; bootm 0x00800000'
Marvell>> saveenv
Marvell>> reset

You should now be good to go.


11 responses to “Debian on Sheeva Plug internal NAND flash”

  1. You can go a step further, and repartition the flash as 1M for uboot and the remainder for rootfs. Then uboot can read the kernel uImage and uInitrd from the filesystem. I’m using this approach with a ubifs rather than jffs2 root on the Seagate DockStar. A similar approach is described here: http://forum.doozan.com/read.php?2,72,261#msg-261

  2. Thank you for the instructions. I created my own jffs2 from my existing sheeva install and copy-pasted your bootloader commands. Unfortunately it didn’t work. The boot stops after “Uncompressing Linux ….. done, booting the kernel.”

    Now that I actually read your commands, they seem somewhat strange. Especially the line

    setenv bootcmd ‘setenv bootargs $(bootargs_console) …

    Is this really correct?

    • It works for me… I decided to go with ubifs instead of jffs2. There’s a lot of overhead for that filesystem and my memory is consumed in the kernel. Yuck.

  3. CJ,

    Thank you for the very informative article. It is very well written and interesting.

    Would you please share a couple of thoughts with me? I would be very grateful.

    I am a decent Linux hack, mostly in the business world: MySql, Php, Apache programming for 20 years. I just recently got interested in compiling, cross-compiling, etc. I have programmed in Visual C++ and Qt C++ with a lot of success (have written a number of applications). So I am not new to Linux..

    BUT..

    I am almost a total dunce when it comes to embedded devices. Recently I wrote a very nice C++ application to run in Linux. It is for my brother’s insurance inspection business. It runs very nicely in Ubuntu and CentOS (my main workstation).

    My idea was to be able to port this application to a small portable computer such as the Chinese A-pad.

    Now, I live part-time in China and I have a good source here. I recently bought a couple of tablets, both with the Cortex A-8 CPU (Telechips), 512 DDR and 8GB of Nand, 7 ” capacitive screen.. both machines work very nicely, including the touch-screens. The problem is that these machines run of Android (uggh!). I dislike Android with a passion and it has become very frustrating trying to do anything with these nice little computers.

    I don’t know where to start but I am hoping you can steer me in the right direction. For you it would take just a few minutes to summarize.. for me, it takes hours and hours of research just trying to understand where to begin.

    Number 1) These machines run on ARM (which I understand).. they also use the Nand flash for memory and disk storage which I don’t understand very well. It totally blows my mind when I can mount a pen-flash disk (also Nand) on my Linux box but cannot mount the Nand on these mini-computers. I am sure it has something to do with the file-systems. These devices are using JFFS2.

    Question 1? How do I get the MTD-TOOLS to install on CentOS? I need to be able to mount a JFFS2 file system. (I know my machine can see the device.. it shows up on “lsusb”.. but, of course, the device’s Nand does not show up on my “fdisk -l” command.

    Number 2) If I can get to point where I can actually see the Nand and work with it then I can compile and build a custom Kernel and firmware to install on the JFFS2 partition.

    Question 2? This may sound dumb, but, is it necessary to communicate with my device using the “serial” route like you described in your article.. OR, can I work the device through a USB connection directly from my Linux machine. These devices DO NOT have a serial port..

    The reason I ask is that Android uses an “ADB bridge” to communicate with their devices.. All of this is done through a USB connection. It really sucks and it also does me no good. The console connection acts like it is totally in a chroot jail almost.

    Any suggestions would be appreciated. I am sure you have better things to do but I am very serious about completing my project. I believe with the popularity of these mini-computers (A-pad tablets) that someone will want to use them for business purposes and NOT simply a ding-a-ling phone running games, movies and music. LOL

    Sincerely,

    Bob Campbell
    Jiashan, China and Tucson, Arizona

    • Hi there Bob,

      Can you do some PIV with Chrystal and/or Scott @plainblack.com? Either that or send me an email address. I’m so terrible at keeping this blog working. We can try to do it here, though ;)

    • Actually, I like the adb bridge. it works pretty well. I often do this:

      $ sudo `which adb` forward tcp:2200 tcp:22

      I do this after I bring the chroot up and launch /etc/init.d/ssh start

      Here, I’ll do it and show you what it consists of.

    • cjac@foxtrot:~$ sudo `which adb` kill-server
      [sudo] password for cjac:
      cjac@foxtrot:~$ sudo `which adb` start-server
      * daemon not running. starting it now on port 5037 *
      * daemon started successfully *
      </pre.

    • $ adb shell cat /sdcard/mount.sh
      #!/bin/bash

      mount -o remount,rw /
      mkdir /mnt/debian
      mount -o remount,ro /
      mount -o dev,remount /mnt/sdcard
      DEVNUM=90
      mknod /dev/block/loop${DEVNUM} b 7 ${DEVNUM}
      losetup /dev/block/loop${DEVNUM} /mnt/sdcard/debian-armel.img
      mount /dev/block/loop${DEVNUM} /mnt/debian

      mount –rbind /dev /mnt/debian/dev/
      mount –rbind /dev/pts /mnt/debian/dev/pts/
      #mount –rbind /dev/shm /mnt/debian/dev/shm/
      mount –rbind /proc /mnt/debian/proc/
      mount –rbind /sys /mnt/debian/sys/

      logcat -b main -f /mnt/debian/var/log/android.main.log -v time V &
      #disown
      logcat -b radio -f /mnt/debian/var/log/android.radio.log -v time V &
      #disown
      logcat -b events -f /mnt/debian/var/log/android.events.log -v time V &
      #disown

      mount –rbind /sdcard /mnt/debian/mnt/sdcard/

    • cjac@foxtrot:~$ adb shell sh /sdcard/mount.sh
      cjac@foxtrot:~$ adb shell
      # chroot /mnt/debian
      sh-3.2# export PATH=/bin:/usr/bin:/sbin:/usr/sbin
      sh-3.2# /etc/init.d/ssh stop
      Stopping OpenBSD Secure Shell server: sshdstart-stop-daemon: warning: failed to kill 8266: No such process
      .
      sh-3.2# /etc/init.d/ssh start
      Starting OpenBSD Secure Shell server: sshd.
      sh-3.2# exit
      exit
      # exit
      cjac@foxtrot:~$ ssh -p 2222 localhost
      The authenticity of host ‘[localhost]:2222 ([127.0.0.1]:2222)’ can’t be established.
      RSA key fingerprint is 2d:6e:8a:c9:b3:7c:73:b7:52:de:43:d9:8f:06:81:42.
      Are you sure you want to continue connecting (yes/no)? ^C
      cjac@foxtrot:~$

Leave a Reply