U-Boot backend support for OSTree

Recently I had to work with OSTree which I think is a very promising and interesting project.

The OSTree site advertises it as

a tool for managing bootable, immutable, versioned filesystem trees

and it uses a combination of chroot and hard links to provide atomic upgrades and rollback of filesystem trees. You can refer to the project’s online manual and README for information about the motivation behind OSTree and its implementation.

When updating the kernel and initial RAM disk images OSTree creates Boot Loader Specification entries. These are drop-in snippets that define a kernel and init ramdisk that have to be used and boot arguments that the bootloader has to pass to the kernel command line on boot.

Currently only gummiboot and GRUB have support for these boot loader snippets.

We wanted to use OSTree on embedded devices and since most boards use U-Boot as their boot loader I needed to figure out what was the best approach to add a U-Boot support for OSTree.

Obviously this would have been to add boot loader spec entries support to U-Boot but there are two issues with this approach:

a) U-Boot does not currently support multi-boot

Since U-Boot is designed for embedded it just boots a single default operating system while the boot loader specification was designed for multi-boot. You can drop any number of snippets under /boot/loader/entries and the boot loader should populate its boot menu.

b) Not every vendor allows you to replace the boot loader

Some vendors do not allow to replace the boot loader binaries (i.e: store it on a read-only memory), implements DRM that requires binaries to be signed or are using a very old U-Boot version which would require to backport this support.

So, the solution was to make OSTree to generate boot information instead that could be used by any already deployed U-Boot. The same approach is used on OSTree to support syslinux.

U-Boot allows to modify boards default boot commands by reading and executing a bootscript file (boot.scr) or importing a plain text file (uEnv.txt) that contains environment variables that could parameterize its default boot command or a bootscript.

So, on deploy or upgrade OSTree reads the Boot Loader Specification snippets files and generates a uEnv.txt file that contains the booting information in a format that could be understood by U-Boot.

The uEnv.txt env var file is created in the path /boot/loader.${bootversion}/uEnv.txt. Also, a /boot/uEnv.txt symbolic link to loader/uEnv.txt is created so U-Boot can always import the file from a fixed path.

Since U-Boot does not support a menu to list a set of Operative Systems, the most recent boot loader entry from the list is used.

To boot an OSTree using the generated uEnv.txt file, a board has to parameterize its default boot command using the following variables defined by OSTree:

    ${kernel_image}:  path to the Linux kernel image
    ${ramdisk_image}: path to the initial ramdisk image
    ${bootargs}:      parameters passed to the kernel command line

Alternatively, for boards that don’t support this scheme, a bootscript that overrides the default boot command can be used.

An example of such a bootscript could be:

    setenv scriptaddr 0x40008000
    setenv kernel_addr 0x40007000
    setenv ramdisk_addr 0x42000000
    load mmc 0:1 ${scriptaddr} uEnv.txt
    env import -t ${scriptaddr} ${filesize}
    load mmc 0:1 ${kernel_addr} ${kernel_image}
    load mmc 0:1 ${ramdisk_addr} ${ramdisk_image}
    bootz ${kernel_addr} ${ramdisk_addr}

For more information you can refer to the commit that added U-Boot as backend and OStree test for U-Boot.

I would like to thank my employer Collabora for sponsoring this work.

Posted in Uncategorized | Tagged , , | Leave a comment

mmap support for Raspberry Pi bcm2835 ALSA driver

Because I work on an awesome company I spent last week improving the Raspberry Pi ALSA driver.

A long standing issue was that the driver did not support memory-mapped I/O mode for audio stream transfers.

ALSA supports two transfers methods for PCM playback: Read/Write transfer where samples are written to the device using standard read and write functions and Direct Read/Write transfers where samples can be written directly to a mapped memory area and the driver is signaled once this has been done.

ALSA provides an API for both cases and each application using ALSA to access the audio device can choose which API to use. But since mmap was not supported by the bcm2835 driver, applications using the mmap API did not work on the Raspberry Pi.

To bypass hardware limitation such as the lack of mmap support, ALSA provides a set of PCM plug-ins that can be used to extend functionality and features of PCM devices.

These plug-ins are used by defining a custom /etc/asound.conf or .asoundrc and one of them is the mmap emulation plug-in (mmap_emul) which emulates mmap access using a set of read/write transfers. This plug-in was needed on the Raspberry Pi to allow applications using ALSA mmap API to work. But of course it introduces some latency and requires a custom configuration to enable it.

So, the best approach was to just add mmap support to the ALSA driver and get rid of the mmap emulation plug-in. Normally this is straightforward since the kernel allows memory areas to be mapped to user-space address space so applications can have direct access to device memory.

This was not the case on the Raspberry Pi since the PCM samples are processed by its VideoCore IVI GPU. The ARM11 CPU communicates with the VideoCore co-processor using a message passing interface (vchiq) which means that the CPU is not able to directly address the audio device hardware buffers and audio samples have to be sent to the device using vchiq messages.

Since hardware buffers can’t be directly mapped to user-space memory, an intermediate buffer is needed. This intermediate buffer is mapped to user-space so applications can store the audio samples there. Once user-space has finished writing the PCM samples they are pushed to VideoCore as vchiq messages.

Fortunately, the kernel ALSA subsystem provides a PCM indirect API which are a set of helper functions and a data structure to manage the intermediate and hardware buffers. It is really helpful so you don’t have to write all the buffer management.

So, after figuring out all of this I wrote a patch to add mmap support to the Raspberry Pi ALSA driver and send a pull request that also contained other improvements to the driver.

Since it has been merged on the Raspberry Pi kernel, this feature will be available on the next raspbian release but if you want to use it now you can do the following:

$ git clone git://github.com/raspberrypi/tools.git
$ git clone git://github.com/raspberrypi/linux.git
$ cd linux
$ git checkoub -b rpi-3.6.y origin/rpi-3.6.y
$ export ARCH=arm
$ export CROSS_COMPILE=../tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
$ make bcmrpi_defconfig
$ make prepare modules_prepare
$ make M=sound/arm
$ sudo cp sound/arm/snd-bcm2835.ko /media/rootfs/lib/modules/3.6.11+/kernel/sound/arm/
$ sudo rm /media/rootfs/etc/asound.conf

The last step is very important since using both a mmap capable ALSA driver and the PCM mmap emulation plug-in does not work.

I want to thank my employer Collabora for allowing me to work on this:

Posted in Uncategorized | Tagged , , , | 8 Comments

Using Siri to control your Linux media center

The Raspberry Pi I bought a few days ago has just arrived. I was looking to existing Raspberry Pi projects to get some ideas on what use I could give to this board. One of the coolest projects I found out there was one that uses SiriProxy and WiringPi to open a garage door.

I thought that while deciding what to do with my Raspberry Pi I could start using it as a media center and let Siri control my multimedia apps.

Thanks to D-Bus talking to Linux apps is extremely easy. So I wrote a very simple SiriProxy plugin that controls the Rhythmbox music player using D-Bus and created a pull request in case upstream is interested in having more sample plugins.

I don’t speak Ruby so probably that won’t be the nicest Ruby code you will ever see (to say the least 🙂 )

To use the plugin just clone the master-rhythmbox branch from my SiriProxy fork on Github and follow the SiriProxy’s README set-up instructions.

Keep in mind that there is a known issue on SiriProxy master and you have to apply the fix found on this pull request.

The last two steps are to install ruby-dbus using Gems and change your .siriproxy/config.yml configuration file to include the Rhythmbox plugin.

$ sudo gem install ruby-dbus
$ echo -e "    - name: 'Rhythmbox'\n      path: './plugins/siriproxy-rhythmbox'" >> ~/.siriproxy/config.yml

That’s all, now you can run siriproxy server and Siri can start playing your favorite songs!

The voice commands currently supported are:

start player: starts the Rhythmbox media player
play, pause, stop, next and previous: to start, pause, stop, go to next and previous track.
shuffle on: turn shuffle mode on
shuffle off: turn shuffle mode off
volume up: turn volume up by 20%
volume down: turn volume down 20%

Posted in Uncategorized | Tagged , | Leave a comment

Device Tree support for IGEPv2 (and IGEP COM Module)

Because I work on an awesome company, I could spend the last few days doing upstream kernel work for the OMAP3 SoC based embedded board I maintain.

Now that SPL/U-Boot and the kernel supports the latest version of the board, the natural next step was to add support for Device Tree (DT).

I didn’t know too much about DT besides it was the new shiny way to describe hardware (instead of the infamous board files) and that it could allow to boot most ARM board using a single kernel image.

So, after spending some time learning about DT, I posted a patch-set that adds DT support for IGEP technology devices (IGEPv2 and IGEP COM Module). Hopefully the patches won’t need too much love before they get merged.

DT is a hot topic on the Linux kernel community right now and it’s been actively developed. Support for it is still premature on some platforms (such as OMAP3). So, these DT don’t have all the hardware support for IGEP that is already implemented using board files.

Currently is working (tested with latest Linux v3.7-rc7 kernel on an IGEPv2 board):
– MMC/SD
– UARTs
– GPIO LEDs
– TWL4030 codec audio
– pinmux/pinconf pinctrl

There are still peripherals not yet supported such as Ethernet, Flash memory and Wifi/BT. Some of these are connected to the OMAP processor through its General Purpose Memory Controller (GPMC) interface and patches to add DT bindings for OMAP GPMC are still flying around. So support for them should be easily added once these patches hit mainline.

It should also work on an IGEP COM Module but since I don’t have this hardware it has been just “compile tested”.

Many thanks to Enric who provided me his initial DT that booted the board, reviewed my patches and gave me lots of feedback and suggestions. Enric’s initial DT and a great explanation on how to boot a kernel with DT can be found on his blog entry.

Also, I’ve updated the oe-core/poky/yocto meta-igep layer to include a mainline Linux kernel recipe. This will make easier to test IGEP support on upstream and to add any remaining hardware enablement bits.

Posted in Uncategorized | Tagged , | 1 Comment

Adding IGEPv2 Rev.C support to mainline u-boot and kernel

I own an IGEPv2 Rev.C board which is a Texas Instrument OMAP3 DM3730 ARM embedded platform very similar to the Beagleboard-MX board but with more peripherals and a 512 NAND flash memory. This board is part of a family of embedded boards known as IGEP-based boards (another popular board from this family is the IGEP COM module).

IGEP’s manufacturer (ISEE) provides a very complete SDK and documentation on how to build a bootable image for the device and use all its features. The SDK is composed of an custom boot-loader (based on TI x-loader and u-boot), a custom kernel (based on v2.6.37 kernel from TI’s arago project), the Linaro ARM cross-toolchain and a root file system with all the necessary software and example code on how to make the best use of the board features. This makes the IGEPv2 a really competitive platform for embedded DIY projects.

Probably ISEE has its reasons to ship a custom kernel and boot-loader instead of their mainline counterparts but I (being a FOSS hacker) wanted to use upstream software on my board. So I started yet another hobby project to do on my (lately very scarce) free time to hack the kernel and u-boot and make them able to boot my IGEPv2 Rev.C board.

Fortunately, ISEE engineers have been pushing support for their IGEP board family to the mainline Linux kernel even though this kernel is not supported by their company. They do this on their free time because they understand the benefits of having their code as close as upstream as possible thus minimizing the size of the patch-set they need to carry on and forward port every time they move to a newer kernel release. But since they do on their spare time, it usually doesn’t support the latest version of their boards (such as the latest IGEPv2 Rev.C I own).

Also, ISEE used to ship u-boot as the IGEP family boot-loader before developing their own boot-loader (igep-x-loader). So it turned out that I only needed to add a few patches to the upstream kernel and u-boot to make them work with my board.

The first issue I had is that previous IGEP boards came with an OneNAND flash memory while newer boards use a NAND flash memory. So the first patch to the kernel was to to give NAND support to the IGEP. With this patch I was able to boot an upstream kernel using ISEE’s custom boot-loader.

The next step was to add the needed support to u-boot. This was a little more complicated since ISEE has not used u-boot for a while and u-boot has added recently a major feature which eliminates the need of a first stage loader (such as TI’s x-loader). Now u-boot has a framework known as SPL (Second Program Loader) that uses the same code base to generate both the first stage and second stage boot-loaders.

So, besides adding NAND support and a compile config option to choose the flash memory type to be used on an IGEP board I added SPL support for IGEP boards and updated the IGEP default kernel command line arguments to use the OMAP-specific serial driver and the EXT4 file system

With these patches my board booted with mainline u-boot and kernel but I found an issue on the IGEP kernel platform code that assumed the boot-loader would set the OMAP mux pin connected to the LAN9221i ethernet chip IRQ line as GPIO input mode (which was true with igep-x-loader but not with u-boot anymore). This should be made on the kernel anyways so the fix was just a trivial one-liner patch to the kernel.

All these patches are upstream now, so to test it just use the latest v3.6-rc4 kernel from Linus and u-boot master branch (git://git.denx.de/u-boot.git).

I had a lot of fun hacking this and my next step is to migrate the IGEP platform code to device trees. So, if anyone else owns an IGEPv2 or an IGEP COM module and is interested on using mainline software instead of ISEE custom one, please contact me so we can share the efforts 🙂

Posted in Uncategorized | Tagged , | 7 Comments

Hardware enablement

Linux 3.4 is close to be released and this version includes a device driver I was working on my free time a few months ago for the Cypress TrueTouch Gen3 family of touchscreen micro-controllers.

So, now these devices found on many embedded devices such as the HP Touchpad, Sony Xperia phone and the Nook Color e-reader are fully supported on Linux and the driver is using the stateful multi-touch protocol type B (identifiable contacts and slots) taking full advantage of the hardware finger tracking capabilities.

Many thanks to Kevin McNeely from Cypress that provided me the last version of Cypress’s Android Gingerbread driver and for answering all my questions about the device operation and hardware registers. First I thought I could just forward port this driver and post it for upstream inclusion. But after posting Cypress’s driver, I had so many change requests from the kernel hackers that I had to basically rewrite the driver (the most important issue was that it used input MT protocol type A instead of B).

The Linux multi-touch and input maintainers, Henrik Rydberg and Dmitry Torokhov helped me a *lot* reviewing my patches, explaining me the correct approach to report the contact slots to the input MT layer and pointing me out lots of issues with the driver. I wish all the Linux subsystem maintainers were as constructive and willing to help as Henrik and Dmitry.

I had fun working with the driver and now the Linux installation on my Nook Color is more close to functional. My next step is to work on the LCD panel driver that’s still not supported. A touch-screen without a panel is not very useful besides running evtest on a console to see how the input evens are reported to user-space 🙂

Finally, if you are a hardware vendor and want your device supported on Linux or have an out-of-tree driver that needs to get merged on the mainline kernel, please drop an email to sales@collabora.co.uk, we will be more than pleased to work with you to make that happen.

Posted in Uncategorized | Tagged , | Leave a comment

Netlink notifier chain

At Collabora we are working on improving the D-Bus IPC system. We are trying different approaches and one of them is implementing the D-Bus routing logic and match rules handling as a Generic Netlink service. Rodrigo wrote a great blog entry on the design of this Netlink solution.

A problem we found is that AF_NETLINK is not connection oriented. Applications don’t establish a connection before transmitting, they just open a socket and start sending messages. So, if an application close its socket, the other peers won’t notice. This also applies to the kernel code since in Generic Netlink, the in kernel service is just another user of the Netlink channel.

The problem is that D-bus is connection oriented, we have to keep track of each connection to the bus and remove it when the socket associate with the connection is closed.

Fortunately, the kernel has a mechanism known as notifier chains that allows kernel code to listen for certain events by registering to a specific notifier chain.

Netlink defines a notifier netlink_chain to notify when a socket is released (NETLINK_URELEASE event). So, we can use that information to remove the D-Bus connection associate with a socket when it is released.

The notifier API is very simple, we only have to define a notifier_block data structure and assign a function handler to the notifier_call function pointer. Once the notifier_block data structure is registered, the notifier_call function handler is called every time the events occurs.

I knew about notifier chains before but haven’t used until today so I thought it was something interesting to share. Here is a small example of how we can use the Netlink notifier chain:

static int dbus_netlink_notify(struct notifier_block *nb, unsigned long state,
                               void *_notify)
{
        struct netlink_notify *notify = _notify;

        if (state == NETLINK_URELEASE && notify->protocol == NETLINK_GENERIC)
                dbus_bus_del_connection(notify->pid);

        return NOTIFY_DONE;
}

static struct notifier_block dbus_netlink_notifier = {
	.notifier_call = dbus_netlink_notify,
};

static int __init dbus_init(void)
{
	int rc;

	rc = genl_register_family_with_ops(&dbus_family, dbus_ops,
					   ARRAY_SIZE(dbus_ops));
	if (rc)
                return rc;

	rc = netlink_register_notifier(&dbus_netlink_notifier);
	if (rc) {
                genl_unregister_family(&dbus_family);
                return rc;
	}

	return 0;
}
Posted in Uncategorized | Tagged | 4 Comments