November 30, 2016

Intel Galileo - Booting, with particular attention to Xinu

Most of this is provided by Jim Lembke in answer to my email questions:

Booting Xinu on the Galileo

The Galileo, which was intended to be an arduino enthusiasts board was really designed to boot Linux and not any other OS. On the SPI flash there is an image of GRUB legacy (https://www.gnu.org/software/grub/grub-legacy.html) which is set up by default to boot a couple "flavors" of the Linux kernel provided by Intel. This GRUB is automatically run by the BIOS on the Galileo firmware when the Galileo boots up.

  1. A small prebuilt Linux kernel that exists on the SPI flash
  2. A larger prebuilt Linux kernel that can be copied to the micro SD card

Each of these images use a ram disk as the root file system and have the ability to mount the micro SD card for additional storage. Notice that this list does not contain "third party" operating systems like Xinu.

Problem #1 - The Galileo board does not and has no intention of ever supporting network booting (BOOTP, PXE, etc). In our previous setup, we had Dell workstation machines which we put a version of GRUB that supported network booting. On startup, this GRUB would contact the DHCP server and boot using BOOTP (https://en.wikipedia.org/wiki/Bootstrap_Protocol). When we wanted to run a new version of Xinu, we just copied the built image to the DHCP server and power-cycled the Dell workstation. On boot, GRUB would pick up the new image, load it, and run it.

When we first started looking into booting Xinu on the Galileo we thought since Xinu supports the multiboot protocol (https://www.gnu.org/software/grub/manual/multiboot/multiboot.html) as does GRUB legacy we could, for experimentation, put the Xinu image on the micro SD card (just like Linux image #2 above) and have the GRUB legacy that exists in the SPI flash boot Xinu right from the SD card. This wouldn't solve the network booting but it would at least allow us to start playing around with Xinu on the Galileo.

Problem #2 - The version of GRUB legacy that is in the SPI flash of the Galileo was changed by Intel to remove a whole bunch of features in order to save space in the SPI flash. One of those features was the multiboot support.

So now we can't boot Xinu directly from the micro SD card since the GRUB that exists in the SPI flash will ONLY boot Linux kernels.

Possible solution to Problem #2 - Rebuild our own GRUB legacy which includes the features we need and load it on the SPI flash. We really wanted to avoid having to change the "stock" SPI image provided by Intel for a couple reasons:

  1. We didn't want to have a situation where we could "brick" our boards
  2. We wanted to provide a solution that was easy for others to set up. From this email it may seem that we did not meet this goal, but at least one of the steps does not involve flashing anything.

Implemented solution to Problem #2 - While the GRUB legacy does not support multiboot, it does support chainloading (loading another boot loader). So it was suggested that we have the GRUB legacy chainload another version of GRUB which does support the features we need, and along came bootia32.efi. This is an image of GRUB version 2 (https://www.gnu.org/software/grub/manual/grub.html) which the GRUB legacy chainloads and contains support for multiboot.

Now we can boot Xinu provided it is NOT a network boot (see problem #1).

To solve problem #1 we invented the idea of XBoot which we could customize to contain the network driver for the Galileo as well as all the BOOTP logic to read an image from our DHCP server. This is exactly what XBoot does. When Xinu is built for the Galileo there is a script which converts the ELF image generated by the compiler into a direct binary image. We then add a custom XBoot header to the binary image. This is then copied to the DHCP server.

After all of this we are left with the final boot process for Xinu on the Galileo:

Platform Data: accessing SPI flash

As far as the SPI flash is concerned I do not know off the top of my head if it's mountable in linux. I do know that a certain portion of the SPI flash is memory mapped. Xinu uses the memory mapped region of the SPI flash which contains the platform data to get the MAC address of the network card. The code to access the platform data is in these two files:
include/quark_pdat.h
system/quark_pdat.c
You can see how the ethernet driver uses these functions on line 199 of
device/eth/ethinit.c
Tom wrote a little routine to scan and print this platform data area. Apparently this stuff is in SPI flash, but mapped to memory address 0xFFF10000
PDAT entry id = 1
 len = 2
 ver = 0
 desc = PlatformID
 data (hex) = 0800
     Platform id = 8
PDAT entry id = 6
 len = 39
 ver = 1
 desc = MrcParams
 data (hex) = 080002000000000000010101000300000200000101017c9200001027000010270000409c000006
PDAT entry id = 3
 len = 6
 ver = 0
 desc = 1st MAC
 data (hex) = 984fee058571
PDAT entry id = 4
 len = 6
 ver = 0
 desc = 2nd MAC
 data (hex) = 02ffffffff01
So, only 4 entries. I was hoping to find a way to distinguish Gen 2 from Gen 1 Galileo units here. Perhaps the PlatformID value (set to "8" on my Gen 2 Galileo) does the trick, but I don't know because I have yet to see these values documented. In the absence of documentation, the descriptor strings are helpful, but no telling what MrcParams are supposed to be.

BSP tools

Also, if you clone the Intel Galileo Runtime, there is a directory called spi-flash-tools which contains several tools for updating the SPI flash.
git clone https://github.com/01org/Galileo-Runtime.git
Also the following document (38 page PDF) gives some instructions on how to use the tools and how the platform data is laid out in the SPI flash.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org