Revision as of 06:15, 25 March 2014 by Craig Peacock (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Updating the Kernel on the GuruPlug

guruplugdisplaylink.png

I have recently acquired an IoGear external DVI Video Interface using Display Link technology. It’s essentially an USB to DVI Video interface and just the thing to add a video display to my Guruplug.

The kernel on my Guruplug is version 2.6.32-00007-g56678ec originally installed when it shipped from Global Scale Technologies in May 2010. According to freedesktop.org the opensource DisplayLink driver was added to the mainline kernel in version 2.6.38, so rather than recompiling the driver as a module for 2.6.38, I made the decision in under 100 milliseconds to upgrade the kernel to the latest whiz bang 2.6 version – 2.6.39.4 at time of publication. After all, Why not?

This was my first serious adventure into the depths of the Guruplug. I was one of the excited individuals (picture Christmas time) to order the Guruplug Server Plus prior to its release, only to find out it was really the GuruPlug Server Plug plus Heat Problems when it arrived. An engineer at sometime, somewhere, underestimated the heat they could dissipate in such a small package and when the two ethernet ports were both used at gigabit rates, the unit would spontaneously reset. In addition, with marginally rated capacitors in the power supply and Australia being 240V and not 110V and there was a high instance of power supply failure.

The enthusiasm to do anything with this device rapidly died. Well until now.

Over the years I have learnt, many times the hard way, that you really need to understand the memory maps, MTD (Memory Technology Device) flash partitions, bootloader and recovery process prior to diving in head first and flashing the device with your newly built kernel.

When I pre-ordered the Guruplug Server Plus, Global Scale threw in a Guru Plug JTAG board that connects directly to the the GuruPlug’s JTAG and console ports. The JTAG board is based on a FTDI FT2232D dual USB serial port with Multi-Protocol Synchronous Serial Engine (MPSSE). Basically, the device has two USB to serial converters – they use one for the 2.5V asynchronous serial based console port and the other one as the JTAG port using the MPSSE. OpenOCD, a free open source On Chip Debugger can then be used to program the device - essential if you break the bootloader and need to recover it.

Bootloader

The boot loader on the Guruplug is DAS u-Boot, or more commonly known as just u-Boot. Yes, you are right – it’s German.

The bootloader installed on my Guruplug is u-Boot 2009.11-rc1-00602-g28a9c08-dirty (Feb 09 2010 – 18:15:21) and looks like a modified version by Marvell, the chip manufacturer of the 1.2GHz Kirkwood processor that powers the plug. The bootloader should be accessible on the console port after power up. The console port is 115,200bps 8N1.

The GuruPlug’s memory consists of 512MB of NAND flash and 512MB of 800MHz DDR2 RAM. The memory map is quite simple.

The u-Boot bootloader, the bootloader’s environment/configuration space, the kernel and filesystem is all stored – naturally – on non-volatile flash. u-Boot and the configuration space occupies the first 1MB of memory. The kernel has the next 4 megabytes starting at offset 0×100000. Then the filesystem has the remaining 507 megabytes from 0×500000.

On the RAM side, u-Boot has the first 8 megabytes reserved. The rest is free. Some developer’s will load kernels and filesystems at 0×800000 for programming to flash. Another common spot is at the 100 megabyte boundary (or offset 0×640000).

u-Boot appears to be able to load a kernel from a FAT formatted USB stick (or drive) or via TFTP. To test your kernel from USB you can use the following commands:

usb reset
fatload usb 1:1 0x800000 uImage-guruplug
setenv bootargs console=ttyS0,115200n8
bootm 0x800000

The USB reset command will reset the USB bus and scan (enumerate) devices on the bus. Running the command on a GuruPlug without any USB devices connectors should return a dialog similar to below:

(Re)start USB...
USB: Register 10011 NbrPorts 1
USB EHCI 1.00
scanning bus for devices... 3 USB Device(s) found
scanning bus for storage devices... Device NOT ready
Request Sense returned 02 3A 00
1 Storage Device(s) found

A quick glance at the schematics will show the Guruplug incorporates a Genesys Logic GL850G 4 Port Hub Controller and Genesys Logic GL836 USB2 Flash Card Reader Controller. The Flash Card reader connects to two micro SD connectors, J3 an Internal connector, not populated on my board and J4 which is the external micro SD card slot.

Cross Compiler

Before you can start building the kernel for the GuruPlug, you will need to install an ARM cross compiler. I used the CodeSourcery G++ Lite 2011.03-42 for ARM EABI and added the compiler’s bin directory to my path after installation.

Kernel

Next, you will need to download the kernel. Marvell has a source tree here but the latest release is 2.6.35rc1. According to people in the know, the Marvell tree is merged with the Kernel.org tree from time to time and vice versa. As 2.6.35rc1 apparently doesn’t have the DisplayLink drivers, I that I just love cutting edge, I couldn’t help to try the latest stable 2.6 version, Linux-2.6.29.4. O.k., I’m don’t crave cutting edge that much to try version 3 of the kernel. The bzip2 version of the source can be downloaded here.

http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.39.4.tar.bz2
tar -xjf linux-2.6.39.4.tar.bz2

Before we delve into building the kernel, u-boot has a special image format called uImage. It includes parameters such as descriptions, the machine/architecture type, compression type, load address, checksums etc. To make these images, you need to have a mkimage tool that comes part of the u-Boot distribution.

wget ftp://ftp.denx.de/pub/u-boot/u-boot-latest.tar.bz2
tar -xjf u-boot-latest.tar.bz2
cd into u-boot directory
make tools
sudo install tools/mkimage /usr/local/bin

u-Boot will not load images intended for a different machine. Doing so will result in an error similar to below:

Marvell>> bootm 0x800000
## Booting kernel from Legacy Image at 00800000 ...
Image Name: Linux-2.6.39.4
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2324344 Bytes = 2.2 MB
Load Address: 00008000
Entry Point: 00008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.

Error: unrecognized/unsupported machine ID (r1 = 0x00000a29).

Available machine support:

ID (hex) NAME
00000690 Marvell DB-88F6281-BP Development Board
00000691 Marvell RD-88F6192-NAS Development Board
00000692 Marvell RD-88F6281 Reference Board
0000078c Marvell 88F6281 GTW GE Board
00000a76 Marvell eSATA SheevaPlug Reference Board
00000831 Marvell SheevaPlug Reference Board
00000a63 Marvell GuruPlug Reference Board
00000bb6 Seagate FreeAgent DockStar
0000085b QNAP TS-119/TS-219
000009c6 QNAP TS-41x
00000b44 Marvell OpenRD Ultimate Board
00000939 Marvell OpenRD Client Board
00000915 Marvell OpenRD Base Board
0000089a LaCie Network Space Max v2
000008a0 LaCie Internet Space v2
00000899 LaCie Network Space v2
0000089b LaCie d2 Network v2
0000089e LaCie 5Big Network v2
0000089c LaCie 2Big Network v2
00000b1e HP t5325 Thin Client

Please check your kernel config and/or bootloader.

If you use bdinfo on the GuruPlug Server Plus shipped from GlobalScale Technologies you will find the architecture number is set to 0xA29 or decimal 2601.

Marvell>> bdinfo
Marvell>> bdinfo
arch_number = 0x00000A29
env_t = 0x00000000
boot_params = 0x00000100
DRAM bank = 0x00000000
-> start = 0x00000000
-> size = 0x10000000
DRAM bank = 0x00000001
-> start = 0x10000000
-> size = 0x10000000
DRAM bank = 0x00000002
-> start = 0x00000000
-> size = 0x00000000
DRAM bank = 0x00000003
-> start = 0x00000000
-> size = 0x00000000
ethaddr = 02:50:43:34:a8:cb
ip_addr = 192.168.0.250
baudrate = 115200 bps
Marvell>>

In the kernel, MACH_TYPE_GURUPLUG is defined as decimal 2659 (0xA63). You have two choices, you can change the environment variable arch_number to 0xA63 or you can hack the include/generated/mach-types.h file and change the define for MACH_TYPE_GURUPLUG to 2601. I took the later option, changing the mach-types.h file. This hopefully allows the ability to interchange my kernels with the original kernel from Global Scale.

#define MACH_TYPE_GURUPLUG 2601

Building the Kernel

Before we can build the kernel, we need to configure it. Build the menu configuration using the following commands:

cd linux-2.6.39.4/
make ARCH=arm kirkwood_defconfig
make ARCH=arm menuconfig

As the objective is to build in DisplayLink USB support, we need to enable support for this.

Under Device Drivers -> Graphics Support -> Support for Frame Buffer Devices, enable built-in support for DisplayLink USB Framebuffer Support.

Also in the Device Drivers -> Graphics Support menu, select Console display driver support and enable built-in Framebuffer Console support.

Map the console to the primary display device

Once you have finished configuring the kernel, you will want to build it:

make ARCH=arm CROSS_COMPILE=arm-none-eabi- uImage

This process should finish with a dialog similar to:

OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
UIMAGE arch/arm/boot/uImage
Image Name: Linux-2.6.39.4
Created: Sat Sep 17 04:26:42 2011
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2324344 Bytes = 2269.87 kB = 2.22 MB
Load Address: 00008000
Entry Point: 00008000
Image arch/arm/boot/uImage is ready

Now build the modules and install them to a suitable path:

make ARCH=arm CROSS_COMPILE=arm-none-eabi- modules
make ARCH=arm CROSS_COMPILE=arm-none-eabi- INSTALL_MOD_PATH=/home/cpeacock/export/rootfs-f12 modules_install