Saturday, August 23, 2014

Windows on Intel Galileo

Apparently there's a way to run Windows on Intel Galileo board with the development and debugging happening through Visual Studio!  According to the instructions, you basically need a (decently sized, minimum 16GB) microSD card which you boot off.

Given how the boot process works, it doesn't surprise me that this would work since all you'd need is an EFI executable bootloader on the SD card.  I've always wondered how decoupled Windows kernel is from all the GUI aspect of it, and I'm guessing this is one of the more stripped down version of Windows with minimum required to run Arduino like workloads.

Looking at the Troubleshooting and Advanced Usage pages, the Galileo on Windows shows up as another Windows PC with open mounts and ability to connect kernel debugger to it.

Unfortunately, Windows is only supported on the original Galileo board, not on Gen 2 boards... though given I have no experience with Windows development at all, it's not that big a loss. :-)

Sunday, August 17, 2014

Opening the Galileo Firmware Update Image

In the Galileo tool installation directory, under hardware/tools/x86/bin, there's a file named sysimage-galileo-1.0.2.cap, which looks awfully like the firmware update image.  The file size is little under 8MB, which is the size of the SPI flash part, and the filename seems to hint at this being the system image of some sort.  There's also upgrade.sh script, which refers to sysimage files.

When I first opened the file in vim and used the handy xxd command to see the hexdump (:%!xxd, which also works magically on Windows), it felt a little disorienting.  However, there are certain things that I knew would be in the firmware update image.  Since the Galileo board is booting from the device, there has to be some sort of bootloader in there (grub legacy, as seen before) as well as the bootloader configuration information (grub.conf).  I also know that the Linux kernel image and the initramfs image must also be included.  In the bootlog, as Linux kernel boots, it helpfully prints the following which gives me the kernel and initramfs sizes.
[Linux-EFI SPI, setup=0x107f, size=0x1e0da0]
[Initrd SPI, addr=0xdb5f000, size=0x298a13]
That's more than enough to start some spelunking.  Since it's easiest to find strings, and I know grub.conf is a simple text file, I started by looking for the title of the boot targets like 'Clanton' and 'SVP' - Voila!  At 0x06a3990, you see the contents of grub.conf that corresponds to the boot menu that we see in the bootlog.
Claton SVP kernel!

Linux kernel image also has some unique features - I know that it'll start with "MZ" as its magic number and will have some blurb about needing a bootloader.  By looking for that string, I found what looks very much like the executable kernel image at 0x04be990.
Start of the Linux Kernel

As I was browsing around, I noticed a certain pattern appearing close to start of the two sections above.  The entire update image itself starts with header string with the string "HSC_", and this header appears 9 times throughout the file aligned at 16 byte boundaries.  More importantly, this appears exactly 1024 bytes before the two sections that I've found above.  Using this big hint, I looked at the different sections and tried to figure out what they might be - initramfs was easy, as it's the only region big enough to fit the file size above.  Grub EFI executable was also easy to determine, but the first sets of regions are a mystery for now.
0x0000000 (size 0x0021500) - ??? looks like some sort of table
0x0021500 (size 0x0062090) - ??? looks like an executable
0x0083590 (size 0x0040000) - ??? looks like an executable
0x00c3590 (size 0x0040000) - ??? looks like an executable
0x0103590 (size 0x0121000) - ??? looks like an executable
0x0224590 (size 0x029A000) - initramfs
0x04be590 (size 0x01E5000) - Kernel Image
0x06a3590 (size 0x0001000) - grub.conf
0x06a4590 (size 0x0051000) - grub.efi executable
Now that we have the regions, we can extract the kernel and initramfs filesystem with a simple dd commands
$ dd if=sysimage-galileo-1.0.2.cap of=initramfs.lzma bs=1 skip=2247056 count=2722323
$ dd if=sysimage-galileo-1.0.2.cap of=vmlinux bs=1 skip=4974992 count=1986560
 Extracting the rootfs from initramfs is pretty straight forward from this point
$ mkdir rootfs
$ cp initramfs.lzma rootfs/
$ cd rootfs
$ unxz initramfs.lzma
$ cpio -ivd < initramfs
And now you have the exact filesystem that you get within Galileo after Linux boots up. We can even see the firmware flashing code in opt/cln/galileo/start_spi_upgrade.sh!  And just for fun, let's try booting the Kernel and initramfs on QEMU :-)
$ qemu-system-i386 -kernel vmlinux -initrd initramfs.lzma -append ="root=/dev/ram0 console=uart earlyprintk=serial apic=debug rw"
After that, you need to switch QEMU to serial0 by pressing Ctrl + Alt + 3, but once done, you see the kernel booting on a completely different QEMU system!

It's booting up!
There are some issues - the final console never comes up, probably because init routines point the consoles elsewhere upon boot...  but it does shows that Galileo is basically a stripped down PC.  How amazing is it when you can take a random kernel and stick it on a completely different system and have it boot up?

Sunday, August 10, 2014

Getting down to Linux

The standoffs that I've ordered are somewhere between Shanghai and US, but the USB to UART bridge is here, allowing me to see what's going on when the Galileo board boots up.  All I had to do is install the CP2102 drivers and connect using PuTTY using 115200 and the COM port assigned by the drivers.

Boot Console up and running!

I put the Galileo Gen 2 boot log into a github gist since it's pretty long, but there are some very interesting tidbits in there.  First, it's using Grub Legacy as the bootloader!  Another place where the PC background shows up.  I've usually seen U-Boot being used as bootloader in embedded systems, but for booting Linux on x86 platform, Grub is as good as any, I suppose.  The other thing that I found interesting is that there doesn't seem to be a typical PC "BIOS" as we know it.  In an embedded system where you don't need to discover hardware, it makes sense to drop some of the legacy features that are not likely to be used.  Looking at the Galileo board schematics and the Quark X1000 datasheet, you can see that there's 8MB serial SPI flash (part W25Q64FV) being used as the boot memory.  In Quark Datasheet Table 50, it shows reset vector being mapped into "Legacy Bridge" which has support for one SPI serial flash to store boot firmware (section 21.1).

The references to the SPI flash shows up throughout the boot log.  Grub bootloader is located there, as well as the Linux kernel image.  There are mentions of different elements being signed, though since Galileo supports booting from SD card, I probably wouldn't mess too much with the SPI flash anyway to reduce the risk of possibly bricking the board necessitating finding a JTAG programmer somewhere.

When booting without a SD card, the root filesystem seems to be initramfs loaded into memory, which explains lack of persistence between boots.  When booting from the SD card, the ext3 filesystem is loaded allowing changes to persist between boots, including previous sketches automatically being reloaded.

Since Arduino tool allows firmware to be upgraded, I rummaged around the Arduino installation directory and found "sysimage-galileo-1.0.2.cap" file in hardware\tools\x86\bin directory, which is about the right size to fit in 8MB SPI flash.  Opening up the file also has some right strings showing up, so that might be a quick way to figure out what exactly is in the different SPI segments.

There's plenty more to poke around, but to show what you can do by having direct access to the underlying Linux, here's a simple shell script version of the Arduino blink example on Galileo Gen 2 board.


It seems like there are faster ways to access GPIOs, but for normal access, the Arduino wrapper seems to use the sysfs gpio interface.  We're simply exporting the GPIO pin in question - the arduino pin number to GPIO number was reverse engineered by looking at the g_APinDescription table in x86/variants/galileo_fab_g/variant.cpp file - and setting the value to be 0 or 1, making the LED blink.

We've peeled back one layer of abstraction, but I'm sure there are plenty more layers hiding underneath it all!

Sunday, August 3, 2014

Galileo and Arduino first impressions

The Galileo board is a lot smaller than I had imagined, and there's a lot more parts on it than I had expected.  Schematics helpfully provided shows them to be various I/O expanders, drivers, PWM generators, buffers, and muxes.  These are type of features that are integrated in a typical microcontroller, and it's interesting to see external parts being used to make up for the missing features in the Quark SoC.  On the flip side, the board has things like Mini PCI Express port so the PC heritage does help in other ways.

The other thing that I noticed - and it actually bothers me quite a bit for some reason - is that the Galileo PCB comes sans standoffs.  The board sits awkwardly on the Mini PCI Express connector and it teeters unnervingly whenever I need to hit the reset button.

You can't tell, but the LED's blinking, I swear!
Galileo runs full fledged Linux distribution under the hood, and the schematic makes it seem like the Linux boot console is likely to be UART1, which comes out of a header.  A bit of sleuthing shows that the original Galileo had the UART wired in to a microphone connector, so I'm glad that I can just get something like this instead of having to cut open a headset cable.  Mouser has the actual FTDI part with breakout board that I prefer, but having to track down some headers to solder on and additional female to female jumper cables makes it much more expensive to go that way.  Driver support for CP210x part seems decent from quick searching, but that's one of those things that you never know until you plug it in the USB port.

Galileo running with a full, modern operating system does present some interesting challenges on the Arduino side.  Looking at the Arduino tools and the example 'sketches', it really shows its microcontroller roots.  Arduino presents a very simple interface to the end users, providing them with a way to write C code divided into 'setup' and 'loop' routines.  Setup sets all the one-time options at the start of operation, and once the system is up and running, loop will run basically forever.  In the sample 'blink' sketch, functions like pinMode and digitalWrite in microcontroller world can probably map directly to a macro that does a simple memory write operation.

The blink magic happens here
Linux (or pretty much any other operating system) can't willy nilly give raw hardware access to any program that comes its way - it's a surefire way to have unstable unusable system once you have more than one program running at the same time.  Things like GPIOs are typically exposed as sysfs in embedded Linux, and sure enough, you dig down just a bit and you can see in places like hardware/arduino/x86/cores/arduino/wiring_digital.c how the magic happens.  Simple functions like pinMode and digitalWrite ends up poking into sysfs, writing strings like "high" and "low" into the sysfs tree to toggle the bits on and off.  This code then gets compiled into Linux ELF binary, and gets sent to the Galileo board using 80s technology over the serial link.

Intel provides Galileo Linux Examples that shows how to expose some of the power of Linux underneath the device, partly by running a series of system() calls.  One of the examples is how to redirect the console to the port used by Arduino tool, but it seems to get stuck for me on Galileo Gen2 - we'll see if I can get the issue figured out before I either dig out an old switch to connect to the ethernet port, or Amazon delivers the USB to UART converter.

What is clear is that Arduino platform is barely scratching the surface of what Galileo is capable of.  To really understand Galileo, I'm going to have to dive down much, much deeper.