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 – 22.214.171.124 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.
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.
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.
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-126.96.36.199. 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-188.8.131.52.tar.bz2 tar -xjf linux-184.108.40.206.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-220.127.116.11 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
Before we can build the kernel, we need to configure it. Build the menu configuration using the following commands:
cd linux-18.104.22.168/ 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-22.214.171.124 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