[GSOC] Panic Room, week #8,*

What have you worked on during the past few weeks?

I tried to finish one of the optional goals of my proposal:

a way to access a payload (possibly a recovery) after the hardware initialisation is complete but the OS has still not taken over.

To define it in more practical terms, I wanted to replace the running payload at the press of a predefined button.

I started by looking into the SMM (System Management Mode) and in particular the SMI (System Management Interrupts) handlers defined by each target board in the coreboot tree.

That was the easy part, it took just a bit of probing my board (Lenovo x60) and a serial cable to retrieve some of the SMI button codes (I planned on using the ThinkAdvantage button, code 0x19).
I added it to the appropriate smihandler.c file, defined the behaviour and that was about it.

The more difficult part was actually implementing a way to make it possible to boot a new payload while in SMM.
SMM can be considered a separate “module” from romstage, etc, this consequently means that it does not have access to all of the same functions.
In particular it cannot access the load_payload() and run_payload() functions defined inside prog_loaders.c, which, as the name implies, are necessary in order to use a payload.

In order to solve the problem I came up with two designs:

  • The first design is quite simple, but in my opinion a bit messy.
    It involves including all of the missing source files into the SMM module at compile time, a.k.a adding more entries inside the Makefile.inc scattered around the source tree.
    I went down this route for a while until I stumbled on a function that needed to use a malloc(), this was expected so I included the definition of that function.
    It then asked to have access to the heap (_eheap) in order to allocate the memory requested, the problem is that the heap is not defined inside SMM.
    I grepped through the source code and found very little about what I was supposed to do in order to define it, so I had to let it go.
    (To add a little bit of context, this was yesterday and if you take a look at this post’s date you’ll realise that there is only 1 day left of GSoC, panic!)
  • The second approach consists of leaving SMM mostly as it is now, and instead find a way to communicate with ramstage, in order to boot the desired payload.
    The thought process was that, if cannot call a function directly from SMM, I would have to use the functions already in place in ramstage, unfortunately those functions are called only once, after the initialisation is done.
    This is where the CMOS memory comes in, I modified the payload loading process and instead of using an hard-coded path defined at compile-time, I made it check for a string inside CMOS and use that as the payload path.
    This method, however, also presented some problems:
    – It seems that currently cmos.defaults is completely ignored and the CMOS string values are not initialised as intended (at least on my board), therefore the payload path resulted always blank.
    – There needs to be quite a bite of space in the CMOS to keep the path there.
    The usual path (fallback/payload), occupies around 160 contiguous bits of the 1024 available ones, which also need to share space with other important configuration bits such as RTC, etc.
    In order to circumvent these limitations it would be possible to replace the string path in the CMOS with an enumeration of the possible paths, this however would need to be defined, maintained and shared both in the CMOS and the rest of coreboot.
    However, same as above, I ran out of time.

That about sums it up for the past few weeks.

Thank you for reading and have a nice week.